Add bandwidth shaping support
authorNeutron Soutmun <neo.neutron@gmail.com>
Tue, 25 Nov 2008 13:19:36 +0000 (20:19 +0700)
committerNeutron Soutmun <neo.neutron@gmail.com>
Tue, 25 Nov 2008 13:19:36 +0000 (20:19 +0700)
2008-11-25  Neutron Soutmun <neo.neutron@gmail.com>

* rahunas.default:
  Add bandwidth shaping support by using the IMQ and iproute2.
* rahunas.firewall:
  Adjust to prevent the re-init firewall that cause the failure on the
stop process.
* rahunas.init:
  Adjust the firewall script caller.
* +rahunas.bandwidth: Add the rahunas bandwidth wrapper script.

* src/rh-task-bandwidth.{h,c}: Add bandwidth shaping task which response to
  the WISPr-Bandwidth-Max-{Up,Down} that reply from RADIUS.
* src/rahunasd.h: Add bandwidth_slot_id into members structure.
* src/rh-task-dbset.c:
  - Add bandwidth_* into dbset_row structure.
  - Add insert, fetch and restore code of bandwidth_* from DB into dbset_row
    structure.
  - Change task priority to 10. (Lowest priority now).
* src/rh-task-ipset.c:
  Change task priority to 30.
* src/rh-task-memset.c:
  Change task priority to 40. (Highest priority).
* src/rh-task.c:
  Include and register new task, bandwidth task.
* src/rh-task.h:
  Change the bandwidth_max_* type from long to unsigned long.
* src/Makefile.am:
  Update accordingly to bandwidth task implementation.
* weblogin/logout.php:
  Update CSS style for loginbox background.
* weblogin/templates/kkulogin/kkulogin.html:
  Update KKU-Login template.
* data/rahunas.db:
  Alter the schema of dbset table to support bandwidth fields.

17 files changed:
ChangeLog
data/rahunas.db
rahunas.bandwidth [new file with mode: 0755]
rahunas.default
rahunas.firewall
rahunas.init
src/Makefile.am
src/rahunasd.h
src/rh-task-bandwidth.c [new file with mode: 0644]
src/rh-task-bandwidth.h [new file with mode: 0644]
src/rh-task-dbset.c
src/rh-task-ipset.c
src/rh-task-memset.c
src/rh-task.c
src/rh-task.h
weblogin/logout.php
weblogin/templates/kkulogin/kkulogin.html

index 3d37954..704ce51 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2008-11-25  Neutron Soutmun <neo.neutron@gmail.com>
+
+       * rahunas.default: 
+         Add bandwidth shaping support by using the IMQ and iproute2.
+       * rahunas.firewall: 
+         Adjust to prevent the re-init firewall that cause the failure on the 
+               stop process.
+       * rahunas.init: 
+         Adjust the firewall script caller.
+       * +rahunas.bandwidth: Add the rahunas bandwidth wrapper script.
+
+       * src/rh-task-bandwidth.{h,c}: Add bandwidth shaping task which response to
+         the WISPr-Bandwidth-Max-{Up,Down} that reply from RADIUS.
+       * src/rahunasd.h: Add bandwidth_slot_id into members structure.
+       * src/rh-task-dbset.c: 
+         - Add bandwidth_* into dbset_row structure.
+         - Add insert, fetch and restore code of bandwidth_* from DB into dbset_row 
+           structure.
+         - Change task priority to 10. (Lowest priority now).
+       * src/rh-task-ipset.c: 
+         Change task priority to 30. 
+       * src/rh-task-memset.c: 
+         Change task priority to 40. (Highest priority).
+       * src/rh-task.c: 
+         Include and register new task, bandwidth task.
+       * src/rh-task.h: 
+         Change the bandwidth_max_* type from long to unsigned long.
+       * src/Makefile.am: 
+         Update accordingly to bandwidth task implementation.
+       * weblogin/logout.php: 
+         Update CSS style for loginbox background.
+       * weblogin/templates/kkulogin/kkulogin.html: 
+         Update KKU-Login template.
+       * data/rahunas.db: 
+         Alter the schema of dbset table to support bandwidth fields.
+
 2008-11-20  Neutron Soutmun <neo.neutron@gmail.com>
 
        * rahunas.firewall: Add excluded IP support.
