Add virtual server concepts for multiple network.
authorNeutron Soutmun <neo.neutron@gmail.com>
Tue, 31 Mar 2009 16:04:41 +0000 (23:04 +0700)
committerNeutron Soutmun <neo.neutron@gmail.com>
Tue, 31 Mar 2009 16:04:41 +0000 (23:04 +0700)
2009-03-31  Neutron Soutmun <neo.neutron@gmail.com>

* +src/rh-server.{h,c}:
  - Add virtual server concepts, make the clients from different interface to
    access the particular virtual server, differentiate clients by their IP.

* src/rahunasd.{h,c}, src/rh-config.{c,h}, src/rh-ipset.{h,c},
  src/rh-task.{h,c}, src/rh-task-{bandwidth,dbset,ipset,memset}.{h,c},
  src/rh-utils.{h,c}, src/rh-xmlrpc-cmd.{h,c}, src/rh-xmlrpc-server.c:
  - Redesign, rewrite and adjust the code to support the virtual server
    concepts.
  - Improve the memory management by replace old static memory allocation by
    dynamic memory allocation (GList), therefore fix the memory leak in
    earlier version.

* example/{bandwidth.sh.in,firewall.sh.in},
  example/rahunas.conf.in,
  +example/rahunas-vserver.conf.in:
  - Add new virtual server config example file which need to put into the
    config directory (default: /etc/rahunas/rahunas.d).
  - Update config file to support the new virtual server concepts,
    for earlier config file is not compatible now.
  - Update the bandwidth and firewall example script to support virtual
    server.

* configure.ac, Makefile.am: Update make file according to new changes.

* weblogin/networkchk.php: Add new client's IP check for determine the
  network of each client and get the appropriate config,
  differentiate client to access the particular virtual server by vserver_id.

* weblogin/{config,index,locale,login,logout}.php,
  weblogin/rahu_xmlrpc.class.php: Adjust for virtual server concepts.

38 files changed:
ChangeLog
configure.ac
data/rahunas.db
example/bandwidth.sh.in
example/firewall.sh.in
example/rahunas-vserver.conf.in [new file with mode: 0644]
example/rahunas.conf.in
src/Makefile.am
src/rahunasd.c
src/rahunasd.h
src/rh-config.c
src/rh-config.h
src/rh-ipset.c
src/rh-ipset.h
src/rh-server.c [new file with mode: 0644]
src/rh-server.h [new file with mode: 0644]
src/rh-task-bandwidth.c
src/rh-task-bandwidth.h
src/rh-task-dbset.c
src/rh-task-dbset.h
src/rh-task-ipset.c
src/rh-task-ipset.h
src/rh-task-memset.c
src/rh-task-memset.h
src/rh-task.c
src/rh-task.h
src/rh-utils.c
src/rh-utils.h
src/rh-xmlrpc-cmd.c
src/rh-xmlrpc-cmd.h
src/rh-xmlrpc-server.c
weblogin/config.php
weblogin/index.php
weblogin/locale.php
weblogin/login.php
weblogin/logout.php
weblogin/networkchk.php [new file with mode: 0644]
weblogin/rahu_xmlrpc.class.php

index 648d902..8f7bd4d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2009-03-31  Neutron Soutmun <neo.neutron@gmail.com>
+
+       * +src/rh-server.{h,c}: 
+         - Add virtual server concepts, make the clients from different interface to
+           access the particular virtual server, differentiate clients by their IP.
+
+       * src/rahunasd.{h,c}, src/rh-config.{c,h}, src/rh-ipset.{h,c}, 
+         src/rh-task.{h,c}, src/rh-task-{bandwidth,dbset,ipset,memset}.{h,c},
+         src/rh-utils.{h,c}, src/rh-xmlrpc-cmd.{h,c}, src/rh-xmlrpc-server.c:
+         - Redesign, rewrite and adjust the code to support the virtual server 
+           concepts.
+         - Improve the memory management by replace old static memory allocation by
+           dynamic memory allocation (GList), therefore fix the memory leak in 
+           earlier version.
+
+       * example/{bandwidth.sh.in,firewall.sh.in},
+         example/rahunas.conf.in,
+         +example/rahunas-vserver.conf.in:
+         - Add new virtual server config example file which need to put into the
+           config directory (default: /etc/rahunas/rahunas.d).
+         - Update config file to support the new virtual server concepts,
+           for earlier config file is not compatible now.
+         - Update the bandwidth and firewall example script to support virtual 
+           server.
+
+       * configure.ac, Makefile.am: Update make file according to new changes.
+
+       * weblogin/networkchk.php: Add new client's IP check for determine the 
+         network of each client and get the appropriate config, 
+         differentiate client to access the particular virtual server by vserver_id.
+         
+       * weblogin/{config,index,locale,login,logout}.php, 
+         weblogin/rahu_xmlrpc.class.php: Adjust for virtual server concepts.
+
 2009-03-18  Neutron Soutmun <neo.neutron@gmail.com>
 
        * example/bandwidth.sh.in, example/rahunas.conf.in:
index d2e651c..cd75ace 100644 (file)
@@ -62,6 +62,7 @@ AC_CONFIG_FILES([
   example/rahunas.default
   example/rahunas.init
   example/rahunas.conf
+  example/rahunas-vserver.conf
   example/firewall.sh
   example/bandwidth.sh
 ])
index 45a8462..e0c79cc 100644 (file)
Binary files a/data/rahunas.db and b/data/rahunas.db differ
index cd73c9e..2d2201b 100755 (executable)
@@ -19,7 +19,9 @@ SHAPING_DOWN_INF=imq0
 SHAPING_UP_INF=imq1
 
 INTERFACE_ID=9999
-P2P_ID=9998
+BITTORRENT_ID=9998
+
+MESSAGE=""
 
 test -f $INIT || exit 0
 . $INIT
@@ -30,16 +32,18 @@ test -f $RAHUNAS_CONFIG || exit 1
 set -e
 
 get_config_value () {
-  key=$1
-  cat $RAHUNAS_CONFIG | grep -v ^/ | grep -w "$key" | cut -d= -f2 | sed 's/^ *\(.*[^ ]\) *$/\1/' | sed 's/"//g'
+  section=$1
+  key=$2
+  file=$3
+
+  cat $file | sed -e "0,/$section = {/ ! { /}/,/$section = {/ ! s/^/>>/ }" | grep "^>>" | sed -e "s/^>>//g" | grep -w "$key" | cut -d= -f2 | sed "s/^ *\(.*[^ ]\) *$/\1/" | sed 's/"//g'
 }
 
-BANDWIDTH_SHAPE_IMQ=`get_config_value bandwidth_shape_imq`
-BITTORRENT_BLOCK=`get_config_value bittorrent_block`
-DOWN_P2P=`get_config_value bittorrent_download_max`
-UP_P2P=`get_config_value bittorrent_upload_max` 
+BANDWIDTH_SHAPE=`get_config_value main bandwidth_shape $RAHUNAS_CONFIG`
+BITTORRENT_DOWNLOAD_MAX=`get_config_value main bittorrent_download_max $RAHUNAS_CONFIG`
+BITTORRENT_UPLOAD_MAX=`get_config_value main bittorrent_upload_max $RAHUNAS_CONFIG` 
 
-test "$BANDWIDTH_SHAPE_IMQ" = "yes" || exit 0 
+test "$BANDWIDTH_SHAPE" = "yes" || exit 0 
 
 interface_setting () {
   case "$1" in
@@ -66,24 +70,24 @@ interface_setting () {
   esac
 }
 
-p2p_setting () {
+bittorrent_setting () {
   case "$1" in
     start)
-      # P2P Download throttling
+      # BITTORRENT Download throttling
       $TC class add dev $SHAPING_DOWN_INF parent 1:${INTERFACE_ID} \
-        classid 1:${P2P_ID} htb rate ${DOWN_P2P}Kbit
-      $TC qdisc add dev $SHAPING_DOWN_INF parent 1:${P2P_ID} \
-        handle ${P2P_ID}: sfq perturb 10
+        classid 1:${BITTORRENT_ID} htb rate ${BITTORRENT_DOWNLOAD_MAX}Kbit
+      $TC qdisc add dev $SHAPING_DOWN_INF parent 1:${BITTORRENT_ID} \
+        handle ${BITTORRENT_ID}: sfq perturb 10
       $TC filter add dev $SHAPING_DOWN_INF parent 1: protocol ip prio 5 \
-        handle 0x3 fw classid 1:${P2P_ID}
+        handle 0x3 fw classid 1:${BITTORRENT_ID}
 
-      # P2P Upload throttling
+      # BITTORRENT Upload throttling
       $TC class add dev $SHAPING_UP_INF parent 2:${INTERFACE_ID} \
-        classid 2:${P2P_ID} htb rate ${UP_P2P}Kbit
-      $TC qdisc add dev $SHAPING_UP_INF parent 2:${P2P_ID} \
-        handle ${P2P_ID}: sfq perturb 10
+        classid 2:${BITTORRENT_ID} htb rate ${BITTORRENT_UPLOAD_MAX}Kbit
+      $TC qdisc add dev $SHAPING_UP_INF parent 2:${BITTORRENT_ID} \
+        handle ${BITTORRENT_ID}: sfq perturb 10
       $TC filter add dev $SHAPING_UP_INF parent 2: protocol ip prio 5 \
-        handle 0x3 fw classid 2:${P2P_ID}
+        handle 0x3 fw classid 2:${BITTORRENT_ID}
       ;;
     stop)
       ;;
@@ -91,19 +95,21 @@ p2p_setting () {
 }
 
 start () {
-  interface_setting start
-  
-  test "$BITTORRENT_BLOCK" = "throttle" && p2p_setting start
-
-  echo "Start OK"
+  if [ ! -e $RUN ]; then
+    interface_setting start
+    bittorrent_setting start
+    MESSAGE="Start OK"
+    touch $RUN
+  fi
 }
 
 stop () {
-  interface_setting stop
-
-  test "$BITTORRENT_BLOCK" = "throttle" && p2p_setting stop
-
-  echo "Stop OK"
+  if [ -e $RUN ]; then
+    interface_setting stop
+    bittorrent_setting stop
+    MESSAGE="Stop OK"
+    rm -f $RUN
+  fi
 }
 
 usage_add() {
@@ -130,7 +136,7 @@ bw_add() {
   IP=$2
   DOWNSPEED=$3
   UPSPEED=$4
-  echo "Add shaping slot id: $ID for $IP with D/U=$DOWNSPEED/$UPSPEED bits/s"
+  MESSAGE="Add shaping slot id: $ID for $IP with D/U=$DOWNSPEED/$UPSPEED bits/s"
 
   # Downlink
   $TC class add dev $SHAPING_DOWN_INF parent 1:${INTERFACE_ID} \
@@ -147,7 +153,7 @@ bw_add() {
 
 bw_del() {
   ID=$1
-  echo "Delete shaping slot id: $ID"
+  MESSAGE="Delete shaping slot id: $ID"
 
   # Filter Removal
   # Downlink/Uplink
@@ -168,16 +174,25 @@ N=@sysconfdir@/rahunas/bandwidth.sh
 
 case "$1" in
   start)
-    test -e $RUN || start
-    touch $RUN
+    start || true 
+    test -n "$MESSAGE" || MESSAGE="NOT COMPLETED"
+    echo $MESSAGE
     ;;
   stop)
-    test ! -e $RUN || stop
-    rm -f $RUN
+    stop || true
+    test -n "$MESSAGE" || MESSAGE="NOT COMPLETED"
+    echo $MESSAGE
+
     ;;
   restart)
-    stop
-    start
+    stop || true
+    test -n "$MESSAGE" || MESSAGE="NOT COMPLETED"
+    echo $MESSAGE
+
+    start || true
+    test -n "$MESSAGE" || MESSAGE="NOT COMPLETED"
+    echo $MESSAGE
+
     ;;
   add)
     if [ "$2" = "--help" ]; then
@@ -191,7 +206,8 @@ case "$1" in
       exit 1
     fi
 
-    bw_add $2 $3 $4 $5
+    bw_add $2 $3 $4 $5 || true
+    echo $MESSAGE
     ;;
   del)
     if [ "$2" = "--help" ]; then
@@ -205,7 +221,8 @@ case "$1" in
       exit 1
     fi
 
-    bw_del $2
+    bw_del $2 || true
+    echo $MESSAGE
     ;;
   *)
     usage $N
index 1bef4d2..f330b8a 100755 (executable)
@@ -13,6 +13,7 @@ IPSET=/usr/sbin/ipset
 NAME="rahunas"
 INIT=@sysconfdir@/default/rahunas
 RUN=@localstatedir@/run/rahunas-firewall
+VSERVER_LIST=@localstatedir@/run/rahunas-vserver
 
 RUN_DAEMON=no
 
@@ -21,69 +22,151 @@ test -f $INIT || exit 0
 
 test "$RUN_DAEMON" = "yes" || exit 0
 test -f $RAHUNAS_CONFIG || exit 1
+test -f $VSERVER_LIST || touch $VSERVER_LIST
+
+get_section_name () {
+  file=$1
+  
+  grep "^.*\= {$" $file | sed "s/= {//" |  sed "s/^ *\(.*[^ ]\) *$/\1/"
+}
 
 get_config_value () {
-  key=$1
-  cat $RAHUNAS_CONFIG | grep -v ^/ | grep -w "$key" | cut -d= -f2 | sed 's/^ *\(.*[^ ]\) *$/\1/' | sed 's/"//g'
+  section=$1
+  key=$2
+  file=$3
+
+  cat $file | sed -e "0,/$section = {/ ! { /}/,/$section = {/ ! s/^/>>/ }" | grep "^>>" | sed -e "s/^>>//g" | grep -w "$key" | cut -d= -f2 | sed "s/^ *\(.*[^ ]\) *$/\1/" | sed 's/"//g'
 }
 
-# Get configuration
-DEV_WAN=`get_config_value dev_wan`
-DEV_LAN=`get_config_value dev_lan`
-BRIDGE=`get_config_value bridge`
-MASQUERADE=`get_config_value masquerade`
-SERVER=`get_config_value server`
-CLIENTS_RANGE_START=`get_config_value clients_range_start`
-CLIENTS_RANGE_END=`get_config_value clients_range_end`
-CLIENTS_NETWORK=`get_config_value clients_network`
-EXCLUDED=`get_config_value excluded`
-IGNORE_MAC=`get_config_value ignore_mac`
-BANDWIDTH_SHAPE_IMQ=`get_config_value bandwidth_shape_imq`
-FORWARD_DHCP=`get_config_value forward_dhcp`
-FORWARD_DNS=`get_config_value forward_dns`
-PROXY_PORT=`get_config_value proxy_port`
-PROXY_HOST=`get_config_value proxy_host`
-TRANSPARENT_PROXY=`get_config_value transparent_proxy`
-SSH=`get_config_value ssh`
-BITTORRENT_BLOCK=`get_config_value bittorrent_block`
-BITTORRENT_ALLOW=`get_config_value bittorrent_allow`
-
-# Bridge config
-if [ "$BRIDGE" = "yes" ]; then
-  DEV_IN_PARAM="-m physdev --physdev-in"
-  DEV_OUT_PARAM="-m physdev --physdev-out"
-else
-  DEV_IN_PARAM="-i"
-  DEV_OUT_PARAM="-o"
-fi
-
-# Set declaration
-SETNAME="${NAME}_set"
-
-# Chains declaration
-CHAIN_INPUT="${NAME}_input"
-CHAIN_INPUT_AUTH="${NAME}_input_authorized"
-CHAIN_FORWARD="${NAME}_forward"
-CHAIN_FORWARD_AUTH="${NAME}_forward_authorized"
-CHAIN_MANGLE_PREROUTING="${NAME}_mangle_prerouting"
-CHAIN_MANGLE_FORWARD="${NAME}_mangle_forward"
-CHAIN_MANGLE_POSTROUTING="${NAME}_mangle_postrouting"
-CHAIN_NAT_PREROUTING="${NAME}_nat_prerouting"
-CHAIN_NAT_POSTROUTING="${NAME}_nat_postrouting"
-CHAIN_NAT_AUTHEN="${NAME}_nat_authen"
-
-# P2P checking chains declaration
-CHAIN_P2P_DETECT="${NAME}_p2p_detect"
-CHAIN_P2P_RECHECK="${NAME}_p2p_recheck"
-CHAIN_P2P_CHECK="${NAME}_p2p_check"
-P2P_SET="rahunas_p2p"
-P2P_ALLOW_SET="rahunas_allow_p2p"
-
-# Allow incoming to server
-SERVER_PORTS_ALLOW="80,443,8443,8888"
-
-# Intercept requesting ports
-SERVER_PORTS_INTERCEPT="80,8080,8088,3128"
+##
+#  Global Declaration
+##
+
+# Main
+MAIN_CONF_DIR=`get_config_value main conf_dir $RAHUNAS_CONFIG`
+MAIN_BANDWIDTH_SHAPE=`get_config_value main bandwidth_shape $RAHUNAS_CONFIG`
+MAIN_BITTORRENT_DOWNLOAD_MAX=`get_config_value main bittorrent_download_max $RAHUNAS_CONFIG`
+MAIN_BITTORRENT_UPLOAD_MAX=`get_config_value main bittorrent_upload_max $RAHUNAS_CONFIG`
+
+# Virtual Server : config
+VSERVER_ID=
+DEV_EXTERNAL=
+DEV_INTERNAL=
+BRIDGE=
+MASQUERADE=
+IGNORE_MAC=
+VSERVER_IP=
+CLIENTS=
+EXCLUDED=
+BANDWIDTH_SHAPE=
+DHCP=
+DNS=
+SSH=
+PROXY=
+PROXY_HOST=
+PROXY_PORT=
+BITTORRENT=
+BITTORRENT_ALLOW=
+BITTORRENT_DOWNLOAD_MAX=
+BITTORRENT_UPLOAD_MAX=
+VSERVER_PORTS_ALLOW=
+VSERVER_PORTS_INTERCEPT=
+
+# Virtual Server : set and chains
+CHAIN_INPUT=
+CHAIN_INPUT_AUTH=
+CHAIN_FORWARD=
+CHAIN_FORWARD_AUTH=
+CHAIN_MANGLE_PREROUTING=
+CHAIN_MANGLE_FORWARD=
+CHAIN_MANGLE_POSTROUTING=
+CHAIN_NAT_PREROUTING=
+CHAIN_NAT_POSTROUTING=
+CHAIN_NAT_AUTHEN=
+CHAIN_P2P_DETECT=
+CHAIN_P2P_RECHECK=
+CHAIN_P2P_CHECK=
+P2P_SET=
+P2P_ALLOW_SET=
+DEV_IN_PARAM=
+DEV_OUT_PARAM=
+SETNAME=
+
+get_config () {
+  file=$1
+  opt=$2
+
+  test -f $file || return 1
+
+  NAME=`get_section_name $file`
+
+  # Get configuration
+  VSERVER_ID=`get_config_value $NAME vserver_id $file`
+  test -n "$VSERVER_ID" || return 2
+
+  if [ "$opt" = "start" ]; then
+    hash="$VSERVER_ID:$NAME"
+    test1=`grep -w "$hash" $VSERVER_LIST` || true
+    test2=`grep -w "$NAME" $VSERVER_LIST` || true
+  
+    test -n "$test1" -o -n "$test2" && return 3 
+
+    echo "$hash:$file" >> $VSERVER_LIST
+  fi
+
+  DEV_EXTERNAL=`get_config_value $NAME dev_external $file`
+  DEV_INTERNAL=`get_config_value $NAME dev_internal $file`
+  BRIDGE=`get_config_value $NAME bridge $file`
+  MASQUERADE=`get_config_value $NAME masquerade $file`
+  IGNORE_MAC=`get_config_value $NAME ignore_mac $file`
+  VSERVER_IP=`get_config_value $NAME vserver_ip $file`
+  CLIENTS=`get_config_value $NAME clients $file`
+  EXCLUDED=`get_config_value $NAME excluded $file`
+  BANDWIDTH_SHAPE=$MAIN_BANDWIDTH_SHAPE
+  DHCP=`get_config_value $NAME dhcp $file`
+  DNS=`get_config_value $NAME dns $file`
+  SSH=`get_config_value $NAME ssh $file`
+  PROXY=`get_config_value $NAME proxy $file`
+  PROXY_HOST=`get_config_value $NAME proxy_host $file`
+  PROXY_PORT=`get_config_value $NAME proxy_port $file`
+  BITTORRENT=`get_config_value $NAME bittorrent $file`
+  BITTORRENT_ALLOW=`get_config_value $NAME bittorrent_allow $file`
+  BITTORRENT_DOWNLOAD_MAX=$MAIN_BITTORRENT_DOWNLOAD_MAX
+  BITTORRENT_UPLOAD_MAX=$MAIN_BITTORRENT_UPLOAD_MAX
+  VSERVER_PORTS_ALLOW=`get_config_value $NAME vserver_ports_allow $file`
+  VSERVER_PORTS_INTERCEPT=`get_config_value $NAME vserver_ports_intercept $file`
+  # Bridge config
+  if [ "$BRIDGE" = "yes" ]; then
+    DEV_IN_PARAM="-m physdev --physdev-in"
+    DEV_OUT_PARAM="-m physdev --physdev-out"
+  else
+    DEV_IN_PARAM="-i"
+    DEV_OUT_PARAM="-o"
+  fi
+  
+  # Set declaration
+  SETNAME="${NAME}"
+  
+  # Chains declaration
+  CHAIN_INPUT="${NAME}_in"
+  CHAIN_INPUT_AUTH="${NAME}_in_auth"
+  CHAIN_FORWARD="${NAME}_fwd"
+  CHAIN_FORWARD_AUTH="${NAME}_fwd_auth"
+  CHAIN_MANGLE_PREROUTING="${NAME}_mg_pre"
+  CHAIN_MANGLE_FORWARD="${NAME}_mg_fwd"
+  CHAIN_MANGLE_POSTROUTING="${NAME}_mg_post"
+  CHAIN_NAT_PREROUTING="${NAME}_nat_pre"
+  CHAIN_NAT_POSTROUTING="${NAME}_nat_post"
+  CHAIN_NAT_AUTHEN="${NAME}_nat_authen"
+  
+  # P2P checking chains declaration
+  CHAIN_P2P_DETECT="${NAME}_p2p_detect"
+  CHAIN_P2P_RECHECK="${NAME}_p2p_rechk"
+  CHAIN_P2P_CHECK="${NAME}_p2p_chk"
+  P2P_SET="${NAME}_p2p"
+  P2P_ALLOW_SET="${NAME}_p2p_allow"
+}
 
 ##
 # Add set
