+++ /dev/null
-/* IPCop helper program - restartshaping\r
- *\r
- * This program is distributed under the terms of the GNU General Public\r
- * Licence. See the file COPYING for details.\r
- *\r
- * Copyright (C) 2002-04-09 Mark Wormgoor <mark@wormgoor.com>\r
- *\r
- * $Id: restartshaping.c,v 1.2.2.5 2005/01/28 13:11:40 riddles Exp $\r
- *\r
- */\r
-\r
-#include "libsmooth.h"\r
-#include "setuid.h"\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <sys/types.h>\r
-#include <sys/stat.h>\r
-#include <fcntl.h>\r
-#include <stdlib.h>\r
-\r
-int main(int argc, char *argv[])\r
-{\r
- FILE *file = NULL, *ifacefile = NULL;\r
- struct keyvalue *kv = NULL;\r
- int uplink, downlink, count = 0, r2q = 10;\r
- char command[STRING_SIZE];\r
- char iface[STRING_SIZE] = "";\r
- char s[STRING_SIZE];\r
- char *result;\r
- char proto[STRING_SIZE];\r
- char *protocol;\r
- char *port;\r
- char *prio;\r
- char *enabled;\r
-\r
- if (!(initsetuid())) {\r
- fprintf(stderr, "Cannot run setuid\n");\r
- exit(1);\r
- }\r
-\r
- /* Init the keyvalue structure */\r
- kv=initkeyvalues();\r
-\r
- /* Read in the current values */\r
- if (!readkeyvalues(kv, CONFIG_ROOT "/shaping/settings"))\r
- {\r
- fprintf(stderr, "Cannot read shaping settings\n");\r
- goto EXIT;\r
- }\r
-\r
- /* See what interface there is */\r
- if ((ifacefile = fopen(CONFIG_ROOT "/red/iface", "r")))\r
- {\r
- fgets(iface, STRING_SIZE, ifacefile);\r
- if (iface[strlen(iface) - 1] == '\n')\r
- iface[strlen(iface) - 1] = '\0';\r
- fclose (ifacefile);\r
- } else {\r
- fprintf(stderr, "Couldn't open iface file\n");\r
- return(1);\r
- }\r
-\r
- if (strspn(iface, LETTERS_NUMBERS) != strlen(iface))\r
- {\r
- fprintf(stderr, "Bad iface: %s\n", iface);\r
- goto EXIT;\r
- }\r
-\r
- /* Find the VALID value */\r
- if (!findkey(kv, "VALID", s))\r
- {\r
- fprintf(stderr, "Cannot read VALID\n");\r
- goto EXIT;\r
- }\r
-\r
- /* Check if config is VALID */\r
- if (! strcmp(s, "yes")==0)\r
- goto EXIT;\r
-\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc qdisc del dev %s root", iface);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc qdisc del dev %s ingress", iface);\r
- safe_system(command);\r
-\r
- /* Find the ENABLE value */\r
- if (!findkey(kv, "ENABLE", s))\r
- {\r
- fprintf(stderr, "Cannot read ENABLE\n");\r
- goto EXIT;\r
- }\r
-\r
- /* Check if shaping is ENABLED */\r
- if (! strcmp(s, "on")==0)\r
- goto EXIT;\r
-\r
- /* Find the UPLINK value */\r
- if (!findkey(kv, "UPLINK", s))\r
- {\r
- fprintf(stderr, "Cannot read UPLINK\n");\r
- goto EXIT;\r
- }\r
- uplink = atoi(s);\r
- if (! uplink > 0) {\r
- fprintf(stderr, "Invalid value for UPLINK\n");\r
- goto EXIT;\r
- }\r
- /* In some limited testing, it was shown that \r
- r2q = ( uplink * 1024 / 1500 );\r
- * produced error messages from the kernel saying r2q needed to be\r
- * changed. 1500 is taken as the MTU, but it seems that 16384 works\r
- * better. -Alan.\r
- */\r
- r2q = ( uplink * 1024 / 16384 );\r
- uplink = (uplink * 100) / 101;\r
-\r
- /* Find the DOWNLINK value */\r
- if (!findkey(kv, "DOWNLINK", s))\r
- {\r
- fprintf(stderr, "Cannot read DOWNLINK\n");\r
- goto EXIT;\r
- }\r
- downlink = atoi(s);\r
- if (! downlink > 0) {\r
- fprintf(stderr, "Invalid value for DOWNLINK\n");\r
- goto EXIT;\r
- }\r
- downlink = (downlink * 200) / 201;\r
-\r
- /* Uplink classes */\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc qdisc add dev %s root handle 1: htb default 20 r2q %d", iface, r2q);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc class add dev %s parent 1: classid 1:1 htb rate %dkbit", iface, uplink);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc class add dev %s parent 1:1 classid 1:10 htb rate %dkbit ceil %dkbit prio 1", iface, (8 * uplink) / 10, uplink);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc class add dev %s parent 1:1 classid 1:20 htb rate %dkbit ceil %dkbit prio 2", iface, (6 * uplink) / 10, uplink);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc class add dev %s parent 1:1 classid 1:30 htb rate %dkbit ceil %dkbit prio 3", iface, (4 * uplink) / 10, uplink);\r
- safe_system(command);\r
-\r
- /* Uplink Stochastic fairness queue */\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc qdisc add dev %s parent 1:10 handle 10: sfq perturb 10", iface);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc qdisc add dev %s parent 1:20 handle 20: sfq perturb 10", iface);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc qdisc add dev %s parent 1:30 handle 30: sfq perturb 10", iface);\r
- safe_system(command);\r
-\r
- /* TOS Minimum Delay and ICMP traffic for high priority queue */\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc filter add dev %s parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:10", iface);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc filter add dev %s parent 1:0 protocol ip prio 10 u32 match ip protocol 1 0xff flowid 1:10", iface);\r
- safe_system(command);\r
-\r
- /* ACK packets for high priority queue (to speed up downloads) */\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc filter add dev %s parent 1: protocol ip prio 10 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid 1:10", iface);\r
- safe_system(command);\r
-\r
- file = fopen(CONFIG_ROOT "/shaping/config", "r");\r
- if (file)\r
- {\r
- while (fgets(s, STRING_SIZE, file) != NULL)\r
- {\r
- if (s[strlen(s) - 1] == '\n')\r
- s[strlen(s) - 1] = '\0';\r
- result = strtok(s, ",");\r
-\r
- count = 0;\r
- protocol = NULL;\r
- port = NULL;\r
- prio = NULL;\r
- enabled = NULL;\r
- while (result)\r
- {\r
- if (count == 0)\r
- protocol = result;\r
- else if (count == 1)\r
- port = result;\r
- else if (count == 2)\r
- prio = result;\r
- else if (count == 3)\r
- enabled = result;\r
- count++;\r
- result = strtok(NULL, ",");\r
- }\r
- if (!(protocol && port && prio && enabled))\r
- break;\r
- if (strcmp(protocol, "tcp") == 0) {\r
- strcpy(proto, "6");\r
- } else if (strcmp(protocol, "udp") == 0) {\r
- strcpy(proto, "17");\r
- } else {\r
- fprintf(stderr, "Bad protocol: %s\n", protocol);\r
- goto EXIT;\r
- }\r
- if (strspn(port, PORT_NUMBERS) != strlen(port))\r
- {\r
- fprintf(stderr, "Bad port: %s\n", port);\r
- goto EXIT;\r
- }\r
- if (strspn(prio, NUMBERS) != strlen(prio))\r
- {\r
- fprintf(stderr, "Bad priority: %s\n", prio);\r
- goto EXIT;\r
- }\r
-\r
- if (strcmp(enabled, "on") == 0)\r
- {\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc filter add dev %s parent 1: protocol ip prio 14 u32 match ip protocol %s 0xff match ip dport %s 0xffff flowid 1:%s", iface, proto, port, prio);\r
-\r
- safe_system(command);\r
-\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc filter add dev %s parent 1: protocol ip prio 15 u32 match ip protocol %s 0xff match ip sport %s 0xffff flowid 1:%s", iface, proto, port, prio);\r
-\r
- safe_system(command);\r
- }\r
- }\r
- }\r
-\r
- /* Setting everything else to the default queue */\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc filter add dev %s parent 1: protocol ip prio 18 u32 match ip dst 0.0.0.0/0 flowid 1:20", iface);\r
- safe_system(command);\r
-\r
- /* Downlink Section */\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc qdisc add dev %s handle ffff: ingress", iface);\r
- safe_system(command);\r
- snprintf(command, STRING_SIZE-1, "/sbin/tc filter add dev %s parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate %dkbit burst 10k drop flowid :1", iface, downlink);\r
- safe_system(command);\r
-\r
-EXIT:\r
- if (kv) freekeyvalues(kv);\r
- if (file) fclose(file);\r
- return 0;\r
-}\r