index d096958..45a8462 100644 (file)
Binary files a/data/rahunas.db and b/data/rahunas.db differ
diff --git a/rahunas.bandwidth b/rahunas.bandwidth
new file mode 100755 (executable)
index 0000000..c560488
--- /dev/null
@@ -0,0 +1,153 @@
+#!/bin/sh
+# File: bandwidth.sh
+# Description: The bandwidth shaper wrapper script for RahuNAS
+
+TC=/sbin/tc
+IP=/sbin/ip
+
+RUN=/var/run/rahunas-bandwidth
+
+# Unclassified clients' bandwidth (Kbit)
+DOWN_UNCLASS=256
+UP_UNCLASS=256
+
+SHAPING_DOWN_INF=imq0
+SHAPING_UP_INF=imq1
+
+# Get configuration
+if [ -r /etc/default/rahunas ]; then
+  . /etc/default/rahunas
+fi
+
+if [ "$RUN_DAEMON" = "no" ]; then
+  exit 0
+fi
+
+start () {
+  # Downlink
+  $TC qdisc add dev $SHAPING_DOWN_INF root handle 1: htb default 9999
+  $TC class add dev $SHAPING_DOWN_INF parent 1: classid 1:9999 htb \
+    rate ${DOWN_UNCLASS}Kbit
+
+  # Uplink
+  $TC qdisc add dev $SHAPING_UP_INF root handle 2: htb default 9999 
+  $TC class add dev $SHAPING_UP_INF parent 2: classid 2:9999 htb \
+    rate ${UP_UNCLASS}Kbit
+
+  echo "Start OK"
+}
+
+stop () {
+  # Downlink
+  $TC qdisc del dev $SHAPING_DOWN_INF root
+
+  # Uplink
+  $TC qdisc del dev $SHAPING_UP_INF root
+
+  echo "Stop OK"
+}
+
+usage_add() {
+  echo "Usage: $1 add ID IP DOWNSPEED UPSPEED"
+  echo "         ID - ID number from 1 to 9998"
+  echo "         IP - IPv4 Address"
+  echo "  DOWNSPEED - Download speed (bits/s)"
+  echo "    UPSPEED - Upload speed (bits/s)"
+}
+
+usage_del() {
+  echo "Usage: $1 del ID"
+  echo "         ID - ID number from 1 to 9998"
+}
+
+usage() {
+  echo "Usage: $1 {start|stop|restart|add|del}"
+  echo "       $1 add --help"
+  echo "       $1 del --help"
+}
+
+bw_add() {
+  ID=$1
+  IP=$2
+  DOWNSPEED=$3
+  UPSPEED=$4
+  echo "Add shaping slot id: $ID for $IP with D/U=$DOWNSPEED/$UPSPEED bits/s"
+
+  # Downlink
+  $TC class add dev $SHAPING_DOWN_INF parent 1: classid 1:${ID} htb \
+    rate ${DOWNSPEED}bit ceil ${DOWNSPEED}bit
+  $TC filter add dev $SHAPING_DOWN_INF parent 1: protocol ip prio 1 \
+    u32 match ip dst ${IP}/32 flowid 1:${ID}
+
+  # Uplink
+  $TC class add dev $SHAPING_UP_INF parent 2: classid 2:${ID} htb \
+    rate ${UPSPEED}bit ceil ${UPSPEED}bit
+  $TC filter add dev $SHAPING_UP_INF parent 2: protocol ip prio 1 \
+    u32 match ip src ${IP}/32 flowid 2:${ID}
+}
+
+bw_del() {
+  ID=$1
+  echo "Delete shaping slot id: $ID"
+
+  # Filter Removal
+  # Downlink/Uplink
+  $TC filter del dev $SHAPING_DOWN_INF parent 1: protocol ip prio 1 u32 \
+    flowid 1:${ID}
+  $TC filter del dev $SHAPING_UP_INF parent 2: protocol ip prio 1 u32 \
+    flowid 2:${ID}
+
+  # Class Removal
+  # Downlink/Uplink
+  $TC class del dev $SHAPING_DOWN_INF parent 1: classid 1:${ID}
+  $TC class del dev $SHAPING_UP_INF parent 2: classid 2:${ID}
+}
+
+case "$1" in
+  start)
+    test -e $RUN || start
+    touch $RUN
+    ;;
+  stop)
+    test ! -e $RUN || stop
+    rm -f $RUN
+    ;;
+  restart)
+    stop
+    start
+    ;;
+  add)
+    if [ "$2" = "--help" ]; then
+      usage_add $0
+      exit 3
+    fi
+
+    if [ $# != 5 ]; then
+      echo "Error: too few arguments"
+      usage_add $0
+      exit 1
+    fi
+
+    bw_add $2 $3 $4 $5
+    ;;
+  del)
+    if [ "$2" = "--help" ]; then
+      usage_del $0
+      exit 3
+    fi
+
+    if [ $# != 2 ]; then
+      echo "Error: too few arguments"
+      usage_del $0
+      exit 1
+    fi
+
+    bw_del $2
+    ;;
+  *)
+    usage $0
+    exit 3
+    ;;
+esac 
+
+exit 0
index 33765a7..907489d 100644 (file)
@@ -34,6 +34,10 @@ CLIENTS_RANGE_END=""
 CLIENTS_NETWORK="172.30.0.0/22"
 CLIENTS_IGNORE_MAC=no
 
