#!/bin/sh
# Apply verification enablers (E1-E3) + candidate fixes for DF-3501/DF-3502
# to the guest's /usr/src copy of ng_fec.c and rebuild the module.
set -e
cd /usr/src/sys/netgraph/fec

# --- E1: DF-3499 fix (bcopy NULL guard) ---
if [ "$(grep -c 'if (ng_fec_units != NULL)' ng_fec.c)" = "1" ]; then
	patch -s < /tmp/fix_df3499.diff && echo E1_APPLIED
else
	echo E1_present
fi

# --- E2: rmnode skips ng_fec_stop (unbalanced deserialize, DF-3500 facet) ---
grep -q "LAB ENABLER E2" ng_fec.c || {
	sed -i "" "s|^\tng_fec_stop(&priv->arpcom.ac_if);|\t/* ng_fec_stop(\&priv->arpcom.ac_if); LAB ENABLER E2 */|" ng_fec.c
	echo E2_APPLIED
}

# --- E3: delport serializes member around if_ioctl (DF-3500 facet) ---
grep -q "LAB ENABLER E3" ng_fec.c || {
	sed -i "" "s|^\tbifp->if_ioctl(bifp, SIOCSIFFLAGS, NULL, NULL);$|\tifnet_serialize_all(bifp); bifp->if_ioctl(bifp, SIOCSIFFLAGS, NULL, NULL); ifnet_deserialize_all(bifp); /* LAB ENABLER E3 */|" ng_fec.c
	echo E3_APPLIED
}

# --- F3501: reject non-ethernet members (arpcom cast is otherwise OOB) ---
grep -q "FIX DF-3501" ng_fec.c || {
	printf '%s\n' 's|^\t/\* See if we have room in the bundle \*/$|\t/* FIX DF-3501: only ethernet (arpcom) interfaces can join a bundle */\n\tif (bifp->if_type != IFT_ETHER) {\n\t\tifnet_unlock();\n\t\tkprintf("fec%d: iface %s is not an ethernet interface\\n",\n\t\t    priv->unit, iface);\n\t\treturn(EPROTONOSUPPORT);\n\t}\n\n\t/* See if we have room in the bundle */|' > /tmp/f1.sed
	sed -i "" -f /tmp/f1.sed ng_fec.c
	echo F3501_APPLIED
}

# --- F3502a: delport clears the member's ac_netgraph (IFP2NG) ---
grep -q "FIX DF-3502a" ng_fec.c || {
	printf '%s\n' 's|^\t/\* Restore MAC address. \*/$|\t/* FIX DF-3502a: stop claiming this member\x27s RX path */\n\tac = (struct arpcom *)bifp;\n\tif (ac->ac_netgraph == (void *)priv->node)\n\t\tac->ac_netgraph = NULL;\n\n\t/* Restore MAC address. */|' > /tmp/f2.sed
	sed -i "" -f /tmp/f2.sed ng_fec.c
	echo F3502a_APPLIED
}

# --- F3502b: refcount the global RX hook arming ---
grep -q "ng_fec_armed" ng_fec.c || {
	printf '%s\n' 's|^static int\tng_units_in_use = 0;$|static int\tng_units_in_use = 0;\nstatic int\tng_fec_armed = 0;\t/* FIX DF-3502b */|' > /tmp/f3.sed
	sed -i "" -f /tmp/f3.sed ng_fec.c
	printf '%s\n' 's|^\t\tng_ether_input_p = ng_fec_input;$|\t\tng_ether_input_p = ng_fec_input;\n\tng_fec_armed++;|' > /tmp/f4.sed
	sed -i "" -f /tmp/f4.sed ng_fec.c
	printf '%s\n' 's|^\t\tng_ether_input_p = NULL;$|\tif (--ng_fec_armed <= 0 \&\& ng_ether_input_p == ng_fec_input)\n\t\tng_ether_input_p = NULL;|' > /tmp/f5.sed
	sed -i "" -f /tmp/f5.sed ng_fec.c
	echo F3502b_APPLIED
}

echo markers: e1=$(grep -c "if (ng_fec_units != NULL)" ng_fec.c) e2=$(grep -c "LAB ENABLER E2" ng_fec.c) e3=$(grep -c "LAB ENABLER E3" ng_fec.c) f1=$(grep -c "FIX DF-3501" ng_fec.c) f2a=$(grep -c "FIX DF-3502a" ng_fec.c) f2b=$(grep -c "ng_fec_armed" ng_fec.c)
make 2>&1 | tail -1
