mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-07-01 03:24:29 +08:00
fix: dhcpv6 client id change by slice overwritten (#22905)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
@@ -119,6 +119,8 @@ var (
|
||||
"platform_names",
|
||||
"enable_change_owner_auto_rename",
|
||||
"default_handlers_whitelist_user_agents",
|
||||
"metadata_server_ip4s",
|
||||
"metadata_server_ip6s",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
|
||||
"yunion.io/x/log"
|
||||
@@ -22,6 +23,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
)
|
||||
|
||||
func OnBaseOptionsChange(oOpts, nOpts interface{}) bool {
|
||||
@@ -63,6 +65,14 @@ func OnBaseOptionsChange(oOpts, nOpts interface{}) bool {
|
||||
if oldOpts.ApiServer != newOpts.ApiServer {
|
||||
log.Debugf("api_server changed from %s to %s", oldOpts.ApiServer, newOpts.ApiServer)
|
||||
}
|
||||
if !reflect.DeepEqual(oldOpts.MetadataServerIp4s, newOpts.MetadataServerIp4s) {
|
||||
netutils2.SetIp4MetadataServers(newOpts.MetadataServerIp4s)
|
||||
log.Debugf("Metadata server IPv4 address changed to %s", newOpts.MetadataServerIp4s)
|
||||
}
|
||||
if !reflect.DeepEqual(oldOpts.MetadataServerIp6s, newOpts.MetadataServerIp6s) {
|
||||
netutils2.SetIp6MetadataServers(newOpts.MetadataServerIp6s)
|
||||
log.Debugf("Metadata server IPv6 address changed to %s", newOpts.MetadataServerIp6s)
|
||||
}
|
||||
if oldOpts.TaskWorkerCount != newOpts.TaskWorkerCount {
|
||||
consts.SetTaskWorkerCount(newOpts.TaskWorkerCount)
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/util/atexit"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -116,6 +117,9 @@ type BaseOptions struct {
|
||||
|
||||
CustomizedPrivatePrefixes []string `help:"customized private prefixes"`
|
||||
|
||||
MetadataServerIp4s []string `help:"metadata server IPv4 addresses, default is 169.254.169.254" default:"169.254.169.254"`
|
||||
MetadataServerIp6s []string `help:"metadata server IPv6 addresses, default is fd00:ec2::254" default:"'fd00:ec2::254'"`
|
||||
|
||||
structarg.BaseOptions
|
||||
|
||||
GlobalHTTPProxy string `help:"Global http proxy"`
|
||||
@@ -365,6 +369,8 @@ func parseOptions(optStruct interface{}, args []string, configFileName string, s
|
||||
|
||||
consts.SetServiceName(optionsRef.ApplicationID)
|
||||
httperrors.SetTimeZone(optionsRef.TimeZone)
|
||||
netutils2.SetIp4MetadataServers(optionsRef.MetadataServerIp4s)
|
||||
netutils2.SetIp6MetadataServers(optionsRef.MetadataServerIp6s)
|
||||
|
||||
// log configuration
|
||||
log.SetVerboseLevel(int32(optionsRef.LogVerboseLevel))
|
||||
|
||||
@@ -464,28 +464,6 @@ func (l *sLinuxRootFs) DeployNetworkingScripts(rootFs IDiskPartition, nics []*ty
|
||||
log.Errorf("rootFs.GenerateSshHostKeys fail %s", err)
|
||||
}
|
||||
}
|
||||
// force dhclient for NetworkManager
|
||||
{
|
||||
err := forceNetworkManagerDhclient(rootFs)
|
||||
if err != nil {
|
||||
log.Errorf("force NetworkManager dhclient fail %s", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func forceNetworkManagerDhclient(rootFs IDiskPartition) error {
|
||||
const nmConfPath = "/etc/NetworkManager/conf.d"
|
||||
if !rootFs.Exists(nmConfPath, false) {
|
||||
return nil
|
||||
}
|
||||
dhcpConfPath := path.Join(nmConfPath, "dhcp-client.conf")
|
||||
content := `[main]
|
||||
dhcp=dhclient
|
||||
`
|
||||
if err := rootFs.FilePutContents(dhcpConfPath, content, false, false); err != nil {
|
||||
return errors.Wrapf(err, "write %s fail", dhcpConfPath)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
{
|
||||
mainIp: "10.168.222.175",
|
||||
nics: []*types.SServerNic{
|
||||
&types.SServerNic{
|
||||
{
|
||||
Name: "eth0",
|
||||
Index: 0,
|
||||
Bridge: "br0",
|
||||
@@ -60,7 +60,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
|
||||
LinkUp: true,
|
||||
},
|
||||
&types.SServerNic{
|
||||
{
|
||||
Name: "eth1",
|
||||
Index: 1,
|
||||
Bridge: "br0",
|
||||
@@ -93,14 +93,14 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
Version: 2,
|
||||
Renderer: netplan.NetworkRendererNetworkd,
|
||||
Ethernets: map[string]*netplan.EthernetConfig{
|
||||
"eth0": &netplan.EthernetConfig{
|
||||
"eth0": {
|
||||
MacAddress: "00:24:c7:16:80:f2",
|
||||
Match: &netplan.EthernetConfigMatch{
|
||||
MacAddress: "00:24:c7:16:80:f2",
|
||||
},
|
||||
Mtu: 1500,
|
||||
},
|
||||
"eth1": &netplan.EthernetConfig{
|
||||
"eth1": {
|
||||
MacAddress: "00:24:c7:16:80:f3",
|
||||
Match: &netplan.EthernetConfigMatch{
|
||||
MacAddress: "00:24:c7:16:80:f3",
|
||||
@@ -109,7 +109,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Bonds: map[string]*netplan.Bond{
|
||||
"bond0": &netplan.Bond{
|
||||
"bond0": {
|
||||
EthernetConfig: netplan.EthernetConfig{
|
||||
Addresses: []string{
|
||||
"10.168.222.175/24",
|
||||
@@ -150,7 +150,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
{
|
||||
mainIp: "10.168.22.175",
|
||||
nics: []*types.SServerNic{
|
||||
&types.SServerNic{
|
||||
{
|
||||
Name: "eth0",
|
||||
Index: 0,
|
||||
Bridge: "br0",
|
||||
@@ -176,7 +176,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
|
||||
LinkUp: true,
|
||||
},
|
||||
&types.SServerNic{
|
||||
{
|
||||
Name: "eth1",
|
||||
Index: 1,
|
||||
Bridge: "br0",
|
||||
@@ -209,14 +209,14 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
Version: 2,
|
||||
Renderer: netplan.NetworkRendererNetworkd,
|
||||
Ethernets: map[string]*netplan.EthernetConfig{
|
||||
"eth0": &netplan.EthernetConfig{
|
||||
"eth0": {
|
||||
MacAddress: "00:24:c7:16:80:f2",
|
||||
Match: &netplan.EthernetConfigMatch{
|
||||
MacAddress: "00:24:c7:16:80:f2",
|
||||
},
|
||||
Mtu: 1500,
|
||||
},
|
||||
"eth1": &netplan.EthernetConfig{
|
||||
"eth1": {
|
||||
MacAddress: "00:24:c7:16:80:f3",
|
||||
Match: &netplan.EthernetConfigMatch{
|
||||
MacAddress: "00:24:c7:16:80:f3",
|
||||
@@ -225,7 +225,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Bonds: map[string]*netplan.Bond{
|
||||
"bond0": &netplan.Bond{
|
||||
"bond0": {
|
||||
EthernetConfig: netplan.EthernetConfig{
|
||||
Addresses: []string{
|
||||
"10.168.222.175/24",
|
||||
@@ -260,7 +260,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
mainIp: "10.168.22.175",
|
||||
mainIp6: "2001:db8::23",
|
||||
nics: []*types.SServerNic{
|
||||
&types.SServerNic{
|
||||
{
|
||||
Name: "eth0",
|
||||
Index: 0,
|
||||
Bridge: "br0",
|
||||
@@ -290,7 +290,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
Masklen6: 64,
|
||||
Gateway6: "2001:db8::1",
|
||||
},
|
||||
&types.SServerNic{
|
||||
{
|
||||
Name: "eth1",
|
||||
Index: 1,
|
||||
Bridge: "br0",
|
||||
@@ -323,14 +323,14 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
Version: 2,
|
||||
Renderer: netplan.NetworkRendererNetworkd,
|
||||
Ethernets: map[string]*netplan.EthernetConfig{
|
||||
"eth0": &netplan.EthernetConfig{
|
||||
"eth0": {
|
||||
MacAddress: "00:24:c7:16:80:f2",
|
||||
Match: &netplan.EthernetConfigMatch{
|
||||
MacAddress: "00:24:c7:16:80:f2",
|
||||
},
|
||||
Mtu: 1500,
|
||||
},
|
||||
"eth1": &netplan.EthernetConfig{
|
||||
"eth1": {
|
||||
MacAddress: "00:24:c7:16:80:f3",
|
||||
Match: &netplan.EthernetConfigMatch{
|
||||
MacAddress: "00:24:c7:16:80:f3",
|
||||
@@ -339,7 +339,7 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Bonds: map[string]*netplan.Bond{
|
||||
"bond0": &netplan.Bond{
|
||||
"bond0": {
|
||||
EthernetConfig: netplan.EthernetConfig{
|
||||
Addresses: []string{
|
||||
"10.168.222.175/24",
|
||||
@@ -362,11 +362,6 @@ func TestNewNetplanConfig(t *testing.T) {
|
||||
To: "fd00:ec2::254/128",
|
||||
Via: "::",
|
||||
},
|
||||
{
|
||||
Metric: 0,
|
||||
To: "fe80::a9fe:a9fe/128",
|
||||
Via: "::",
|
||||
},
|
||||
},
|
||||
},
|
||||
Interfaces: []string{
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
@@ -271,36 +270,11 @@ func getGuestConfig(
|
||||
conf.Routes6 = route6
|
||||
|
||||
if len(nicdesc.Dns) > 0 {
|
||||
conf.DNSServers = make([]net.IP, 0)
|
||||
conf.DNSServers6 = make([]net.IP, 0)
|
||||
for _, dns := range strings.Split(nicdesc.Dns, ",") {
|
||||
if regutils.MatchIP4Addr(dns) {
|
||||
conf.DNSServers = append(conf.DNSServers, net.ParseIP(dns))
|
||||
} else if regutils.MatchIP6Addr(dns) {
|
||||
conf.DNSServers6 = append(conf.DNSServers6, net.ParseIP(dns))
|
||||
}
|
||||
}
|
||||
conf.DNSServers, conf.DNSServers6 = netutils2.SplitV46Addr2IP(nicdesc.Dns)
|
||||
}
|
||||
|
||||
if len(nicdesc.Ntp) > 0 {
|
||||
conf.NTPServers = make([]net.IP, 0)
|
||||
conf.NTPServers6 = make([]net.IP, 0)
|
||||
for _, ntp := range strings.Split(nicdesc.Ntp, ",") {
|
||||
if regutils.MatchIP4Addr(ntp) {
|
||||
conf.NTPServers = append(conf.NTPServers, net.ParseIP(ntp))
|
||||
} else if regutils.MatchIP6Addr(ntp) {
|
||||
conf.NTPServers6 = append(conf.NTPServers6, net.ParseIP(ntp))
|
||||
} else if regutils.MatchDomainName(ntp) {
|
||||
ntpAddrs, _ := net.LookupHost(ntp)
|
||||
for _, ntpAddr := range ntpAddrs {
|
||||
if regutils.MatchIP4Addr(ntpAddr) {
|
||||
conf.NTPServers = append(conf.NTPServers, net.ParseIP(ntpAddr))
|
||||
} else if regutils.MatchIP6Addr(ntpAddr) {
|
||||
conf.NTPServers6 = append(conf.NTPServers6, net.ParseIP(ntpAddr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
conf.NTPServers, conf.NTPServers6 = netutils2.SplitV46Addr2IP(nicdesc.Ntp)
|
||||
}
|
||||
|
||||
if nicdesc.Mtu > 0 {
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/util/icmp6"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
)
|
||||
|
||||
type sRARequest struct {
|
||||
@@ -72,8 +73,8 @@ func (s *SGuestDHCP6Server) handleNeighborAdvertisement(msg *icmp6.SNeighborAdve
|
||||
|
||||
func (s *SGuestDHCP6Server) requestGatewayMac(gwIP net.IP, vlanId uint16) {
|
||||
// Solicited-Node Multicast Address, FF02::1:FF00:0/104, 33:33:ff:00:00:00
|
||||
destIP := net.IP{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, gwIP[13], gwIP[14], gwIP[15]}
|
||||
destMac := net.HardwareAddr{0x33, 0x33, 0xff, gwIP[13], gwIP[14], gwIP[15]}
|
||||
destIP := netutils2.IP2SolicitMcastIP(gwIP)
|
||||
destMac := netutils2.IP2SolicitMcastMac(gwIP)
|
||||
|
||||
ns := &icmp6.SNeighborSolicitation{
|
||||
SBaseICMP6Message: icmp6.SBaseICMP6Message{
|
||||
@@ -112,9 +113,9 @@ func (s *SGuestDHCP6Server) sendRouterAdvertisement(solicitation *icmp6.SRouterS
|
||||
gwMac := gwMacObj.(net.HardwareAddr)
|
||||
|
||||
pref := icmp6.PreferenceMedium
|
||||
if conf.IsDefaultGW {
|
||||
pref = icmp6.PreferenceHigh
|
||||
}
|
||||
//if conf.IsDefaultGW {
|
||||
// pref = icmp6.PreferenceHigh
|
||||
//}
|
||||
|
||||
_, ipnet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", conf.ClientIP6, conf.PrefixLen6))
|
||||
if err != nil {
|
||||
@@ -170,7 +171,7 @@ func (s *SGuestDHCP6Server) sendRouterAdvertisement(solicitation *icmp6.SRouterS
|
||||
RouteLifetime: 9000,
|
||||
Prefix: route.Prefix,
|
||||
PrefixLen: route.PrefixLen,
|
||||
Preference: icmp6.PreferenceMedium,
|
||||
Preference: pref,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,11 +366,9 @@ func NewNIC(desc string) (*SNIC, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(nic.Ip) > 0 {
|
||||
nic.dhcpServer, err = hostdhcp.NewGuestDHCPServer(nic.Bridge, options.HostOptions.DhcpServerPort, relayConf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "NewGuestDHCPServer(%s, %d, %#v)", nic.Bridge, options.HostOptions.DhcpServerPort, relayConf)
|
||||
}
|
||||
nic.dhcpServer, err = hostdhcp.NewGuestDHCPServer(nic.Bridge, options.HostOptions.DhcpServerPort, relayConf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "NewGuestDHCPServer(%s, %d, %#v)", nic.Bridge, options.HostOptions.DhcpServerPort, relayConf)
|
||||
}
|
||||
|
||||
var relayConf6 *hostdhcp.SDHCPRelayUpstream
|
||||
@@ -384,12 +382,11 @@ func NewNIC(desc string) (*SNIC, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(nic.Ip6) > 0 {
|
||||
nic.dhcpServer6, err = hostdhcp.NewGuestDHCP6Server(nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "NewGuestDHCP6Server(%s, %d, %#v)", nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6)
|
||||
}
|
||||
nic.dhcpServer6, err = hostdhcp.NewGuestDHCP6Server(nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "NewGuestDHCP6Server(%s, %d, %#v)", nic.Bridge, options.HostOptions.Dhcp6ServerPort, relayConf6)
|
||||
}
|
||||
|
||||
// dhcp server start after guest manager init
|
||||
return nic, nil
|
||||
}
|
||||
|
||||
@@ -297,10 +297,10 @@ type Option6 struct {
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
func optionToBytes(o Option6) []byte {
|
||||
buf := make([]byte, 4)
|
||||
buf := make([]byte, 4+len(o.Value))
|
||||
binary.BigEndian.PutUint16(buf[0:2], uint16(o.Code))
|
||||
binary.BigEndian.PutUint16(buf[2:4], uint16(len(o.Value)))
|
||||
buf = append(buf, o.Value...)
|
||||
copy(buf[4:], o.Value)
|
||||
return buf
|
||||
}
|
||||
|
||||
@@ -316,15 +316,17 @@ func (p Packet) GetOption6s() []Option6 {
|
||||
options := make([]Option6, 0)
|
||||
offset := 4
|
||||
if p.IsRelayMsg() {
|
||||
offset = 18
|
||||
offset = 16*2 + 2
|
||||
}
|
||||
i := offset
|
||||
for i < len(p) {
|
||||
code := binary.BigEndian.Uint16(p[i : i+2])
|
||||
length := binary.BigEndian.Uint16(p[i+2 : i+4])
|
||||
value := make([]byte, length)
|
||||
copy(value, p[i+4:i+4+int(length)])
|
||||
options = append(options, Option6{
|
||||
Code: OptionCode6(code),
|
||||
Value: p[i+4 : i+4+int(length)],
|
||||
Value: value,
|
||||
})
|
||||
i += 4 + int(length)
|
||||
}
|
||||
@@ -377,13 +379,25 @@ func makeIAAddr(ip net.IP, preferLT, validLT uint32, opts []Option6) []byte {
|
||||
}
|
||||
|
||||
func responseIANA(buf []byte, opts []Option6) []byte {
|
||||
if len(buf) > 12 {
|
||||
// IA_NA structure: IAID (4 bytes) + T1 (4 bytes) + T2 (4 bytes)
|
||||
// Preserve the original IAID, T1, and T2 values from the client request
|
||||
if len(buf) < 12 {
|
||||
// If buffer is too short, pad with zeros
|
||||
padding := make([]byte, 12-len(buf))
|
||||
buf = append(buf, padding...)
|
||||
} else if len(buf) > 12 {
|
||||
// If buffer is too long, truncate to 12 bytes (IAID + T1 + T2)
|
||||
buf = buf[:12]
|
||||
}
|
||||
// iaID := binary.BigEndian.Uint32(buf[0:4])
|
||||
// t1 := binary.BigEndian.Uint32(buf[4:8])
|
||||
// t2 := binary.BigEndian.Uint32(buf[8:12])
|
||||
// log.Debugf("responseIANA IA_NA IAID %d t1 %d t2 %d", iaID, t1, t2)
|
||||
|
||||
// Log the IA_NA parameters for debugging
|
||||
if len(buf) >= 12 {
|
||||
iaID := binary.BigEndian.Uint32(buf[0:4])
|
||||
t1 := binary.BigEndian.Uint32(buf[4:8])
|
||||
t2 := binary.BigEndian.Uint32(buf[8:12])
|
||||
log.Debugf("responseIANA IA_NA IAID %d t1 %d t2 %d", iaID, t1, t2)
|
||||
}
|
||||
|
||||
buf = append(buf, optionsToBytes(opts)...)
|
||||
return buf
|
||||
}
|
||||
@@ -414,19 +428,18 @@ func makeDHCPReplyPacket6(pkt Packet, conf *ResponseConfig, msgType MessageType)
|
||||
return nil, errors.Wrapf(err, "TID6")
|
||||
}
|
||||
|
||||
resp := NewPacket6(msgType, tid)
|
||||
originOpts := pkt.GetOption6s()
|
||||
getOption := func(code OptionCode6) Option6 {
|
||||
for _, o := range originOpts {
|
||||
getOption := func(opts []Option6, code OptionCode6) *Option6 {
|
||||
for _, o := range opts {
|
||||
if o.Code == code {
|
||||
return o
|
||||
return &o
|
||||
}
|
||||
}
|
||||
return Option6{}
|
||||
return nil
|
||||
}
|
||||
|
||||
reqInfo := getOption(DHCPV6_OPTION_ORO)
|
||||
if len(reqInfo.Value) > 0 {
|
||||
reqInfo := getOption(originOpts, DHCPV6_OPTION_ORO)
|
||||
if reqInfo != nil && len(reqInfo.Value) > 0 {
|
||||
reqOpts := decodeRequestOptions(reqInfo.Value)
|
||||
reqOptsStr := make([]string, len(reqOpts))
|
||||
for i, opt := range reqOpts {
|
||||
@@ -437,21 +450,35 @@ func makeDHCPReplyPacket6(pkt Packet, conf *ResponseConfig, msgType MessageType)
|
||||
|
||||
options := make([]Option6, 0)
|
||||
|
||||
reqCliID := getOption(originOpts, DHCPV6_OPTION_CLIENTID)
|
||||
if reqCliID == nil {
|
||||
return nil, errors.Wrapf(errors.ErrInvalidFormat, "clientID option not found")
|
||||
}
|
||||
// copy clientID
|
||||
options = append(options, getOption(DHCPV6_OPTION_CLIENTID))
|
||||
options = append(options, Option6{
|
||||
Code: DHCPV6_OPTION_CLIENTID,
|
||||
Value: reqCliID.Value,
|
||||
})
|
||||
// serverID
|
||||
options = append(options, Option6{
|
||||
Code: DHCPV6_OPTION_SERVERID,
|
||||
Value: makeServerId(conf.InterfaceMac),
|
||||
})
|
||||
// Identity Association for Non-temporary Addresses Option
|
||||
ianaOpt := getOption(DHCPV6_OPTION_IA_NA)
|
||||
ianaOpt := getOption(originOpts, DHCPV6_OPTION_IA_NA)
|
||||
if ianaOpt == nil {
|
||||
return nil, errors.Wrapf(errors.ErrInvalidFormat, "IA_NA option not found")
|
||||
}
|
||||
// Calculate proper timing values for IA_NA
|
||||
validLifetime := uint32(conf.LeaseTime.Seconds()) // Valid lifetime should be longer than preferred
|
||||
preferredLifetime := validLifetime / 2
|
||||
|
||||
options = append(options, Option6{
|
||||
Code: DHCPV6_OPTION_IA_NA,
|
||||
Value: responseIANA(ianaOpt.Value, []Option6{
|
||||
{
|
||||
Code: DHCPV6_OPTION_IAADDR,
|
||||
Value: makeIAAddr(conf.ClientIP6, uint32(conf.LeaseTime.Seconds()), uint32(conf.LeaseTime.Seconds()), []Option6{
|
||||
Value: makeIAAddr(conf.ClientIP6, preferredLifetime, validLifetime, []Option6{
|
||||
{
|
||||
Code: DHCPV6_OPTION_STATUS_CODE,
|
||||
Value: []byte{0, 0, 'S', 'u', 'c', 'c', 'e', 's', 's'},
|
||||
@@ -475,6 +502,19 @@ func makeDHCPReplyPacket6(pkt Packet, conf *ResponseConfig, msgType MessageType)
|
||||
})
|
||||
}
|
||||
|
||||
// Handle rapid commit option for SOLICIT messages
|
||||
if pkt.Type6() == DHCPV6_SOLICIT {
|
||||
rapidCmtOpt := getOption(originOpts, DHCPV6_OPTION_RAPID_COMMIT)
|
||||
if rapidCmtOpt != nil {
|
||||
// Client requested rapid commit, respond with REPLY instead of ADVERTISE
|
||||
msgType = DHCPV6_REPLY
|
||||
options = append(options, Option6{
|
||||
Code: DHCPV6_OPTION_RAPID_COMMIT,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resp := NewPacket6(msgType, tid)
|
||||
resp = append(resp, optionsToBytes(options)...)
|
||||
|
||||
return resp, nil
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
var PSEUDO_VIP = "169.254.169.231"
|
||||
@@ -354,6 +355,33 @@ func isExitAddress(ip string) bool {
|
||||
return netutils.IsExitAddress(ipv4)
|
||||
}
|
||||
|
||||
var (
|
||||
Ip4MetadataServers = []string{
|
||||
"169.254.169.254",
|
||||
}
|
||||
Ip6MetadataServers = []string{
|
||||
"fd00:ec2::254",
|
||||
}
|
||||
)
|
||||
|
||||
func SetIp4MetadataServers(ip4s []string) {
|
||||
if len(ip4s) == 0 {
|
||||
ip4s = []string{
|
||||
"169.254.169.254",
|
||||
}
|
||||
}
|
||||
Ip4MetadataServers = ip4s
|
||||
}
|
||||
|
||||
func SetIp6MetadataServers(ip6s []string) {
|
||||
if len(ip6s) == 0 {
|
||||
ip6s = []string{
|
||||
"fd00:ec2::254",
|
||||
}
|
||||
}
|
||||
Ip6MetadataServers = ip6s
|
||||
}
|
||||
|
||||
func AddNicRoutes(routes4 []SRouteInfo, routes6 []SRouteInfo, nicDesc *types.SServerNic, mainIp string, mainIp6 string, nicCnt int) ([]SRouteInfo, []SRouteInfo) {
|
||||
// always add static routes, even if this is the default NIC
|
||||
// if mainIp == nicDesc.Ip {
|
||||
@@ -373,11 +401,16 @@ func AddNicRoutes(routes4 []SRouteInfo, routes6 []SRouteInfo, nicDesc *types.SSe
|
||||
|
||||
if len(mainIp) > 0 && nicDesc.Ip == mainIp {
|
||||
// always add 169.254.169.254 for default NIC
|
||||
routes4 = addRoute(routes4, "169.254.169.254/32", "0.0.0.0")
|
||||
for _, ip := range Ip4MetadataServers {
|
||||
pref := ip + "/32"
|
||||
routes4 = addRoute(routes4, pref, "0.0.0.0")
|
||||
}
|
||||
}
|
||||
if len(mainIp6) > 0 && nicDesc.Ip6 == mainIp6 {
|
||||
routes6 = addRoute(routes6, "fd00:ec2::254/128", "::")
|
||||
routes6 = addRoute(routes6, "fe80::a9fe:a9fe/128", "::")
|
||||
for _, ip6 := range Ip6MetadataServers {
|
||||
pref := ip6 + "/128"
|
||||
routes6 = addRoute(routes6, pref, "::")
|
||||
}
|
||||
}
|
||||
|
||||
return routes4, routes6
|
||||
@@ -702,3 +735,48 @@ func TestTcpPort(ip string, port int, timeoutSecs int, tries int) error {
|
||||
}
|
||||
return errors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
func IP2SolicitMcastIP(ip6 net.IP) net.IP {
|
||||
// Solicited-Node Multicast Address, FF02::1:FF00:0/104
|
||||
return net.IP{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, ip6[13], ip6[14], ip6[15]}
|
||||
}
|
||||
|
||||
func IP2SolicitMcastMac(ip6 net.IP) net.HardwareAddr {
|
||||
// Solicited-Node Multicast Address, 33:33:ff:00:00:00
|
||||
return net.HardwareAddr{0x33, 0x33, 0xff, ip6[13], ip6[14], ip6[15]}
|
||||
}
|
||||
|
||||
func SplitV46Addr(addrsStr string) ([]string, []string) {
|
||||
servers4 := stringutils2.NewSortedStrings(nil)
|
||||
servers6 := stringutils2.NewSortedStrings(nil)
|
||||
for _, ntp := range strings.Split(addrsStr, ",") {
|
||||
if regutils.MatchIP4Addr(ntp) {
|
||||
servers4 = servers4.Append(ntp)
|
||||
} else if regutils.MatchIP6Addr(ntp) {
|
||||
servers6 = servers6.Append(ntp)
|
||||
} else if regutils.MatchDomainName(ntp) {
|
||||
ntpAddrs, _ := net.LookupHost(ntp)
|
||||
for _, ntpAddr := range ntpAddrs {
|
||||
if regutils.MatchIP4Addr(ntpAddr) {
|
||||
servers4 = servers4.Append(ntpAddr)
|
||||
} else if regutils.MatchIP6Addr(ntpAddr) {
|
||||
servers6 = servers6.Append(ntpAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return servers4, servers6
|
||||
}
|
||||
|
||||
func SplitV46Addr2IP(addrsStr string) ([]net.IP, []net.IP) {
|
||||
addrs4, addrs6 := SplitV46Addr(addrsStr)
|
||||
ip4s := make([]net.IP, len(addrs4))
|
||||
ip6s := make([]net.IP, len(addrs6))
|
||||
for i := range addrs4 {
|
||||
ip4s[i] = net.ParseIP(addrs4[i])
|
||||
}
|
||||
for i := range addrs6 {
|
||||
ip6s[i] = net.ParseIP(addrs6[i])
|
||||
}
|
||||
return ip4s, ip6s
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package netutils2
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -195,3 +196,31 @@ func TestGetRouteSpecs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitV46Addr(t *testing.T) {
|
||||
cases := []struct {
|
||||
in string
|
||||
want4 []string
|
||||
want6 []string
|
||||
}{
|
||||
{
|
||||
in: "192.168.1.1,192.168.1.2,192.168.1.3,192.168.1.10",
|
||||
want4: []string{"192.168.1.1", "192.168.1.10", "192.168.1.2", "192.168.1.3"},
|
||||
want6: []string{},
|
||||
},
|
||||
{
|
||||
in: "192.168.1.1,192.168.1.2,fe80::1,192.168.1.10",
|
||||
want4: []string{"192.168.1.1", "192.168.1.10", "192.168.1.2"},
|
||||
want6: []string{"fe80::1"},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got4, got6 := SplitV46Addr(c.in)
|
||||
if !reflect.DeepEqual(got4, c.want4) {
|
||||
t.Errorf("SplitV46Addr(%s) = %v, want %v", c.in, got4, c.want4)
|
||||
}
|
||||
if !reflect.DeepEqual(got6, c.want6) {
|
||||
t.Errorf("SplitV46Addr(%s) = %v, want %v", c.in, got6, c.want6)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,12 @@ import (
|
||||
"yunion.io/x/ovsdb/types"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
commonapis "yunion.io/x/onecloud/pkg/apis"
|
||||
apis "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
agentmodels "yunion.io/x/onecloud/pkg/vpcagent/models"
|
||||
"yunion.io/x/onecloud/pkg/vpcagent/options"
|
||||
"yunion.io/x/onecloud/pkg/vpcagent/ovn/mac"
|
||||
@@ -438,7 +438,7 @@ func (keeper *OVNNorthboundKeeper) ClaimVpcEipgw(ctx context.Context, vpc *agent
|
||||
return keeper.cli.Must(ctx, "ClaimVpcEipgw", args)
|
||||
}
|
||||
|
||||
func formatNtpServers(srvs string) string {
|
||||
/*func formatNtpServers(srvs string) string {
|
||||
srv := make([]string, 0)
|
||||
for _, part := range strings.Split(srvs, ",") {
|
||||
part = strings.TrimSpace(part)
|
||||
@@ -451,7 +451,7 @@ func formatNtpServers(srvs string) string {
|
||||
}
|
||||
}
|
||||
return strings.Join(srv, ",")
|
||||
}
|
||||
}*/
|
||||
|
||||
func generateDhcpOptions(ctx context.Context, guestnetwork *agentmodels.Guestnetwork, opts *options.Options) *ovn_nb.DHCPOptions {
|
||||
var (
|
||||
@@ -516,8 +516,9 @@ func generateDhcpOptions(ctx context.Context, guestnetwork *agentmodels.Guestnet
|
||||
if dnsSrvs == "" {
|
||||
dnsSrvs = opts.DNSServer
|
||||
}
|
||||
if len(dnsSrvs) > 0 {
|
||||
dhcpopts.Options["dns_server"] = "{" + dnsSrvs + "}"
|
||||
dnsSrvs4List, _ := netutils2.SplitV46Addr(dnsSrvs)
|
||||
if len(dnsSrvs4List) > 0 {
|
||||
dhcpopts.Options["dns_server"] = "{" + strings.Join(dnsSrvs4List, ",") + "}"
|
||||
}
|
||||
}
|
||||
{
|
||||
@@ -542,9 +543,10 @@ func generateDhcpOptions(ctx context.Context, guestnetwork *agentmodels.Guestnet
|
||||
ntpSrvs = strings.Join(ntp, ",")
|
||||
}
|
||||
}
|
||||
if len(ntpSrvs) > 0 {
|
||||
ntpSrvs4List, _ := netutils2.SplitV46Addr(ntpSrvs)
|
||||
if len(ntpSrvs4List) > 0 {
|
||||
// bug on OVN, should not use ntp server: QiuJian
|
||||
dhcpopts.Options["ntp_server"] = "{" + formatNtpServers(ntpSrvs) + "}"
|
||||
dhcpopts.Options["ntp_server"] = "{" + strings.Join(ntpSrvs4List, ",") + "}"
|
||||
}
|
||||
}
|
||||
return dhcpopts
|
||||
@@ -562,13 +564,42 @@ func generateDhcp6Options(ctx context.Context, guestnetwork *agentmodels.Guestne
|
||||
dhcpopts := &ovn_nb.DHCPOptions{
|
||||
Cidr: cidr6,
|
||||
Options: map[string]string{
|
||||
"server_id": dhcpMac,
|
||||
// "dhcpv6_stateless": "false",
|
||||
"server_id": dhcpMac,
|
||||
"dhcpv6_stateless": "false",
|
||||
},
|
||||
ExternalIds: map[string]string{
|
||||
externalKeyOcRef: ocDhcpRef,
|
||||
},
|
||||
}
|
||||
{
|
||||
dnsSrvs := network.GuestDns
|
||||
if dnsSrvs == "" {
|
||||
dns, err := auth.GetDNSServers(opts.Region, "")
|
||||
if err != nil {
|
||||
// ignore the error
|
||||
// log.Errorf("auth.GetDNSServers fail %s", err)
|
||||
} else {
|
||||
dnsSrvs = strings.Join(dns, ",")
|
||||
}
|
||||
}
|
||||
if dnsSrvs == "" {
|
||||
dnsSrvs = opts.DNSServer
|
||||
}
|
||||
_, dnsSrvs6List := netutils2.SplitV46Addr(dnsSrvs)
|
||||
if len(dnsSrvs6List) > 0 {
|
||||
dhcpopts.Options["dns_server"] = "{" + strings.Join(dnsSrvs6List, ",") + "}"
|
||||
}
|
||||
}
|
||||
{
|
||||
dnsDomain := network.GuestDomain
|
||||
if dnsDomain == "" {
|
||||
dnsDomain = opts.DNSDomain
|
||||
}
|
||||
if len(dnsDomain) > 0 && !commonapis.IsIllegalSearchDomain(dnsDomain) {
|
||||
dhcpopts.Options["domain_name"] = "\"" + dnsDomain + "\""
|
||||
}
|
||||
}
|
||||
|
||||
return dhcpopts
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user