+# Enable Bandwidth shaping using IMQ and iproute2
+# BANDWIDTH_SHAPE_IMQ=[yes|no]
+BANDWIDTH_SHAPE_IMQ=yes
+
 # Enable DHCP Forwarding
 # FORWARD_DHCP=[yes|no]
 FORWARD_DHCP=no
index 595bd3b..e1a28f5 100755 (executable)
@@ -7,6 +7,7 @@ IPTABLES=/sbin/iptables
 IPSET=/usr/sbin/ipset
 
 NAME="rahunas"
+RUN=/var/run/rahunas-firewall
 
 # These values are overriden in /etc/default/rahunas if they exist
 RUN_DAEMON=no
@@ -226,6 +227,7 @@ rules () {
   ##
   $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set rahunas_set dst -j CONNMARK --set-mark 0x2 
   $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set rahunas_set src -j CONNMARK --set-mark 0x2 
+
   
   ##
   # Accept Forwarding for the authorized clients
@@ -291,7 +293,17 @@ et-mark 0x2
 et-mark 0x2
   done 
   
-  #
+  ##
+  # 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
+  fi
+
+  ##
   # Return to main chains
   ##
   $IPTABLES -A $CHAIN_INPUT_AUTH -j RETURN
@@ -305,26 +317,38 @@ et-mark 0x2
 }
 
 start () {
+  test ! -f $RUN || exit 0
+
   add_set
   new_chains
   policy 
   rules
+
+  touch $RUN
 }
 
 stop () {
+  test -f $RUN || exit 0
+
   cleanup
   cleanup_policy
   cleanup_set
+  rm -f $RUN
 }
 
 reload() {
+  test -f $RUN || exit 0
+
   # Do not cleanup set
   cleanup
   cleanup_policy
+  rm -f $RUN
 
   new_chains
   policy 
   rules
+  touch $RUN
 }
 
 case "$1" in
index 947d679..0d93e1b 100755 (executable)
@@ -14,6 +14,7 @@
 
 PATH=/sbin:/bin:/usr/sbin:/usr/bin
 DAEMON=/usr/bin/rahunasd
+FIREWALL=/etc/rahunas/firewall.sh
 NAME=rahunasd
 DESC="rahunasd: Rahu Network Access Server"
 
@@ -21,6 +22,7 @@ DESC="rahunasd: Rahu Network Access Server"
 RUN_DAEMON=no
 
 test -f $DAEMON || exit 0
