#!/bin/bash set -u PUBLIC_PREFIX=20 # 20, 21, 22... MCAST_PREFIX_BASE="235" MCAST_COMMON_ADDR="$MCAST_PREFIX_BASE.0.0.1" MCAST_BASE_PORT=4000 set +u [ -z "$USER" ] && export USER=$(id -un) set -u error() { echo ERROR : "allocator : $@ !" exit 1 } # Numéro de l'utilisteur sur la machine # Utilisé par la redirection de port computeLocalUser() { set +u [ -z "$USER" ] && export USER=$(id -un) set -u local u=$USER #[ $# = 2 ] && u=$2 ps --no-headers --sort=start_time -eo user:14,lstart | gawk -v USER=$u -e ' BEGIN { n=0 } /[^[:space:]]+ .*/ { user=$1 #print $0 USER "===" user if(user == USER) { print n%32 exit 0 } if ( ! ( user in users ) ) { #print "SET USER : user :" $0 users[user]=n n=n+1 } } ' } # Calcule les paramètres d'un hôte # $1 : hôte computeDb() { local split host network user domain [ -d $VDN_PATH/allocators/db-$VDN_RESOURCES_ALLOCATOR ] && dir=$VDN_PATH/allocators/db-$VDN_RESOURCES_ALLOCATOR [ -d /etc/vdn/allocators/db-$VDN_RESOURCES_ALLOCATOR ] && dir=/etc/vdn/allocators/db-$VDN_RESOURCES_ALLOCATOR ALLOCATOR_DIR=$dir [ -z "$dir" ] && error "Allocators dir not found!" split="${1//./ }" set - $split set +u host=$1 network=$2 user=$3 domain=$4 [ -z "$domain" ] && domain=vdn [ $domain != vdn ] && error "computeDb : bad domain $domain" set +u [ -z "$user" -a -n "$GUEST_OWNER" ] && user=$GUEST_OWNER set -u [ -z "$user" ] && user=$USER [ -z "$network" ] && { [ -z "$NETWORK_DIR" ] && error "computeDb : no network and NETWORK_DIR is empty !" network=$(basename $NETWORK_DIR) } [ -z "$host" ] && error "computeDb : host is empty !" #echo "computeDb : $VDN_NETWORKS_BASE_DIR/$network/$host.conf" >&2 ##[ ! -e $VDN_NETWORKS_BASE_DIR/$network/$host.conf ] && \ ## error "computeDb : host $host not found in network $network!" grep -q $network:$host $dir/hosts || { error "host $host not found in network $network" } ### set +u [ -z "$DB_CURRENT_USER" ] && DB_CURRENT_USER="" set -u [ "$user" != "$DB_CURRENT_USER" ] && { ! cat $dir/users | grep -q "^$user$" && error "computeDb : user $user not found" export DB_CURRENT_USER_NUM=$(cat $dir/users | grep -n "^$user$" | cut -d ':' -f 1) export DB_CURRENT_USER=$user export DB_CURRENT_LOCAL_USER_NUM=$(computeLocalUser $user $host) } [ -z "$DB_CURRENT_LOCAL_USER_NUM" ] && $(computeLocalUser $user $host) set +u [ -z "$DB_CURRENT_NETWORK" ] && DB_CURRENT_NETWORK="" set -u [ "$network" != "$DB_CURRENT_NETWORK" ] && { #local netList=$(cd $VDN_NETWORKS_BASE_DIR; find . -maxdepth 1 -type d) local netList=$(cat $dir/networks) export DB_CURRENT_NETWORKS_LIST="$netList" DB_CURRENT_NETWORK_NUM=$(echo "$DB_CURRENT_NETWORKS_LIST" | grep -n "^$network$" | cut -d ':' -f 1) [ -z "$DB_CURRENT_NETWORK_NUM" ] && error "computeDb : DB_CURRENT_NETWORK_NUM empty (not in $VDN_NETWORKS_BASE_DIR ?)" #local hostsList=$(cd $VDN_NETWORKS_BASE_DIR/$network; find . -maxdepth 1 -type f -name '*.conf' ) local hostsList=$(cat $dir/hosts | grep "^$network:" | cut -d ':' -f 2 ) export DB_CURRENT_HOSTS_LIST="$hostsList" DB_CURRENT_HOST_NUM=$(echo "$DB_CURRENT_HOSTS_LIST" | grep -n "^$host$" | cut -d ':' -f 1) [ -z "$DB_CURRENT_HOST_NUM" ] && { error "computeDb : DB_CURRENT_HOST_NUM empty (not in $VDN_NETWORKS_BASE_DIR/$network/*.conf ?)" } DB_CURRENT_NETWORK=$network DB_CURRENT_HOST=$host } cat << EOF > /dev/null echo " host:$host network:$network user:$user hostNum:$DB_CURRENT_HOST_NUM networkNum:$DB_CURRENT_NETWORK_NUM userNum=$DB_CURRENT_USER_NUM " EOF } # $1 : host # $2 : proto (tcp/udp) # $3 : port à redirigé # en sortie : affichage d'un port libre computeRedir() { local base dst proto=$2 computeDb $1 base=$(( 5000+$DB_CURRENT_LOCAL_USER_NUM*1024 )) dst=$(( $base + $DB_CURRENT_HOST_NUM*32+($3%16) )) dst=$(findUnusedPort $proto $dst) echo $dst } # Affiche l'IP PUBLIC de la machine # L'hôte (ex : tiny.demo.user.vdn) computePublicIp() { computeDb $1 grep -q "$DB_CURRENT_NETWORK:$DB_CURRENT_HOST" $ALLOCATOR_DIR/hosts.global || return #echo $NETWORKS | egrep -q 'NET_0|NET_G' || return #echo "keys: $DB_CURRENT_USER $DB_CURRENT_NETWORK $DB_CURRENT_HOST" #echo "keys: userNum networkNum hostNum : $DB_CURRENT_USER_NUM $DB_CURRENT_NETWORK_NUM $DB_CURRENT_HOST_NUM" # 20.X.Y.Z => 24 bits dispo # Une adresse IP_PUBLIC par machine # 13 bits de poids fort pour le numero de l'utilisateur (max 8192) # 6 bits pour le numéro réseau (max 64 réseaux) # 5 bits pour le numéro d'hôte (max 32 hôte par réseau) # # IP = -------- -------- --------- # ^ ^^ ^^ ^ # +------------++------++---+ # user net host local ip=$(( $DB_CURRENT_USER_NUM * 2**11 + $DB_CURRENT_NETWORK_NUM * 2**5 + $DB_CURRENT_HOST_NUM)) ip1=$(( $ip/2**24 )) ip2=$(( ($ip-$ip1*2**24) / 2**16 )) ip3=$(( ($ip- $ip1*2**24 - $ip2*2**16) / 2**8 )) ip4=$(( $ip % 256 )) echo "$(($PUBLIC_PREFIX+$2)).$ip2.$ip3.$ip4" } # $1 : # $2 : le numéro du lien souhaihé computeMacAddr() { computeDb $1 # xx:xx:xx:xx:xx:xx # 52 ----- -- -- -- # ^ -interface (8 bits, max 256 interface par hôte) # ^- host (8 bits, max 256 hôtes par réseau) # ^network (8 bits, max 256 réseaux) # ^user (16 bits, max 65536 utilisateurs) local uHigh=$(($DB_CURRENT_USER_NUM /256)) local uLow=$(($DB_CURRENT_USER_NUM %256)) printf "52:%02X:%02X:%02X:%02X:%02X\n" $uHigh $uLow $DB_CURRENT_NETWORK_NUM $DB_CURRENT_HOST_NUM $2 } # Affiche l'adresse IPv4 multicast du brin ethernet n°$1 # $1 : l'hôte # $2 : le numéro du lien souhaité computeEthLink() { computeDb $1 echo "=== computeEthLink:$2" >&2 echo "DB_CURRENT_USER_NUM:$DB_CURRENT_USER_NUM" >&2 echo "DB_CURRENT_NETWORK_NUM:$DB_CURRENT_NETWORK_NUM" >&2 #echo "DB_CURRENT_HOST_NUM:$DB_CURRENT_HOST_NUM" >&2 # idem que pour l'IP publique sauf : # - préfixe de l'adresse mcast IPv4 # - le numéro de brin remplace le numéro d'hôte. # (5bits = 32 brins max par réseau) # 230.X.Y.Z # 13 bits de poids fort pour le numero de l'utilisateur (max 8192) # 6 bits pour le numéro réseau (max 64 réseaux) # 5 bits pour le numéro de brins (max 32 hôte par réseau) # # IP = -------- -------- --------- # ^ ^^ ^^ ^ # +------------++----++---+ # user net link local ip=$(( $DB_CURRENT_USER_NUM * 2**11 + $DB_CURRENT_NETWORK_NUM * 2**5)) ip1=$(( $ip/2**24 )) ip2=$(( ($ip-$ip1*2**24) / 2**16 )) ip3=$(( ($ip- $ip1*2**24 - $ip2*2**16) / 2**8 )) ip4=$(( $ip % 256 )) echo "==> $MCAST_PREFIX_BASE.$ip2.$ip3.$ip4:$MCAST_BASE_PORT" >&2 echo "$MCAST_PREFIX_BASE.$ip2.$ip3.$ip4:$MCAST_BASE_PORT" }