@@ -92,11 +175,7 @@ add_set () {
   ipset_opt=""
   ipset_ignoremac=""
   
-  if [ "$CLIENTS_NETWORK" != "" ]; then
-    ipset_opt="--network $CLIENTS_NETWORK"
-  else
-    ipset_opt="--from $CLIENTS_RANGE_START --to $CLIENTS_RANGE_END"
-  fi
+  ipset_opt="--network $CLIENTS"
   
   if [ "$IGNORE_MAC" = "yes" ]; then
     ipset_ignoremac="--ignoremac"
@@ -104,7 +183,7 @@ add_set () {
   
   $IPSET -N $SETNAME rahunas $ipset_opt $ipset_ignoremac 
 
-  if [ "$BITTORRENT_BLOCK" = "throttle" ]; then
+  if [ "$BITTORRENT" = "throttle" ]; then
     $IPSET -N $P2P_SET iphash
   fi
 
@@ -124,7 +203,7 @@ cleanup_set () {
   $IPSET -F $SETNAME
   $IPSET -X $SETNAME
 
-  if [ "$BITTORRENT_BLOCK" = "throttle" ]; then
+  if [ "$BITTORRENT" = "throttle" ]; then
     $IPSET -F $P2P_SET
     $IPSET -X $P2P_SET 
   fi
@@ -136,19 +215,88 @@ cleanup_set () {
 }
 
 ##
+# Navigation rules
+##
+navigation_rules () {
+  opt=$1
+  if [ "$opt" = "start" ]; then
+    action="-I"
+  elif [ "$opt" = "stop" ]; then
+    action="-D"
+  fi
+
+  # INPUT from external
+  # TODO: Make a common firewall to filter the external requests.
+  $IPTABLES $action INPUT \
+    $DEV_IN_PARAM $DEV_EXTERNAL -j ACCEPT 
+
+  # INPUT
+  $IPTABLES $action INPUT \
+    $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
+    -j $CHAIN_INPUT
+  $IPTABLES $action INPUT -m connmark --mark 2/2 \
+    $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
+    -j $CHAIN_INPUT_AUTH
+
+  # FORWARD
+  $IPTABLES $action FORWARD \
+    $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
+    -j $CHAIN_FORWARD
+  $IPTABLES $action FORWARD \
+    $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
+    -j $CHAIN_FORWARD
+  $IPTABLES $action FORWARD -m connmark --mark 2/2 \
+    $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
+    -j $CHAIN_FORWARD_AUTH
+  $IPTABLES $action FORWARD -m connmark --mark 2/2 \
+    $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
+    -j $CHAIN_FORWARD_AUTH
+
+  # MANGLE
+  $IPTABLES -t mangle $action PREROUTING \
+    $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
+    -j $CHAIN_MANGLE_PREROUTING
+  $IPTABLES -t mangle $action PREROUTING \
+    $DEV_IN_PARAM $DEV_EXTERNAL -d $CLIENTS \
+    -j $CHAIN_MANGLE_PREROUTING
+
+  $IPTABLES -t mangle $action FORWARD \
+    $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
+    -j $CHAIN_MANGLE_FORWARD
+  $IPTABLES -t mangle $action FORWARD \
+    $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
+    -j $CHAIN_MANGLE_FORWARD
+
+  $IPTABLES -t mangle $action POSTROUTING \
+    $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
+    -j $CHAIN_MANGLE_POSTROUTING
+  $IPTABLES -t mangle $action POSTROUTING \
+    $DEV_OUT_PARAM $DEV_EXTERNAL -s $CLIENTS \
+    -j $CHAIN_MANGLE_POSTROUTING
+
+  # NAT
+  $IPTABLES -t nat $action PREROUTING \
+    $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
+    -j $CHAIN_NAT_PREROUTING
+  $IPTABLES -t nat $action PREROUTING \
+    $DEV_IN_PARAM $DEV_EXTERNAL -d $CLIENTS \
+    -j $CHAIN_NAT_PREROUTING
+
+  $IPTABLES -t nat $action POSTROUTING \
+    $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
+    -j $CHAIN_NAT_POSTROUTING
+  $IPTABLES -t nat $action POSTROUTING \
+    $DEV_OUT_PARAM $DEV_EXTERNAL -s $CLIENTS \
+    -j $CHAIN_NAT_POSTROUTING
+}
+
+##
 # Cleanup old rules
 ##
 cleanup () {
-  $IPTABLES -D INPUT -m connmark --mark 2/2 -j $CHAIN_INPUT_AUTH
-  $IPTABLES -D INPUT -j $CHAIN_INPUT
-  $IPTABLES -D FORWARD -m connmark --mark 2/2 -j $CHAIN_FORWARD_AUTH
-  $IPTABLES -D FORWARD -j $CHAIN_FORWARD
-  $IPTABLES -t mangle -D PREROUTING -j $CHAIN_MANGLE_PREROUTING
-  $IPTABLES -t mangle -D FORWARD -j $CHAIN_MANGLE_FORWARD
-  $IPTABLES -t mangle -D POSTROUTING -j $CHAIN_MANGLE_POSTROUTING
-  $IPTABLES -t nat -D PREROUTING -j $CHAIN_NAT_PREROUTING
-  $IPTABLES -t nat -D POSTROUTING -j $CHAIN_NAT_POSTROUTING
-  
+
+  navigation_rules stop  
+
   $IPTABLES -F $CHAIN_INPUT_AUTH
   $IPTABLES -X $CHAIN_INPUT_AUTH
 
@@ -179,7 +327,7 @@ cleanup () {
   $IPTABLES -t nat -F $CHAIN_NAT_AUTHEN
   $IPTABLES -t nat -X $CHAIN_NAT_AUTHEN
 
-  if [ "$BITTORRENT_BLOCK" = "throttle" ]; then
+  if [ "$BITTORRENT" = "throttle" ]; then
     $IPTABLES -t mangle -F $CHAIN_P2P_CHECK
     $IPTABLES -t mangle -X $CHAIN_P2P_CHECK
 
@@ -206,7 +354,7 @@ new_chains () {
   $IPTABLES -t nat -N $CHAIN_NAT_POSTROUTING
   $IPTABLES -t nat -N $CHAIN_NAT_AUTHEN
 
-  if [ "$BITTORRENT_BLOCK" = "throttle" ]; then
+  if [ "$BITTORRENT" = "throttle" ]; then
     $IPTABLES -t mangle -N $CHAIN_P2P_CHECK
     $IPTABLES -t mangle -N $CHAIN_P2P_RECHECK
     $IPTABLES -t mangle -N $CHAIN_P2P_DETECT
@@ -220,6 +368,8 @@ policy () {
   $IPTABLES -P INPUT DROP
   $IPTABLES -P OUTPUT ACCEPT
   $IPTABLES -P FORWARD DROP 
+
+  $IPTABLES -A INPUT -i lo -j ACCEPT
 }
 
 cleanup_policy () {
@@ -227,23 +377,13 @@ cleanup_policy () {
   $IPTABLES -P INPUT ACCEPT
   $IPTABLES -P OUTPUT ACCEPT
   $IPTABLES -P FORWARD ACCEPT 
+
+  $IPTABLES -D INPUT -i lo -j ACCEPT
 }
 
 rules () {
-  ##
-  # Init rules
-  ##
-  $IPTABLES -I INPUT -j $CHAIN_INPUT
-  $IPTABLES -I INPUT -m connmark --mark 2/2 -j $CHAIN_INPUT_AUTH
-  $IPTABLES -I FORWARD -j $CHAIN_FORWARD
-  $IPTABLES -I FORWARD -m connmark --mark 2/2 -j $CHAIN_FORWARD_AUTH
 
-  $IPTABLES -t mangle -I PREROUTING -j $CHAIN_MANGLE_PREROUTING
-  $IPTABLES -t mangle -I FORWARD -j $CHAIN_MANGLE_FORWARD
-  $IPTABLES -t mangle -I POSTROUTING -j $CHAIN_MANGLE_POSTROUTING
-
-  $IPTABLES -t nat -I PREROUTING -j $CHAIN_NAT_PREROUTING
-  $IPTABLES -t nat -I POSTROUTING -j $CHAIN_NAT_POSTROUTING
+  navigation_rules start
   
   ##
   # Allow all traffic for established and related connections
@@ -257,66 +397,71 @@ rules () {
   ##
   # Allow incoming to our DNS server
   ##
-  if [ "$FORWARD_DNS" = "yes" ]; then
+  if [ "$DNS" = "yes" ]; then
     $IPTABLES -A $CHAIN_INPUT -p udp --dport domain -j ACCEPT
+    $IPTABLES -A $CHAIN_FORWARD -p udp --dport domain -j DROP
+  elif [ "$DNS" = "no" ]; then
+    $IPTABLES -A $CHAIN_INPUT -p udp --dport domain -j DROP
     $IPTABLES -A $CHAIN_FORWARD -p udp --dport domain -j ACCEPT
-  else
+  elif [ "$DNS" = "forward" ]; then
     $IPTABLES -A $CHAIN_INPUT -p udp --dport domain -j ACCEPT
-    $IPTABLES -A $CHAIN_FORWARD -p udp --dport domain -j DROP
+    $IPTABLES -A $CHAIN_FORWARD -p udp --dport domain -j ACCEPT
   fi 
 
   ##
   # Allow incoming to our HTTP server for login page
   ##
-  $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport --dports $SERVER_PORTS_ALLOW \
-    -m recent --rcheck --seconds 15 --name INCOMING_THROTTLE -j DROP
+  $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport -d $VSERVER_IP\
+     --dports $VSERVER_PORTS_ALLOW \
+    -m recent --rcheck --seconds 15 --name incoming_throttle -j DROP
 
-  $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport --dports $SERVER_PORTS_ALLOW \
+  $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport -d $VSERVER_IP \
+    --dports $VSERVER_PORTS_ALLOW \
     -m hashlimit --hashlimit 5/sec \
     --hashlimit-mode srcip --hashlimit-burst 10 \
     --hashlimit-htable-expire 15000 --hashlimit-name incoming \
     -j ACCEPT
 
-  $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport --dports $SERVER_PORTS_ALLOW \
-    -m recent --set --name INCOMING_THROTTLE -j DROP
+  $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport -d $VSERVER_IP \
+    --dports $VSERVER_PORTS_ALLOW \
+    -m recent --set --name incoming_throttle -j DROP
   
   ##
   # Allow incoming to our SSH server for remote maintenance access
   ##
   if [ "$SSH" = "yes" ]; then
-    $IPTABLES -A $CHAIN_INPUT -p tcp --dport ssh -j ACCEPT
+    $IPTABLES -A $CHAIN_INPUT -p tcp -d $VSERVER_IP --dport ssh -j ACCEPT
   fi
 
   ##
   # Allow rate limited ICMP 
   ##
-  $IPTABLES -A $CHAIN_INPUT -p icmp -m limit --limit 1/second -j ACCEPT
+  $IPTABLES -A $CHAIN_INPUT -p icmp -m limit --limit 5/second \
+    -d $VSERVER_IP -j ACCEPT
 
   ##
   # Allow incoming DHCP request
   ##
 
-  if [ "$FORWARD_DHCP" = "yes" ]; then
-    $IPTABLES -A $CHAIN_INPUT $DEV_IN_PARAM $DEV_LAN \
-      -p udp --dport 67:68 -j DROP 
-    $IPTABLES -A $CHAIN_FORWARD $DEV_IN_PARAM $DEV_LAN \
-      -p udp --dport 67:68 -j ACCEPT
-  else
-    $IPTABLES -A $CHAIN_INPUT $DEV_IN_PARAM $DEV_LAN \
-      -p udp --dport 67:68 -j ACCEPT 
-    $IPTABLES -A $CHAIN_FORWARD $DEV_IN_PARAM $DEV_LAN \
-      -p udp --dport 67:68 -j DROP
+  if [ "$DHCP" = "yes" ]; then
+    $IPTABLES -A $CHAIN_INPUT -p udp --dport 67:68 -j ACCEPT 
+    $IPTABLES -A $CHAIN_FORWARD -p udp --dport 67:68 -j DROP
+  elif [ "$DHCP" = "no" ]; then
+    $IPTABLES -A $CHAIN_INPUT -p udp --dport 67:68 -j DROP 
+    $IPTABLES -A $CHAIN_FORWARD -p udp --dport 67:68 -j DROP
+  elif [ "$DHCP" = "forward" ]; then
+    $IPTABLES -A $CHAIN_INPUT -p udp --dport 67:68 -j DROP 
+    $IPTABLES -A $CHAIN_FORWARD -p udp --dport 67:68 -j ACCEPT
   fi
 
   ##
   # Bittorrent Blocking (layer7 module in kernel is needed)
   # Note: 
-  #   bittorrent-announce is custom pattern defined may warning with official
-  #   pattern downloaded from l7-filter site.
+  #   bittorrent-announce is customized pattern, warning if not exists.
   ##
-  if [ "$BITTORRENT_BLOCK" = "yes" -o -n "$BITTORRENT_ALLOW" ]; then
+  if [ "$BITTORRENT" = "yes" -o -n "$BITTORRENT_ALLOW" ]; then
     if [ -n "$BITTORRENT_ALLOW" ]; then
-      BITTORRENT_ALLOW_OPTIONS="$DEV_IN_PARAM $DEV_LAN -m set ! --set $P2P_ALLOW_SET"
+      BITTORRENT_ALLOW_OPTIONS="-m set ! --set $P2P_ALLOW_SET"
 
       # Source host
       $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m layer7 --l7proto bittorrent-announce $BITTORRENT_ALLOW_OPTIONS src -j DROP
@@ -331,13 +476,13 @@ rules () {
   ##
   # Mark the connections that have been authorized
   ##
-  $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set rahunas_set dst -j CONNMARK --set-mark 2 
-  $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set rahunas_set src -j CONNMARK --set-mark 2 
+  $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set $SETNAME dst -j CONNMARK --set-mark 2 
+  $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set $SETNAME src -j CONNMARK --set-mark 2 
 
   ##
   # P2P Throttle
   ##
-  if [ "$BITTORRENT_BLOCK" = "throttle" ]; then
+  if [ "$BITTORRENT" = "throttle" ]; then
     $IPTABLES -t mangle -A $CHAIN_MANGLE_FORWARD -m connmark --mark 2/2 -j $CHAIN_P2P_CHECK
     $IPTABLES -t mangle -A $CHAIN_MANGLE_FORWARD -m set --set $P2P_SET src -j MARK --set-mark 3
     $IPTABLES -t mangle -A $CHAIN_MANGLE_FORWARD -m set --set $P2P_SET dst -j MARK --set-mark 3
@@ -353,7 +498,6 @@ rules () {
     $IPTABLES -t mangle -A $CHAIN_P2P_DETECT -j SET --add-set $P2P_SET src
     $IPTABLES -t mangle -A $CHAIN_P2P_DETECT -m recent --name $P2P_SET --set -j RETURN
 
-
     $IPTABLES -t mangle -A $CHAIN_P2P_RECHECK -m recent --name $P2P_SET --rcheck --seconds 600 -j RETURN
     $IPTABLES -t mangle -A $CHAIN_P2P_RECHECK -j SET --del-set $P2P_SET src
     $IPTABLES -t mangle -A $CHAIN_P2P_RECHECK -m recent --name $P2P_SET --remove -j RETURN 
@@ -367,19 +511,19 @@ rules () {
   ##
   # SQUID Cache-Proxy
   ##
-  if [ "$PROXY_PORT" != "0" ]; then
-    if [ "$PROXY_HOST" = "localhost" ]; then
+  if [ "$PROXY" = "yes" -o "$PROXY" = "transparent" ]; then
+    if [ "$PROXY_HOST" = "localhost" -o "$PROXY_HOST" = "127.0.0.1" ]; then
       $IPTABLES -A $CHAIN_INPUT_AUTH -p tcp --dport $PROXY_PORT -j ACCEPT
     fi
 
-    if [ "$TRANSPARENT_PROXY" = "yes" ]; then
-      if [ "$PROXY_HOST" = "localhost" ]; then
+    if [ "$PROXY" = "transparent" ]; then
+      if [ "$PROXY_HOST" = "localhost" -o "$PROXY_HOST" = "127.0.0.1" ]; then
         $IPTABLES -t nat -A $CHAIN_NAT_PREROUTING -p tcp --dport http \
           -m connmark --mark 2/2 -j REDIRECT --to-ports $PROXY_PORT
       else
         $IPTABLES -t nat -A $CHAIN_NAT_PRETROUTING -p tcp --dport http \
           -m connmark --mark 2/2 \
-          -j DNAT --to-destination ${PROXY_HOST}:${PROXY_PORT}
+          -j DNAT --to-destination $PROXY_HOST:$PROXY_PORT
       fi
     fi
   fi
@@ -389,17 +533,18 @@ rules () {
   ##
   
   $IPTABLES -t nat -A $CHAIN_NAT_PREROUTING -p tcp -m multiport \
-    --dports $SERVER_PORTS_INTERCEPT -d ! $SERVER \
-    $DEV_IN_PARAM $DEV_LAN -m connmark ! --mark 2/2 \
+    --dports $VSERVER_PORTS_INTERCEPT -d ! $VSERVER_IP \
+    -m connmark ! --mark 2/2 \
     -j $CHAIN_NAT_AUTHEN
   
-  $IPTABLES -t nat -A $CHAIN_NAT_AUTHEN -p tcp -j REDIRECT --to-port 8888
+  $IPTABLES -t nat -A $CHAIN_NAT_AUTHEN -p tcp \
+    -j DNAT --to-destination $VSERVER_IP:80
 
   ##
   # MASQUERADE
   ##
   if [ "$MASQUERADE" = "yes" ]; then
-    $IPTABLES -t nat -A $CHAIN_NAT_POSTROUTING $DEV_OUT_PARAM $DEV_WAN \
+    $IPTABLES -t nat -A $CHAIN_NAT_POSTROUTING $DEV_OUT_PARAM $DEV_EXTERNAL \
       -j MASQUERADE
   fi
 
@@ -417,11 +562,9 @@ rules () {
   ##
   # Bandwidth Shaping: IMQ - Intermediate Queueing Device
   ##
-  if [ "$BANDWIDTH_SHAPE_IMQ" = "yes" ]; then
-    $IPTABLES -t mangle -I $CHAIN_MANGLE_POSTROUTING $DEV_OUT_PARAM $DEV_LAN \
-      -j IMQ --todev 0
-    $IPTABLES -t mangle -I $CHAIN_MANGLE_PREROUTING $DEV_IN_PARAM $DEV_LAN \
-      -j IMQ --todev 1
+  if [ "$BANDWIDTH_SHAPE" = "yes" ]; then
+    $IPTABLES -t mangle -I $CHAIN_MANGLE_POSTROUTING $DEV_OUT_PARAM $DEV_INTERNAL -j IMQ --todev 0
+    $IPTABLES -t mangle -I $CHAIN_MANGLE_PREROUTING $DEV_IN_PARAM $DEV_INTERNAL -j IMQ --todev 1
   fi
 
   ##
@@ -438,40 +581,79 @@ rules () {
   $IPTABLES -t nat -A $CHAIN_NAT_POSTROUTING -j RETURN
 }
 
+do_get_config () {
+  file=$1
+  opt=$2
+  get_config $file $opt || true
+  if [ $? -eq 1 ]; then
+    echo "Error: Could not parsing $file, file does not exists"
+    return 1
+  elif [ $? -eq 2 ]; then
+    echo "Error: Could not parsing $file, config file is malformed"
+    return 2
+  elif [ $? -eq 3 ]; then
+    if [ "$opt" != "stop" ]; then
+      echo "Error: Could not parsing $file, network's name is duplicated!"
+      return 3
+    fi
+  fi
+}
+
 start () {
-  test ! -f $RUN || exit 0
+  test ! -f $RUN || return 0
+
+  if [ ! -d $MAIN_CONF_DIR ]; then
+    echo "Error: The config directory $MAIN_CONF_DIR does not exists"
+    exit 1
+  fi
 
-  add_set
-  new_chains
-  policy 
-  rules
+  for file in `find $MAIN_CONF_DIR -name '*.conf'`;
+  do
+    do_get_config $file start
+    if [ $? -gt 0 ]; then
+      continue
+    fi 
+
+    add_set
+    new_chains
+    policy 
+    rules  
+  done
 
   touch $RUN
 }
 
 stop () {
-  test -f $RUN || exit 0
+  opt=$1
+  test -f $RUN || return 0
 
-  cleanup
-  cleanup_policy
-  cleanup_set
-  rm -f $RUN
-}
+  for line in `cat $VSERVER_LIST`;
+  do
+    file=`echo $line | cut -d: -f3` 
+    test -n $file || continue;
+    do_get_config $file stop
+    if [ $? -gt 0 ]; then
+      continue
+    fi
 
-reload() {
-  test -f $RUN || exit 0
+    cleanup
+    cleanup_policy
+    test "$opt" = "reload" || cleanup_set
+  done
 
-  # Do not cleanup set
-  cleanup
-  cleanup_policy
+   
   rm -f $RUN
+  echo "" > $VSERVER_LIST
+}
 
-  add_set
-  new_chains
-  policy 
-  rules
-  touch $RUN
+restart() {
+  stop
+  start
+}
+
+reload() {
+  stop reload
+  start
 }
 
 case "$1" in
@@ -482,8 +664,7 @@ case "$1" in
     stop
     ;;
   restart)
-    stop
-    start
+    restart
     ;;
   reload)
     reload     
diff --git a/example/rahunas-vserver.conf.in b/example/rahunas-vserver.conf.in
new file mode 100644 (file)
index 0000000..48f5f9c
--- /dev/null
@@ -0,0 +1,39 @@
+rahunas_default = {
+  vserver_id = "1"
+  dev_external = "eth0"
+  dev_internal = "eth1"
+  vlan = "no"
+  vlan_raw_dev_external = ""
+  vlan_raw_dev_internal = ""
+  bridge = "no"
+  masquerade = "yes"
+  ignore_mac = "no"
+  vserver_ip = "172.30.0.1"
+  vserver_fqdn = "authen.rahunas.local"
+  clients = "172.30.0.0/22"
+  excluded = ""
+  idle_timeout = "600"
+
+  dhcp = "yes"
+  dhcp_range = "172.30.0.10 172.30.3.254"
+  dns = "yes"
+  ssh = "yes"
+  proxy = "transparent"
+  proxy_host = "localhost"
+  proxy_port = "3128"
+  bittorrent = "block"
+  bittorrent_allow = ""
+
+  radius_host = "localhost"
+  radius_secret = "testing123"
+  radius_encrypt = "CHAP_MD5"
+  radius_auth_port = "0"
+  radius_account_port = "0"
+
+  nas_identifier = "RahuNAS-01"
+  nas_port = "1"
+  nas_login_title = "RahuNAS Network"
+  nas_default_redirect = "http://www.rahunas.org"
+  nas_default_language = "Thai"
+  nas_weblogin_template = "rahunas"
+}
index 95567de..bafa62e 100644 (file)
 // Date: 2008-11-26                                     //
 //////////////////////////////////////////////////////////
 
-/////////////////////////
-// Daemon              //
-/////////////////////////
-
-//// XML-RPC Server hostname or IP address
-//// default: localhost
-// xml_serv_host = "localhost"
-
-//// XML-RPC Server port
-//// default: 8888
-// xml_serv_port = "8888"
-
-//// XML-RPC URL
-//// default: /xmlrpc_service.php
-// xml_serv_url = "/xmlrpc_service.php"
-
-//// Polling interval (seconds)
-//// default: 60
-// polling_interval = "60"
-
-//// Idle threshold
-//// default: 600 (600 seconds = 10 minutes)
-// idle_threshold = "600"
-
-//// Log file
-log_file = "@prefix@/var/log/rahunas/rahunas.log"
-
-/////////////////////////
-// Start-Up            //
-/////////////////////////
-
-//// External Interface
-dev_wan = "eth0"
-
-//// Internal Interface
-dev_lan = "eth1"
-
-//// Bridging the External and Internal interface (Transparent Inline)
-bridge = "no"
-
-//// MASQUERADE (automatic source NAT) for the packets going outside (External)
-masquerade = "yes"
-
-//// RahuNAS Server's IP address or hostname
-server = "172.30.0.1"
-
-//// Clients IP 
-//// clients_range_start and clients_range_end are single ip, eg. 172.30.0.1.
-//// clients_network is network address/netmask, eg 172.30.0.0/22.
-////
-//// Note: The clients_network will overide the clients_range_start and 
-////       clients_range_end.
-
-clients_range_start = ""
-clients_range_end = ""
-clients_network = "172.30.0.0/22"
-
-//// Excluded IP address
-//// space separated IP address, it can be single ip or network address/netmask
-//// example: excluded = "172.30.0.100 202.28.92.0/24"
-excluded = ""
-
-//// Ignore MAC address
-//// no  - RahuNAS connected to the clients network locally and can grap MAC.
-//// yes - RahuNAS can not grap MAC, use only IP for identification. (Remote/L3)
-ignore_mac = "no"
-
-//// Enable bandwidth shaping using IMQ and iproute2
-bandwidth_shape_imq = "yes"
-
-//// Enable DHCP forwarding
-//// yes - The DHCP server is not setup on RahuNAS box, forwarding the request 
-////       out of the box.
-forward_dhcp = "no"
-
-//// Enable DNS forwarding 
-//// yes - The DNS server is not setup on RahuNAS box, forwarding the request 
-////       out of the box.
-forward_dns = "no"
-
-//// Enable SQUID Cache/Proxy 
-//// proxy_port = "0" to disable.
-proxy_port = "0"
-proxy_host = "localhost"
-
-//// Enable transparent proxy
-//// Do the http request interception and redirect to the proxy_host:proxy_port
-transparent_proxy = "no"
-
-//// Enable SSH - Secure Shell
-ssh = "yes"
-
-//// Enable Bittorrent blocking
-bittorrent_block = "no"
-bittorrent_allow = ""
-bittorrent_download_max = "512"
-bittorrent_upload_max = "256"
+main = {
+  conf_dir = "@prefix@/etc/rahunas/rahunas.d"
+  log_file = "@prefix@/var/log/rahunas/rahunas.log"
+
+  bandwidth_shape = "yes"  
+  bittorrent_download_max = "512"
+  bittorrent_upload_max = "256"
+}
index fa9a2bd..502da69 100644 (file)
@@ -18,6 +18,8 @@ AM_CFLAGS = \
 rahunasd_SOURCES = \
        rahunasd.c \
        rahunasd.h \
+       rh-server.c \
+       rh-server.h \
        rh-xmlrpc-server.c \
        rh-xmlrpc-server.h \
        rh-xmlrpc-cmd.c \
@@ -28,10 +30,10 @@ rahunasd_SOURCES = \
        rh-utils.h \
        rh-task.c \
        rh-task.h \
-       rh-task-ipset.c \
-       rh-task-ipset.h \
        rh-task-memset.c \
        rh-task-memset.h \
+       rh-task-ipset.c \
+       rh-task-ipset.h \
        rh-task-dbset.c \
        rh-task-dbset.h \
   rh-task-bandwidth.c \
index e6ebfe1..8a33db8 100644 (file)
  */
 
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <sys/wait.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
 #include <signal.h>
 #include <syslog.h>
 
 #include "rahunasd.h"
+#include "rh-server.h"
 #include "rh-xmlrpc-server.h"
 #include "rh-xmlrpc-cmd.h"
 #include "rh-ipset.h"
 #include "rh-utils.h"
 #include "rh-task.h"
 
-/* Abstract functions */
-int logmsg(int priority, const char *msg, ...); 
-int getline(int fd, char *buf, size_t size);
-
-size_t expired_check(void *data);
-
-/* Declaration */
-struct rahunas_config rh_config;
-struct rahunas_map *map = NULL;
-struct set *rahunas_set = NULL;
-
-struct set **set_list = NULL;
-ip_set_id_t max_sets = 0;
-
 const char *termstring = '\0';
 pid_t pid, sid;
 
-uint32_t iptoid(struct rahunas_map *map, const char *ip) {
-  uint32_t ret;
-  struct in_addr req_ip;
-
-  if (!map || !ip)
-    return (-1);
-
-  if (!(inet_aton(ip, &req_ip))) {
-    DP("Could not convert IP: %s", ip);
-    return (-1);  
-  }
-
-  DP("Request IP: %s", ip);
-  
-  ret = ntohl(req_ip.s_addr) - ntohl(map->first_ip);
-  if (ret < 0 || ret > (map->size - 1))
-    ret = (-1);
-
-  DP("Request Index: %lu", ret);
-  return ret; 
-}
-
-char *idtoip(struct rahunas_map *map, uint32_t id) {
-  struct in_addr sess_addr;
-
-  if (!map)
-    return termstring;
-
-  if (id < 0)
-    return termstring;
-
-  sess_addr.s_addr = htonl((ntohl(map->first_ip) + id));
-
-  return inet_ntoa(sess_addr);
-}
-
-void rh_free_member (struct rahunas_member *member)
-{
-  if (member->username && member->username != termstring)
-    free(member->username);
-
-  if (member->session_id && member->session_id != termstring)
-    free(member->session_id);
-  
-  memset(member, 0, sizeof(struct rahunas_member));
-  member->username = termstring;
-  member->session_id = termstring;
-}
-
-int rh_openlog(const char *filename)
-{
-  return open(filename, O_WRONLY | O_APPEND | O_CREAT);
-}
-
-int rh_closelog(int fd)
-{
-  if (close(fd) == 0)
-    return 1;
-  else
-    return 0;
-}
-
-int logmsg(int priority, const char *msg, ...) 
-{
-  int n, size = 256;
-  va_list ap;
-  char *time_fmt = "%b %e %T";
-  char *p = NULL;
-  char *np = NULL;
-
-  if (priority < RH_LOG_LEVEL)
-    return 0;
-
-  if ((p = rh_malloc(size)) == NULL) {
-    return (-1);
-  }
-
-  while (1) {
-    va_start(ap, msg);
-    n = vsnprintf(p, size, msg, ap);
-    va_end(ap);
-
-    if (n > -1 && n < size)
-      break;
-    if (n > -1)
-      size = n+1;
-    else
-      size *= 2;
-
-    if ((np = realloc(p, size)) == NULL) {
-      free(p);
-      p = NULL;
-      break;
-    } else {
-      p = np;
-    }
-  }
-
-  if (!p)
-    return (-1);
+struct main_server rh_main_server_instance = {
+  .vserver_list = NULL,
+  .task_list = NULL,
+};
 
-  fprintf(stderr, "%s : %s\n", timemsg(), p);
+struct main_server *rh_main_server = &rh_main_server_instance;
 
-  rh_free(&p);
-  rh_free(&np);
-}
+int getline(int fd, char *buf, size_t size);
+size_t expired_check(void *data);
 
 void rh_sighandler(int sig)
 {
@@ -190,59 +77,82 @@ int getline(int fd, char *buf, size_t size)
   return (current - buf);
 }
 
-gboolean polling(gpointer data) {
-  struct rahunas_map *map = (struct rahunas_map *)data;
-  DP("%s", "Start polling!");
-  walk_through_set(&expired_check);
-  return TRUE;
-}
-
 size_t expired_check(void *data)
 {
-  struct ip_set_list *setlist = (struct ip_set_list *) data;
-  struct set *set = set_list[setlist->index];
+  struct processing_set *process = (struct processing_set *) data;
+  struct ip_set_list *setlist = (struct ip_set_list *) process->list;
   size_t offset;
   struct ip_set_rahunas *table = NULL;
-  struct rahunas_member *members = map->members;
   struct task_req req;
-  unsigned int i;
+  unsigned int id;
   char *ip = NULL;
   int res  = 0;
+  GList *runner = g_list_first(process->vs->v_map->members);
+  struct rahunas_member *member = NULL;
+
+  if (process == NULL)
+    return (-1);
+
+  if (process->list == NULL)
+    return (-1); 
 
   offset = sizeof(struct ip_set_list) + setlist->header_size;
-  table = (struct ip_set_rahunas *)(data + offset);
-
-  DP("Map size %d", map->size);
-  for (i = 0; i < map->size; i++) {
-    if (test_bit(IPSET_RAHUNAS_ISSET, (void *)&table[i].flags)) {
-      if ((time(NULL) - table[i].timestamp) > rh_config.idle_threshold) {
-        // Idle Timeout
-        DP("Found IP: %s idle timeout", idtoip(map, i));
-        req.id = i;
-        memcpy(req.mac_address, &table[i].ethernet, ETH_ALEN);
-        req.req_opt = RH_RADIUS_TERM_IDLE_TIMEOUT;
-        send_xmlrpc_stopacct(map, i, RH_RADIUS_TERM_IDLE_TIMEOUT);
-        res = rh_task_stopsess(map, &req);
-      } else if (members[i].session_timeout != 0 && 
-                   time(NULL) > members[i].session_timeout) {
-        // Session Timeout (Expired)
-        DP("Found IP: %s session timeout", idtoip(map, i));
-        req.id = i;
-        memcpy(req.mac_address, &table[i].ethernet, ETH_ALEN);
-        req.req_opt = RH_RADIUS_TERM_SESSION_TIMEOUT;
-        send_xmlrpc_stopacct(map, i, RH_RADIUS_TERM_SESSION_TIMEOUT);
-        res = rh_task_stopsess(map, &req);
-      }
+  table = (struct ip_set_rahunas *)(process->list + offset);
+
+  while (runner != NULL) {
+    member = (struct rahunas_member *)runner->data;
+    id = member->id;
+
+    DP("Processing id = %d", id);
+
+    DP("Time diff = %d, idle_timeout=%d", (time(NULL) - table[id].timestamp),
+         process->vs->vserver_config->idle_timeout);
+
+    if ((time(NULL) - table[id].timestamp) > 
+         process->vs->vserver_config->idle_timeout) {
+      // Idle Timeout
+      DP("Found IP: %s idle timeout", idtoip(process->vs->v_map, id));
+      req.id = id;
+      memcpy(req.mac_address, &table[id].ethernet, ETH_ALEN);
+      req.req_opt = RH_RADIUS_TERM_IDLE_TIMEOUT;
+      send_xmlrpc_stopacct(process->vs, id, 
+                           RH_RADIUS_TERM_IDLE_TIMEOUT);
+      res = rh_task_stopsess(process->vs, &req);
+    } else if (member->session_timeout != 0 && 
+               time(NULL) > member->session_timeout) {
+      // Session Timeout (Expired)
+      DP("Found IP: %s session timeout", idtoip(process->vs->v_map, id));
+      req.id = id;
+      memcpy(req.mac_address, &table[id].ethernet, ETH_ALEN);
+      req.req_opt = RH_RADIUS_TERM_SESSION_TIMEOUT;
+      send_xmlrpc_stopacct(process->vs, id, 
+                           RH_RADIUS_TERM_SESSION_TIMEOUT);
+      res = rh_task_stopsess(process->vs, &req);
     }
+
+    runner = g_list_next(runner);
   }
 }
 
+gboolean polling_expired_check(struct main_server *ms, struct vserver *vs) {
+  walk_through_set(&expired_check, vs);
+  return TRUE;
+}
+
+gboolean polling(gpointer data) {
+  struct main_server *ms = (struct main_server *)data;
+  struct vserver *vs = NULL;
+  DP("%s", "Start polling!");
+  walk_through_vserver(&polling_expired_check, ms);
+  return TRUE;
+}
+
 void rh_exit()
 {
-  rh_task_stopservice(map);
-  rh_task_cleanup();
-  rh_closelog(rh_config.log_file);
+  walk_through_vserver(&rh_task_stopservice, rh_main_server);
+  walk_through_vserver(&rh_task_cleanup, rh_main_server);
+  rh_task_unregister(rh_main_server);
+  rh_closelog(rh_main_server->main_config->log_file);
 }
 
 static void
@@ -253,9 +163,7 @@ watch_child(char *argv[])
   time_t start;
   time_t stop;
   int status;
-
   int nullfd;
-  int pidfd;
   
   if (*(argv[0]) == '(')
     return;
@@ -266,12 +174,7 @@ watch_child(char *argv[])
     exit(EXIT_FAILURE);
   } else if (pid > 0) {
     /* parent */
-    pidfd = open(DEFAULT_PID, O_WRONLY | O_TRUNC | O_CREAT);
-    if (pidfd) {
-      dup2(pidfd, STDOUT_FILENO);
-      fprintf(stdout, "%d\n", pid);
-      close(pidfd);
-    }
+    rh_writepid(DEFAULT_PID, pid);
     exit(EXIT_SUCCESS);
   }
 
@@ -343,15 +246,32 @@ watch_child(char *argv[])
   }
 }
 
+void rh_free_member (struct rahunas_member *member)
+{
+  if (member->username && member->username != termstring)
+    free(member->username);
+
+  if (member->session_id && member->session_id != termstring)
+    free(member->session_id);
+}
+
 int main(int argc, char **argv) 
 {
   gchar* addr = "localhost";
   int port    = 8123;
   int fd_log;
 
-  char line[256];
   char version[256];
 
+  char line[256];
+
+  union rahunas_config rh_main_config = {
+    .rh_main.polling_interval = POLLING,
+    .rh_main.bandwidth_shape = BANDWIDTH_SHAPE,
+    .rh_main.conf_dir = NULL,
+    .rh_main.log_file = NULL,
+  };
+
   GNetXmlRpcServer *server = NULL;
   GMainLoop* main_loop     = NULL;
 
@@ -359,25 +279,40 @@ int main(int argc, char **argv)
 
   watch_child(argv);
 
-  /* Get configuration from config file */
-  if (config_init(&rh_config) < 0) {
-    syslog(LOG_ERR, "Could not open config file %s", CONFIG_FILE);
-    exit(EXIT_FAILURE);
+  /* Get main server config */
+  get_config(CONFIG_FILE, &rh_main_config);
+  rh_main_server->main_config = (struct rahunas_main_config *) &rh_main_config;
+
+  /* Open and select main log file */
+  if (rh_main_server->main_config->log_file != NULL) {
+    syslog(LOG_INFO, "Open log file: %s", 
+           rh_main_server->main_config->log_file);
+    rh_main_server->log_fd = rh_openlog(rh_main_server->main_config->log_file);
+
+    if (!rh_main_server->log_fd) {
+      syslog(LOG_ERR, "Could not open log file %s\n", 
+             rh_main_server->main_config->log_file);
+      exit(EXIT_FAILURE);
+    }
+
+    rh_logselect(rh_main_server->log_fd);
   }
 
-  /* Open log file */
-  if ((fd_log = rh_openlog(rh_config.log_file)) < 0) {
-    syslog(LOG_ERR, "Could not open log file %s", rh_config.log_file);
+  syslog(LOG_INFO, "Config directory: %s", rh_main_server->main_config->conf_dir);
+
+  /* Get vserver(s) config */
+  if (rh_main_server->main_config->conf_dir != NULL) {
+    get_vservers_config(rh_main_server->main_config->conf_dir, rh_main_server);
+  } else {
+    syslog(LOG_ERR, "The main configuration file is incompleted, lack of conf_dir\n");
     exit(EXIT_FAILURE);
   }
 
-  dup2(fd_log, STDERR_FILENO);
-
   sprintf(version, "Starting %s - Version %s", PROGRAM, RAHUNAS_VERSION);
   logmsg(RH_LOG_NORMAL, version);
-  syslog(LOG_INFO, version);
 
-  rh_task_init();
+  rh_task_register(rh_main_server);
+  walk_through_vserver(&rh_task_init, rh_main_server);
 
   gnet_init();
   main_loop = g_main_loop_new (NULL, FALSE);
@@ -387,28 +322,31 @@ int main(int argc, char **argv)
 
   if (!server) {
     syslog(LOG_ERR, "Could not start XML-RPC server!");
-    rh_task_stopservice(map);
+    walk_through_vserver(&rh_task_stopservice, rh_main_server);
     exit (EXIT_FAILURE);
   }
 
   gnet_xmlrpc_server_register_command (server, 
                                        "startsession", 
                                        do_startsession, 
-                                       map);
+                                       rh_main_server);
 
   gnet_xmlrpc_server_register_command (server, 
                                        "stopsession", 
                                        do_stopsession, 
-                                       map);
+                                       rh_main_server);
 
   gnet_xmlrpc_server_register_command (server, 
                                        "getsessioninfo", 
                                        do_getsessioninfo, 
-                                       map);
+                                       rh_main_server);
+
+  DP("Polling interval = %d", rh_main_server->main_config->polling_interval);
 
-  g_timeout_add_seconds (rh_config.polling_interval, polling, map);
+  g_timeout_add_seconds (rh_main_server->main_config->polling_interval, 
+                         polling, rh_main_server);
 
-  rh_task_startservice(map);
+  walk_through_vserver(&rh_task_startservice, rh_main_server);
 
   g_main_loop_run(main_loop);
 
index 43b5354..8582304 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef __RAHUNASD_H
 #define __RAHUNASD_H
 
-
 #include <stdio.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 
 #define DEFAULT_MAC "00:00:00:00:00:00"
 
-extern struct rahunas_config rh_config; 
-extern struct rahunas_map *map;
-extern struct set *rahunas_set;
 extern const char *termstring; 
+extern struct main_server rh_main_server_instance;
 
 enum RH_LOG {
   RH_LOG_DEBUG,
@@ -47,14 +44,14 @@ enum RH_LOG {
 #endif
 
 struct rahunas_map {
-  struct rahunas_member *members;
+  GList *members;
   in_addr_t first_ip;
   in_addr_t last_ip;
   unsigned int size;
 };
 
 struct rahunas_member {
-  unsigned short flags; 
+  uint32_t id; 
   unsigned short expired;
   time_t session_start;
   time_t session_timeout;
@@ -66,10 +63,7 @@ struct rahunas_member {
   unsigned char mac_address[ETH_ALEN];
 };
 
-uint32_t iptoid(struct rahunas_map *map, const char *ip);
-char *idtoip(struct rahunas_map *map, uint32_t id);
-
-void rh_free_member (struct rahunas_member *member);
+void rh_free_member(struct rahunas_member *member);
 
 static const char *timemsg()
 {
index 42379d7..a12d8e0 100755 (executable)
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
+#include <dirent.h>
+#include <errno.h>
 
+#include "rahunasd.h"
 #include "rh-config.h"
 
-void config_default(struct rahunas_config *config) {
-  config->polling_interval = POLLING;
-  config->idle_threshold = IDLE_THRESHOLD;
-  config->xml_serv_port = XMLSERVICE_PORT;
-  config->xml_serv_host = strdup(XMLSERVICE_HOST);
-  config->xml_serv_url = strdup(XMLSERVICE_URL);
-  config->set_name = strdup(SET_NAME);
-  config->log_file = strdup(DEFAULT_LOG);
-}
-
 enum lcfg_status rahunas_visitor(const char *key, void *data, size_t size, 
                                  void *user_data) {
-  struct rahunas_config *config = (struct rahunas_config *)user_data;
+  char *value = strndup(data, size);
+  union rahunas_config *config = (union rahunas_config *)user_data;
+  char *clone_key = NULL;
+  char *sep = NULL; 
+  char *main_key = NULL;
+  char *sub_key = NULL;
+  enum config_type cfg_type;
 
   if(config == NULL)
     return lcfg_status_error;
 
-  char *value = strndup(data, size);
-
   if(value == NULL)
     return lcfg_status_error;
 
-  if(!strcmp(key, "log_file")) {
-    config->log_file = value;
-  } else if (!strcmp(key, "idle_threshold")) {
-    config->idle_threshold = atoi(value);
-  } else if (!strcmp(key, "polling")) {
-    config->polling_interval = atoi(value);
-  } else if (!strcmp(key, "set_name")) {
-    config->set_name = value;
-  } else if (!strcmp(key, "xml_service_host")) {
-    config->xml_serv_host = value;
-  } else if (!strcmp(key, "xml_service_port")) {
-    config->xml_serv_port = atoi(value);
-  } else if (!strcmp(key, "xml_service_url")) {
-    config->xml_serv_url = value; 
+  clone_key = strdup(key);
+  if (clone_key == NULL)
+    return lcfg_status_error;
+
+  sep = strstr(clone_key, ".");
+  main_key = clone_key;
+  sub_key = sep + 1;
+  *sep = '\0';
+
+  if (strncmp(main_key, "main", 4) == 0) {
+    cfg_type = MAIN;
+  } else {
+    cfg_type = VSERVER;
+    if (config->rh_vserver.vserver_name == NULL)
+      config->rh_vserver.vserver_name = strdup(main_key);
   }
 
-  return lcfg_status_ok;
-}
+  switch (cfg_type) {
+    case MAIN:
+      if (strncmp(sub_key, "conf_dir", 8) == 0) {
+        if (config->rh_main.conf_dir != NULL)
+          free(config->rh_main.conf_dir);
+        config->rh_main.conf_dir = strdup(value);
+      } else if (strncmp(sub_key, "bandwidth_shape", 15) == 0) {
+        if (strncmp(value, "yes", 3) == 0)
+          config->rh_main.bandwidth_shape = 1; 
+        else
+          config->rh_main.bandwidth_shape = 0;
+      } else if (strncmp(sub_key, "polling_interval", 16) == 0) {
+        config->rh_main.polling_interval = atoi(value);
+      } else if (strncmp(sub_key, "log_file", 8) == 0) {
+        if (config->rh_main.log_file != NULL)
+          free(config->rh_main.log_file);
+        config->rh_main.log_file = strdup(value); 
+      }
+      break;
+
+    case VSERVER:
+      if (strncmp(sub_key, "vserver_id", 10) == 0) {
+        config->rh_vserver.vserver_id = atoi(value);
+      } else if (strncmp(sub_key, "idle_timeout", 12) == 0) {
+        config->rh_vserver.idle_timeout = atoi(value);
+      } else if (strncmp(sub_key, "xml_serv_port", 13) == 0) {
+        config->rh_vserver.xml_serv_port = atoi(value); 
+      } else if (strncmp(sub_key, "xml_serv_host", 13) == 0) {
+        if (config->rh_vserver.xml_serv_host != NULL)
+          free(config->rh_vserver.xml_serv_host);
+        config->rh_vserver.xml_serv_host = strdup(value); 
+      } else if (strncmp(sub_key, "xml_serv_url", 12) == 0) {
+        if (config->rh_vserver.xml_serv_url != NULL)
+          free(config->rh_vserver.xml_serv_url);
+        config->rh_vserver.xml_serv_url = strdup(value); 
+      }
+      break;
+  }
 
-int config_init(struct rahunas_config *config) {
+  
+  rh_free(&clone_key);
 
-  config_default(config);
+  return lcfg_status_ok;
+}
 
+int get_config(const char *cfg_file, union rahunas_config *config) {
   lcfg_visitor_function visitor_func = rahunas_visitor;
-  struct lcfg *c = lcfg_new(CONFIG_FILE);
+  struct lcfg *c = lcfg_new(cfg_file);
   
+  syslog(LOG_INFO, "Parsing config file: %s", cfg_file);
+
   if (lcfg_parse(c) != lcfg_status_ok) {
     syslog(LOG_ERR, "config error: %s", lcfg_error_get(c));
     lcfg_delete(c);
     return -1;
   }
 
+  syslog(LOG_INFO, "Processing config file: %s", cfg_file);
   if (lcfg_accept(c, visitor_func, config) != lcfg_status_ok) {
     syslog(LOG_ERR, "config error: %s", lcfg_error_get(c));
     lcfg_delete(c);
     return -1;
   }
 
-  if (c != NULL)
+  lcfg_delete(c);
+
+  return 0;
+}
+
+
+int get_value(const char *cfg_file, const char *key, void **data, size_t *len)
+{
+  lcfg_visitor_function visitor_func = rahunas_visitor;
+  struct lcfg *c = lcfg_new(cfg_file);
+  
+  if (lcfg_parse(c) != lcfg_status_ok) {
+    syslog(LOG_ERR, "config error: %s", lcfg_error_get(c));
+    lcfg_delete(c);
+    return -1;
+  }
+
+  if (lcfg_value_get(c, key, data, len) != lcfg_status_ok) {
     lcfg_delete(c);
+    return -1;
+  } 
+
+  lcfg_delete(c);
+
+  return 0;
+}
+
+int get_vservers_config(const char *conf_dir, struct main_server *server)
+{
+  DIR *dp;
+  struct dirent *dirp;
+  void *data = NULL;
+  size_t len;
+  char conf_file[200];
+
+  if ((dp = opendir(conf_dir)) == NULL)
+    return errno;
+  
+  while ((dirp = readdir(dp)) != NULL) {
+    if (strstr(dirp->d_name, ".conf") == NULL)
+      continue;
+
+    memset(conf_file, 0, sizeof(conf_file));
+
+    strncat(conf_file, conf_dir, sizeof(conf_file));
+    strncat(conf_file, "/", 1);
+    strncat(conf_file, dirp->d_name, sizeof(conf_file));
+
+    syslog(LOG_INFO, "Loading config file: %s", conf_file);
+    
+    register_vserver(server, conf_file);
+  }
+  
+  closedir(dp);
+  return 0;
+}
+
+
+int cleanup_vserver_config(struct rahunas_vserver_config *config)
+{
+  rh_free(&(config->vserver_name));  
+  rh_free(&(config->xml_serv_host));
+  rh_free(&(config->xml_serv_url));
+  return 0;
+}
 
+int cleanup_mainserver_config(struct rahunas_main_config *config)
+{
+  rh_free(&(config->conf_dir));  
+  rh_free(&(config->log_file));
   return 0;
 }
index 90ad9cd..99c7075 100644 (file)
@@ -7,30 +7,53 @@
 #define __RH_CONFIG_H 
 
 #include "../lcfg/lcfg_static.h"
+#include "rh-server.h"
 
 #define DEFAULT_LOG RAHUNAS_LOG_DIR "rahunas.log"
-#define IDLE_THRESHOLD 600
+#define VSERVER_ID 99
+#define IDLE_TIMEOUT 600
 #define POLLING 60 
-#define SET_NAME "rahunas_set"
+#define BANDWIDTH_SHAPE 0
+
 #define XMLSERVICE_HOST "localhost"
-#define XMLSERVICE_PORT 8888
+#define XMLSERVICE_PORT 80
 #define XMLSERVICE_URL  "/xmlrpc_service.php"
 
 #define CONFIG_FILE RAHUNAS_CONF_DIR "rahunas.conf"
 #define DEFAULT_PID RAHUNAS_RUN_DIR "rahunasd.pid"
 #define DB_NAME "rahunas"
 
-struct rahunas_config {
+struct rahunas_main_config {
+  char *conf_dir;
+  char *log_file;
   int  polling_interval;
-  int  idle_threshold;
+  int  bandwidth_shape;
+};
+
+struct rahunas_vserver_config {
+  int  vserver_id;
+  char *vserver_name;
+  int  idle_timeout;
   int  xml_serv_port;
   char *xml_serv_host;
   char *xml_serv_url;
-  char *set_name;
-  char *log_file;
 };
 
-int config_init(struct rahunas_config *config);
+union rahunas_config {
+  struct rahunas_main_config rh_main;
+  struct rahunas_vserver_config rh_vserver;
+};
+
+enum config_type {
+  MAIN,
+  VSERVER
+};
+
+int get_config(const char *cfg_file, union rahunas_config *config);
+int get_value(const char *cfg_file, const char *key, void **data, size_t *len);
+int get_vservers_config(const char *conf_dir, struct main_server *server);
+int cleanup_vserver_config(struct rahunas_vserver_config *config);
+int cleanup_mainserver_config(struct rahunas_main_config *config);
 enum lcfg_status rahunas_visitor(const char *key, void *data, size_t size, 
                                  void *user_data);
 #endif // __RH_CONFIG_H 
index 9475f00..a5ee646 100644 (file)
@@ -12,6 +12,8 @@
 #include "rh-ipset.h"
 #include "rh-utils.h"
 
+ip_set_id_t max_sets;
+
 int kernel_getsocket(void)
 {
   int sockfd = -1;
@@ -196,7 +198,7 @@ int set_adtip(struct set *rahunas_set, const char *adtip, const char *adtmac,
 }
 
 int set_adtip_nb(struct set *rahunas_set, ip_set_ip_t *adtip, 
-                     unsigned char adtmac[ETH_ALEN], unsigned op)
+                 unsigned char adtmac[ETH_ALEN], unsigned op)
 {
   struct ip_set_req_adt *req_adt = NULL;
   struct ip_set_req_rahunas req;
@@ -263,7 +265,7 @@ void set_flush(const char *name)
   kernel_sendto(&req, sizeof(struct ip_set_req_std));
 }
 
-size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
+size_t load_set_list(struct vserver *vs, const char name[IP_SET_MAXNAMELEN],
           ip_set_id_t *idx,
           unsigned op, unsigned cmd)
 {
@@ -281,15 +283,7 @@ size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
         name);
   
 tryagain:
-  if (set_list != NULL) {
-    for (i = 0; i < max_sets; i++)
-      if (set_list[i] != NULL) {
-        free(set_list[i]);
-        set_list[i] = NULL;
-      }
-    free(set_list);
-    set_list = NULL;
-  }
+
   /* Get max_sets */
   req_max_sets.op = IP_SET_OP_MAX_SETS;
   req_max_sets.version = IP_SET_PROTOCOL_VERSION;
@@ -300,14 +294,13 @@ tryagain:
   DP("got MAX_SETS: sets %d, max_sets %d",
      req_max_sets.sets, req_max_sets.max_sets);
 
-  max_sets = req_max_sets.max_sets;
-  set_list = rh_malloc(max_sets * sizeof(struct set *));
-  memset(set_list, 0, max_sets * sizeof(struct set *));
   *idx = req_max_sets.set.index;
+  max_sets = req_max_sets.max_sets;
 
-  if (req_max_sets.sets == 0)
+  if (req_max_sets.sets == 0) {
     /* No sets in kernel */
     return 0;
+  }
 
   /* Get setnames */
   size = req_size = sizeof(struct ip_set_req_setnames) 
@@ -328,27 +321,16 @@ tryagain:
          " the sets has gone down.", LIST_TRIES);
     return -1;
   }
-    
-  /* Load in setnames */
-  size = sizeof(struct ip_set_req_setnames);      
-  while (size + sizeof(struct ip_set_name_list) <= req_size) {
-    name_list = (struct ip_set_name_list *)
-      (data + size);
-    set = rh_malloc(sizeof(struct set));
-    strcpy(set->name, name_list->name);
-    set->index = name_list->index;
-    set->id = name_list->id;
-    set_list[name_list->index] = set;
-    size += sizeof(struct ip_set_name_list);
-  }
+
   /* Size to get set members, bindings */
   size = ((struct ip_set_req_setnames *)data)->size;
+
   rh_free(&data);
   
   return size;
 }
 
-int get_header_from_set (struct rahunas_map *map)
+int get_header_from_set (struct vserver *vs)
 {
   struct ip_set_req_rahunas_create *header = NULL;
   void *data = NULL;
@@ -359,13 +341,19 @@ int get_header_from_set (struct rahunas_map *map)
   in_addr_t first_ip;
   in_addr_t last_ip;
 
-  size = req_size = load_set_list(rh_config.set_name, &idx, 
+  if (vs == NULL)
+    return (-1);
+
+  size = req_size = load_set_list(vs, vs->vserver_config->vserver_name, &idx, 
                                   IP_SET_OP_LIST_SIZE, CMD_LIST); 
 
   DP("Get Set Size: %d", size);
   
   if (size) {
     data = rh_malloc(size);
+    if (data == NULL)
+      return (-1);
+
     ((struct ip_set_req_list *) data)->op = IP_SET_OP_LIST;
     ((struct ip_set_req_list *) data)->index = idx;
     res = kernel_getfrom_handleerrno(data, &size);
@@ -384,26 +372,33 @@ int get_header_from_set (struct rahunas_map *map)
   first_ip = htonl(header->from); 
   last_ip = htonl(header->to); 
   
-  memcpy(&map->first_ip, &first_ip, sizeof(in_addr_t));
-  memcpy(&map->last_ip, &last_ip, sizeof(in_addr_t));
-  map->size = ntohl(map->last_ip) - ntohl(map->first_ip) + 1;
-
-  logmsg(RH_LOG_NORMAL, "First IP: %s", ip_tostring(ntohl(map->first_ip)));
-  logmsg(RH_LOG_NORMAL, "Last  IP: %s", ip_tostring(ntohl(map->last_ip)));
-  logmsg(RH_LOG_NORMAL, "Set Size: %lu", map->size);
+  memcpy(&(vs->v_map->first_ip), &first_ip, sizeof(in_addr_t));
+  memcpy(&(vs->v_map->last_ip), &last_ip, sizeof(in_addr_t));
+  vs->v_map->size = ntohl(last_ip) - ntohl(first_ip) + 1;
+
+  logmsg(RH_LOG_NORMAL, "[%s] First IP: %s", 
+         vs->vserver_config->vserver_name,
+         ip_tostring(ntohl(vs->v_map->first_ip)));
+  logmsg(RH_LOG_NORMAL, "[%s] Last  IP: %s", 
+         vs->vserver_config->vserver_name,
+         ip_tostring(ntohl(vs->v_map->last_ip)));
+  logmsg(RH_LOG_NORMAL, "[%s] Set Size: %lu", 
+         vs->vserver_config->vserver_name,
+         vs->v_map->size);
 
   rh_free(&data);
   return res;
 }
 
-int walk_through_set (int (*callback)(void *))
+int walk_through_set (int (*callback)(void *), struct vserver *vs)
 {
+  struct processing_set process;
   void *data = NULL;
   ip_set_id_t idx;
   socklen_t size, req_size;
   int res = 0;
 
-  size = req_size = load_set_list(rh_config.set_name, &idx, 
+  size = req_size = load_set_list(vs, vs->vserver_config->vserver_name, &idx, 
                                   IP_SET_OP_LIST_SIZE, CMD_LIST); 
 
   DP("Get Set Size: %d", size);
@@ -422,8 +417,11 @@ int walk_through_set (int (*callback)(void *))
     size = 0;
   }
   
-  if (data != NULL)
-    (*callback)(data);
+  if (data != NULL) {
+    process.vs = vs;
+    process.list = data;
+    (*callback)(&process);
+  }
 
   rh_free(&data);
   return res;
index 9314573..05abe5e 100644 (file)
@@ -27,6 +27,12 @@ struct set {
   struct settype *settype;    /* Pointer to set type functions */
 };
 
+struct processing_set {
+  struct vserver *vs;
+  void *list;
+};
+
+
 enum rh_adt_result {
   RH_IS_IN_SET,
   RH_IS_NOT_IN_SET,
@@ -80,13 +86,13 @@ int set_adtip_nb(struct set *rahunas_set, ip_set_ip_t *adtip,
 
 void set_flush(const char *name);
 
-size_t load_set_list(const char name[IP_SET_MAXNAMELEN],
+size_t load_set_list(struct vserver *vs, const char name[IP_SET_MAXNAMELEN],
           ip_set_id_t *idx,
           unsigned op, unsigned cmd);
 
-int get_header_from_set (struct rahunas_map *map);
+int get_header_from_set (struct vserver *vs);
 
-int walk_through_set (int (*callback)(void *));
+int walk_through_set (int (*callback)(void *), struct vserver *vs);
 
 void parse_ip(const char *str, ip_set_ip_t *ip);
 void parse_mac(const char *mac, unsigned char *ethernet);
diff --git a/src/rh-server.c b/src/rh-server.c
new file mode 100644 (file)
index 0000000..484fd02
--- /dev/null
@@ -0,0 +1,167 @@
+/**
+ * RahuNAS server
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2009-03-24
+ */
+#include <stdio.h>
+#include "rahunasd.h"
+#include "rh-server.h"
+#include "rh-utils.h"
+
+int vserver_exists(GList *vserver_list, int vserver_id, 
+                   const char *vserver_name)
+{
+  GList *runner = g_list_first(vserver_list);
+  struct vserver *lvserver = NULL;
+
+  while (runner != NULL) {
+    lvserver = (struct vserver *)runner->data;
+   
+    if (lvserver->vserver_config->vserver_id == vserver_id)
+      return 1; 
+
+    if (strcmp(lvserver->vserver_config->vserver_name, vserver_name) == 0)
+      return 2;
+
+    runner = g_list_next(runner); 
+  } 
+  return 0;
+}
+
+struct vserver *vserver_get_by_id(struct main_server *ms, int search_id)
+{
+  GList *runner = g_list_first(ms->vserver_list);
+  struct vserver *lvserver = NULL;
+
+  while (runner != NULL) {
+    lvserver = (struct vserver *)runner->data;
+   
+    if (lvserver->vserver_config->vserver_id == search_id) {
+      return lvserver;
+    }
+
+    runner = g_list_next(runner); 
+  } 
+  return NULL;
+}
+
+int vserver_cleanup(struct vserver *vs)
+{
+  if (vs == NULL)
+    return 0;
+
+  if (vs->vserver_config != NULL)
+    cleanup_vserver_config(vs->vserver_config);  
+
+  if (vs->v_map != NULL)
+    // TODO: cleanup map
+
+  if (vs->v_set != NULL)
+    // TODO: cleanup set
+
+  return 0;
+}
+
+int mainserver_cleanup(struct main_server *ms)
+{
+  if (ms == NULL)
+    return 0;
+
+  if (ms->main_config != NULL)
+    cleanup_mainserver_config(ms->main_config);  
+
+  return 0;
+}
+
+int register_vserver(struct main_server *ms, const char *vserver_cfg_file)
+{
+  GList *vserver_list = ms->vserver_list;
+  GList *chk = NULL;
+  GList *node = NULL;
+  FILE  *cfg_file = NULL;
+  
+  union rahunas_config *cfg_get = NULL;
+  struct rahunas_vserver_config *vserver_config = NULL;
+  struct vserver *new_vserver = NULL;
+
+  union rahunas_config config = {
+    .rh_vserver.vserver_id = VSERVER_ID,
+    .rh_vserver.vserver_name = NULL,
+    .rh_vserver.idle_timeout = IDLE_TIMEOUT,
+    .rh_vserver.xml_serv_port = XMLSERVICE_PORT,
+    .rh_vserver.xml_serv_host = strdup(XMLSERVICE_HOST),
+    .rh_vserver.xml_serv_url = strdup(XMLSERVICE_URL),
+  };
+
+  cfg_file = fopen(vserver_cfg_file, "r");
+  if (cfg_file == NULL)
+    return -1;
+
+  vserver_config = (struct rahunas_vserver_config *) rh_malloc(sizeof(struct rahunas_vserver_config));
+
+  if (vserver_config == NULL)
+    return -1;
+
+  memset(vserver_config, 0, sizeof(struct rahunas_vserver_config));
+
+  if (get_config(vserver_cfg_file, &config) != 0) {
+    rh_free(&config.rh_vserver.xml_serv_host);
+    rh_free(&config.rh_vserver.xml_serv_url);
+    return -1;
+  }
+
+  memcpy(vserver_config, &config, sizeof(struct rahunas_vserver_config));
+
+  if (vserver_exists(vserver_list, vserver_config->vserver_id, 
+                     vserver_config->vserver_name)) {
+    return 1;
+  }
+
+  new_vserver = (struct vserver *) rh_malloc(sizeof(struct vserver));
+
+  if (new_vserver == NULL)
+    return -1;
+
+  memset(new_vserver, 0, sizeof(struct vserver));
+
+  new_vserver->vserver_config = vserver_config;
+
+  ms->vserver_list = g_list_append(ms->vserver_list, new_vserver);
+  return 0; 
+}
+
+int unregister_vserver(struct main_server *ms, int vserver_id)
+{
+}
+
+int unregister_vserver_all(struct main_server *ms)
+{
+  GList *vserver_list = ms->vserver_list;
+  GList *runner = g_list_first(vserver_list);
+  struct vserver *lvserver = NULL;
+
+  while (runner != NULL) {
+    lvserver = (struct vserver *)runner->data;
+    vserver_cleanup(lvserver);
+    runner = g_list_delete_link(runner, runner);
+  }
+  
+  return 0;
+}
+
+int walk_through_vserver(int (*callback)(void *, void *), struct main_server *ms)
+{
+  GList *vserver_list = ms->vserver_list;
+  GList *runner = g_list_first(vserver_list);
+  struct vserver *vs = NULL;
+
+  while (runner != NULL) {
+    vs = (struct vserver *)runner->data;
+
+    (*callback)(ms, vs);
+
+    runner = g_list_next(runner); 
+  } 
+
+  return 0;
+}
diff --git a/src/rh-server.h b/src/rh-server.h
new file mode 100644 (file)
index 0000000..be825c9
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * RahuNAS server 
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2009-03-24
+ */
+#ifndef __RH_SERVER_H
+#define __RH_SERVER_H
+
+#include <glib.h>
+#include "rh-config.h"
+
+struct vserver {
+  struct rahunas_vserver_config *vserver_config;
+  struct rahunas_map *v_map;
+  struct set *v_set;
+};
+
+struct main_server {
+  struct rahunas_main_config *main_config;
+  GList *vserver_list;
+  GList *task_list;
+  int log_fd;
+};
+
+int vserver_exists(GList *vserver_list, int vserver_id, 
+                   const char *vserver_name);
+struct vserver *vserver_get_by_id(struct main_server *ms, int search_id);
+int vserver_cleanup(struct vserver *vs);
+int mainserver_cleanup(struct main_server *ms);
+int walk_through_vserver(int (*callback)(void *, void *), struct main_server *ms);
+int register_vserver(struct main_server *ms, const char *vserver_cfg_file);
+int unregister_vserver(struct main_server *ms, int vserver_id);
+int unregister_vserver_all(struct main_server *ms);
+
+
+#endif // __RH_SERVER_H
index b24d0ec..0744f3f 100644 (file)
 
 #include "rahunasd.h"
 #include "rh-task.h"
+#include "rh-task-bandwidth.h"
+#include "rh-task-memset.h"
+#include "rh-utils.h"
 
 
-/* MAX_SLOT_PAGE is calculated from the formula of
-   MAX_SLOT_PAGE = ceil(MAX_SLOT_ID/PAGE_SIZE)
-
-   where
-     PAGE_SIZE = sizeof(short) * 8
-*/
-
-#define MAX_SLOT_ID    9900
-#define PAGE_SIZE      16
-#define MAX_SLOT_PAGE  619
 
 #define BANDWIDTH_WRAPPER "/etc/rahunas/bandwidth.sh"
 
 static unsigned short slot_flags[MAX_SLOT_PAGE] = {1};
 static unsigned short slot_count = 0;
-
-struct bandwidth_req {
-  char slot_id[5];
-  char ip[16];
-  char bandwidth_max_down[15];
-  char bandwidth_max_up[15];
-};
+static int bw_service = 0;
 
 unsigned short _get_slot_id()
 {
@@ -72,7 +59,7 @@ unsigned short _get_slot_id()
   return slot_id;
 }
 
-void _mark_reserved_slot_id(unsigned int slot_id)
+void mark_reserved_slot_id(unsigned int slot_id)
 {
   unsigned short page       = 0;
   unsigned char  id_on_page = 0;
@@ -84,7 +71,7 @@ void _mark_reserved_slot_id(unsigned int slot_id)
   slot_flags[page] |= 1 << id_on_page;
 }
 
-int _bandwidth_exec(char *const args[])
+int bandwidth_exec(struct vserver *vs, char *const args[])
 {
   pid_t ws;
   pid_t pid;
@@ -93,6 +80,7 @@ int _bandwidth_exec(char *const args[])
   char buffer[150];
   char *endline = NULL;
   int ret = 0;
+  int fd = 0;
   
   memset(buffer, '\0', sizeof(buffer));
 
@@ -100,6 +88,7 @@ int _bandwidth_exec(char *const args[])
     logmsg(RH_LOG_ERROR, "Error: pipe()");
     return -1;
   }
+  DP("pipe0=%d,pipe1=%d", exec_pipe[0], exec_pipe[1]);
 
   pid = vfork();
   dup2(exec_pipe[1], STDOUT_FILENO);
@@ -107,7 +96,6 @@ int _bandwidth_exec(char *const args[])
   if (pid == 0) {
     // Child
     execv(BANDWIDTH_WRAPPER, args);
-
   } else if (pid < 0) {
     // Fork error
     logmsg(RH_LOG_ERROR, "Error: vfork()"); 
@@ -119,13 +107,21 @@ int _bandwidth_exec(char *const args[])
     DP("Bandwidth: Return (%d)", WEXITSTATUS(status));
 
     // Return message log
+    DP("Read message");
     read(exec_pipe[0], buffer, sizeof(buffer));
+
     if (buffer != NULL) {
+      DP("Got message: %s", buffer);
       endline = strstr(buffer, "\n");
       if (endline != NULL) 
         *endline = '\0';
 
-      logmsg(RH_LOG_NORMAL, "Bandwidth: %s", buffer);
+      if (vs != NULL) {
+        logmsg(RH_LOG_NORMAL, "[%s] Bandwidth: %s", 
+          vs->vserver_config->vserver_name, buffer);
+      } else {
+        logmsg(RH_LOG_NORMAL, "[main server] Bandwidth: %s", buffer);
+      }
     }
 
     if (WIFEXITED(status)) {
@@ -140,7 +136,7 @@ int _bandwidth_exec(char *const args[])
   return ret;
 }
 
-int _bandwidth_start()
+int bandwidth_start()
 {
   char *args[3];
 
@@ -150,10 +146,10 @@ int _bandwidth_start()
   args[1] = "start";
   args[2] = (char *) 0;
 
-  return _bandwidth_exec(args);
+  return bandwidth_exec(NULL, args);
 }
 
-int _bandwidth_stop()
+int bandwidth_stop()
 {
   char *args[3];
 
@@ -163,10 +159,10 @@ int _bandwidth_stop()
   args[1] = "stop";
   args[2] = (char *) 0;
 
-  return _bandwidth_exec(args);
+  return bandwidth_exec(NULL, args);
 }
 
-int _bandwidth_add(struct bandwidth_req *bw_req)
+int bandwidth_add(struct vserver *vs, struct bandwidth_req *bw_req)
 {
   char *args[7];
 
@@ -181,10 +177,10 @@ int _bandwidth_add(struct bandwidth_req *bw_req)
   args[5] = bw_req->bandwidth_max_up;
   args[6] = (char *) 0;
 
-  return _bandwidth_exec(args);
+  return bandwidth_exec(vs, args);
 }
 
-int _bandwidth_del(struct bandwidth_req *bw_req)
+int bandwidth_del(struct vserver *vs, struct bandwidth_req *bw_req)
 {
   char *args[4];
 
@@ -195,88 +191,113 @@ int _bandwidth_del(struct bandwidth_req *bw_req)
   args[2] = bw_req->slot_id;
   args[3] = (char *) 0;
 
-  return _bandwidth_exec(args);
+  return bandwidth_exec(vs, args);
 }
 
 /* Initialize */
-static void init (void)
+static void init (struct vserver *vs)
 {
-  logmsg(RH_LOG_NORMAL, "Task BANDWIDTH init..");  
+  logmsg(RH_LOG_NORMAL, "[%s] Task BANDWIDTH init..", 
+         vs->vserver_config->vserver_name);  
 }
 
 /* Cleanup */
-static void cleanup (void)
+static int cleanup (struct vserver *vs)
 {
-  logmsg(RH_LOG_NORMAL, "Task BANDWIDTH cleanup..");  
+  logmsg(RH_LOG_NORMAL, "[%s] Task BANDWIDTH cleanup..",
+         vs->vserver_config->vserver_name);  
 }
 
 /* Start service task */
-static int startservice (struct rahunas_map *map)
+static int startservice (struct vserver *vs)
 {
-  return _bandwidth_start();
+  if (!(bw_service++))
+    return bandwidth_start();
+
+  return 0;
 }
 
 /* Stop service task */
-static int stopservice  (struct rahunas_map *map)
+static int stopservice  (struct vserver *vs)
 {
-  return _bandwidth_stop();
+  if ((--bw_service) == 0)
+    return bandwidth_stop();
+  
+  return 0;
 }
 
 /* Start session task */
-static int startsess (struct rahunas_map *map, struct task_req *req)
+static int startsess (struct vserver *vs, struct task_req *req)
 {
   struct bandwidth_req bw_req;
   unsigned short slot_id;
   unsigned char max_try = 3;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
+
+  member_node = member_get_node_by_id(vs, req->id);
+  if (member_node == NULL)
+    return (-1);
+
+  member = (struct rahunas_member *) member_node->data;
 
-  if (map->members[req->id].bandwidth_max_down == 0 && 
-      map->members[req->id].bandwidth_max_up == 0)
+  if (member->bandwidth_max_down == 0 && member->bandwidth_max_up == 0)
     return 0;
 
-  if (map->members[req->id].bandwidth_slot_id > 0)
+  if (member->bandwidth_slot_id > 0)
     return 0;
   
   // Formating the bandwidth request
-  sprintf(bw_req.ip, "%s", idtoip(map, req->id));
+  sprintf(bw_req.ip, "%s", idtoip(vs->v_map, req->id));
   sprintf(bw_req.bandwidth_max_down, "%lu", 
-    map->members[req->id].bandwidth_max_down);
+    member->bandwidth_max_down);
   sprintf(bw_req.bandwidth_max_up, "%lu", 
-    map->members[req->id].bandwidth_max_up);
+    member->bandwidth_max_up);
   
   while (max_try > 0) { 
     slot_id = _get_slot_id();
     sprintf(bw_req.slot_id, "%d", slot_id);
-
-    if (_bandwidth_add(&bw_req) == 0)
+    if (bandwidth_add(vs, &bw_req) == 0)
       break;
     else
       max_try--;
   }
 
+
   if (max_try == 0) {
-    logmsg(RH_LOG_ERROR, "Bandwidth: Maximum trying, failed!");
+    logmsg(RH_LOG_ERROR, "[%s] Bandwidth: Maximum trying, failed!",
+           vs->vserver_config->vserver_name);
     return -1;
   }
 
-  _mark_reserved_slot_id(slot_id);
-  map->members[req->id].bandwidth_slot_id = slot_id;
+  mark_reserved_slot_id(slot_id);
+  member->bandwidth_slot_id = slot_id;
  
   return 0;
 }
 
 /* Stop session task */
-static int stopsess  (struct rahunas_map *map, struct task_req *req)
+static int stopsess  (struct vserver *vs, struct task_req *req)
 {
   struct bandwidth_req bw_req;
-  unsigned short slot_id = map->members[req->id].bandwidth_slot_id;
+  unsigned short slot_id = 0;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
+  
+  member_node = member_get_node_by_id(vs, req->id);
+  if (member_node == NULL)
+    return (-1); 
+  
+  member = (struct rahunas_member *) member_node->data;
+  slot_id = member->bandwidth_slot_id;
 
   if (slot_id < 1)
     return 0;
 
   sprintf(bw_req.slot_id, "%d", slot_id);
 
-  if (_bandwidth_del(&bw_req) == 0) {
-    map->members[req->id].bandwidth_slot_id = 0;
+  if (bandwidth_del(vs, &bw_req) == 0) {
+    member->bandwidth_slot_id = 0;
 
     if (slot_count > 0)
       slot_count--;
@@ -288,30 +309,30 @@ static int stopsess  (struct rahunas_map *map, struct task_req *req)
 }
 
 /* Commit start session task */
-static int commitstartsess (struct rahunas_map *map, struct task_req *req)
+static int commitstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Commit stop session task */
-static int commitstopsess  (struct rahunas_map *map, struct task_req *req)
+static int commitstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback start session task */
-static int rollbackstartsess (struct rahunas_map *map, struct task_req *req)
+static int rollbackstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback stop session task */
-static int rollbackstopsess  (struct rahunas_map *map, struct task_req *req)
+static int rollbackstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
-static struct task task_bandwidth = {
+static struct task taskbandwidth = {
   .taskname = "BANDWIDTH",
   .taskprio = 20,
   .init = &init,
@@ -326,6 +347,6 @@ static struct task task_bandwidth = {
   .rollbackstopsess = &rollbackstopsess,
 };
 
-void rh_task_bandwidth_reg(void) {
-  task_register(&task_bandwidth);
+void rh_task_bandwidth_reg(struct main_server *ms) {
+  task_register(ms, &taskbandwidth);
 }
index 47bd9d7..4a73f0a 100644 (file)
@@ -6,6 +6,27 @@
 #ifndef __RH_TASK_BANDWIDTH_H
 #define __RH_TASK_BANDWIDTH_H
 
-extern void rh_task_bandwidth_reg(void);
+/* MAX_SLOT_PAGE is calculated from the formula of
+   MAX_SLOT_PAGE = ceil(MAX_SLOT_ID/PAGE_SIZE)
 
+   where
+     PAGE_SIZE = sizeof(short) * 8
+*/
+
+#define MAX_SLOT_ID    9900
+#define PAGE_SIZE      16
+#define MAX_SLOT_PAGE  619
+
+extern void rh_task_bandwidth_reg(struct main_server *ms);
+
+struct bandwidth_req {
+  char slot_id[5];
+  char ip[16];
+  char bandwidth_max_down[15];
+  char bandwidth_max_up[15];
+};
+
+int bandwidth_add(struct vserver *vs, struct bandwidth_req *bw_req);
+int bandwidth_exec(struct vserver *vs, char *const args[]);
+void mark_reserved_slot_id(unsigned int slot_id);
 #endif // __RH_TASK_BANDWIDTH_H
index 59b5cc8..6445045 100644 (file)
 #include "rahunasd.h"
 #include "rh-task.h"
 #include "rh-ipset.h"
+#include "rh-utils.h"
+#include "rh-task-memset.h"
+#include "rh-task-bandwidth.h"
 
 struct dbset_row {
   gchar *session_id;
+  gchar *vserver_id;
   gchar *username;
   gchar *ip;
   gchar *mac;
@@ -25,6 +29,8 @@ struct dbset_row {
   long bandwidth_max_up;
 };
 
+static db_init = 0;
+
 gboolean get_errors (GdaConnection * connection)
 {
   GList *list;
@@ -76,6 +82,8 @@ gboolean *parse_dm_to_struct(GList **data_list, GdaDataModel *dm) {
                
       if (strncmp("session_id", title, 10) == 0) {
         row->session_id = g_strdup(str);
+      } else if (strncmp("vserver_id", title, 10) == 0) {
+        row->vserver_id = g_strdup(str);
       } else if (strncmp("username", title, 8) == 0) {
         row->username = g_strdup(str);
       } else if (strncmp("ip", title, 2) == 0) {
@@ -183,6 +191,7 @@ void free_data_list(GList *data_list)
          node = g_list_next (node)) {
     row = (struct dbset_row *) node->data;
     g_free(row->session_id);
+    g_free(row->vserver_id);
     g_free(row->username);
     g_free(row->ip);
     g_free(row->mac);
@@ -191,94 +200,144 @@ void free_data_list(GList *data_list)
   g_list_free (data_list);  
 }
 
-gboolean restore_set(GList **data_list, struct rahunas_map *map)
+gboolean restore_set(GList **data_list, struct vserver *vs)
 {
-  GList *node;
-  struct rahunas_member *members = NULL;
+  GList *node = NULL;
   struct dbset_row *row = NULL;
   uint32_t id;
-
-  if (!map)
-    return FALSE;
-
-  members = map->members;
-
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
+  struct bandwidth_req bw_req;
+  unsigned char max_try = 3;
   node = g_list_first(*data_list);
 
   if (node == NULL)
     return TRUE;
 
+  DP("Get data from DB if exist");
+
   for (node; node != NULL; node = g_list_next(node)) {
     row = (struct dbset_row *) node->data;
 
-    id = iptoid(map, row->ip);
+    if (atoi(row->vserver_id) != vs->vserver_config->vserver_id)
+      continue;
+
+    id = iptoid(vs->v_map, row->ip);
+
+    DP("id=%d", id);
     
     if (id < 0)
       continue;
 
+    member_node = member_get_node_by_id(vs, id);
+
+    if (member_node == NULL) {
+      DP("Create new member");
+      member = (struct rahunas_member *) rh_malloc(sizeof(struct rahunas_member));
+      if (member == NULL)
+        continue; 
+      
+      memset(member, 0, sizeof(struct rahunas_member));
+      vs->v_map->members =
+        g_list_insert_sorted(vs->v_map->members, member, idcmp);
+    } else {
+      DP("Member already exists");
+      member = (struct rahunas_member *) member_node->data;
+    }
+
     // MEMSET
-    members[id].session_id = g_strdup(row->session_id);
-    members[id].username   = g_strdup(row->username);
-    parse_mac(row->mac, &members[id].mac_address); 
-    memcpy(&row->session_start, &members[id].session_start, sizeof(time_t));
-    memcpy(&row->session_timeout, &members[id].session_timeout, sizeof(time_t));
-    members[id].bandwidth_slot_id = row->bandwidth_slot_id;
-    members[id].bandwidth_max_down = row->bandwidth_max_down;
-    members[id].bandwidth_max_up = row->bandwidth_max_up;
+    member->id = id;
+    member->session_id = g_strdup(row->session_id);
+    member->username   = g_strdup(row->username);
+    parse_mac(row->mac, &member->mac_address); 
+    memcpy(&member->session_start, &row->session_start, 
+           sizeof(time_t));
+    memcpy(&member->session_timeout, &row->session_timeout, 
+           sizeof(time_t));
+    member->bandwidth_slot_id = row->bandwidth_slot_id;
+    member->bandwidth_max_down = row->bandwidth_max_down;
+    member->bandwidth_max_up = row->bandwidth_max_up;
 
     // IPSET
-    set_adtip(rahunas_set, row->ip, row->mac, IP_SET_OP_ADD_IP);
+    DP("Restore, ip=%s, mac=%s", row->ip, row->mac);
+    set_adtip(vs->v_set, row->ip, row->mac, IP_SET_OP_ADD_IP);
+
+
+    // Bandwidth
+    sprintf(bw_req.ip, "%s", row->ip);
+    sprintf(bw_req.bandwidth_max_down, "%lu", row->bandwidth_max_down);
+    sprintf(bw_req.bandwidth_max_up, "%lu", row->bandwidth_max_up);
+    sprintf(bw_req.slot_id, "%u", row->bandwidth_slot_id); 
+
+    mark_reserved_slot_id(row->bandwidth_slot_id);
+
+    while (max_try-- > 0) { 
+      if (bandwidth_add(vs, &bw_req) == 0)
+        break;
+    }
   }
   return TRUE;
 }
 
 /* Initialize */
-static void init (void)
+static void init (struct vserver *vs)
 {
   char ds_name[] = PROGRAM;
   char ds_provider[] = "SQLite";
   char ds_cnc_string[] = "DB_DIR=" RAHUNAS_CONF_DIR ";DB_NAME=" DB_NAME; 
   char ds_desc[] = "RahuNAS DB Set";
 
-  logmsg(RH_LOG_NORMAL, "Task DBSET init..");  
-
-  gda_init(PROGRAM, RAHUNAS_VERSION, NULL, NULL);
-
-  gda_config_save_data_source(ds_name, ds_provider, ds_cnc_string, ds_desc,
-                              NULL, NULL, FALSE);
-  list_datasource();
+  if (!(db_init++)) {
+    logmsg(RH_LOG_NORMAL, "Task DBSET init..");
+    
+    gda_init(ds_name, RAHUNAS_VERSION, NULL, NULL);
+    
+    gda_config_save_data_source(ds_name, ds_provider, 
+                                ds_cnc_string, ds_desc,
+                                NULL, NULL, FALSE);
+   
+    list_datasource();
+  }
 }
 
 /* Cleanup */
-static void cleanup (void)
+static void cleanup (struct vserver *vs)
 {
-  char ds_name[] = PROGRAM;
-
-  logmsg(RH_LOG_NORMAL, "Task DBSET cleanup..");  
+  if ((--db_init) == 0) {
+    logmsg(RH_LOG_NORMAL, "Task DBSET cleanup..");  
   
-  gda_config_remove_data_source (ds_name);
+    gda_config_remove_data_source (PROGRAM);
+  }
 }
 
 
 /* Start service task */
-static int startservice (struct rahunas_map *map)
+static int startservice (struct vserver *vs)
 {
   GdaClient *client;
   GdaConnection *connection;
   GList *data_list;
   GList *node;
   struct dbset_row *row;
+  char select_cmd[256];
 
-  logmsg(RH_LOG_NORMAL, "Task DBSET start..");  
+  logmsg(RH_LOG_NORMAL, "[%s] Task DBSET start..",
+         vs->vserver_config->vserver_name);  
 
   client = gda_client_new ();
-  connection = gda_client_open_connection (client, PROGRAM, NULL, NULL,
+  connection = gda_client_open_connection (client, 
+                 PROGRAM, NULL, NULL,
                  GDA_CONNECTION_OPTIONS_READ_ONLY, NULL);
 
-  data_list = execute_sql_command(connection, "SELECT * FROM dbset");
+  sprintf(select_cmd, "SELECT * FROM dbset WHERE vserver_id='%d'",
+          vs->vserver_config->vserver_id);
+
+  DP("SQL: %s", select_cmd);
+
+  data_list = execute_sql_command(connection, select_cmd); 
 
-  restore_set(&data_list, map);
+  restore_set(&data_list, vs);
 
   free_data_list(data_list);
 
@@ -290,14 +349,15 @@ static int startservice (struct rahunas_map *map)
 }
 
 /* Stop service task */
-static int stopservice  (struct rahunas_map *map)
+static int stopservice  (struct vserver *vs)
 {
   /* Do nothing or need to implement */
-  logmsg(RH_LOG_NORMAL, "Task DBSET stop..");  
+  logmsg(RH_LOG_NORMAL, "[%s] Task DBSET stop..",
+         vs->vserver_config->vserver_name);  
 }
 
 /* Start session task */
-static int startsess (struct rahunas_map *map, struct task_req *req)
+static int startsess (struct vserver *vs, struct task_req *req)
 {
   GdaClient *client;
   GdaConnection *connection;
@@ -305,22 +365,38 @@ static int startsess (struct rahunas_map *map, struct task_req *req)
   char startsess_cmd[256];
   char time_str[32];
   char time_str2[32];
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
 
   client = gda_client_new ();
-  connection = gda_client_open_connection (client, PROGRAM, NULL, NULL,
+  connection = gda_client_open_connection (client, 
+                 PROGRAM, NULL, NULL,
                  GDA_CONNECTION_OPTIONS_NONE, NULL);
   
   strftime(&time_str, sizeof time_str, "%s", localtime(&req->session_start));
   strftime(&time_str2, sizeof time_str2, "%s", 
     localtime(&req->session_timeout));
 
+  member_node = member_get_node_by_id(vs, req->id);
+  if (member_node == NULL)
+    return (-1);
+
+  member = (struct rahunas_member *) member_node->data;
+
   sprintf(startsess_cmd, "INSERT INTO dbset"
-         "(session_id,username,ip,mac,session_start,session_timeout,"
-         "bandwidth_slot_id,bandwidth_max_down,bandwidth_max_up) "
-         "VALUES('%s','%s','%s','%s',%s,%s,%u,%lu,%lu)",
-         req->session_id, req->username, idtoip(map, req->id), 
-         mac_tostring(req->mac_address), time_str, time_str2,
-         map->members[req->id].bandwidth_slot_id, req->bandwidth_max_down,
+         "(session_id,vserver_id,username,ip,mac,session_start,"
+         "session_timeout,bandwidth_slot_id,bandwidth_max_down,"
+         "bandwidth_max_up) "
+         "VALUES('%s','%d','%s','%s','%s',%s,%s,%u,%lu,%lu)",
+         req->session_id, 
+         vs->vserver_config->vserver_id, 
+         req->username, 
+         idtoip(vs->v_map, req->id), 
+         mac_tostring(req->mac_address), 
+         time_str, 
+         time_str2,
+         member->bandwidth_slot_id, 
+         req->bandwidth_max_down,
          req->bandwidth_max_up);
 
   DP("SQL: %s", startsess_cmd);
@@ -335,24 +411,34 @@ static int startsess (struct rahunas_map *map, struct task_req *req)
 }
 
 /* Stop session task */
-static int stopsess (struct rahunas_map *map, struct task_req *req)
+static int stopsess (struct vserver *vs, struct task_req *req)
 {
   GdaClient *client;
   GdaConnection *connection;
   gint res;
   char stopsess_cmd[256];
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
+
+  member_node = member_get_node_by_id(vs, req->id);
+  if (member_node == NULL)
+    return (-1);
+
+  member = (struct rahunas_member *) member_node->data;
 
   client = gda_client_new ();
-  connection = gda_client_open_connection (client, PROGRAM, NULL, NULL,
+  connection = gda_client_open_connection (client, 
+                 PROGRAM, NULL, NULL,
                  GDA_CONNECTION_OPTIONS_NONE, NULL);
 
-  DP("Username  : %s", map->members[req->id].username);
-  DP("SessionID : %s", map->members[req->id].session_id);
+  DP("Username  : %s", member->username);
+  DP("SessionID : %s", member->session_id);
 
   sprintf(stopsess_cmd, "DELETE FROM dbset WHERE "
-         "session_id='%s' AND username='%s'",
-         map->members[req->id].session_id, 
-         map->members[req->id].username);
+         "session_id='%s' AND username='%s' AND vserver_id='%d'",
+         member->session_id, 
+         member->username,
+         vs->vserver_config->vserver_id);
 
   DP("SQL: %s", stopsess_cmd);
 
@@ -366,25 +452,25 @@ static int stopsess (struct rahunas_map *map, struct task_req *req)
 }
 
 /* Commit start session task */
-static int commitstartsess (struct rahunas_map *map, struct task_req *req)
+static int commitstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Commit stop session task */
-static int commitstopsess  (struct rahunas_map *map, struct task_req *req)
+static int commitstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback start session task */
-static int rollbackstartsess (struct rahunas_map *map, struct task_req *req)
+static int rollbackstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback stop session task */
-static int rollbackstopsess  (struct rahunas_map *map, struct task_req *req)
+static int rollbackstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
@@ -404,6 +490,6 @@ static struct task task_dbset = {
   .rollbackstopsess = &rollbackstopsess,
 };
 
-void rh_task_dbset_reg(void) {
-  task_register(&task_dbset);
+void rh_task_dbset_reg(struct main_server *ms) {
+  task_register(ms, &task_dbset);
 }
index 3063002..c0de20a 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __RH_TASK_DBSET_H
 #define __RH_TASK_DBSET_H
 
-extern void rh_task_dbset_reg(void);
+extern void rh_task_dbset_reg(struct main_server *ms);
 
 #endif // __RH_TASK_MEMSET_H
 
index cb32f6b..32a6663 100644 (file)
 
 size_t nas_stopservice(void *data)
 {
-  struct ip_set_list *setlist = (struct ip_set_list *) data;
-  struct set *set = set_list[setlist->index];
+  struct processing_set *process = (struct processing_set *) data;
+  struct ip_set_list *setlist = (struct ip_set_list *) process->list;
   size_t offset;
   struct ip_set_rahunas *table = NULL;
-  struct rahunas_member *members = map->members;
   struct task_req req;
-  unsigned int i;
+  unsigned int id;
   char *ip = NULL;
   int res  = 0;
+  GList *runner = g_list_first(process->vs->v_map->members);
+  struct rahunas_member *member = NULL;
+
+  if (process == NULL)
+    return (-1);
 
   offset = sizeof(struct ip_set_list) + setlist->header_size;
-  table = (struct ip_set_rahunas *)(data + offset);
-
-  DP("Map size %d", map->size);
-  for (i = 0; i < map->size; i++) {
-    if (test_bit(IPSET_RAHUNAS_ISSET, (void *)&table[i].flags)) {
-      DP("Found IP: %s in set, try logout", idtoip(map, i));
-      req.id = i;
-      memcpy(req.mac_address, &table[i].ethernet, ETH_ALEN);
-      req.req_opt = RH_RADIUS_TERM_NAS_REBOOT;
-      send_xmlrpc_stopacct(map, i, RH_RADIUS_TERM_NAS_REBOOT);
-      rh_task_stopsess(map, &req);
-    }
+  table = (struct ip_set_rahunas *)(process->list + offset);
+
+  while (runner != NULL) {
+    member = (struct rahunas_member *) runner->data;
+    id = member->id;
+
+    DP("Found IP: %s in set, try logout", idtoip(process->vs->v_map, id));
+    req.id = id;
+    memcpy(req.mac_address, &table[id].ethernet, ETH_ALEN);
+    req.req_opt = RH_RADIUS_TERM_NAS_REBOOT;
+    send_xmlrpc_stopacct(process->vs, id, RH_RADIUS_TERM_NAS_REBOOT);
+    rh_task_stopsess(process->vs, &req);
+
+    runner = g_list_next(runner);
   }
 }
 
 /* Initialize */
-static void init (void)
+static void init (struct vserver *vs)
 {
-  logmsg(RH_LOG_NORMAL, "Task IPSET init..");  
-
-  rahunas_set = set_adt_get(rh_config.set_name);
+  vs->v_set = set_adt_get(vs->vserver_config->vserver_name);
+  logmsg(RH_LOG_NORMAL, "[%s] Task IPSET init..",
+         vs->vserver_config->vserver_name);  
 
-  DP("getsetname: %s", rahunas_set->name);
-  DP("getsetid: %d", rahunas_set->id);
-  DP("getsetindex: %d", rahunas_set->index);
+  DP("getsetname: %s", vs->v_set->name);
+  DP("getsetid: %d", vs->v_set->id);
+  DP("getsetindex: %d", vs->v_set->index);
 }
 
 /* Cleanup */
-static void cleanup (void)
+static void cleanup (struct vserver *vs)
 {
-  logmsg(RH_LOG_NORMAL, "Task IPSET cleanup..");  
-  set_flush(rh_config.set_name);
+  logmsg(RH_LOG_NORMAL, "[%s] Task IPSET cleanup..",
+         vs->vserver_config->vserver_name);  
+  set_flush(vs->vserver_config->vserver_name);
 
-  rh_free(&rahunas_set);
+  rh_free(&(vs->v_set));
 }
 
 /* Start service task */
-static int startservice (struct rahunas_map *map)
+static int startservice (struct vserver *vs)
 {
   /* Ensure the set is empty */
-  set_flush(rh_config.set_name);
+  set_flush(vs->vserver_config->vserver_name);
 }
 
 /* Stop service task */
-static int stopservice  (struct rahunas_map *map)
+static int stopservice  (struct vserver *vs)
 {
-  logmsg(RH_LOG_NORMAL, "Task IPSET stop..");  
-  walk_through_set(&nas_stopservice);
+  logmsg(RH_LOG_NORMAL, "[%s] Task IPSET stop..",
+         vs->vserver_config->vserver_name);  
+  walk_through_set(&nas_stopservice, vs);
 
   return 0;
 }
 
 /* Start session task */
-static int startsess (struct rahunas_map *map, struct task_req *req)
+static int startsess (struct vserver *vs, struct task_req *req)
 {
   int res = 0;
   ip_set_ip_t ip;
-  parse_ip(idtoip(map, req->id), &ip);
+  parse_ip(idtoip(vs->v_map, req->id), &ip);
 
-  res = set_adtip_nb(rahunas_set, &ip, req->mac_address, IP_SET_OP_ADD_IP);
+  res = set_adtip_nb(vs->v_set, &ip, req->mac_address, IP_SET_OP_ADD_IP);
 
   return res;
 }
 
 /* Stop session task */
-static int stopsess  (struct rahunas_map *map, struct task_req *req)
+static int stopsess  (struct vserver *vs, struct task_req *req)
 {
   int res = 0;
   ip_set_ip_t ip;
-  parse_ip(idtoip(map, req->id), &ip);
+  parse_ip(idtoip(vs->v_map, req->id), &ip);
 
-  res = set_adtip_nb(rahunas_set, &ip, req->mac_address, IP_SET_OP_DEL_IP);
+  res = set_adtip_nb(vs->v_set, &ip, req->mac_address, IP_SET_OP_DEL_IP);
 
   return res;
 }
 
 /* Commit start session task */
-static int commitstartsess (struct rahunas_map *map, struct task_req *req)
+static int commitstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Commit stop session task */
-static int commitstopsess  (struct rahunas_map *map, struct task_req *req)
+static int commitstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback start session task */
-static int rollbackstartsess (struct rahunas_map *map, struct task_req *req)
+static int rollbackstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback stop session task */
-static int rollbackstopsess  (struct rahunas_map *map, struct task_req *req)
+static int rollbackstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
@@ -141,6 +148,6 @@ static struct task task_ipset = {
   .rollbackstopsess = &rollbackstopsess,
 };
 
-void rh_task_ipset_reg(void) {
-  task_register(&task_ipset);
+void rh_task_ipset_reg(struct main_server *ms) {
+  task_register(ms, &task_ipset);
 }
index d169021..ee92786 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef __RH_TASK_MEMSET_H
 #define __RH_TASK_MEMSET_H
 
-extern void rh_task_ipset_reg(void);
+extern void rh_task_ipset_reg(struct main_server *ms);
 
 #endif // __RH_TASK_MEMSET_H
 
index 69590eb..10740d8 100644 (file)
 #include "rh-task.h"
 #include "rh-ipset.h"
 
+GList *member_get_node_by_id(struct vserver *vs, uint32_t id) 
+{
+  GList *runner = g_list_first(vs->v_map->members);
+  struct rahunas_member *member = NULL;
+
+  while (runner != NULL) {
+    member = (struct rahunas_member *) runner->data;
+
+    if (member->id == id)
+      return runner;
+
+    runner = g_list_next(runner);
+  }
+
+  return NULL;
+}
+
+gint idcmp(struct rahunas_member *a, struct rahunas_member *b)
+{
+  if (a == NULL || b == NULL)
+    return 0;
+
+  if (a != NULL && b != NULL)
+    return (a->id - b->id);
+}
+
 /* Initialize */
-static void init (void)
+static void init (struct vserver *vs)
 {
-  struct rahunas_member *members = NULL;
   int size;
 
-  logmsg(RH_LOG_NORMAL, "Task MEMSET init..");  
-  map = (struct rahunas_map*)(rh_malloc(sizeof(struct rahunas_map)));
+  logmsg(RH_LOG_NORMAL, "[%s] Task MEMSET init..",
+         vs->vserver_config->vserver_name);  
 
-  map->members = NULL;
-  map->size = 0;
+  vs->v_map = (struct rahunas_map *)(rh_malloc(sizeof(struct rahunas_map)));
+  if (vs->v_map == NULL) {
+    logmsg(RH_LOG_ERROR, "[%s] Could not allocate memory...",
+           vs->vserver_config->vserver_name); 
+    exit(EXIT_FAILURE);
+  }
 
-  if (get_header_from_set(map) < 0) {
+  memset(vs->v_map, 0, sizeof(struct rahunas_map));
+
+  if (get_header_from_set(vs) < 0) {
     syslog(LOG_ERR, "Could not fetch IPSET header");
     exit(EXIT_FAILURE);
   }
+}
 
-  size = map->size == 0 ? MAX_MEMBERS : map->size;
+/* Cleanup */
+static void cleanup (struct vserver *vs)
+{
+  GList *runner = NULL;
+  struct rahunas_member *member = NULL;
 
-  members = 
-    (struct rahunas_member*)(rh_malloc(sizeof(struct rahunas_member)*size));
+  logmsg(RH_LOG_NORMAL, "[%s] Task MEMSET cleanup..",
+         vs->vserver_config->vserver_name);  
 
-  memset(members, 0, sizeof(struct rahunas_member)*size);
+  if (vs->v_map != NULL) {
 
-  map->members = members;
-}
+    runner = g_list_first(vs->v_map->members);
 
-/* Cleanup */
-static void cleanup (void)
-{
-  struct rahunas_member *members = NULL;
-  int i;
-  int end;
-
-  logmsg(RH_LOG_NORMAL, "Task MEMSET cleanup..");  
-
-  if (map) {
-    if (map->members) {
-      members = map->members;
-      end = map->size;
-    } else {
-      end = 0;
-    }  
-
-    for (i=0; i < end; i++) {
-        rh_free_member(&members[i]);
+    while (runner != NULL) {
+      member = (struct rahunas_member *) runner->data; 
+
+      rh_free_member(member);
+
+      runner = g_list_delete_link(runner, runner);
     }
 
-    rh_free(&(map->members));
-    rh_free(&map);
+    g_list_free(vs->v_map->members);
+
+    rh_free(&(vs->v_map->members));
+    rh_free(&(vs->v_map));
   }
 
   return 0;
@@ -69,66 +93,96 @@ static void cleanup (void)
 
 
 /* Start service task */
-static int startservice (struct rahunas_map *map)
+static int startservice (struct vserver *vs)
 {
   /* Do nothing or need to implement */
 }
 
 /* Stop service task */
-static int stopservice  (struct rahunas_map *map)
+static int stopservice  (struct vserver *vs)
 {
   /* Do nothing or need to implement */
 }
 
 /* Start session task */
-static int startsess (struct rahunas_map *map, struct task_req *req)
+static int startsess (struct vserver *vs, struct task_req *req)
 {
-  struct rahunas_member *members = map->members;
   uint32_t id = req->id;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
+
+  member_node = member_get_node_by_id(vs, id);
 
-  members[id].flags = 1;
-  if (members[id].username && members[id].username != termstring)
-    free(members[id].username);
+  if (member_node == NULL) {
+    DP("Create new member");
+    member = (struct rahunas_member *)rh_malloc(sizeof(struct rahunas_member));
+    if (member == NULL)
+      return (-1);
 
-  if (members[id].session_id && members[id].username != termstring)
-    free(members[id].session_id);
+    memset(member, 0, sizeof(struct rahunas_member));
+
+    vs->v_map->members = 
+      g_list_insert_sorted(vs->v_map->members, member, idcmp);
+  } else {
+    DP("Member already exists");
+    member = (struct rahunas_member *)member_node->data;
+  }
 
-  members[id].username   = strdup(req->username);
-  if (!members[id].username)
-    members[id].username = termstring;
+  member->id = id; 
 
-  members[id].session_id = strdup(req->session_id);
-  if (!members[id].session_id)
-    members[id].session_id = termstring;
+  if (member->username && member->username != termstring)
+    free(member->username);
 
-  time(&(members[id].session_start));
-  memcpy(&req->session_start, &members[id].session_start, sizeof(time_t));
+  if (member->session_id && member->username != termstring)
+    free(member->session_id);
 
-  memcpy(&members[id].mac_address, &(req->mac_address), ETH_ALEN);
+  member->username   = strdup(req->username);
+  if (!member->username)
+    member->username = termstring;
 
-  memcpy(&members[id].session_timeout, &req->session_timeout, sizeof(time_t));
-  members[id].bandwidth_max_down = req->bandwidth_max_down;
-  members[id].bandwidth_max_up = req->bandwidth_max_up;
+  member->session_id = strdup(req->session_id);
+  if (!member->session_id)
+    member->session_id = termstring;
+
+  time(&(member->session_start));
+  memcpy(&req->session_start, &member->session_start, 
+         sizeof(time_t));
+
+  memcpy(&member->mac_address, &req->mac_address, ETH_ALEN);
+
+  memcpy(&member->session_timeout, &req->session_timeout, 
+         sizeof(time_t));
+  member->bandwidth_max_down = req->bandwidth_max_down;
+  member->bandwidth_max_up = req->bandwidth_max_up;
  
   DP("Session-Timeout %d", req->session_timeout);
   DP("Bandwidth - Down: %lu, Up: %lu", req->bandwidth_max_down, 
        req->bandwidth_max_up);
 
-  logmsg(RH_LOG_NORMAL, "Session Start, User: %s, IP: %s, "
+  logmsg(RH_LOG_NORMAL, "[%s] Session Start, User: %s, IP: %s, "
                         "Session ID: %s, MAC: %s",
-                        members[id].username, 
-                        idtoip(map, id), 
-                        members[id].session_id,
-                        mac_tostring(members[id].mac_address)); 
+                        vs->vserver_config->vserver_name,
+                        member->username, 
+                        idtoip(vs->v_map, id), 
+                        member->session_id,
+                        mac_tostring(member->mac_address)); 
   return 0;
 }
 
 /* Stop session task */
-static int stopsess  (struct rahunas_map *map, struct task_req *req)
+static int stopsess  (struct vserver *vs, struct task_req *req)
 {
-  struct rahunas_member *members = map->members;
   uint32_t id = req->id;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
   char cause[16] = "";
+
+  member_node = member_get_node_by_id(vs, id);
+  if (member_node == NULL)
+    return (-1);
+
+  member = (struct rahunas_member *)member_node->data;
+
   switch (req->req_opt) {
     case RH_RADIUS_TERM_IDLE_TIMEOUT :
       strcpy(cause, "idle timeout");
@@ -146,46 +200,48 @@ static int stopsess  (struct rahunas_map *map, struct task_req *req)
       strcpy(cause, "admin reset");
       break;
   }
-  if (!members[id].username)
-    members[id].username = termstring;
+  if (!member->username)
+    member->username = termstring;
 
-  if (!members[id].session_id)
-    members[id].session_id = termstring;
+  if (!member->session_id)
+    member->session_id = termstring;
 
-  logmsg(RH_LOG_NORMAL, "Session Stop (%s), User: %s, IP: %s, "
+  logmsg(RH_LOG_NORMAL, "[%s] Session Stop (%s), User: %s, IP: %s, "
                         "Session ID: %s, MAC: %s",
+                        vs->vserver_config->vserver_name,
                         cause,
-                        members[id].username, 
-                        idtoip(map, id), 
-                        members[id].session_id,
-                        mac_tostring(members[id].mac_address)); 
+                        member->username, 
+                        idtoip(vs->v_map, id), 
+                        member->session_id,
+                        mac_tostring(member->mac_address)); 
 
-  rh_free_member(&members[id]);   
+  rh_free_member(member);   
+
+  vs->v_map->members = g_list_delete_link(vs->v_map->members, member_node);
 
   return 0;
 }
 
 /* Commit start session task */
-static int commitstartsess (struct rahunas_map *map, struct task_req *req)
+static int commitstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Commit stop session task */
-static int commitstopsess  (struct rahunas_map *map, struct task_req *req)
+static int commitstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback start session task */
-static int rollbackstartsess (struct rahunas_map *map, struct task_req *req)
+static int rollbackstartsess (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
 
 /* Rollback stop session task */
-static int rollbackstopsess  (struct rahunas_map *map, struct task_req *req)
+static int rollbackstopsess  (struct vserver *vs, struct task_req *req)
 {
   /* Do nothing or need to implement */
 }
@@ -205,6 +261,6 @@ static struct task task_memset = {
   .rollbackstopsess = &rollbackstopsess,
 };
 
-void rh_task_memset_reg(void) {
-  task_register(&task_memset);
+void rh_task_memset_reg(struct main_server *ms) {
+  task_register(ms, &task_memset);
 }
index 62c68e9..b32b4c5 100644 (file)
@@ -6,7 +6,9 @@
 #ifndef __RH_TASK_MEMSET_H
 #define __RH_TASK_MEMSET_H
 
-extern void rh_task_memset_reg(void);
+extern void rh_task_memset_reg(struct main_server *ms);
 
+GList *member_get_node_by_id(struct vserver *vs, uint32_t id);
+gint idcmp(struct rahunas_member *a, struct rahunas_member *b);
 #endif // __RH_TASK_MEMSET_H
 
index 202e986..fdc18bc 100644 (file)
@@ -11,7 +11,7 @@
 #include "rh-task-dbset.h"
 #include "rh-task-bandwidth.h"
 
-void task_register(struct task *task)
+void task_register(struct main_server *ms, struct task *task)
 {
   GList *chk  = NULL;
   GList *node = NULL;
@@ -22,7 +22,7 @@ void task_register(struct task *task)
 
   DP("Registering Task: %s", task->taskname);
 
-  chk = g_list_find(task_list, task);
+  chk = g_list_find(ms->task_list, task);
 
   /* Already register */
   if (chk != NULL) {
@@ -30,72 +30,79 @@ void task_register(struct task *task)
     return;
   }
 
-  if (task_list == NULL) {
-    task_list = g_list_append(task_list, task);
+  if (ms->task_list == NULL) {
+    ms->task_list = g_list_append(ms->task_list, task);
     return;
   }
 
-  for (node = g_list_first(task_list); node != NULL; node = g_list_next(node)) {
+  for (node = g_list_first(ms->task_list); node != NULL; node = g_list_next(node)) {
     ltask = (struct task *)node->data;
     if (task->taskprio >= ltask->taskprio)
       break;  
   }
   
-  task_list = g_list_insert_before(task_list, node, task);
+  ms->task_list = g_list_insert_before(ms->task_list, node, task);
 }
 
-static void rh_task_call_init (void)
+void rh_task_init (struct main_server *ms, struct vserver *vs)
 {
-  GList *runner = g_list_first(task_list);
+  GList *runner = g_list_first(ms->task_list);
   struct task *ltask = NULL;
 
   DP("Initialize...");
 
   while (runner != NULL) {
     ltask = (struct task *)runner->data;
-    (*ltask->init)();
+    (*ltask->init)(vs);
     runner = g_list_next(runner);
   }
 }
 
-void rh_task_init(void)
+void rh_task_register(struct main_server *ms)
 {
-  /* Register all tasks */
-  rh_task_ipset_reg();
-  rh_task_memset_reg();
-  rh_task_dbset_reg();
-  rh_task_bandwidth_reg();
-
-  /* Call each init */
-  rh_task_call_init();
+  static int task_registered = 0;
+
+  if (task_registered == 0) {
+    /* Register all tasks */
+    rh_task_memset_reg(ms);
+    rh_task_ipset_reg(ms);
+
+    if (ms->main_config->bandwidth_shape)
+      rh_task_bandwidth_reg(ms);
+
+    rh_task_dbset_reg(ms);
+    task_registered = 1;
+  }
 }
 
-void rh_task_cleanup(void)
+void rh_task_unregister(struct main_server *ms) {
+  g_list_free(ms->task_list);
+}
+
+void rh_task_cleanup(struct main_server *ms, struct vserver *vs)
 {
-  GList *runner = g_list_last(task_list);
+  GList *runner = g_list_last(ms->task_list);
   struct task *ltask = NULL;
 
   DP("Task Cleanup");
 
   while (runner != NULL) {
     ltask = (struct task *)runner->data;
-    (*ltask->cleanup)();
+    (*ltask->cleanup)(vs);
     runner = g_list_previous(runner);
   }  
-
-  g_list_free(task_list);
 }
 
-int  rh_task_startservice(struct rahunas_map *map)
+int  rh_task_startservice(struct main_server *ms, struct vserver *vs)
 {
-  GList *runner = g_list_first(task_list);
+  GList *runner = g_list_first(ms->task_list);
   struct task *ltask = NULL;
 
   DP("Start service");
 
   while (runner != NULL) {
     ltask = (struct task *)runner->data;
-    (*ltask->startservice)(map);
+    (*ltask->startservice)(vs);
     runner = g_list_next(runner);
   }  
 
@@ -103,66 +110,68 @@ int  rh_task_startservice(struct rahunas_map *map)
   return 0;
 }
 
-int  rh_task_stopservice(struct rahunas_map *map)
+int  rh_task_stopservice(struct main_server *ms, struct vserver *vs)
 {  
-  GList *runner = g_list_last(task_list);
+  GList *runner = g_list_last(ms->task_list);
   struct task *ltask = NULL;
 
   DP("Stop service");
 
   while (runner != NULL) {
     ltask = (struct task *)runner->data;
-    (*ltask->stopservice)(map);
+    (*ltask->stopservice)(vs);
     runner = g_list_previous(runner);
   }  
 
   logmsg(RH_LOG_NORMAL, "Service stopped");
 }
 
-int  rh_task_startsess(struct rahunas_map *map, struct task_req *req)
+int  rh_task_startsess(struct vserver *vs, struct task_req *req)
 {
-  GList *runner = g_list_first(task_list);
+  struct main_server *ms = &rh_main_server_instance;
+  GList *runner = g_list_first(ms->task_list);
   struct task *ltask = NULL;
 
   DP("Start session called");
 
   while (runner != NULL) {
     ltask = (struct task *)runner->data;
-    (*ltask->startsess)(map, req);
+    (*ltask->startsess)(vs, req);
     runner = g_list_next(runner);
   }  
 
   return 0;
 }
 
-int  rh_task_stopsess(struct rahunas_map *map, struct task_req *req)
+int  rh_task_stopsess(struct vserver *vs, struct task_req *req)
 {
-  GList *runner = g_list_last(task_list);
+  struct main_server *ms = &rh_main_server_instance;
+  GList *runner = g_list_last(ms->task_list);
   struct task *ltask = NULL;
 
   DP("Stop session called");
-
   while (runner != NULL) {
     ltask = (struct task *)runner->data;
-    (*ltask->stopsess)(map, req);
+    (*ltask->stopsess)(vs, req);
     runner = g_list_previous(runner);
   }  
 
   return 0;
 }
 
-int  rh_task_commitstartsess(struct rahunas_map *map, struct task_req *req)
+int  rh_task_commitstartsess(struct vserver *vs, struct task_req *req)
 {
 }
 
-int  rh_task_commitstopsess(struct rahunas_map *map, struct task_req *req)
+int  rh_task_commitstopsess(struct vserver *vs, struct task_req *req)
 {
 }
 
-int  rh_task_rollbackstartsess(struct rahunas_map *map, struct task_req *req)
+int  rh_task_rollbackstartsess(struct vserver *vs, struct task_req *req)
 {
 }
 
-int  rh_task_rollbackstopsess(struct rahunas_map *map, struct task_req *req)
+int  rh_task_rollbackstopsess(struct vserver *vs, struct task_req *req)
 {
 }
index 1ad1d0a..93a141d 100644 (file)
@@ -13,6 +13,7 @@
 
 struct task_req {
   uint32_t id;
+  int vserver_id;
   const char *username;
   const char *session_id;
   unsigned char mac_address[ETH_ALEN];
@@ -29,49 +30,49 @@ struct task {
   unsigned int taskprio;
 
   /* Initialize */
-  void (*init) (void);
+  void (*init) (struct vserver *vs);
 
   /* Cleanup */
-  void (*cleanup) (void);
+  void (*cleanup) (struct vserver *vs);
   
   /* Start service task */
-  int (*startservice) (struct rahunas_map *map);
+  int (*startservice) (struct vserver *vs);
 
   /* Stop service task */
-  int (*stopservice) (struct rahunas_map *map);
+  int (*stopservice) (struct vserver *vs);
 
   /* Start session task */
-  int (*startsess) (struct rahunas_map *map, struct task_req *req);
+  int (*startsess) (struct vserver *vs, struct task_req *req);
 
   /* Stop session task */
-  int (*stopsess) (struct rahunas_map *map, struct task_req *req);
+  int (*stopsess) (struct vserver *vs, struct task_req *req);
 
   /* Commit start session task */
-  int (*commitstartsess) (struct rahunas_map *map, struct task_req *req);
+  int (*commitstartsess) (struct vserver *vs, struct task_req *req);
 
   /* Commit stop session task */
-  int (*commitstopsess) (struct rahunas_map *map, struct task_req *req);
+  int (*commitstopsess) (struct vserver *vs, struct task_req *req);
 
   /* Rollback start session task */
-  int (*rollbackstartsess) (struct rahunas_map *map, struct task_req *req);
+  int (*rollbackstartsess) (struct vserver *vs, struct task_req *req);
 
   /* Rollback stop session task */
-  int (*rollbackstopsess) (struct rahunas_map *map, struct task_req *req);
+  int (*rollbackstopsess) (struct vserver *vs, struct task_req *req);
 };
 
-static GList *task_list = NULL;
-
-extern void task_register(struct task *task);
-
-void rh_task_init(void);
-void rh_task_cleanup(void);
-int  rh_task_startservice(struct rahunas_map *map);
-int  rh_task_stopservice(struct rahunas_map *map);
-int  rh_task_startsess(struct rahunas_map *map, struct task_req *req);
-int  rh_task_stopsess(struct rahunas_map *map, struct task_req *req);
-int  rh_task_commitstartsess(struct rahunas_map *map, struct task_req *req);
-int  rh_task_commitstopsess(struct rahunas_map *map, struct task_req *req);
-int  rh_task_rollbackstartsess(struct rahunas_map *map, struct task_req *req);
-int  rh_task_rollbackstopsess(struct rahunas_map *map, struct task_req *req);
+extern void task_register(struct main_server *ms, struct task *task);
+
+void rh_task_register(struct main_server *ms);
+void rh_task_unregister(struct main_server *ms);
+void rh_task_init(struct main_server *ms, struct vserver *vs);
+void rh_task_cleanup(struct main_server *ms, struct vserver *vs);
+int  rh_task_startservice(struct main_server *ms, struct vserver *vs);
+int  rh_task_stopservice(struct main_server *ms, struct vserver *vs);
+int  rh_task_startsess(struct vserver *vs, struct task_req *req);
+int  rh_task_stopsess(struct vserver *vs, struct task_req *req);
+int  rh_task_commitstartsess(struct vserver *vs, struct task_req *req);
+int  rh_task_commitstopsess(struct vserver *vs, struct task_req *req);
+int  rh_task_rollbackstartsess(struct vserver *vs, struct task_req *req);
+int  rh_task_rollbackstopsess(struct vserver *vs, struct task_req *req);
 
 #endif // __RH_TASK_H
index 2e26ede..4995842 100644 (file)
@@ -7,7 +7,13 @@
 #include <syslog.h>
 #include <glib.h>
 #include <time.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
 
+#include "rahunasd.h"
 #include "rh-utils.h"
 
 void *rh_malloc(size_t size)
@@ -70,3 +76,120 @@ const char *rh_string_get_sep(const char *haystack, const char *sep,
     }
   }
 }
+
+int rh_openlog(const char *filename)
+{
+  return open(filename, O_WRONLY | O_APPEND | O_CREAT);
+}
+
+int rh_closelog(int fd)
+{
+  if (close(fd) == 0)
+    return 1;
+  else
+    return 0;
+}
+
+int logmsg(int priority, const char *msg, ...) 
+{
+  int n, size = 256;
+  va_list ap;
+  char *time_fmt = "%b %e %T";
+  char *p = NULL;
+  char *np = NULL;
+
+  if (priority < RH_LOG_LEVEL)
+    return 0;
+
+  if ((p = rh_malloc(size)) == NULL) {
+    return (-1);
+  }
+
+  while (1) {
+    va_start(ap, msg);
+    n = vsnprintf(p, size, msg, ap);
+    va_end(ap);
+
+    if (n > -1 && n < size)
+      break;
+    if (n > -1)
+      size = n+1;
+    else
+      size *= 2;
+
+    if ((np = realloc(p, size)) == NULL) {
+      free(p);
+      p = NULL;
+      break;
+    } else {
+      p = np;
+    }
+  }
+
+  
+  if (!p)
+    return (-1);
+
+  fprintf(stderr, "%s : %s\n", timemsg(), p);
+
+  rh_free(&p);
+  rh_free(&np);
+}
+
+
+int rh_writepid(const char *pidfile, int pid)
+{
+  int pidfd;
+
+  pidfd = open(DEFAULT_PID, O_WRONLY | O_TRUNC | O_CREAT);
+  if (pidfd) {
+    dup2(pidfd, STDOUT_FILENO);
+    fprintf(stdout, "%d\n", pid);
+    close(pidfd);
+  }
+}
+
+int rh_logselect(int fd)
+{
+  dup2(fd, STDERR_FILENO);
+  return 0;
+}
+
+uint32_t iptoid(struct rahunas_map *map, const char *ip) {
+  uint32_t ret;
+  struct in_addr req_ip;
+
+  if (!map || !ip)
+    return (-1);
+
+  if (!(inet_aton(ip, &req_ip))) {
+    DP("Could not convert IP: %s", ip);
+    return (-1);  
+  }
+
+  DP("Request IP: %s", ip);
+  
+  ret = ntohl(req_ip.s_addr) - ntohl(map->first_ip);
+  if (ret < 0 || ret > (map->size - 1))
+    ret = (-1);
+
+  DP("Request Index: %lu", ret);
+  return ret; 
+}
+
+char *idtoip(struct rahunas_map *map, uint32_t id) {
+  struct in_addr sess_addr;
+
+  if (!map)
+    return termstring;
+
+  if (id < 0)
+    return termstring;
+
+  sess_addr.s_addr = htonl((ntohl(map->first_ip) + id));
+
+  return inet_ntoa(sess_addr);
+}
+
+
index ad5cafe..68dc35e 100644 (file)
@@ -8,9 +8,20 @@
 
 #include <stdlib.h>
 
+#define LOG_MAIN_FD  -1
+
 void *rh_malloc(size_t size);
 void rh_free(void **data);
 
 const char *rh_string_get_sep(const char *haystack, const char *sep, 
                               unsigned short idx);
+int rh_openlog(const char *filename);
+int rh_closelog(int fd);
+int rh_logselect(int fd);
+int rh_writepid(const char *pidfile, int pid); 
+int logmsg(int priority, const char *msg, ...);
+
+uint32_t iptoid(struct rahunas_map *map, const char *ip);
+char *idtoip(struct rahunas_map *map, uint32_t id);
+
 #endif // __RH_UTILS_H
index 2057d31..51a307b 100644 (file)
@@ -7,41 +7,43 @@
 #include "../xmlrpc/xmlrpc.h"
 #include "rahunasd.h"
 #include "rh-xmlrpc-cmd.h"
+#include "rh-task-memset.h"
 
-int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id, int cause) {
-  struct rahunas_member *members = NULL;
+int send_xmlrpc_stopacct(struct vserver *vs, uint32_t id, int cause) {
   GNetXmlRpcClient *client = NULL;
   gchar *reply  = NULL;
   gchar *params = NULL;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
 
-  if (!map)
+  if (!vs)
     return (-1);
 
-  if (!map->members)
+  if (id < 0 || id > (vs->v_map->size - 1))
     return (-1);
 
-  if (id < 0 || id > (map->size - 1))
+  member_node = member_get_node_by_id(vs, id);
+  if (member_node == NULL)
     return (-1);
   
-  members = map->members;
-
+  member = (struct rahunas_member *)member_node->data;
   params = g_strdup_printf("%s|%s|%s|%d|%s|%d", 
-                           idtoip(map, id),
-                           members[id].username,
-                           members[id].session_id,
-                           members[id].session_start,
-                           mac_tostring(members[id].mac_address),
+                           idtoip(vs->v_map, id),
+                           member->username,
+                           member->session_id,
+                           member->session_start,
+                           mac_tostring(member->mac_address),
                            cause);
 
   if (params == NULL)
     return (-1);
 
-  client = gnet_xmlrpc_client_new(rh_config.xml_serv_host, 
-                                  rh_config.xml_serv_url, 
-                                  rh_config.xml_serv_port);
+  client = gnet_xmlrpc_client_new(vs->vserver_config->xml_serv_host, 
+                                  vs->vserver_config->xml_serv_url, 
+                                  vs->vserver_config->xml_serv_port);
 
   if (!client) {
-    logmsg(RH_LOG_ERROR, "Could not connect to XML-RPC service");
+    logmsg(RH_LOG_ERROR, "[%s] Could not connect to XML-RPC service", vs->vserver_config->vserver_name);
     return (-1);
   }
   
index d08198a..4c30ec2 100644 (file)
@@ -7,6 +7,6 @@
 #define __RH_XMLRPC_CMD_H
 #include "rh-radius.h"
 
-int send_xmlrpc_stopacct(struct rahunas_map *map, uint32_t id, int cause);
+int send_xmlrpc_stopacct(struct vserver *vs, uint32_t id, int cause);
 
 #endif // __RH_XMLRPC_CMD_H
index ea6e1a2..93bd671 100644 (file)
@@ -13,6 +13,7 @@
 #include "rh-ipset.h"
 #include "rh-utils.h"
 #include "rh-task.h"
+#include "rh-task-memset.h"
 
 extern const char* termstring;
 
@@ -22,8 +23,8 @@ int do_startsession(GNetXmlRpcServer *server,
                     gpointer user_data,
                     gchar **reply_string) 
 {
-  struct rahunas_map *map = (struct rahunas_map *)user_data;
-  struct rahunas_member *members = NULL;
+  struct main_server *ms = (struct main_server *)user_data; 
+  struct vserver *vs = NULL;
   unsigned char ethernet[ETH_ALEN] = {0,0,0,0,0,0};
   struct task_req req;
   gchar *ip = NULL;
@@ -33,18 +34,15 @@ int do_startsession(GNetXmlRpcServer *server,
   gchar *session_timeout = NULL;
   gchar *bandwidth_max_down = NULL;
   gchar *bandwidth_max_up = NULL;
+  gchar *vserver_id = NULL;
   uint32_t id;
-
-  if (!map)
-    goto out;
-
-  if (!map->members)
-    goto out;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
 
   if (param == NULL)
     goto out;
 
-  members = map->members;
+  DP("RPC Receive: %s", param);
 
   ip          = rh_string_get_sep(param, "|", 1);
   username    = rh_string_get_sep(param, "|", 2);
@@ -53,15 +51,21 @@ int do_startsession(GNetXmlRpcServer *server,
   session_timeout    = rh_string_get_sep(param, "|", 5);
   bandwidth_max_down = rh_string_get_sep(param, "|", 6);
   bandwidth_max_up   = rh_string_get_sep(param, "|", 7);
+  vserver_id         = rh_string_get_sep(param, "|", 8);
 
-  if (ip == NULL || username == NULL 
-        || session_id == NULL)
+  if (ip == NULL || username == NULL || session_id == NULL 
+      || vserver_id == NULL)
+    goto out;
+
+  vs = vserver_get_by_id(ms, atoi(vserver_id));
+
+  if (vs == NULL)
     goto out;
 
   if (mac_address == NULL)
     mac_address = g_strdup(DEFAULT_MAC);
 
-  id = iptoid(map, ip);
+  id = iptoid(vs->v_map, ip);
 
   if (id < 0) {
     *reply_string = g_strdup("Invalid IP Address");
@@ -69,6 +73,7 @@ int do_startsession(GNetXmlRpcServer *server,
   }
 
   req.id = id;
+  req.vserver_id = atoi(vserver_id);
   req.username = username;
   req.session_id = session_id;
   parse_mac(mac_address, &ethernet);
@@ -90,18 +95,24 @@ int do_startsession(GNetXmlRpcServer *server,
   else
     req.bandwidth_max_up = 0;
 
-  rh_task_startsess(map, &req);
+  rh_task_startsess(vs, &req);
 
-  *reply_string = g_strdup_printf("Greeting! Got: IP %s, User %s, ID %s", 
-                                   ip, members[id].username, 
-                                   members[id].session_id);
-  goto cleanup;
+  member_node = member_get_node_by_id(vs, id);
+
+  if (member_node != NULL) {
+    member = (struct rahunas_member *)member_node->data;
+    *reply_string = g_strdup_printf("Greeting! Got: IP %s, User %s, ID %s", 
+                                    ip, member->username, 
+                                    member->session_id);
+    goto cleanup;
+  }
 
 out:
     *reply_string = g_strdup("Invalid input parameters");
     goto cleanup;
 
 cleanup:
+  DP("RPC Reply: %s", *reply_string);
   g_free(ip);
   g_free(username);
   g_free(session_id);
@@ -109,6 +120,7 @@ cleanup:
   g_free(session_timeout);
   g_free(bandwidth_max_down);
   g_free(bandwidth_max_up);
+  g_free(vserver_id);
   return 0;
 }
 
@@ -118,24 +130,19 @@ int do_stopsession(GNetXmlRpcServer *server,
                    gpointer user_data,
                    gchar **reply_string)
 {
-  struct rahunas_map *map = (struct rahunas_map *)user_data;
-  struct rahunas_member *members;
+  struct main_server *ms = (struct main_server *)user_data;
+  struct vserver *vs = NULL;
   struct task_req req;
   gchar *ip = NULL;
   gchar *mac_address = NULL;
   gchar *cause = NULL;
+  gchar *vserver_id = NULL;
   int cause_id = 0;
   uint32_t   id;
   int res = 0;
   unsigned char ethernet[ETH_ALEN] = {0,0,0,0,0,0};
-
-  if (!map)
-    goto out;
-
-  if (!map->members)
-    goto out;
-
-  members = map->members;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
 
   if (param == NULL)
     goto out;
@@ -145,14 +152,19 @@ int do_stopsession(GNetXmlRpcServer *server,
   ip          = rh_string_get_sep(param, "|", 1);
   mac_address = rh_string_get_sep(param, "|", 2);
   cause       = rh_string_get_sep(param, "|", 3);
+  vserver_id  = rh_string_get_sep(param, "|", 4);
+
+  if (ip == NULL || vserver_id == NULL)
+    goto out;
+  vs = vserver_get_by_id(ms, atoi(vserver_id));
 
-  if (ip == NULL)
+  if (vs == NULL)
     goto out;
 
   if (mac_address == NULL)
     mac_address = g_strdup(DEFAULT_MAC);
 
-  id = iptoid(map, ip);
+  id = iptoid(vs->v_map, ip);
 
   if (id < 0) {
     *reply_string = g_strdup("Invalid IP Address");
@@ -162,8 +174,12 @@ int do_stopsession(GNetXmlRpcServer *server,
   parse_mac(mac_address, &ethernet);
   memcpy(req.mac_address, &ethernet, ETH_ALEN);
 
-  if (members[id].flags) {
-    if (memcmp(&ethernet, &members[id].mac_address, ETH_ALEN) == 0) {
+  member_node = member_get_node_by_id(vs, id);
+
+  if (member_node != NULL) {
+    member = (struct rahunas_member *) member_node->data;
+    if (memcmp(&ethernet, &member->mac_address, 
+        ETH_ALEN) == 0) {
       req.id = id;
       
       if (cause == NULL) {
@@ -178,13 +194,13 @@ int do_stopsession(GNetXmlRpcServer *server,
         }
       }
 
-      res = rh_task_stopsess(map, &req);
+      res = rh_task_stopsess(vs, &req);
       if (res == 0) {
         *reply_string = g_strdup_printf("Client IP %s was removed!", 
-                                          idtoip(map, id));
+                                          idtoip(vs->v_map, id));
       } else {
          *reply_string = g_strdup_printf("Client IP %s error remove!", 
-                                        idtoip(map, id));
+                                        idtoip(vs->v_map, id));
       }
       goto cleanup;
     } 
@@ -198,9 +214,11 @@ out:
   goto cleanup;
 
 cleanup:
+  DP("RPC Reply: %s", *reply_string);
   g_free(ip);
   g_free(mac_address);
   g_free(cause);
+  g_free(vserver_id);
   return 0;
 }
 
@@ -210,55 +228,71 @@ int do_getsessioninfo(GNetXmlRpcServer *server,
                       gpointer user_data,
                       gchar **reply_string)
 {
-  struct rahunas_map *map = (struct rahunas_map *)user_data;
-  struct rahunas_member *members = NULL;
+  struct main_server *ms = (struct main_server *)user_data;
+  struct vserver *vs = NULL;
   gchar *ip = NULL;
+  gchar *vserver_id = NULL;
   uint32_t   id;
+  GList *member_node = NULL;
+  struct rahunas_member *member = NULL;
 
-  if (!map)
+  if (param == NULL)
     goto out;
 
-  if (!map->members)
+  DP("RPC Receive: %s", param);
+
+  ip          = rh_string_get_sep(param, "|", 1);
+  vserver_id  = rh_string_get_sep(param, "|", 2);
+
+  if (ip == NULL || vserver_id == NULL)
     goto out;
 
-  members = map->members;
+  vs = vserver_get_by_id(ms, atoi(vserver_id));
 
-  if (param == NULL)
+  if (vs == NULL)
     goto out;
 
-  ip = param;
-  id = iptoid(map, ip);
+  id = iptoid(vs->v_map, ip);
 
   if (id < 0) {
     *reply_string = g_strdup("Invalid IP Address");
-    return 0;
+    goto cleanup;
   }
 
-  if (members[id].flags) {
-    if (!members[id].username) {
+  member_node = member_get_node_by_id(vs, id);
+
+  if (member_node != NULL) {
+    member = (struct rahunas_member *) member_node->data;
+    if (!member->username) {
       *reply_string = g_strdup("Invalid Username");
-      return 0;
+      goto cleanup;
     }
 
-    if (!members[id].session_id) {
+    if (!member->session_id) {
       *reply_string = g_strdup("Invalid Session ID");
-      return 0;
+      goto cleanup;
     }
     
     *reply_string = g_strdup_printf("%s|%s|%s|%d|%s|%d", 
-                                      ip, 
-                                      members[id].username,
-                                      members[id].session_id,
-                                      members[id].session_start,
-                                      mac_tostring(members[id].mac_address),
-                                      members[id].session_timeout);
-    return 0;
+                                    ip, 
+                                    member->username,
+                                    member->session_id,
+                                    member->session_start,
+                                    mac_tostring(member->mac_address),
+                                    member->session_timeout);
+    goto cleanup;
   }
 
   *reply_string = g_strdup_printf("%s", ip);
-  return 0;
+  goto cleanup;
 
 out:
     *reply_string = g_strdup("Invalid input parameters");
-    return 0;
+     goto cleanup;
+
+cleanup:
+  DP("RPC Reply: %s", *reply_string);
+  g_free(ip);
+  g_free(vserver_id);
+  return 0;
 }
index 82b8eda..5c8a4ee 100644 (file)
@@ -31,7 +31,8 @@
     any other GPL-like (LGPL, GPL2) License.
 */
 
-$config = array(
+$config_list['172.30.0.0/22'] = array(
+  "VSERVER_ID" => "1",
   "RADIUS_HOST" => "localhost",
   "RADIUS_SECRET" => "testing123",
   "RADIUS_ENCRYPT" => "CHAP_MD5",
@@ -41,12 +42,12 @@ $config = array(
   "RAHUNAS_PORT" => "8123",
   "NAS_IDENTIFIER" => "RahuNAS-01",
   "NAS_IP_ADDRESS" => "172.30.0.1",
-  "NAS_LOGIN_HOST" => "172.30.0.1",
-  "NAS_LOGIN_PORT" => "8443",
+  "NAS_LOGIN_HOST" => "authen.rahunas.local",
+  "NAS_LOGIN_PORT" => "443",
   "NAS_LOGIN_PROTO" => "https",
   "NAS_PORT" => 1,
   "NAS_LOGIN_TITLE" => "RahuNAS Network",
-  "DEFAULT_REDIRECT_URL" => "http://www.kku.ac.th",
+  "DEFAULT_REDIRECT_URL" => "http://www.rahunas.org",
   "DEFAULT_LANGUAGE" => "Thai",
   "UAM_TEMPLATE" => "rahunas"
 );
index 94072f5..6d60ac2 100644 (file)
 
 require_once 'config.php';
 require_once 'header.php';
+require_once 'networkchk.php';
+
+$ip = $_SERVER['REMOTE_ADDR'];
+$config = get_config_by_network($ip, $config_list);
+$vserver_id = $config["VSERVER_ID"];
 
 $forward_uri  = $config['NAS_LOGIN_PROTO'] . "://" . $config['NAS_LOGIN_HOST'];
 $forward_uri .= !empty($config['NAS_LOGIN_PORT']) ? ":" . $config['NAS_LOGIN_PORT'] : "";
index 1ce4e6c..599c0e2 100644 (file)
 */
 
 require_once "config.php";
+require_once 'networkchk.php';
+
+$ip = $_SERVER['REMOTE_ADDR'];
+$config = get_config_by_network($ip, $config_list);
+$vserver_id = $config["VSERVER_ID"];
 
 function explode_querystring($query_string) {
   // Explode the query string into array
index bcd5b3b..4cc2c5c 100644 (file)
@@ -40,8 +40,12 @@ require_once 'config.php';
 require_once 'header.php';
 require_once 'locale.php';
 require_once 'messages.php';
+require_once 'networkchk.php';
 
 $ip = $_SERVER['REMOTE_ADDR'];
+$config = get_config_by_network($ip, $config_list);
+$vserver_id = $config["VSERVER_ID"];
+
 $forward = false;
 $LogoutURL  = $config['NAS_LOGIN_PROTO'] . "://" . $config['NAS_LOGIN_HOST'];
 $LogoutURL .= !empty($config['NAS_LOGIN_PORT']) ? 
@@ -57,7 +61,7 @@ $xmlrpc = new rahu_xmlrpc_client();
 $xmlrpc->host = $config["RAHUNAS_HOST"];
 $xmlrpc->port = $config["RAHUNAS_PORT"];
 try {
-  $retinfo = $xmlrpc->do_getsessioninfo($ip);
+  $retinfo = $xmlrpc->do_getsessioninfo($vserver_id, $ip);
   if (is_array($retinfo) && !empty($retinfo['session_id'])) {
     $forward = true;
   }
@@ -104,7 +108,7 @@ if (!empty($_POST['user']) && !empty($_POST['passwd'])) {
         "Session-Timeout" => $rauth->attributes['session_timeout'],
         "Bandwidth-Max-Down" => $rauth->attributes['WISPr-Bandwidth-Max-Down'],
         "Bandwidth-Max-Up" => $rauth->attributes['WISPr-Bandwidth-Max-Up']);
-      $result = $xmlrpc->do_startsession($prepareData);
+      $result = $xmlrpc->do_startsession($vserver_id, $prepareData);
       if (strstr($result,"Client already login")) {
         $message = get_message('ERR_ALREADY_LOGIN');
         $forward = false;
index ae84306..e864c88 100644 (file)
@@ -40,6 +40,7 @@ require_once 'config.php';
 require_once 'header.php';
 require_once 'locale.php';
 require_once 'messages.php';
+require_once 'networkchk.php';
 
 $current_url = $_SERVER['REQUEST_URI'];
 $interval = 60;
@@ -49,6 +50,10 @@ if ($auto_refresh) {
   header("Refresh: $interval; url=$current_url");
 }
 
+$ip = $_SERVER['REMOTE_ADDR'];
+$config = get_config_by_network($ip, $config_list);
+$vserver_id = $config["VSERVER_ID"];
+
 $forward_uri  = $config['NAS_LOGIN_PROTO'] . "://" . $config['NAS_LOGIN_HOST'];
 $forward_uri .= !empty($config['NAS_LOGIN_PORT']) ? ":" . $config['NAS_LOGIN_PORT'] : "";
 $forward_uri .= "/login.php?sss=" . time();
@@ -56,7 +61,8 @@ $forward_uri .= "/login.php?sss=" . time();
 $request_url = $_SESSION['request_url'];
 $request_url_text = strlen($request_url) < 20 ? $request_url : substr($request_url, 0, 20) . " ...";
 
-$ip = $_SERVER['REMOTE_ADDR'];
+
+
 $xmlrpc = new rahu_xmlrpc_client();
 $xmlrpc->host = $config["RAHUNAS_HOST"];
 $xmlrpc->port = $config["RAHUNAS_PORT"];
@@ -64,7 +70,7 @@ $valid = false;
 $isinfo = false;
 $isstopacct = false;
 $info = array();
-$retinfo = $xmlrpc->do_getsessioninfo($ip);
+$retinfo = $xmlrpc->do_getsessioninfo($vserver_id, $ip);
 if (is_array($retinfo)) {
   // Send stop accounting to Radius
   $ip =& $retinfo["ip"];
@@ -79,7 +85,7 @@ if (is_array($retinfo)) {
 
 if (!empty($_POST['do_logout'])) {
   if ($isinfo) {
-    $result = $xmlrpc->do_stopsession($ip, returnMacAddress(), 
+    $result = $xmlrpc->do_stopsession($vserver_id, $ip, returnMacAddress(), 
                                       RADIUS_TERM_USER_REQUEST);
     if ($result === true) {
       $valid = false;
@@ -113,7 +119,7 @@ if (!empty($_POST['do_logout'])) {
 }
 
 if ($show_info) {
-  $result = $xmlrpc->do_getsessioninfo($ip);
+  $result = $xmlrpc->do_getsessioninfo($vserver_id, $ip);
   if (is_array($result)) {
     if (!empty($result['session_id'])) {
       $valid = true;
diff --git a/weblogin/networkchk.php b/weblogin/networkchk.php
new file mode 100644 (file)
index 0000000..8d6fb2f
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/*
+  Copyright (c) 2008-2009, Neutron Soutmun <neo.neutron@gmail.com>
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without 
+  modification, are permitted provided that the following conditions 
+  are met:
+
+  1. Redistributions of source code must retain the above copyright 
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in the 
+     documentation and/or other materials provided with the distribution.
+  3. The names of the authors may not be used to endorse or promote products 
+     derived from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
+  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+  POSSIBILITY OF SUCH DAMAGE.
+
+  This code cannot simply be copied and put under the GNU Public License or 
+    any other GPL-like (LGPL, GPL2) License.
+*/
+
+require_once 'Net/IPv4.php';
+
+function get_config_by_network($ip, &$config_list) {
+  if (!is_array($config_list))
+    return array();
+  foreach ($config_list as $network=>$config) {
+    if (Net_IPv4::ipInNetwork($ip, $network))
+      return $config;
+  }
+  
+  return array();
+}
+?>
index 826ba0d..269fef1 100644 (file)
@@ -55,17 +55,18 @@ class rahu_xmlrpc_client {
 
   }
 
-  function do_startsession($data) {
+  function do_startsession($vserver_id, $data) {
     $client = $this->getClient(); 
     $params = implode("|", $data);
-    $params .= "|";
+    $params = sprintf("%s|%s", $params, $vserver_id);
     $result = $client->startsession($params);
     return $result;
   }
 
-  function do_stopsession($ip, $mac, $cause = RADIUS_TERM_USER_REQUEST) {
+  function do_stopsession($vserver_id, $ip, $mac, 
+                          $cause = RADIUS_TERM_USER_REQUEST) {
     $client = $this->getClient(); 
-    $params = sprintf("%s|%s|%s", $ip, $mac, $cause);
+    $params = sprintf("%s|%s|%s|%s", $ip, $mac, $cause, $vserver_id);
     $result = $client->stopsession($params);
     if (strstr($result, "was removed"))
       return true;
@@ -73,10 +74,10 @@ class rahu_xmlrpc_client {
       return false;
   }
 
-  function do_getsessioninfo($ip) {
+  function do_getsessioninfo($vserver_id, $ip) {
     $client = $this->getClient(); 
-    $params = sprintf("%s", $ip);
-    $result = $client->getsessioninfo($ip);
+    $params = sprintf("%s|%s", $ip, $vserver_id);
+    $result = $client->getsessioninfo($params);
     $ret = explode("|", $result);
 
     /* $ret[0] - ip
@@ -101,5 +102,4 @@ class rahu_xmlrpc_client {
     return $result;
   }
 }
-
 ?>