+test -f $FIREWALL || exit 0
 
 set -e
 
@@ -33,7 +35,7 @@ case "$1" in
   start)
        echo -n "Starting $DESC: "
 
-       /etc/rahunas/firewall.sh start
+  $FIREWALL start
 
        if [ "$RUN_DAEMON" = "yes" ]; then
                start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
@@ -46,11 +48,10 @@ case "$1" in
   stop)
        echo -n "Stopping $DESC: "
 
-
        start-stop-daemon --stop --oknodo --quiet --pidfile /var/run/$NAME.pid \
                --exec $DAEMON
        echo done 
-       /etc/rahunas/firewall.sh stop
+       $FIREWALL stop
        ;;
   restart|force-reload)
        echo -n "Restarting $DESC: "
@@ -59,7 +60,7 @@ case "$1" in
                /var/run/$NAME.pid --exec $DAEMON
        sleep 1
 
-       /etc/rahunas/firewall.sh restart
+       $FIREWALL restart
 
        start-stop-daemon --start --quiet --pidfile \
                /var/run/$NAME.pid --exec $DAEMON
index 2c794a0..c628982 100644 (file)
@@ -32,6 +32,8 @@ rahunasd_SOURCES = \
        rh-task-memset.h \
        rh-task-dbset.c \
        rh-task-dbset.h \
+  rh-task-bandwidth.c \
+  rh-task-bandwidth.h \
   rh-radius.h \
        rh-config.h
 
index 00657ec..9a2c7c9 100644 (file)
@@ -59,6 +59,7 @@ struct rahunas_member {
   time_t session_timeout;
   long bandwidth_max_down;
   long bandwidth_max_up;
+  unsigned short bandwidth_slot_id;
        char *username;
   char *session_id;
   unsigned char mac_address[ETH_ALEN];
diff --git a/src/rh-task-bandwidth.c b/src/rh-task-bandwidth.c
new file mode 100644 (file)
index 0000000..872ed95
--- /dev/null
@@ -0,0 +1,331 @@
+/**
+ * RahuNAS task bandwidth implementation 
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-11-20
+ */
+
+#include <stdlib.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rahunasd.h"
+#include "rh-task.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    9998
+#define PAGE_SIZE      16
+#define MAX_SLOT_PAGE  625
+
+#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];
+};
+
+unsigned short _get_slot_id()
+{
+  unsigned short slot_id    = 0;
+  unsigned short page       = 0;
+  unsigned char  id_on_page = 0;
+  time_t random_time;
+
+  // Slot is full 
+  if (slot_count >= MAX_SLOT_ID)
+    return 0;
+
+  // Do a random slot_id 
+  while (slot_id == 0) {
+    time(&(random_time));
+    srandom(random_time);
+    slot_id = random()/(int)(((unsigned int)RAND_MAX + 1) / (MAX_SLOT_ID + 1));
+   
+    // Check validity
+    page = slot_id / PAGE_SIZE; 
+    id_on_page = slot_id % PAGE_SIZE;
+   
+    if (!(slot_flags[page] & (1 << id_on_page))) {
+      // Slot available
+      break;
+    }
+
+    // Slot not available, retry
+    slot_id = 0;
+  }
+
+  return slot_id;
+}
+
+void _mark_reserved_slot_id(unsigned int slot_id)
+{
+  unsigned short page       = 0;
+  unsigned char  id_on_page = 0;
+
+  page = slot_id / PAGE_SIZE; 
+  id_on_page = slot_id % PAGE_SIZE;
+
+  slot_count++;
+  slot_flags[page] |= 1 << id_on_page;
+}
+
+int _bandwidth_exec(char *const args[])
+{
+  pid_t ws;
+  pid_t pid;
+  int status;
+  int exec_pipe[2];
+  char buffer[150];
+  char *endline = NULL;
+  int ret = 0;
+  
+  memset(buffer, '\0', sizeof(buffer));
+
+  if (pipe(exec_pipe) == -1) {
+    logmsg(RH_LOG_ERROR, "Error: pipe()");
+    return -1;
+  }
+
+  pid = vfork();
+  dup2(exec_pipe[1], STDOUT_FILENO);
+
+  if (pid == 0) {
+    // Child
+    execv(BANDWIDTH_WRAPPER, args);
+
+  } else if (pid < 0) {
+    // Fork error
+    logmsg(RH_LOG_ERROR, "Error: vfork()"); 
+    ret = -1;
+  } else {
+    // Parent
+    ws = waitpid(pid, &status, 0);
+
+    DP("Bandwidth: Return (%d)", WEXITSTATUS(status));
+
+    // Return message log
+    read(exec_pipe[0], buffer, sizeof(buffer));
+    if (buffer != NULL) {
+      endline = strstr(buffer, "\n");
+      if (endline != NULL) 
+        *endline = '\0';
+
+      logmsg(RH_LOG_NORMAL, "Bandwidth: %s", buffer);
+    }
+
+    if (WIFEXITED(status)) {
+      ret = WEXITSTATUS(status);
+    } else {
+      ret = -1;
+    } 
+  }
+
+  close(exec_pipe[0]);
+  close(exec_pipe[1]);
+  return ret;
+}
+
+int _bandwidth_start()
+{
+  char *args[3];
+
+  DP("Bandwidth: start");
+
+  args[0] = BANDWIDTH_WRAPPER;
+  args[1] = "start";
+  args[2] = (char *) 0;
+
+  return _bandwidth_exec(args);
+}
+
+int _bandwidth_stop()
+{
+  char *args[3];
+
+  DP("Bandwidth: stop");
+
+  args[0] = BANDWIDTH_WRAPPER;
+  args[1] = "stop";
+  args[2] = (char *) 0;
+
+  return _bandwidth_exec(args);
+}
+
+int _bandwidth_add(struct bandwidth_req *bw_req)
+{
+  char *args[7];
+
+  DP("Bandwidth: request %s %s %s %s", bw_req->slot_id, 
+     bw_req->ip, bw_req->bandwidth_max_down, bw_req->bandwidth_max_up);
+
+  args[0] = BANDWIDTH_WRAPPER;
+  args[1] = "add";
+  args[2] = bw_req->slot_id;
+  args[3] = bw_req->ip;
+  args[4] = bw_req->bandwidth_max_down;
+  args[5] = bw_req->bandwidth_max_up;
+  args[6] = (char *) 0;
+
+  return _bandwidth_exec(args);
+}
+
+int _bandwidth_del(struct bandwidth_req *bw_req)
+{
+  char *args[4];
+
+  DP("Bandwidth: request %s", bw_req->slot_id);
+
+  args[0] = BANDWIDTH_WRAPPER;
+  args[1] = "del";
+  args[2] = bw_req->slot_id;
+  args[3] = (char *) 0;
+
+  return _bandwidth_exec(args);
+}
+
+/* Initialize */
+static void init (void)
+{
+  logmsg(RH_LOG_NORMAL, "Task BANDWIDTH init..");  
+}
+
+/* Cleanup */
+static void cleanup (void)
+{
+  logmsg(RH_LOG_NORMAL, "Task BANDWIDTH cleanup..");  
+}
+
+/* Start service task */
+static int startservice (struct rahunas_map *map)
+{
+  return _bandwidth_start();
+}
+
+/* Stop service task */
+static int stopservice  (struct rahunas_map *map)
+{
+  return _bandwidth_stop();
+}
+
+/* Start session task */
+static int startsess (struct rahunas_map *map, struct task_req *req)
+{
+  struct bandwidth_req bw_req;
+  unsigned short slot_id;
+  unsigned char max_try = 3;
+
+  if (map->members[req->id].bandwidth_max_down == 0 && 
+      map->members[req->id].bandwidth_max_up == 0)
+    return 0;
+
+  if (map->members[req->id].bandwidth_slot_id > 0)
+    return 0;
+  
+  // Formating the bandwidth request
+  sprintf(bw_req.ip, "%s", idtoip(map, req->id));
+  sprintf(bw_req.bandwidth_max_down, "%lu", 
+    map->members[req->id].bandwidth_max_down);
+  sprintf(bw_req.bandwidth_max_up, "%lu", 
+    map->members[req->id].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)
+      break;
+    else
+      max_try--;
+  }
+
+  if (max_try == 0) {
+    logmsg(RH_LOG_ERROR, "Bandwidth: Maximum trying, failed!");
+    return -1;
+  }
+
+  _mark_reserved_slot_id(slot_id);
+  map->members[req->id].bandwidth_slot_id = slot_id;
+  return 0;
+}
+
+/* Stop session task */
+static int stopsess  (struct rahunas_map *map, struct task_req *req)
+{
+  struct bandwidth_req bw_req;
+  unsigned short slot_id = map->members[req->id].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 (slot_count > 0)
+      slot_count--;
+  
+    return 0; 
+  } else {
+    return -1;
+  }
+}
+
+/* Commit start session task */
+static int commitstartsess (struct rahunas_map *map, 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)
+{
+  /* Do nothing or need to implement */
+}
+
+/* Rollback start session task */
+static int rollbackstartsess (struct rahunas_map *map, 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)
+{
+  /* Do nothing or need to implement */
+}
+
+static struct task task_bandwidth = {
+  .taskname = "BANDWIDTH",
+  .taskprio = 20,
+  .init = &init,
+  .cleanup = &cleanup,
+  .startservice = &startservice,
+  .stopservice = &stopservice,
+  .startsess = &startsess,
+  .stopsess = &stopsess,
+  .commitstartsess = &commitstartsess,
+  .commitstopsess = &commitstopsess,
+  .rollbackstartsess = &rollbackstartsess,
+  .rollbackstopsess = &rollbackstopsess,
+};
+
+void rh_task_bandwidth_reg(void) {
+  task_register(&task_bandwidth);
+}
diff --git a/src/rh-task-bandwidth.h b/src/rh-task-bandwidth.h
new file mode 100644 (file)
index 0000000..47bd9d7
--- /dev/null
@@ -0,0 +1,11 @@
+/**
+ * RahuNAS task bandwidth implementation 
+ * Author: Neutron Soutmun <neo.neutron@gmail.com>
+ * Date:   2008-11-20
+ */
+#ifndef __RH_TASK_BANDWIDTH_H
+#define __RH_TASK_BANDWIDTH_H
+
+extern void rh_task_bandwidth_reg(void);
+
+#endif // __RH_TASK_BANDWIDTH_H
index be72e14..59b5cc8 100644 (file)
@@ -19,6 +19,10 @@ struct dbset_row {
   gchar *ip;
   gchar *mac;
   time_t session_start;
+  time_t session_timeout;
+  unsigned short bandwidth_slot_id; 
+  long bandwidth_max_down;
+  long bandwidth_max_up;
 };
 
 gboolean get_errors (GdaConnection * connection)
