Skip to content

Instantly share code, notes, and snippets.

@baseboxorg
Forked from kntyskw/ec2_multicast.sh
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baseboxorg/1a47afe1cbf87a11a6c5 to your computer and use it in GitHub Desktop.
Save baseboxorg/1a47afe1cbf87a11a6c5 to your computer and use it in GitHub Desktop.
#!/bin/sh
[[ -n "$1" && -n "$2" ]] || { echo "Usage: $0 <interface to grab multicast packets from> <interface to send modified packets to> [target MAC address 1] [target MAC address 2] ..."; exit 0 ; }
IIF=$1
OIF=$2
shift
shift
SRC_MACADDR=`ip link show $OIF | awk '/ether/ {print $2}' | tr -d :`
HANDLE=10
TC=tc
BASE_PRIO=100
# File which stores the priority of the tc filter that is to be registered
PRIO_FILE=/var/run/ec2_broadcastd_tc_prio
# Load the priority that the previous filter is registered with
if [ -r $PRIO_FILE ]; then
BASE_PRIO=`cat $PRIO_FILE`
fi
# Determine the priority that the new filter will be registered with
# (Any number which is different from the previous one is fine unless
# other filters exist.)
if [ `expr $BASE_PRIO % 2` -eq 1 ]; then
PRIO=`expr $BASE_PRIO + 1`
else
PRIO=`expr $BASE_PRIO - 1`
fi
# Create queue discipline for the origin network interface
$TC qdisc add dev $IIF root handle ${HANDLE}: prio >& /dev/null
# Calculate bit mask for modifying packet ID. (We will send duplicate IP packets.
# In order not to break underlying packet fragmentation and reconstruction,
# each IP packet needs to have different ID)
RETAIN_MASK=0xfff0
# Create the list of actions to apply to outgoing multicast packets
i=0
for DST_MACADDR in $*
do
DST_MACADDR=`echo $DST_MACADDR | tr -d :`
if [ "${actions}X" != "X" ]; then
# Action to mirror the filtered packet to the outgoing interface
actions="$actions action mirred egress mirror dev $OIF "
fi
# Actions to modify Ethernet header
# Offset 0 is the beginning of the IP header
# Offset has to be factor of 4
# Last a few bits of the packet ID are modified to make each packet unique
actions="$actions action pedit
munge offset -16 u32 set 0x0000`echo $DST_MACADDR | cut -c 1-4`
munge offset -12 u32 set 0x`echo $DST_MACADDR | cut -c 5-12`
munge offset -8 u32 set 0x`echo $SRC_MACADDR | cut -c 1-8`
munge offset 4 u16 set 0x`printf "%04x" $i` retain $RETAIN_MASK pipe "
# Recalculate IP header checksum because we have modified the packet ID field
actions="$actions action csum ip4h pipe "
i=`expr $i + 1`
done
# Action to redirect the filtered packet to the outgoing interface
# (Note that this suppresses to send out the original frame with
# the broadcast address.)
actions="$actions action mirred egress redirect dev $OIF"
# Register the filter that matches ethernet broadcast frames which
# carry IP packets addressed to class D (IP multicast)
$TC filter add dev $IIF parent ${HANDLE}: protocol ip prio $PRIO u32 \
match u8 0x01 0x01 at 0 match u8 0xe0 0xe0 at 16 $actions
# Delete the old filter if exists
if [ -r $PRIO_FILE ]; then
$TC filter del dev $IIF parent ${HANDLE}: prio $BASE_PRIO
fi
# Store the priority used for the filter for future reference
echo $PRIO > $PRIO_FILE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment