From: bodea Date: Tue, 11 Oct 2005 09:04:53 +0000 (+0000) Subject: add Cisco-AVPairs to RADIUS accounting records via plugin_radius_account X-Git-Tag: release_2_1_9 X-Git-Url: http://git.sameswireless.fr/l2tpns.git/commitdiff_plain/f6b56a0f4d893dc98cf029de7bd58ac4f2a64db7 add Cisco-AVPairs to RADIUS accounting records via plugin_radius_account --- diff --git a/Changes b/Changes index dfeabaa..aee33c3 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,7 @@ - Fix RADIUS authentication on DAE responses. - Don't send tunnel HELLO when there are pending control messages. - Move plugin_radius_reset from *ctl to auto* plugins. +- Add Cisco-AVPairs to RADIUS accounting records via plugin_radius_account. * Mon Sep 19 2005 Brendan O'Dea 2.1.8 - Move code from signal handlers into mainloop, avoiding a race diff --git a/autosnoop.c b/autosnoop.c index 4ac2171..fa3de8b 100644 --- a/autosnoop.c +++ b/autosnoop.c @@ -4,46 +4,72 @@ /* set up intercept based on RADIUS reply */ -char const *cvs_id = "$Id: autosnoop.c,v 1.11 2005/10/11 07:59:09 bodea Exp $"; +char const *cvs_id = "$Id: autosnoop.c,v 1.12 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -struct pluginfuncs *p; +static struct pluginfuncs *f = 0; int plugin_radius_response(struct param_radius_response *data) { - if (!strcmp(data->key, "intercept")) + if (!strcmp(data->key, "intercept")) + { + char *p; + data->s->snoop_ip = 0; + data->s->snoop_port = 0; + if ((p = strchr(data->value, ':'))) { - char *x; + *p++ = 0; + if (*data->value) + data->s->snoop_ip = inet_addr(data->value); + + if (data->s->snoop_ip == INADDR_NONE) data->s->snoop_ip = 0; - data->s->snoop_port = 0; - if ((x = strchr(data->value, ':'))) - { - *x++ = 0; - if (*data->value) data->s->snoop_ip = inet_addr(data->value); - if (data->s->snoop_ip == INADDR_NONE) data->s->snoop_ip = 0; - if (*x) data->s->snoop_port = atoi(x); - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Intercepting user to %s:%d\n", - p->fmtaddr(data->s->snoop_ip, 0), data->s->snoop_port); - } - else - { - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Not Intercepting user (reply string should be intercept=ip:port)\n"); - } + + if (*p) + data->s->snoop_port = atoi(p); + + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Intercepting user to %s:%d\n", + f->fmtaddr(data->s->snoop_ip, 0), data->s->snoop_port); + } + else + { + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Not Intercepting user (reply string should" + " be intercept=ip:port)\n"); } + } return PLUGIN_RET_OK; } int plugin_radius_reset(struct param_radius_reset *data) { - data->s->snoop_ip = 0; - data->s->snoop_port = 0; - return PLUGIN_RET_OK; + data->s->snoop_ip = 0; + data->s->snoop_port = 0; + return PLUGIN_RET_OK; +} + +int plugin_radius_account(struct param_radius_account *data) +{ + if (data->s->snoop_ip && data->s->snoop_port) + { + uint8_t *p = *data->packet; + + *p = 26; // vendor-specific + *(uint32_t *) (p + 2) = htonl(9); // Cisco + p[6] = 1; // Cisco-AVPair + p[7] = 2 + sprintf((char *) p + 8, "intercept=%s:%d", + f->fmtaddr(data->s->snoop_ip, 0), data->s->snoop_port); + + p[1] = p[7] + 6; + *data->packet += p[1]; + } + + return PLUGIN_RET_OK; } int plugin_init(struct pluginfuncs *funcs) { - return ((p = funcs)) ? 1 : 0; + return ((f = funcs)) ? 1 : 0; } diff --git a/autothrottle.c b/autothrottle.c index 8f81776..cd42365 100644 --- a/autothrottle.c +++ b/autothrottle.c @@ -13,110 +13,146 @@ * throttle=no */ -char const *cvs_id = "$Id: autothrottle.c,v 1.15 2005/10/11 07:59:09 bodea Exp $"; +char const *cvs_id = "$Id: autothrottle.c,v 1.16 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -struct pluginfuncs *p; +static struct pluginfuncs *f = 0; #define THROTTLE_KEY "lcp:interface-config" int plugin_radius_response(struct param_radius_response *data) { - if (!strncmp(data->key, THROTTLE_KEY, sizeof(THROTTLE_KEY) - 1)) + if (!strncmp(data->key, THROTTLE_KEY, sizeof(THROTTLE_KEY) - 1)) + { + char *sp = strchr(data->value, ' '); + char type; + int rate; + + if (!sp || sp - data->value < 4 || + strncmp("service-policy", data->value, sp - data->value)) + return PLUGIN_RET_OK; + + while (*sp == ' ') sp++; + data->value = sp; + + if (!(sp = strchr(data->value, ' ')) || + (strncmp("input", data->value, sp - data->value) && + strncmp("output", data->value, sp - data->value))) { - char *sp = strchr(data->value, ' '); - char type; - int rate; - - if (!sp || sp - data->value < 4 || - strncmp("service-policy", data->value, sp - data->value)) - return PLUGIN_RET_OK; - - while (*sp == ' ') sp++; - data->value = sp; - - if (!(sp = strchr(data->value, ' ')) || - (strncmp("input", data->value, sp - data->value) && - strncmp("output", data->value, sp - data->value))) - { - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Not throttling user (invalid type %.*s)\n", - sp - data->value, data->value); - - return PLUGIN_RET_OK; - } - - type = *data->value; - - while (*sp == ' ') sp++; - data->value = sp; - - if ((rate = strtol(data->value, &sp, 10)) < 0 || *sp) - { - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Not throttling user (invalid rate %s)\n", - data->value); - - return PLUGIN_RET_OK; - } - - if (type == 'i') - { - data->s->throttle_in = rate; - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Throttling user input to %dkb/s\n", - rate); - } - else - { - data->s->throttle_out = rate; - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Throttling user output to %dkb/s\n", - rate); - } + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Not throttling user (invalid type %.*s)\n", + sp - data->value, data->value); + + return PLUGIN_RET_OK; + } + + type = *data->value; + + while (*sp == ' ') sp++; + data->value = sp; + + if ((rate = strtol(data->value, &sp, 10)) < 0 || *sp) + { + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Not throttling user (invalid rate %s)\n", + data->value); + + return PLUGIN_RET_OK; } - if (!strcmp(data->key, "throttle")) + if (type == 'i') { - char *e; - int rate; - - if ((rate = strtol(data->value, &e, 10)) < 0 || *e) - { - rate = -1; - if (!strcmp(data->value, "yes")) - { - unsigned long *ts = p->getconfig("throttle_speed", UNSIGNED_LONG); - if (ts) - rate = *ts; - } - else if (!strcmp(data->value, "no")) - rate = 0; - } - - if (rate < 0) - return PLUGIN_RET_OK; - - if (rate) - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Throttling user to %dkb/s\n", rate); - else - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, - " Not throttling user\n"); - - data->s->throttle_in = data->s->throttle_out = rate; + data->s->throttle_in = rate; + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Throttling user input to %dkb/s\n", rate); } + else + { + data->s->throttle_out = rate; + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Throttling user output to %dkb/s\n", rate); + } + } + else if (!strcmp(data->key, "throttle")) + { + char *e; + int rate; + + if ((rate = strtol(data->value, &e, 10)) < 0 || *e) + { + rate = -1; + if (!strcmp(data->value, "yes")) + { + unsigned long *ts = f->getconfig("throttle_speed", UNSIGNED_LONG); + if (ts) + rate = *ts; + } + else if (!strcmp(data->value, "no")) + rate = 0; + } + + if (rate < 0) + return PLUGIN_RET_OK; - return PLUGIN_RET_OK; + if (rate) + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Throttling user to %dkb/s\n", rate); + else + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + " Not throttling user\n"); + + data->s->throttle_in = data->s->throttle_out = rate; + } + + return PLUGIN_RET_OK; } int plugin_radius_reset(struct param_radius_reset *data) { - p->throttle(p->get_id_by_session(data->s), 0, 0); - return PLUGIN_RET_OK; + f->throttle(f->get_id_by_session(data->s), 0, 0); + return PLUGIN_RET_OK; +} + +int plugin_radius_account(struct param_radius_account *data) +{ + if (data->s->throttle_in || data->s->throttle_out) + { + uint8_t *p = *data->packet; + int i = 1; + + if (data->s->throttle_in) + { + *p = 26; // vendor-specific + *(uint32_t *) (p + 2) = htonl(9); // Cisco + p[6] = 1; // Cisco-AVPair + p[7] = 2 + sprintf((char *) p + 8, + "lcp:interface-config#%d=service-policy input %d", i++, + data->s->throttle_in); + + p[1] = p[7] + 6; + p += p[1]; + } + + if (data->s->throttle_out) + { + *p = 26; // vendor-specific + *(uint32_t *) (p + 2) = htonl(9); // Cisco + p[6] = 1; // Cisco-AVPair + p[7] = 2 + sprintf((char *) p + 8, + "lcp:interface-config#%d=service-policy output %d", i++, + data->s->throttle_out); + + p[1] = p[7] + 6; + p += p[1]; + } + + *data->packet = p; + } + + return PLUGIN_RET_OK; } int plugin_init(struct pluginfuncs *funcs) { - return ((p = funcs)) ? 1 : 0; + return ((f = funcs)) ? 1 : 0; } diff --git a/garden.c b/garden.c index b352e7b..e445d41 100644 --- a/garden.c +++ b/garden.c @@ -9,35 +9,35 @@ /* walled garden */ -char const *cvs_id = "$Id: garden.c,v 1.23 2005/06/02 11:32:30 bodea Exp $"; +char const *cvs_id = "$Id: garden.c,v 1.24 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -static struct pluginfuncs *p = 0; +static struct pluginfuncs *f = 0; static int iam_master = 0; // We're all slaves! Slaves I tell you! char *up_commands[] = { - "iptables -t nat -N garden >/dev/null 2>&1", // Create a chain that all gardened users will go through - "iptables -t nat -F garden", - ". " PLUGINCONF "/build-garden", // Populate with site-specific DNAT rules - "iptables -t nat -N garden_users >/dev/null 2>&1", // Empty chain, users added/removed by garden_session - "iptables -t nat -F garden_users", - "iptables -t nat -A PREROUTING -j garden_users", // DNAT any users on the garden_users chain - "sysctl -w net.ipv4.ip_conntrack_max=512000 >/dev/null", // lots of entries - NULL, + "iptables -t nat -N garden >/dev/null 2>&1", // Create a chain that all gardened users will go through + "iptables -t nat -F garden", + ". " PLUGINCONF "/build-garden", // Populate with site-specific DNAT rules + "iptables -t nat -N garden_users >/dev/null 2>&1", // Empty chain, users added/removed by garden_session + "iptables -t nat -F garden_users", + "iptables -t nat -A PREROUTING -j garden_users", // DNAT any users on the garden_users chain + "sysctl -w net.ipv4.ip_conntrack_max=512000 >/dev/null", // lots of entries + NULL, }; char *down_commands[] = { - "iptables -t nat -F PREROUTING", - "iptables -t nat -F garden_users", - "iptables -t nat -X garden_users", - "iptables -t nat -F garden", - "iptables -t nat -X garden", - "rmmod iptable_nat", // Should also remove ip_conntrack, but + "iptables -t nat -F PREROUTING", + "iptables -t nat -F garden_users", + "iptables -t nat -X garden_users", + "iptables -t nat -F garden", + "iptables -t nat -X garden", + "rmmod iptable_nat", // Should also remove ip_conntrack, but // doing so can take hours... literally. // If a master is re-started as a slave, // either rmmod manually, or reboot. - NULL, + NULL, }; #define F_UNGARDEN 0 @@ -48,234 +48,249 @@ int garden_session(sessiont *s, int flag, char *newuser); int plugin_post_auth(struct param_post_auth *data) { - // Ignore if user authentication was successful - if (data->auth_allowed) return PLUGIN_RET_OK; - - p->log(3, p->get_id_by_session(data->s), data->s->tunnel, "Walled Garden allowing login\n"); - data->auth_allowed = 1; - data->s->walled_garden = 1; + // Ignore if user authentication was successful + if (data->auth_allowed) return PLUGIN_RET_OK; + + f->log(3, f->get_id_by_session(data->s), data->s->tunnel, + "Walled Garden allowing login\n"); + + data->auth_allowed = 1; + data->s->walled_garden = 1; + return PLUGIN_RET_OK; } int plugin_new_session(struct param_new_session *data) { - if (!iam_master) - return PLUGIN_RET_OK; // Slaves don't do walled garden processing. + if (!iam_master) + return PLUGIN_RET_OK; // Slaves don't do walled garden processing. - if (data->s->walled_garden) - garden_session(data->s, F_GARDEN, 0); + if (data->s->walled_garden) + garden_session(data->s, F_GARDEN, 0); - return PLUGIN_RET_OK; + return PLUGIN_RET_OK; } int plugin_kill_session(struct param_new_session *data) { - if (!iam_master) - return PLUGIN_RET_OK; // Slaves don't do walled garden processing. + if (!iam_master) + return PLUGIN_RET_OK; // Slaves don't do walled garden processing. - if (data->s->walled_garden) - garden_session(data->s, F_CLEANUP, 0); + if (data->s->walled_garden) + garden_session(data->s, F_CLEANUP, 0); - return PLUGIN_RET_OK; + return PLUGIN_RET_OK; } char *plugin_control_help[] = { - " garden USER|SID Put user into the walled garden", - " ungarden SID [USER] Release session from garden", - 0 + " garden USER|SID Put user into the walled garden", + " ungarden SID [USER] Release session from garden", + 0 }; int plugin_control(struct param_control *data) { - sessionidt session; - sessiont *s = 0; - int flag; - char *end; + sessionidt session; + sessiont *s = 0; + int flag; + char *end; - if (data->argc < 1) - return PLUGIN_RET_OK; + if (data->argc < 1) + return PLUGIN_RET_OK; - if (strcmp(data->argv[0], "garden") && strcmp(data->argv[0], "ungarden")) - return PLUGIN_RET_OK; // not for us + if (strcmp(data->argv[0], "garden") && strcmp(data->argv[0], "ungarden")) + return PLUGIN_RET_OK; // not for us - if (!iam_master) - return PLUGIN_RET_NOTMASTER; + if (!iam_master) + return PLUGIN_RET_NOTMASTER; - flag = data->argv[0][0] == 'g' ? F_GARDEN : F_UNGARDEN; + flag = data->argv[0][0] == 'g' ? F_GARDEN : F_UNGARDEN; - if (data->argc < 2 || data->argc > 3 || (data->argc > 2 && flag == F_GARDEN)) - { - data->response = NSCTL_RES_ERR; - data->additional = flag == F_GARDEN - ? "requires username or session id" - : "requires session id and optional username"; + if (data->argc < 2 || data->argc > 3 || (data->argc > 2 && flag == F_GARDEN)) + { + data->response = NSCTL_RES_ERR; + data->additional = flag == F_GARDEN + ? "requires username or session id" + : "requires session id and optional username"; - return PLUGIN_RET_STOP; - } + return PLUGIN_RET_STOP; + } - if (!(session = strtol(data->argv[1], &end, 10)) || *end) - { - if (flag) - session = p->get_session_by_username(data->argv[1]); - else - session = 0; // can't ungarden by username - } + if (!(session = strtol(data->argv[1], &end, 10)) || *end) + { + if (flag) + session = f->get_session_by_username(data->argv[1]); + else + session = 0; // can't ungarden by username + } - if (session) - s = p->get_session_by_id(session); + if (session) + s = f->get_session_by_id(session); - if (!s || !s->ip) - { - data->response = NSCTL_RES_ERR; - data->additional = "session not found"; - return PLUGIN_RET_STOP; - } + if (!s || !s->ip) + { + data->response = NSCTL_RES_ERR; + data->additional = "session not found"; + return PLUGIN_RET_STOP; + } - if (s->walled_garden == flag) - { - data->response = NSCTL_RES_ERR; - data->additional = flag ? "already in walled garden" : "not in walled garden"; - return PLUGIN_RET_STOP; - } + if (s->walled_garden == flag) + { + data->response = NSCTL_RES_ERR; + data->additional = flag ? "already in walled garden" : "not in walled garden"; + return PLUGIN_RET_STOP; + } - garden_session(s, flag, data->argc > 2 ? data->argv[2] : 0); - p->session_changed(session); + garden_session(s, flag, data->argc > 2 ? data->argv[2] : 0); + f->session_changed(session); - data->response = NSCTL_RES_OK; - data->additional = 0; + data->response = NSCTL_RES_OK; + data->additional = 0; - return PLUGIN_RET_STOP; + return PLUGIN_RET_STOP; } int plugin_become_master(void) { - int i; - iam_master = 1; // We just became the master. Wow! + int i; + iam_master = 1; // We just became the master. Wow! - for (i = 0; up_commands[i] && *up_commands[i]; i++) - { - p->log(3, 0, 0, "Running %s\n", up_commands[i]); - system(up_commands[i]); - } + for (i = 0; up_commands[i] && *up_commands[i]; i++) + { + f->log(3, 0, 0, "Running %s\n", up_commands[i]); + system(up_commands[i]); + } - return PLUGIN_RET_OK; + return PLUGIN_RET_OK; } // Called for each active session after becoming master int plugin_new_session_master(sessiont *s) { - if (s->walled_garden) - garden_session(s, F_GARDEN, 0); + if (s->walled_garden) + garden_session(s, F_GARDEN, 0); - return PLUGIN_RET_OK; + return PLUGIN_RET_OK; } int garden_session(sessiont *s, int flag, char *newuser) { - char cmd[2048]; - sessionidt sess; + char cmd[2048]; + sessionidt sess; + + if (!s) return 0; + if (!s->opened) return 0; + + sess = f->get_id_by_session(s); + if (flag == F_GARDEN) + { + f->log(2, sess, s->tunnel, "Garden user %s (%s)\n", s->user, + f->fmtaddr(htonl(s->ip), 0)); + + snprintf(cmd, sizeof(cmd), + "iptables -t nat -A garden_users -s %s -j garden", + f->fmtaddr(htonl(s->ip), 0)); + + f->log(3, sess, s->tunnel, "%s\n", cmd); + system(cmd); + s->walled_garden = 1; + } + else + { + sessionidt other; + int count = 40; + + // Normal User + f->log(2, sess, s->tunnel, "Un-Garden user %s (%s)\n", s->user, f->fmtaddr(htonl(s->ip), 0)); + if (newuser) + { + snprintf(s->user, MAXUSER, "%s", newuser); + f->log(2, sess, s->tunnel, " Setting username to %s\n", s->user); + } - if (!s) return 0; - if (!s->opened) return 0; + // Kick off any duplicate usernames + // but make sure not to kick off ourself + if (s->ip && !s->die && (other = f->get_session_by_username(s->user)) && + s != f->get_session_by_id(other)) + { + f->sessionkill(other, + "Duplicate session when user released from walled garden"); + } + + /* Clean up counters */ + s->pin = s->pout = 0; + s->cin = s->cout = 0; + s->cin_delta = s->cout_delta = 0; + s->cin_wrap = s->cout_wrap = 0; - sess = p->get_id_by_session(s); - if (flag == F_GARDEN) + snprintf(cmd, sizeof(cmd), + "iptables -t nat -D garden_users -s %s -j garden", + f->fmtaddr(htonl(s->ip), 0)); + + f->log(3, sess, s->tunnel, "%s\n", cmd); + while (--count) { - p->log(2, sess, s->tunnel, "Garden user %s (%s)\n", s->user, p->fmtaddr(htonl(s->ip), 0)); - snprintf(cmd, sizeof(cmd), "iptables -t nat -A garden_users -s %s -j garden", p->fmtaddr(htonl(s->ip), 0)); - p->log(3, sess, s->tunnel, "%s\n", cmd); - system(cmd); - s->walled_garden = 1; + int status = system(cmd); + if (WEXITSTATUS(status) != 0) break; } - else + + s->walled_garden = 0; + + if (flag != F_CLEANUP) { - sessionidt other; - int count = 40; - - // Normal User - p->log(2, sess, s->tunnel, "Un-Garden user %s (%s)\n", s->user, p->fmtaddr(htonl(s->ip), 0)); - if (newuser) - { - snprintf(s->user, MAXUSER, "%s", newuser); - p->log(2, sess, s->tunnel, " Setting username to %s\n", s->user); - } - - // Kick off any duplicate usernames - // but make sure not to kick off ourself - if (s->ip && !s->die && (other = p->get_session_by_username(s->user)) && s != p->get_session_by_id(other)) { - p->sessionkill(other, "Duplicate session when user released from walled garden"); - } - /* Clean up counters */ - s->pin = s->pout = 0; - s->cin = s->cout = 0; - s->cin_delta = s->cout_delta = 0; - s->cin_wrap = s->cout_wrap = 0; - - snprintf(cmd, sizeof(cmd), "iptables -t nat -D garden_users -s %s -j garden", p->fmtaddr(htonl(s->ip), 0)); - p->log(3, sess, s->tunnel, "%s\n", cmd); - while (--count) - { - int status = system(cmd); - if (WEXITSTATUS(status) != 0) break; - } - - s->walled_garden = 0; - - if (flag != F_CLEANUP) - { - /* OK, we're up! */ - uint16_t r = p->radiusnew(p->get_id_by_session(s)); - if (r) p->radiussend(r, RADIUSSTART); - } + /* OK, we're up! */ + uint16_t r = f->radiusnew(f->get_id_by_session(s)); + if (r) f->radiussend(r, RADIUSSTART); } + } - return 1; + return 1; } int plugin_init(struct pluginfuncs *funcs) { - FILE *tables; - int found_nat = 0; + FILE *tables; + int found_nat = 0; - if (!funcs) - return 0; + if (!funcs) + return 0; - p = funcs; + f = funcs; - if ((tables = fopen("/proc/net/ip_tables_names", "r"))) - { - char buf[1024]; - while (fgets(buf, sizeof(buf), tables) && !found_nat) - found_nat = !strcmp(buf, "nat\n"); + if ((tables = fopen("/proc/net/ip_tables_names", "r"))) + { + char buf[1024]; + while (fgets(buf, sizeof(buf), tables) && !found_nat) + found_nat = !strcmp(buf, "nat\n"); - fclose(tables); - } + fclose(tables); + } - /* master killed/crashed? */ - if (found_nat) + /* master killed/crashed? */ + if (found_nat) + { + int i; + for (i = 0; down_commands[i] && *down_commands[i]; i++) { - int i; - for (i = 0; down_commands[i] && *down_commands[i]; i++) - { - p->log(3, 0, 0, "Running %s\n", down_commands[i]); - system(down_commands[i]); - } + f->log(3, 0, 0, "Running %s\n", down_commands[i]); + system(down_commands[i]); } + } - return 1; + return 1; } void plugin_done() { - int i; + int i; - if (!iam_master) // Never became master. nothing to do. - return; + if (!iam_master) // Never became master. nothing to do. + return; - for (i = 0; down_commands[i] && *down_commands[i]; i++) - { - p->log(3, 0, 0, "Running %s\n", down_commands[i]); - system(down_commands[i]); - } + for (i = 0; down_commands[i] && *down_commands[i]; i++) + { + f->log(3, 0, 0, "Running %s\n", down_commands[i]); + system(down_commands[i]); + } } diff --git a/l2tpns.c b/l2tpns.c index ec2bd17..6d1bb54 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -4,7 +4,7 @@ // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // vim: sw=8 ts=8 -char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.143 2005/10/11 07:06:56 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.144 2005/10/11 09:04:53 bodea Exp $"; #include #include @@ -162,6 +162,7 @@ static char *plugin_functions[] = { "plugin_control", "plugin_radius_response", "plugin_radius_reset", + "plugin_radius_account", "plugin_become_master", "plugin_new_session_master", }; diff --git a/plugin.h b/plugin.h index faf3a5e..a57d700 100644 --- a/plugin.h +++ b/plugin.h @@ -6,18 +6,19 @@ enum { - PLUGIN_PRE_AUTH = 1, - PLUGIN_POST_AUTH, - PLUGIN_PACKET_RX, - PLUGIN_PACKET_TX, - PLUGIN_TIMER, - PLUGIN_NEW_SESSION, - PLUGIN_KILL_SESSION, - PLUGIN_CONTROL, - PLUGIN_RADIUS_RESPONSE, - PLUGIN_RADIUS_RESET, - PLUGIN_BECOME_MASTER, - PLUGIN_NEW_SESSION_MASTER, + PLUGIN_PRE_AUTH = 1, + PLUGIN_POST_AUTH, + PLUGIN_PACKET_RX, + PLUGIN_PACKET_TX, + PLUGIN_TIMER, + PLUGIN_NEW_SESSION, + PLUGIN_KILL_SESSION, + PLUGIN_CONTROL, + PLUGIN_RADIUS_RESPONSE, + PLUGIN_RADIUS_RESET, + PLUGIN_RADIUS_ACCOUNT, + PLUGIN_BECOME_MASTER, + PLUGIN_NEW_SESSION_MASTER, }; #define PLUGIN_RET_ERROR 0 @@ -27,95 +28,102 @@ enum struct pluginfuncs { - void (*log)(int level, sessionidt s, tunnelidt t, const char *format, ...); - void (*log_hex)(int level, const char *title, const uint8_t *data, int maxsize); - char *(*fmtaddr)(in_addr_t addr, int n); - sessionidt (*get_session_by_username)(char *username); - sessiont *(*get_session_by_id)(sessionidt s); - sessionidt (*get_id_by_session)(sessiont *s); - uint16_t (*radiusnew)(sessionidt s); - void (*radiussend)(uint16_t r, uint8_t state); - void *(*getconfig)(char *key, enum config_typet type); - void (*sessionshutdown)(sessionidt s, char *reason, int result, int error); - void (*sessionkill)(sessionidt s, char *reason); - void (*throttle)(sessionidt s, int rate_in, int rate_out); - int (*session_changed)(int sid); + void (*log)(int level, sessionidt s, tunnelidt t, const char *format, ...); + void (*log_hex)(int level, const char *title, const uint8_t *data, int maxsize); + char *(*fmtaddr)(in_addr_t addr, int n); + sessionidt (*get_session_by_username)(char *username); + sessiont *(*get_session_by_id)(sessionidt s); + sessionidt (*get_id_by_session)(sessiont *s); + uint16_t (*radiusnew)(sessionidt s); + void (*radiussend)(uint16_t r, uint8_t state); + void *(*getconfig)(char *key, enum config_typet type); + void (*sessionshutdown)(sessionidt s, char *reason, int result, int error); + void (*sessionkill)(sessionidt s, char *reason); + void (*throttle)(sessionidt s, int rate_in, int rate_out); + int (*session_changed)(int sid); }; struct param_pre_auth { - tunnelt *t; - sessiont *s; - char *username; - char *password; - int protocol; - int continue_auth; + tunnelt *t; + sessiont *s; + char *username; + char *password; + int protocol; + int continue_auth; }; struct param_post_auth { - tunnelt *t; - sessiont *s; - char *username; - short auth_allowed; - int protocol; + tunnelt *t; + sessiont *s; + char *username; + short auth_allowed; + int protocol; }; struct param_packet_rx { - tunnelt *t; - sessiont *s; - char *buf; - int len; + tunnelt *t; + sessiont *s; + char *buf; + int len; }; struct param_packet_tx { - tunnelt *t; - sessiont *s; - char *buf; - int len; + tunnelt *t; + sessiont *s; + char *buf; + int len; }; struct param_timer { - time_t time_now; + time_t time_now; }; struct param_control { - int iam_master; - int argc; - char **argv; - // output - int response; - char *additional; + int iam_master; + int argc; + char **argv; + // output + int response; + char *additional; }; struct param_new_session { - tunnelt *t; - sessiont *s; + tunnelt *t; + sessiont *s; }; struct param_kill_session { - tunnelt *t; - sessiont *s; + tunnelt *t; + sessiont *s; }; struct param_radius_response { - tunnelt *t; - sessiont *s; - char *key; - char *value; + tunnelt *t; + sessiont *s; + char *key; + char *value; }; struct param_radius_reset { - tunnelt *t; - sessiont *s; + tunnelt *t; + sessiont *s; +}; + +struct param_radius_account +{ + tunnelt *t; + sessiont *s; + uint8_t **packet; }; #endif /* __PLUGIN_H__ */ diff --git a/radius.c b/radius.c index 0059fcc..55aa6cb 100644 --- a/radius.c +++ b/radius.c @@ -1,6 +1,6 @@ // L2TPNS Radius Stuff -char const *cvs_id_radius = "$Id: radius.c,v 1.43 2005/10/11 02:27:40 foonly Exp $"; +char const *cvs_id_radius = "$Id: radius.c,v 1.44 2005/10/11 09:04:53 bodea Exp $"; #include #include @@ -304,18 +304,11 @@ void radiussend(uint16_t r, uint8_t state) p[1] = 6; *(uint32_t *) (p + 2) = htonl(session[s].cout_wrap); p += p[1]; - } - - if (session[s].snoop_ip && session[s].snoop_port) - { - *p = 26; // vendor-specific - *(uint32_t *) (p + 2) = htonl(9); // Cisco - p[6] = 1; // Cisco-AVPair - p[7] = 2 + sprintf((char *) p + 8, "intercept=%s:%d", - fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port); - p[1] = p[7] + 6; - p += p[1]; + { + struct param_radius_account acct = { &tunnel[session[s].tunnel], &session[s], &p }; + run_plugins(PLUGIN_RADIUS_ACCOUNT, &acct); + } } } } diff --git a/sessionctl.c b/sessionctl.c index 1b6d7f7..cc6a113 100644 --- a/sessionctl.c +++ b/sessionctl.c @@ -5,10 +5,10 @@ /* session control */ -char const *cvs_id = "$Id: sessionctl.c,v 1.3 2005/06/28 14:48:28 bodea Exp $"; +char const *cvs_id = "$Id: sessionctl.c,v 1.4 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -static struct pluginfuncs *p = 0; +static struct pluginfuncs *f = 0; char *plugin_control_help[] = { " drop USER|SID [REASON] Shutdown user session", @@ -40,10 +40,10 @@ int plugin_control(struct param_control *data) } if (!(session = strtol(data->argv[1], &end, 10)) || *end) - session = p->get_session_by_username(data->argv[1]); + session = f->get_session_by_username(data->argv[1]); if (session) - s = p->get_session_by_id(session); + s = f->get_session_by_id(session); if (!s || !s->ip) { @@ -58,9 +58,9 @@ int plugin_control(struct param_control *data) reason = "Requested by administrator."; if (data->argv[0][0] == 'd') - p->sessionshutdown(session, reason, 3, 0); + f->sessionshutdown(session, reason, 3, 0); else - p->sessionkill(session, reason); + f->sessionkill(session, reason); data->response = NSCTL_RES_OK; data->additional = 0; @@ -70,5 +70,5 @@ int plugin_control(struct param_control *data) int plugin_init(struct pluginfuncs *funcs) { - return ((p = funcs)) ? 1 : 0; + return ((f = funcs)) ? 1 : 0; } diff --git a/setrxspeed.c b/setrxspeed.c index fcb129d..2e9e663 100644 --- a/setrxspeed.c +++ b/setrxspeed.c @@ -4,34 +4,38 @@ /* fudge up session rx speed if not set */ -char const *cvs_id = "$Id: setrxspeed.c,v 1.3 2004/11/17 08:23:35 bodea Exp $"; +char const *cvs_id = "$Id: setrxspeed.c,v 1.4 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -static struct pluginfuncs *p = 0; +static struct pluginfuncs *f = 0; int plugin_post_auth(struct param_post_auth *data) { - if (!data->auth_allowed) return PLUGIN_RET_OK; - - if (!data->s->rx_connect_speed) - { - switch (data->s->tx_connect_speed) - { - case 256 : - data->s->rx_connect_speed = 64; - break; - case 512 : - data->s->rx_connect_speed = 128; - break; - case 1500 : - data->s->rx_connect_speed = 256; - break; - } - } - return PLUGIN_RET_OK; + if (!data->auth_allowed) + return PLUGIN_RET_OK; + + if (data->s->rx_connect_speed) + return PLUGIN_RET_OK; + + switch (data->s->tx_connect_speed) + { + case 256: + data->s->rx_connect_speed = 64; + break; + + case 512: + data->s->rx_connect_speed = 128; + break; + + case 1500: + data->s->rx_connect_speed = 256; + break; + } + + return PLUGIN_RET_OK; } int plugin_init(struct pluginfuncs *funcs) { - return ((p = funcs)) ? 1 : 0; + return ((f = funcs)) ? 1 : 0; } diff --git a/snoopctl.c b/snoopctl.c index 0bb46da..6c79087 100644 --- a/snoopctl.c +++ b/snoopctl.c @@ -5,118 +5,118 @@ /* snoop control */ -char const *cvs_id = "$Id: snoopctl.c,v 1.6 2005/10/11 07:59:09 bodea Exp $"; +char const *cvs_id = "$Id: snoopctl.c,v 1.7 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -static struct pluginfuncs *p = 0; +static struct pluginfuncs *f = 0; char *plugin_control_help[] = { - " snoop USER|SID IP PORT Intercept user traffic", - " unsnoop USER|SID Stop intercepting user", - 0 + " snoop USER|SID IP PORT Intercept user traffic", + " unsnoop USER|SID Stop intercepting user", + 0 }; int plugin_control(struct param_control *data) { - sessionidt session; - sessiont *s = 0; - int flag; - char *end; + sessionidt session; + sessiont *s = 0; + int flag; + char *end; - if (data->argc < 1) - return PLUGIN_RET_OK; + if (data->argc < 1) + return PLUGIN_RET_OK; - if (strcmp(data->argv[0], "snoop") && strcmp(data->argv[0], "unsnoop")) - return PLUGIN_RET_OK; // not for us + if (strcmp(data->argv[0], "snoop") && strcmp(data->argv[0], "unsnoop")) + return PLUGIN_RET_OK; // not for us - if (!data->iam_master) - return PLUGIN_RET_NOTMASTER; + if (!data->iam_master) + return PLUGIN_RET_NOTMASTER; - flag = data->argv[0][0] != 'u'; + flag = data->argv[0][0] != 'u'; - if (flag) + if (flag) + { + if (data->argc != 4) { - if (data->argc != 4) - { - data->response = NSCTL_RES_ERR; - data->additional = "requires username or session id and host, port"; - return PLUGIN_RET_STOP; - } + data->response = NSCTL_RES_ERR; + data->additional = "requires username or session id and host, port"; + return PLUGIN_RET_STOP; } - else + } + else + { + if (data->argc != 2) { - if (data->argc != 2) - { - data->response = NSCTL_RES_ERR; - data->additional = "requires username or session id"; - return PLUGIN_RET_STOP; - } + data->response = NSCTL_RES_ERR; + data->additional = "requires username or session id"; + return PLUGIN_RET_STOP; } + } - if (!(session = strtol(data->argv[1], &end, 10)) || *end) - session = p->get_session_by_username(data->argv[1]); + if (!(session = strtol(data->argv[1], &end, 10)) || *end) + session = f->get_session_by_username(data->argv[1]); - if (session) - s = p->get_session_by_id(session); + if (session) + s = f->get_session_by_id(session); - if (!s || !s->ip) + if (!s || !s->ip) + { + data->response = NSCTL_RES_ERR; + data->additional = "session not found"; + return PLUGIN_RET_STOP; + } + + if (flag) + { + in_addr_t ip = inet_addr(data->argv[2]); + uint16_t port = atoi(data->argv[3]); + + if (!ip || ip == INADDR_NONE) { - data->response = NSCTL_RES_ERR; - data->additional = "session not found"; - return PLUGIN_RET_STOP; + data->response = NSCTL_RES_ERR; + data->additional = "invalid ip address"; + return PLUGIN_RET_STOP; } - if (flag) + if (!port) { - in_addr_t ip = inet_addr(data->argv[2]); - uint16_t port = atoi(data->argv[3]); - - if (!ip || ip == INADDR_NONE) - { - data->response = NSCTL_RES_ERR; - data->additional = "invalid ip address"; - return PLUGIN_RET_STOP; - } - - if (!port) - { - data->response = NSCTL_RES_ERR; - data->additional = "invalid port"; - return PLUGIN_RET_STOP; - } - - if (ip == s->snoop_ip && port == s->snoop_port) - { - data->response = NSCTL_RES_ERR; - data->additional = "already intercepted"; - return PLUGIN_RET_STOP; - } - - s->snoop_ip = ip; - s->snoop_port = port; + data->response = NSCTL_RES_ERR; + data->additional = "invalid port"; + return PLUGIN_RET_STOP; } - else + + if (ip == s->snoop_ip && port == s->snoop_port) { - if (!s->snoop_ip) - { - data->response = NSCTL_RES_ERR; - data->additional = "not intercepted"; - return PLUGIN_RET_STOP; - } - - s->snoop_ip = 0; - s->snoop_port = 0; + data->response = NSCTL_RES_ERR; + data->additional = "already intercepted"; + return PLUGIN_RET_STOP; } - p->session_changed(session); + s->snoop_ip = ip; + s->snoop_port = port; + } + else + { + if (!s->snoop_ip) + { + data->response = NSCTL_RES_ERR; + data->additional = "not intercepted"; + return PLUGIN_RET_STOP; + } - data->response = NSCTL_RES_OK; - data->additional = 0; + s->snoop_ip = 0; + s->snoop_port = 0; + } - return PLUGIN_RET_STOP; + f->session_changed(session); + + data->response = NSCTL_RES_OK; + data->additional = 0; + + return PLUGIN_RET_STOP; } int plugin_init(struct pluginfuncs *funcs) { - return ((p = funcs)) ? 1 : 0; + return ((f = funcs)) ? 1 : 0; } diff --git a/stripdomain.c b/stripdomain.c index 37bb53e..748efc9 100644 --- a/stripdomain.c +++ b/stripdomain.c @@ -4,28 +4,28 @@ /* strip domain part of username before sending RADIUS requests */ -char const *cvs_id = "$Id: stripdomain.c,v 1.7 2004/11/29 02:17:18 bodea Exp $"; +char const *cvs_id = "$Id: stripdomain.c,v 1.8 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -static struct pluginfuncs *p = 0; +static struct pluginfuncs *f = 0; int plugin_pre_auth(struct param_pre_auth *data) { - char *x; + char *p; - if (!data->continue_auth) return PLUGIN_RET_STOP; + if (!data->continue_auth) return PLUGIN_RET_STOP; - // Strip off @domain - if ((x = strchr(data->username, '@'))) - { - p->log(3, 0, 0, "Stripping off trailing domain name \"%s\"\n", x); - *x = 0; - } + // Strip off @domain + if ((p = strchr(data->username, '@'))) + { + f->log(3, 0, 0, "Stripping off trailing domain name \"%s\"\n", p); + *p = 0; + } - return PLUGIN_RET_OK; + return PLUGIN_RET_OK; } int plugin_init(struct pluginfuncs *funcs) { - return ((p = funcs)) ? 1 : 0; + return ((f = funcs)) ? 1 : 0; } diff --git a/throttlectl.c b/throttlectl.c index f0106f8..0f0b055 100644 --- a/throttlectl.c +++ b/throttlectl.c @@ -5,131 +5,131 @@ /* throttle control */ -char const *cvs_id = "$Id: throttlectl.c,v 1.8 2005/10/11 07:59:09 bodea Exp $"; +char const *cvs_id = "$Id: throttlectl.c,v 1.9 2005/10/11 09:04:53 bodea Exp $"; int plugin_api_version = PLUGIN_API_VERSION; -static struct pluginfuncs *p = 0; +static struct pluginfuncs *f = 0; char *plugin_control_help[] = { - " throttle USER|SID [RATE|[in|out] RATE ...] Throttle user traffic", - " unthrottle USER|SID Stop throttling user", - 0 + " throttle USER|SID [RATE|[in|out] RATE ...] Throttle user traffic", + " unthrottle USER|SID Stop throttling user", + 0 }; int plugin_control(struct param_control *data) { - sessionidt session; - sessiont *s = 0; - int flag; - char *end; - int rate_in = 0; - int rate_out = 0; + sessionidt session; + sessiont *s = 0; + int flag; + char *end; + int rate_in = 0; + int rate_out = 0; - if (data->argc < 1) - return PLUGIN_RET_OK; + if (data->argc < 1) + return PLUGIN_RET_OK; - if (strcmp(data->argv[0], "throttle") - && strcmp(data->argv[0], "unthrottle")) - return PLUGIN_RET_OK; // not for us + if (strcmp(data->argv[0], "throttle") && + strcmp(data->argv[0], "unthrottle")) + return PLUGIN_RET_OK; // not for us - if (!data->iam_master) - return PLUGIN_RET_NOTMASTER; + if (!data->iam_master) + return PLUGIN_RET_NOTMASTER; - flag = data->argv[0][0] == 't'; + flag = data->argv[0][0] == 't'; - if (flag) + if (flag) + { + if (data->argc < 2 || data->argc > 6) { - if (data->argc < 2 || data->argc > 6) - { - data->response = NSCTL_RES_ERR; - data->additional = "requires username or session id and optional rate(s)"; - return PLUGIN_RET_STOP; - } + data->response = NSCTL_RES_ERR; + data->additional = "requires username or session id and optional rate(s)"; + return PLUGIN_RET_STOP; } - else + } + else + { + if (data->argc != 2) { - if (data->argc != 2) - { - data->response = NSCTL_RES_ERR; - data->additional = "requires username or session id"; - return PLUGIN_RET_STOP; - } + data->response = NSCTL_RES_ERR; + data->additional = "requires username or session id"; + return PLUGIN_RET_STOP; } + } - if (!(session = strtol(data->argv[1], &end, 10)) || *end) - session = p->get_session_by_username(data->argv[1]); + if (!(session = strtol(data->argv[1], &end, 10)) || *end) + session = f->get_session_by_username(data->argv[1]); - if (session) - s = p->get_session_by_id(session); + if (session) + s = f->get_session_by_id(session); - if (!s || !s->ip) + if (!s || !s->ip) + { + data->response = NSCTL_RES_ERR; + data->additional = "session not found"; + return PLUGIN_RET_STOP; + } + + if (flag) + { + rate_in = rate_out = -1; + if (data->argc == 2) { - data->response = NSCTL_RES_ERR; - data->additional = "session not found"; - return PLUGIN_RET_STOP; + unsigned long *rate = f->getconfig("throttle_speed", UNSIGNED_LONG); + rate_in = rate_out = *rate; } - - if (flag) + else if (data->argc == 3) { - rate_in = rate_out = -1; - if (data->argc == 2) + rate_in = rate_out = atoi(data->argv[2]); + } + else + { + int i; + for (i = 2; i < data->argc - 1; i += 2) + { + int len = strlen(data->argv[i]); + if (!strncmp(data->argv[i], "in", len)) { - unsigned long *rate = p->getconfig("throttle_speed", UNSIGNED_LONG); - rate_in = rate_out = *rate; + rate_in = atoi(data->argv[i+1]); } - else if (data->argc == 3) + else if (!strncmp(data->argv[i], "out", len)) { - rate_in = rate_out = atoi(data->argv[2]); + rate_out = atoi(data->argv[i+1]); } else { - int i; - for (i = 2; i < data->argc - 1; i += 2) - { - int len = strlen(data->argv[i]); - if (!strncmp(data->argv[i], "in", len)) - { - rate_in = atoi(data->argv[i+1]); - } - else if (!strncmp(data->argv[i], "out", len)) - { - rate_out = atoi(data->argv[i+1]); - } - else - { - data->response = NSCTL_RES_ERR; - data->additional = "invalid rate"; - return PLUGIN_RET_STOP; - } - } - } - - if (!rate_in || !rate_out) - { - data->response = NSCTL_RES_ERR; - data->additional = "invalid rate"; - return PLUGIN_RET_STOP; + data->response = NSCTL_RES_ERR; + data->additional = "invalid rate"; + return PLUGIN_RET_STOP; } + } } - if (rate_in != -1 && rate_in == s->throttle_in && - rate_out != -1 && rate_out == s->throttle_out) + if (!rate_in || !rate_out) { - data->response = NSCTL_RES_ERR; - data->additional = flag ? "already throttled" : "not throttled"; - return PLUGIN_RET_STOP; + data->response = NSCTL_RES_ERR; + data->additional = "invalid rate"; + return PLUGIN_RET_STOP; } + } + + if (rate_in != -1 && rate_in == s->throttle_in && + rate_out != -1 && rate_out == s->throttle_out) + { + data->response = NSCTL_RES_ERR; + data->additional = flag ? "already throttled" : "not throttled"; + return PLUGIN_RET_STOP; + } - p->throttle(session, rate_in, rate_out); - p->session_changed(session); + f->throttle(session, rate_in, rate_out); + f->session_changed(session); - data->response = NSCTL_RES_OK; - data->additional = 0; + data->response = NSCTL_RES_OK; + data->additional = 0; - return PLUGIN_RET_STOP; + return PLUGIN_RET_STOP; } int plugin_init(struct pluginfuncs *funcs) { - return ((p = funcs)) ? 1 : 0; + return ((f = funcs)) ? 1 : 0; }