@@ -82,7 +86,17 @@ gboolean *parse_dm_to_struct(GList **data_list, GdaDataModel *dm) {
         strptime(str, "%s", &tm);
         time = mktime(&tm);
         memcpy(&row->session_start, &time, sizeof(time_t));
-      } 
+      } else if (strncmp("session_timeout", title, 15) == 0) {
+        strptime(str, "%s", &tm);
+        time = mktime(&tm);
+        memcpy(&row->session_timeout, &time, sizeof(time_t));
+      } else if (strncmp("bandwidth_slot_id", title, 17) == 0) {
+        row->bandwidth_slot_id = atoi(str);
+      } else if (strncmp("bandwidth_max_down", title, 18) == 0) {
+        row->bandwidth_max_down = atol(str);
+      } else if (strncmp("bandwidth_max_up", title, 18) == 0) {
+        row->bandwidth_max_up = atol(str);
+      }
     }
   }
   
@@ -207,6 +221,10 @@ gboolean restore_set(GList **data_list, struct rahunas_map *map)
     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;
 
     // IPSET
     set_adtip(rahunas_set, row->ip, row->mac, IP_SET_OP_ADD_IP);
@@ -286,17 +304,24 @@ static int startsess (struct rahunas_map *map, struct task_req *req)
   gint res;
   char startsess_cmd[256];
   char time_str[32];
