meta-google: gbmc-ncsi-config: Only impersonate host under NCSI

This adds a flag to the interface based on the presence of the NCSI
state machine. Non-NCSI connections will not impersonate the CN to avoid
breaking flat network topologies where the BMC and CN share an ethernet
channel.

Tested: On a machine without an NCSI stack to verify the impersonation
record is not present. Also on a machine with NCSI to prove that
impersonation is still working.

Change-Id: Ifb8048abe443c60a333e7eff7cdc9d063a8c656a
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-alias.service.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-alias.service.in
new file mode 100644
index 0000000..93ad535
--- /dev/null
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-alias.service.in
@@ -0,0 +1,12 @@
+[Unit]
+BindsTo=ncsid@@NCSI_IF@.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/bin/ip link set @NCSI_IF@ alias ncsi
+ExecStop=/usr/bin/ip link set @NCSI_IF@ alias ''
+
+[Install]
+WantedBy=nic-hostful@@NCSI_IF@.target
+WantedBy=nic-hostless@@NCSI_IF@.target
diff --git a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in
index a1b16ca..5d6411d 100644
--- a/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in
+++ b/meta-google/recipes-google/ncsi/files/gbmc-ncsi-br-deprecated-ips.sh.in
@@ -19,11 +19,15 @@
 gbmc_ncsi_br_deprecated_ips_init=
 gbmc_ncsi_br_deprecated_ips_confip=
 gbmc_ncsi_br_deprecated_ips_lastip=
+gbmc_ncsi_br_deprecated_ips_lastncsi=
+gbmc_ncsi_br_deprecated_ips_confncsi=
 
 gbmc_ncsi_br_deprecated_ips_update() {
   [ -n "$gbmc_ncsi_br_deprecated_ips_init" ] || return
-  [ "$gbmc_ncsi_br_deprecated_ips_confip" != "$gbmc_ncsi_br_deprecated_ips_lastip" ] || return
+  [ "$gbmc_ncsi_br_deprecated_ips_confip" != "$gbmc_ncsi_br_deprecated_ips_lastip" ] || \
+    [ "$gbmc_ncsi_br_deprecated_ips_confncsi" != "$gbmc_ncsi_br_deprecated_ips_lastncsi" ] || return
   gbmc_ncsi_br_deprecated_ips_confip="$gbmc_ncsi_br_deprecated_ips_lastip"
+  gbmc_ncsi_br_deprecated_ips_confncsi="$gbmc_ncsi_br_deprecated_ips_lastncsi"
 
   printf 'gBMC NCSI Deprecated Addrs: %s\n' \
     "${gbmc_ncsi_br_deprecated_ips_lastip:-(deleted)}" >&2
@@ -46,20 +50,24 @@
     fi
     pfx_bytes[8]=0
     pfx_bytes[9]=0
-    local host_pfx="$(ip_bytes_to_str pfx_bytes)"
+    local host_pfx=
+    if [ -n "${gbmc_ncsi_br_deprecated_ips_confncsi}" ]; then
+      # Only impersonate the host if we have an NCSI state machine
+      host_pfx="$(ip_bytes_to_str pfx_bytes)"
+    fi
     read -r -d '' contents <<EOF
 [Network]
 IPv6ProxyNDP=yes
 IPv6ProxyNDPAddress=$pfx
 IPv6ProxyNDPAddress=$stateless_pfx
-IPv6ProxyNDPAddress=$host_pfx
+${host_pfx:+IPv6ProxyNDPAddress=}$host_pfx
 ${stateless_ip:+IPv6ProxyNDPAddress=}$stateless_ip
 EOF
     read -r -d '' nfcontents <<EOF
 table inet filter {
   chain ncsi_input {
     ip6 saddr != $pfx/76 ip6 daddr $pfx/76 goto ncsi_gbmc_br_pub_input
-    ip6 daddr $host_pfx/64 goto ncsi_legacy_input
+    ${host_pfx:+ip6 daddr $host_pfx/64 goto ncsi_legacy_input}
   }
   chain ncsi_forward {
     ip6 saddr != $pfx/76 ip6 daddr $pfx/76 accept
@@ -128,6 +136,14 @@
       gbmc_ncsi_br_deprecated_ips_lastip=
       gbmc_ip_monitor_defer
     fi
+  elif [ "$change" = 'link' -a "$action" = 'add' -a "$intf" = '@NCSI_IF@' ]; then
+    if ip link show '@NCSI_IF@' | grep -q '^ *alias ncsi$'; then
+      gbmc_ncsi_br_deprecated_ips_lastncsi=1
+      gbmc_ip_monitor_defer
+    else
+      gbmc_ncsi_br_deprecated_ips_lastncsi=
+      gbmc_ip_monitor_defer
+    fi
   fi
 }
 
diff --git a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
index 364afee..3ae1c72 100644
--- a/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
+++ b/meta-google/recipes-google/ncsi/gbmc-ncsi-config.bb
@@ -21,6 +21,7 @@
   file://gbmc-ncsi-br-pub-addr.sh.in \
   file://gbmc-ncsi-br-deprecated-ips.sh.in \
   file://gbmc-ncsi-set-nicenabled.service.in \
+  file://gbmc-ncsi-alias.service.in \
   file://50-gbmc-ncsi-clear-ip.sh.in \
   "
 
@@ -92,6 +93,13 @@
   install -d -m0755 "$wantdir"
   ln -sv ../ncsid@.service "$wantdir"/ncsid@$if_name.service
 
+  sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-alias.service.in \
+    >${D}${systemd_system_unitdir}/gbmc-ncsi-alias.service
+  install -d -m0755 "${D}${systemd_system_unitdir}/nic-hostless@$if_name.target.wants"
+  ln -sv ../gbmc-ncsi-alias.service "${D}${systemd_system_unitdir}/nic-hostless@$if_name.target.wants"/
+  install -d -m0755 "${D}${systemd_system_unitdir}/nic-hostful@$if_name.target.wants"
+  ln -sv ../gbmc-ncsi-alias.service "${D}${systemd_system_unitdir}/nic-hostful@$if_name.target.wants"/
+
   install -m 0644 ${WORKDIR}/gbmc-ncsi-sslh.service ${D}${systemd_system_unitdir}
   sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-sslh.socket.in \
     >${D}${systemd_system_unitdir}/gbmc-ncsi-sslh.socket