+  char time_str2[32];
 
   client = gda_client_new ();
   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));
+
   sprintf(startsess_cmd, "INSERT INTO dbset"
-         "(session_id,username,ip,mac,session_start) "
-         "VALUES('%s','%s','%s','%s',%s)",
+         "(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);
+         mac_tostring(req->mac_address), time_str, time_str2,
+         map->members[req->id].bandwidth_slot_id, req->bandwidth_max_down,
+         req->bandwidth_max_up);
 
   DP("SQL: %s", startsess_cmd);
 
@@ -366,7 +391,7 @@ static int rollbackstopsess  (struct rahunas_map *map, struct task_req *req)
 
 static struct task task_dbset = {
   .taskname = "DBSET",
-  .taskprio = 1,
+  .taskprio = 10,
   .init = &init,
   .cleanup = &cleanup,
   .startservice = &startservice,
index 691ad06..1b09b5d 100644 (file)
@@ -128,7 +128,7 @@ static int rollbackstopsess  (struct rahunas_map *map, struct task_req *req)
 
 static struct task task_ipset = {
   .taskname = "IPSET",
-  .taskprio = 2,
+  .taskprio = 30,
   .init = &init,
   .cleanup = &cleanup,
   .startservice = &startservice,
index a1fd02f..1a5fb1d 100644 (file)
@@ -186,7 +186,7 @@ static int rollbackstopsess  (struct rahunas_map *map, struct task_req *req)
 
 static struct task task_memset = {
   .taskname = "MEMSET",
-  .taskprio = 3,
+  .taskprio = 40,
   .init = &init,
   .cleanup = &cleanup,
   .startservice = &startservice,
index 7c22f2f..202e986 100644 (file)
@@ -8,6 +8,8 @@
 #include "rh-task.h"
 #include "rh-task-memset.h"
 #include "rh-task-ipset.h"
+#include "rh-task-dbset.h"
+#include "rh-task-bandwidth.h"
 
 void task_register(struct task *task)
 {
@@ -62,6 +64,7 @@ void rh_task_init(void)
   rh_task_ipset_reg();
   rh_task_memset_reg();
   rh_task_dbset_reg();
+  rh_task_bandwidth_reg();
 
   /* Call each init */
   rh_task_call_init();
index 58eb8ea..4d15f61 100644 (file)
@@ -18,8 +18,8 @@ struct task_req {
   unsigned char mac_address[ETH_ALEN];
        time_t session_start;
   time_t session_timeout;
-  long bandwidth_max_down;
-  long bandwidth_max_up;
+  unsigned long bandwidth_max_down;
+  unsigned long bandwidth_max_up;
   unsigned short req_opt;
 };
 
index 2929ae3..8b78073 100644 (file)
@@ -126,7 +126,7 @@ $valid_text = !$valid ? "" : "" .
 "</table>";
 $request_uri = $_SERVER['REQUEST_URI'];
 $loginbox = "<style>" .
-            "#bg { background: #000000; width: 80%;}".
+            "#bg { color: #FFFFFF; background: #000000; width: 80%;}".
             "#rh_login_text { font-weight: bolder; }\n" .
             "#waiting { " .
             " position: absolute; ".
index 6b7affb..bee0a84 100644 (file)
                             </tr>\r
                             <tr>\r
                               <td></td>\r
+                              <td><font size="2" color="#FFFFFF">- สมัคร KKU-NET สำหรับนักศึกษา <a href="http://202.12.97.2/account/">Click</a></font></td>\r
+                            </tr>\r
+                            <tr>\r
+                              <td></td>\r
                               <td>&nbsp;</td>\r
                             </tr>\r
                           </table></td>\r