Import Debian changes 2.1.19-1
l2tpns (2.1.19-1) unstable; urgency=low
* New upstream release.
* Add debian/watch file.
* Bump Standards-Version to 3.7.2.0 (no changes).
Jonathan McDowell authored 17 years ago
Sebastien Badia committed 4 years ago
0 | * Fri Jun 23 2006 Brendan O'Dea <bod@optus.net> 2.1.19 | |
1 | - Kludge around problem with Netgear DM602 authentication. | |
2 | - Use result code AVP to set Acct-Terminate-Cause is disconnect cause | |
3 | AVP is not present. | |
4 | ||
5 | * Tue Apr 18 2006 Brendan O'Dea <bod@optus.net> 2.1.18 | |
6 | - Don't shutdown on TerminateReq, wait for CDN. | |
7 | - Interpret "local" direction correctly (as LAC) in disconnect AVPs. | |
8 | ||
9 | * Thu Apr 13 2006 Brendan O'Dea <bod@optus.net> 2.1.17 | |
10 | - Fix IPCP length test to allow Terminate-Request (4 bytes). | |
11 | - Send nsctl responses back using the correct source address (thanks ltd). | |
12 | - Similarly set the source for DAE responses; use bind_address when | |
13 | handling forwarded packets on the master. | |
14 | - Add Acct-Terminate-Cause to RADIUS stop records. | |
15 | ||
0 | 16 | * Thu Feb 23 2006 Brendan O'Dea <bod@optus.net> 2.1.16 |
1 | 17 | - Send configured magic-no in LCP EchoReq when LCP is opened. |
2 | 18 | - Correct addition of single IP to pool (Jonathan Yarden). |
24 | 24 | Jon Morby <jon@fido.net> |
25 | 25 | Paul Martin <pm@zetnet.net> |
26 | 26 | Jonathan Yarden <jyarden@bluegrass.net> |
27 | Patrick Cole <z@amused.net> |
0 | 0 | // L2TPNS Command Line Interface |
1 | 1 | // vim: sw=8 ts=8 |
2 | 2 | |
3 | char const *cvs_name = "$Name: release_2_1_16 $"; | |
3 | char const *cvs_name = "$Name: release_2_1_19 $"; | |
4 | 4 | char const *cvs_id_cli = "$Id: cli.c,v 1.71 2005/12/06 09:43:42 bodea Exp $"; |
5 | 5 | |
6 | 6 | #include <stdio.h> |
0 | 0 | // L2TPNS Clustering Stuff |
1 | 1 | |
2 | char const *cvs_id_cluster = "$Id: cluster.c,v 1.49 2005/12/05 14:10:42 bodea Exp $"; | |
2 | char const *cvs_id_cluster = "$Id: cluster.c,v 1.50 2006/04/05 02:13:48 bodea Exp $"; | |
3 | 3 | |
4 | 4 | #include <stdio.h> |
5 | 5 | #include <stdlib.h> |
1654 | 1654 | |
1655 | 1655 | STAT(recv_forward); |
1656 | 1656 | if (type == C_FORWARD_DAE) |
1657 | processdae(p, s, &a, sizeof(a)); | |
1657 | { | |
1658 | struct in_addr local; | |
1659 | local.s_addr = config->bind_address ? config->bind_address : my_address; | |
1660 | processdae(p, s, &a, sizeof(a), &local); | |
1661 | } | |
1658 | 1662 | else |
1659 | 1663 | processudp(p, s, &a); |
1660 | 1664 |
0 | l2tpns (2.1.19-1) unstable; urgency=low | |
1 | ||
2 | * New upstream release. | |
3 | * Add debian/watch file. | |
4 | * Bump Standards-Version to 3.7.2.0 (no changes). | |
5 | ||
6 | -- Jonathan McDowell <noodles@earth.li> Sat, 22 Jul 2006 14:11:14 +0100 | |
7 | ||
0 | 8 | l2tpns (2.1.16-1) unstable; urgency=low |
1 | 9 | |
2 | 10 | * New upstream release. |
2 | 2 | Priority: optional |
3 | 3 | Maintainer: Jonathan McDowell <noodles@earth.li> |
4 | 4 | Build-Depends: debhelper (>> 4), libcli-dev (>> 1.8.5) |
5 | Standards-Version: 3.6.2.0 | |
5 | Standards-Version: 3.7.2.0 | |
6 | 6 | |
7 | 7 | Package: l2tpns |
8 | 8 | Architecture: any |
0 | # format version number, currently 3; this line is compulsory! | |
1 | version=3 | |
2 | ||
3 | http://sf.net/l2tpns/l2tpns-(.*)\.tar\.gz |
3 | 3 | // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced |
4 | 4 | // vim: sw=8 ts=8 |
5 | 5 | |
6 | char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.156 2006/02/17 13:27:07 bodea Exp $"; | |
6 | char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.161.2.1 2006/06/22 15:30:50 bodea Exp $"; | |
7 | 7 | |
8 | 8 | #include <arpa/inet.h> |
9 | 9 | #include <assert.h> |
199 | 199 | static int add_plugin(char *plugin_name); |
200 | 200 | static int remove_plugin(char *plugin_name); |
201 | 201 | static void plugins_done(void); |
202 | static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen); | |
202 | static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local); | |
203 | 203 | static tunnelidt new_tunnel(void); |
204 | 204 | static void unhide_value(uint8_t *value, size_t len, uint16_t type, uint8_t *vector, size_t vec_len); |
205 | 205 | |
633 | 633 | addr.sin_port = htons(NSCTL_PORT); |
634 | 634 | controlfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
635 | 635 | setsockopt(controlfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); |
636 | setsockopt(controlfd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto | |
636 | 637 | if (bind(controlfd, (void *) &addr, sizeof(addr)) < 0) |
637 | 638 | { |
638 | 639 | LOG(0, 0, 0, "Error in control bind: %s\n", strerror(errno)); |
645 | 646 | addr.sin_port = htons(config->radius_dae_port); |
646 | 647 | daefd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
647 | 648 | setsockopt(daefd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); |
649 | setsockopt(daefd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); // recvfromto | |
648 | 650 | if (bind(daefd, (void *) &addr, sizeof(addr)) < 0) |
649 | 651 | { |
650 | 652 | LOG(0, 0, 0, "Error in DAE bind: %s\n", strerror(errno)); |
1556 | 1558 | } |
1557 | 1559 | |
1558 | 1560 | // start tidy shutdown of session |
1559 | void sessionshutdown(sessionidt s, char *reason, int result, int error) | |
1561 | void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_error, int term_cause) | |
1560 | 1562 | { |
1561 | 1563 | int walled_garden = session[s].walled_garden; |
1562 | 1564 | |
1584 | 1586 | { |
1585 | 1587 | // stop, if not already trying |
1586 | 1588 | if (radius[r].state != RADIUSSTOP) |
1589 | { | |
1590 | radius[r].term_cause = term_cause; | |
1591 | radius[r].term_msg = reason; | |
1587 | 1592 | radiussend(r, RADIUSSTOP); |
1593 | } | |
1588 | 1594 | } |
1589 | 1595 | else |
1590 | 1596 | LOG(1, s, session[s].tunnel, "No free RADIUS sessions for Stop message\n"); |
1624 | 1630 | if (session[s].throttle_in || session[s].throttle_out) // Unthrottle if throttled. |
1625 | 1631 | throttle_session(s, 0, 0); |
1626 | 1632 | |
1627 | if (result) | |
1633 | if (cdn_result) | |
1628 | 1634 | { // Send CDN |
1629 | 1635 | controlt *c = controlnew(14); // sending CDN |
1630 | if (error) | |
1636 | if (cdn_error) | |
1631 | 1637 | { |
1632 | 1638 | uint8_t buf[4]; |
1633 | *(uint16_t *) buf = htons(result); | |
1634 | *(uint16_t *) (buf+2) = htons(error); | |
1639 | *(uint16_t *) buf = htons(cdn_result); | |
1640 | *(uint16_t *) (buf+2) = htons(cdn_error); | |
1635 | 1641 | controlb(c, 1, buf, 4, 1); |
1636 | 1642 | } |
1637 | 1643 | else |
1638 | control16(c, 1, result, 1); | |
1644 | control16(c, 1, cdn_result, 1); | |
1639 | 1645 | |
1640 | 1646 | control16(c, 14, s, 1); // assigned session (our end) |
1641 | 1647 | controladd(c, session[s].far, session[s].tunnel); // send the message |
1741 | 1747 | } |
1742 | 1748 | |
1743 | 1749 | session[s].die = TIME; |
1744 | sessionshutdown(s, reason, 3, 0); // close radius/routes, etc. | |
1750 | sessionshutdown(s, reason, CDN_ADMIN_DISC, TERM_ADMIN_RESET); // close radius/routes, etc. | |
1745 | 1751 | if (sess_local[s].radius) |
1746 | 1752 | radiusclear(sess_local[s].radius, s); // cant send clean accounting data, session is killed |
1747 | 1753 | |
1806 | 1812 | // close session |
1807 | 1813 | for (s = 1; s <= config->cluster_highest_sessionid ; ++s) |
1808 | 1814 | if (session[s].tunnel == t) |
1809 | sessionshutdown(s, reason, 0, 0); | |
1815 | sessionshutdown(s, reason, CDN_NONE, TERM_ADMIN_RESET); | |
1810 | 1816 | |
1811 | 1817 | tunnel[t].state = TUNNELDIE; |
1812 | 1818 | tunnel[t].die = TIME + 700; // Clean up in 70 seconds |
2045 | 2051 | int error = 0; |
2046 | 2052 | char *msg = 0; |
2047 | 2053 | |
2054 | // Default disconnect cause/message on receipt of CDN. Set to | |
2055 | // more specific value from attribute 1 (result code) or 46 | |
2056 | // (disconnect cause) if present below. | |
2057 | int disc_cause_set = 0; | |
2058 | int disc_cause = TERM_NAS_REQUEST; | |
2059 | char const *disc_reason = "Closed (Received CDN)."; | |
2060 | ||
2048 | 2061 | // process AVPs |
2049 | 2062 | while (l && !(fatal & 0x80)) // 0x80 = mandatory AVP |
2050 | 2063 | { |
2052 | 2065 | uint8_t *b = p; |
2053 | 2066 | uint8_t flags = *p; |
2054 | 2067 | uint16_t mtype; |
2068 | ||
2055 | 2069 | if (n > l) |
2056 | 2070 | { |
2057 | 2071 | LOG(1, s, t, "Invalid length in AVP\n"); |
2150 | 2164 | case 1: // result code |
2151 | 2165 | { |
2152 | 2166 | uint16_t rescode = ntohs(*(uint16_t *) b); |
2153 | const char* resdesc = "(unknown)"; | |
2167 | char const *resdesc = "(unknown)"; | |
2168 | char const *errdesc = NULL; | |
2169 | int cause = 0; | |
2170 | ||
2154 | 2171 | if (message == 4) |
2155 | 2172 | { /* StopCCN */ |
2156 | 2173 | resdesc = l2tp_stopccn_result_code(rescode); |
2174 | cause = TERM_LOST_SERVICE; | |
2157 | 2175 | } |
2158 | 2176 | else if (message == 14) |
2159 | 2177 | { /* CDN */ |
2160 | 2178 | resdesc = l2tp_cdn_result_code(rescode); |
2179 | if (rescode == 1) | |
2180 | cause = TERM_LOST_CARRIER; | |
2181 | else | |
2182 | cause = TERM_ADMIN_RESET; | |
2161 | 2183 | } |
2162 | 2184 | |
2163 | 2185 | LOG(4, s, t, " Result Code %d: %s\n", rescode, resdesc); |
2164 | 2186 | if (n >= 4) |
2165 | 2187 | { |
2166 | 2188 | uint16_t errcode = ntohs(*(uint16_t *)(b + 2)); |
2167 | LOG(4, s, t, " Error Code %d: %s\n", errcode, l2tp_error_code(errcode)); | |
2189 | errdesc = l2tp_error_code(errcode); | |
2190 | LOG(4, s, t, " Error Code %d: %s\n", errcode, errdesc); | |
2168 | 2191 | } |
2169 | 2192 | if (n > 4) |
2170 | 2193 | LOG(4, s, t, " Error String: %.*s\n", n-4, b+4); |
2194 | ||
2195 | if (cause && disc_cause_set < mtype) // take cause from attrib 46 in preference | |
2196 | { | |
2197 | disc_cause_set = mtype; | |
2198 | disc_reason = errdesc ? errdesc : resdesc; | |
2199 | disc_cause = cause; | |
2200 | } | |
2171 | 2201 | |
2172 | 2202 | break; |
2173 | 2203 | } |
2188 | 2218 | } |
2189 | 2219 | break; |
2190 | 2220 | case 3: // framing capabilities |
2191 | // LOG(4, s, t, "Framing capabilities\n"); | |
2192 | 2221 | break; |
2193 | 2222 | case 4: // bearer capabilities |
2194 | // LOG(4, s, t, "Bearer capabilities\n"); | |
2195 | 2223 | break; |
2196 | 2224 | case 5: // tie breaker |
2197 | 2225 | // We never open tunnels, so we don't care about tie breakers |
2198 | // LOG(4, s, t, "Tie breaker\n"); | |
2199 | 2226 | continue; |
2200 | 2227 | case 6: // firmware revision |
2201 | // LOG(4, s, t, "Firmware revision\n"); | |
2202 | 2228 | break; |
2203 | 2229 | case 7: // host name |
2204 | 2230 | memset(tunnel[t].hostname, 0, sizeof(tunnel[t].hostname)); |
2353 | 2379 | memcpy(session[s].random_vector, b, n); |
2354 | 2380 | session[s].random_vector_length = n; |
2355 | 2381 | break; |
2382 | case 46: // ppp disconnect cause | |
2383 | if (n >= 5) | |
2384 | { | |
2385 | uint16_t code = ntohs(*(uint16_t *) b); | |
2386 | uint16_t proto = ntohs(*(uint16_t *) (b + 2)); | |
2387 | uint8_t dir = *(b + 4); | |
2388 | ||
2389 | LOG(4, s, t, " PPP disconnect cause " | |
2390 | "(code=%u, proto=%04X, dir=%u, msg=\"%.*s\")\n", | |
2391 | code, proto, dir, n - 5, b + 5); | |
2392 | ||
2393 | disc_cause_set = mtype; | |
2394 | ||
2395 | switch (code) | |
2396 | { | |
2397 | case 1: // admin disconnect | |
2398 | disc_cause = TERM_ADMIN_RESET; | |
2399 | disc_reason = "Administrative disconnect"; | |
2400 | break; | |
2401 | case 3: // lcp terminate | |
2402 | if (dir != 2) break; // 1=peer (LNS), 2=local (LAC) | |
2403 | disc_cause = TERM_USER_REQUEST; | |
2404 | disc_reason = "Normal disconnection"; | |
2405 | break; | |
2406 | case 4: // compulsory encryption unavailable | |
2407 | if (dir != 1) break; // 1=refused by peer, 2=local | |
2408 | disc_cause = TERM_USER_ERROR; | |
2409 | disc_reason = "Compulsory encryption refused"; | |
2410 | break; | |
2411 | case 5: // lcp: fsm timeout | |
2412 | disc_cause = TERM_PORT_ERROR; | |
2413 | disc_reason = "LCP: FSM timeout"; | |
2414 | break; | |
2415 | case 6: // lcp: no recognisable lcp packets received | |
2416 | disc_cause = TERM_PORT_ERROR; | |
2417 | disc_reason = "LCP: no recognisable LCP packets"; | |
2418 | break; | |
2419 | case 7: // lcp: magic-no error (possibly looped back) | |
2420 | disc_cause = TERM_PORT_ERROR; | |
2421 | disc_reason = "LCP: magic-no error (possible loop)"; | |
2422 | break; | |
2423 | case 8: // lcp: echo request timeout | |
2424 | disc_cause = TERM_PORT_ERROR; | |
2425 | disc_reason = "LCP: echo request timeout"; | |
2426 | break; | |
2427 | case 13: // auth: fsm timeout | |
2428 | disc_cause = TERM_SERVICE_UNAVAILABLE; | |
2429 | disc_reason = "Authentication: FSM timeout"; | |
2430 | break; | |
2431 | case 15: // auth: unacceptable auth protocol | |
2432 | disc_cause = TERM_SERVICE_UNAVAILABLE; | |
2433 | disc_reason = "Unacceptable authentication protocol"; | |
2434 | break; | |
2435 | case 16: // auth: authentication failed | |
2436 | disc_cause = TERM_SERVICE_UNAVAILABLE; | |
2437 | disc_reason = "Authentication failed"; | |
2438 | break; | |
2439 | case 17: // ncp: fsm timeout | |
2440 | disc_cause = TERM_SERVICE_UNAVAILABLE; | |
2441 | disc_reason = "NCP: FSM timeout"; | |
2442 | break; | |
2443 | case 18: // ncp: no ncps available | |
2444 | disc_cause = TERM_SERVICE_UNAVAILABLE; | |
2445 | disc_reason = "NCP: no NCPs available"; | |
2446 | break; | |
2447 | case 19: // ncp: failure to converge on acceptable address | |
2448 | disc_cause = TERM_SERVICE_UNAVAILABLE; | |
2449 | disc_reason = (dir == 1) | |
2450 | ? "NCP: too many Configure-Naks received from peer" | |
2451 | : "NCP: too many Configure-Naks sent to peer"; | |
2452 | break; | |
2453 | case 20: // ncp: user not permitted to use any address | |
2454 | disc_cause = TERM_SERVICE_UNAVAILABLE; | |
2455 | disc_reason = (dir == 1) | |
2456 | ? "NCP: local link address not acceptable to peer" | |
2457 | : "NCP: remote link address not acceptable"; | |
2458 | break; | |
2459 | } | |
2460 | } | |
2461 | break; | |
2356 | 2462 | default: |
2357 | 2463 | { |
2358 | 2464 | static char e[] = "unknown AVP 0xXXXX"; |
2474 | 2580 | |
2475 | 2581 | case 14: // CDN |
2476 | 2582 | controlnull(t); // ack |
2477 | sessionshutdown(s, "Closed (Received CDN).", 0, 0); | |
2583 | sessionshutdown(s, disc_reason, CDN_NONE, disc_cause); | |
2478 | 2584 | break; |
2479 | 2585 | case 0xFFFF: |
2480 | 2586 | LOG(1, s, t, "Missing message type\n"); |
2804 | 2910 | } |
2805 | 2911 | else |
2806 | 2912 | { |
2807 | sessionshutdown(s, "No response to LCP ConfigReq.", 3, 0); | |
2913 | sessionshutdown(s, "No response to LCP ConfigReq.", CDN_ADMIN_DISC, TERM_LOST_SERVICE); | |
2808 | 2914 | STAT(session_timeout); |
2809 | 2915 | } |
2810 | 2916 | |
2833 | 2939 | } |
2834 | 2940 | else |
2835 | 2941 | { |
2836 | sessionshutdown(s, "No response to IPCP ConfigReq.", 3, 0); | |
2942 | sessionshutdown(s, "No response to IPCP ConfigReq.", CDN_ADMIN_DISC, TERM_LOST_SERVICE); | |
2837 | 2943 | STAT(session_timeout); |
2838 | 2944 | } |
2839 | 2945 | |
2899 | 3005 | // Drop sessions who have not responded within IDLE_TIMEOUT seconds |
2900 | 3006 | if (session[s].last_packet && (time_now - session[s].last_packet >= IDLE_TIMEOUT)) |
2901 | 3007 | { |
2902 | sessionshutdown(s, "No response to LCP ECHO requests.", 3, 0); | |
3008 | sessionshutdown(s, "No response to LCP ECHO requests.", CDN_ADMIN_DISC, TERM_LOST_SERVICE); | |
2903 | 3009 | STAT(session_timeout); |
2904 | 3010 | s_actions++; |
2905 | 3011 | continue; |
2935 | 3041 | if (a & CLI_SESS_KILL) |
2936 | 3042 | { |
2937 | 3043 | LOG(2, s, session[s].tunnel, "Dropping session by CLI\n"); |
2938 | sessionshutdown(s, "Requested by administrator.", 3, 0); | |
3044 | sessionshutdown(s, "Requested by administrator.", CDN_ADMIN_DISC, TERM_ADMIN_RESET); | |
2939 | 3045 | a = 0; // dead, no need to check for other actions |
2940 | 3046 | s_actions++; |
2941 | 3047 | } |
3247 | 3353 | if (n) |
3248 | 3354 | { |
3249 | 3355 | struct sockaddr_in addr; |
3356 | struct in_addr local; | |
3250 | 3357 | socklen_t alen; |
3251 | 3358 | int c, s; |
3252 | 3359 | int udp_ready = 0; |
3263 | 3370 | for (c = n, i = 0; i < c; i++) |
3264 | 3371 | { |
3265 | 3372 | struct event_data *d = events[i].data.ptr; |
3373 | ||
3266 | 3374 | switch (d->type) |
3267 | 3375 | { |
3268 | 3376 | case FD_TYPE_CLI: // CLI connections |
3289 | 3397 | |
3290 | 3398 | case FD_TYPE_CONTROL: // nsctl commands |
3291 | 3399 | alen = sizeof(addr); |
3292 | processcontrol(buf, recvfrom(controlfd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen); | |
3400 | s = recvfromto(controlfd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); | |
3401 | if (s > 0) processcontrol(buf, s, &addr, alen, &local); | |
3293 | 3402 | n--; |
3294 | 3403 | break; |
3295 | 3404 | |
3296 | 3405 | case FD_TYPE_DAE: // DAE requests |
3297 | 3406 | alen = sizeof(addr); |
3298 | processdae(buf, recvfrom(daefd, buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen), &addr, alen); | |
3407 | s = recvfromto(daefd, buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen, &local); | |
3408 | if (s > 0) processdae(buf, s, &addr, alen, &local); | |
3299 | 3409 | n--; |
3300 | 3410 | break; |
3301 | 3411 | |
3302 | 3412 | case FD_TYPE_RADIUS: // RADIUS response |
3303 | 3413 | alen = sizeof(addr); |
3304 | s = recvfrom(radfds[d->index], buf, sizeof(buf), MSG_WAITALL, (void *) &addr, &alen); | |
3414 | s = recvfrom(radfds[d->index], buf, sizeof(buf), MSG_WAITALL, (struct sockaddr *) &addr, &alen); | |
3305 | 3415 | if (s >= 0 && config->cluster_iam_master) |
3306 | 3416 | { |
3307 | 3417 | if (addr.sin_addr.s_addr == config->radiusserver[0] || |
4495 | 4605 | if (!session[s].ip) |
4496 | 4606 | { |
4497 | 4607 | LOG(0, s, t, " No IP allocated. The IP address pool is FULL!\n"); |
4498 | sessionshutdown(s, "No IP addresses available.", 2, 7); // try another | |
4608 | sessionshutdown(s, "No IP addresses available.", CDN_TRY_ANOTHER, TERM_SERVICE_UNAVAILABLE); | |
4499 | 4609 | return 0; |
4500 | 4610 | } |
4501 | 4611 | LOG(3, s, t, " No IP allocated. Assigned %s from pool\n", |
4882 | 4992 | run_plugin_done(p); |
4883 | 4993 | } |
4884 | 4994 | |
4885 | static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) | |
4995 | static void processcontrol(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local) | |
4886 | 4996 | { |
4887 | 4997 | struct nsctl request; |
4888 | 4998 | struct nsctl response; |
5040 | 5150 | r = pack_control(buf, NSCTL_MAX_PKT_SZ, response.type, response.argc, response.argv); |
5041 | 5151 | if (r > 0) |
5042 | 5152 | { |
5043 | sendto(controlfd, buf, r, 0, (const struct sockaddr *) addr, alen); | |
5153 | sendtofrom(controlfd, buf, r, 0, (const struct sockaddr *) addr, alen, local); | |
5044 | 5154 | if (log_stream && config->debug >= 4) |
5045 | 5155 | { |
5046 | 5156 | LOG(4, 0, 0, "Sent [%s] ", fmtaddr(addr->sin_addr.s_addr, 0)); |
0 | 0 | // L2TPNS Global Stuff |
1 | // $Id: l2tpns.h,v 1.109 2005/12/20 04:57:16 bodea Exp $ | |
1 | // $Id: l2tpns.h,v 1.113.2.1 2006/05/26 07:33:52 bodea Exp $ | |
2 | 2 | |
3 | 3 | #ifndef __L2TPNS_H__ |
4 | 4 | #define __L2TPNS_H__ |
13 | 13 | #include <sys/types.h> |
14 | 14 | #include <libcli.h> |
15 | 15 | |
16 | #define VERSION "2.1.16" | |
16 | #define VERSION "2.1.19" | |
17 | 17 | |
18 | 18 | // Limits |
19 | 19 | #define MAXTUNNEL 500 // could be up to 65535 |
146 | 146 | |
147 | 147 | // reset state machine counters |
148 | 148 | #define initialise_restart_count(_s, _fsm) \ |
149 | sess_local[_s]._fsm.conf_sent = sess_local[_s]._fsm.nak_sent = 0 | |
149 | sess_local[_s]._fsm.conf_sent = \ | |
150 | sess_local[_s]._fsm.nak_sent = 0 | |
151 | ||
152 | // no more attempts | |
153 | #define zero_restart_count(_s, _fsm) ({ \ | |
154 | sess_local[_s]._fsm.conf_sent = \ | |
155 | config->ppp_max_configure; \ | |
156 | sess_local[_s]._fsm.restart = \ | |
157 | time_now + config->ppp_restart_time; \ | |
158 | }) | |
150 | 159 | |
151 | 160 | // increment ConfReq counter and reset timer |
152 | 161 | #define restart_timer(_s, _fsm) ({ \ |
344 | 353 | } |
345 | 354 | tunnelt; |
346 | 355 | |
347 | // 160 bytes per radius session | |
356 | // 164 bytes per radius session | |
348 | 357 | typedef struct // outstanding RADIUS requests |
349 | 358 | { |
350 | 359 | sessionidt session; // which session this applies to |
355 | 364 | uint8_t try; // which try we are on |
356 | 365 | uint8_t state; // state of radius requests |
357 | 366 | uint8_t chap; // set if CHAP used (is CHAP identifier) |
367 | uint8_t term_cause; // Stop record: Acct-Terminate-Cause | |
368 | char const *term_msg; // terminate reason | |
358 | 369 | } |
359 | 370 | radiust; |
360 | 371 | |
673 | 684 | int used; // session ref count |
674 | 685 | } ip_filtert; |
675 | 686 | |
687 | // CDN result/error codes | |
688 | #define CDN_NONE 0, 0 | |
689 | #define CDN_TRY_ANOTHER 2, 7 | |
690 | #define CDN_ADMIN_DISC 3, 0 | |
691 | #define CDN_UNAVAILABLE 4, 0 | |
692 | ||
693 | // RADIUS Acct-Terminate-Cause values | |
694 | #define TERM_USER_REQUEST 1 | |
695 | #define TERM_LOST_CARRIER 2 | |
696 | #define TERM_LOST_SERVICE 3 | |
697 | #define TERM_IDLE_TIMEOUT 4 | |
698 | #define TERM_SESSION_TIMEOUT 5 | |
699 | #define TERM_ADMIN_RESET 6 | |
700 | #define TERM_ADMIN_REBOOT 7 | |
701 | #define TERM_PORT_ERROR 8 | |
702 | #define TERM_NAS_ERROR 9 | |
703 | #define TERM_NAS_REQUEST 10 | |
704 | #define TERM_NAS_REBOOT 11 | |
705 | #define TERM_PORT_UNNEEDED 12 | |
706 | #define TERM_PORT_PREEMPTED 13 | |
707 | #define TERM_PORT_SUSPENDED 14 | |
708 | #define TERM_SERVICE_UNAVAILABLE 15 | |
709 | #define TERM_CALLBACK 16 | |
710 | #define TERM_USER_ERROR 17 | |
711 | #define TERM_HOST_REQUEST 18 | |
712 | #define TERM_SUPPLICANT_RESTART 19 | |
713 | #define TERM_REAUTHENTICATION_FAILURE 20 | |
714 | #define TERM_PORT_REINIT 21 | |
715 | #define TERM_PORT_DISABLED 22 | |
716 | ||
676 | 717 | // arp.c |
677 | 718 | void sendarp(int ifr_idx, const unsigned char* mac, in_addr_t ip); |
678 | 719 | |
702 | 743 | void radiusretry(uint16_t r); |
703 | 744 | uint16_t radiusnew(sessionidt s); |
704 | 745 | void radiusclear(uint16_t r, sessionidt s); |
705 | void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen); | |
746 | void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local); | |
706 | 747 | |
707 | 748 | |
708 | 749 | // l2tpns.c |
715 | 756 | void increment_counter(uint32_t *counter, uint32_t *wrap, uint32_t delta); |
716 | 757 | void random_data(uint8_t *buf, int len); |
717 | 758 | void sessionkill(sessionidt s, char *reason); |
718 | void sessionshutdown(sessionidt s, char *reason, int result, int error); | |
759 | void sessionshutdown(sessionidt s, char const *reason, int cdn_result, int cdn_error, int term_cause); | |
719 | 760 | void filter_session(sessionidt s, int filter_in, int filter_out); |
720 | 761 | void send_garp(in_addr_t ip); |
721 | 762 | void tunnelsend(uint8_t *buf, uint16_t l, tunnelidt t); |
0 | 0 | Summary: A high-speed clustered L2TP LNS |
1 | 1 | Name: l2tpns |
2 | Version: 2.1.16 | |
2 | Version: 2.1.19 | |
3 | 3 | Release: 1 |
4 | 4 | License: GPL |
5 | 5 | Group: System Environment/Daemons |
42 | 42 | %attr(644,root,root) /usr/share/man/man[58]/* |
43 | 43 | |
44 | 44 | %changelog |
45 | * Thu Feb 23 2006 Brendan O'Dea <bod@optus.net> 2.1.16-1 | |
46 | - 2.1.16 release, see /usr/share/doc/l2tpns-2.1.16/Changes | |
45 | * Fri Jun 23 2006 Brendan O'Dea <bod@optus.net> 2.1.19-1 | |
46 | - 2.1.19 release, see /usr/share/doc/l2tpns-2.1.19/Changes |
0 | 0 | #ifndef __PLUGIN_H__ |
1 | 1 | #define __PLUGIN_H__ |
2 | 2 | |
3 | #define PLUGIN_API_VERSION 6 | |
3 | #define PLUGIN_API_VERSION 7 | |
4 | 4 | #define MAX_PLUGIN_TYPES 30 |
5 | 5 | |
6 | 6 | enum |
36 | 36 | uint16_t (*radiusnew)(sessionidt s); |
37 | 37 | void (*radiussend)(uint16_t r, uint8_t state); |
38 | 38 | void *(*getconfig)(char *key, enum config_typet type); |
39 | void (*sessionshutdown)(sessionidt s, char *reason, int result, int error); | |
39 | void (*sessionshutdown)(sessionidt s, char const *reason, int result, int error, int term_cause); | |
40 | 40 | void (*sessionkill)(sessionidt s, char *reason); |
41 | 41 | void (*throttle)(sessionidt s, int rate_in, int rate_out); |
42 | 42 | int (*session_changed)(int sid); |
0 | 0 | // L2TPNS PPP Stuff |
1 | 1 | |
2 | char const *cvs_id_ppp = "$Id: ppp.c,v 1.96 2006/02/17 15:05:14 bodea Exp $"; | |
2 | char const *cvs_id_ppp = "$Id: ppp.c,v 1.99.2.1 2006/05/26 07:33:52 bodea Exp $"; | |
3 | 3 | |
4 | 4 | #include <stdio.h> |
5 | 5 | #include <string.h> |
39 | 39 | { |
40 | 40 | LOG(1, s, t, "Short PAP %u bytes\n", l); |
41 | 41 | STAT(tunnel_rx_errors); |
42 | sessionshutdown(s, "Short PAP packet.", 3, 0); | |
42 | sessionshutdown(s, "Short PAP packet.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
43 | 43 | return; |
44 | 44 | } |
45 | 45 | |
47 | 47 | { |
48 | 48 | LOG(1, s, t, "Length mismatch PAP %u/%u\n", hl, l); |
49 | 49 | STAT(tunnel_rx_errors); |
50 | sessionshutdown(s, "PAP length mismatch.", 3, 0); | |
50 | sessionshutdown(s, "PAP length mismatch.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
51 | 51 | return; |
52 | 52 | } |
53 | 53 | l = hl; |
56 | 56 | { |
57 | 57 | LOG(1, s, t, "Unexpected PAP code %d\n", *p); |
58 | 58 | STAT(tunnel_rx_errors); |
59 | sessionshutdown(s, "Unexpected PAP code.", 3, 0); | |
59 | sessionshutdown(s, "Unexpected PAP code.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
60 | 60 | return; |
61 | 61 | } |
62 | 62 | |
109 | 109 | else |
110 | 110 | { |
111 | 111 | LOG(1, s, t, "No RADIUS session available to authenticate session...\n"); |
112 | sessionshutdown(s, "No free RADIUS sessions.", 4, 0); | |
112 | sessionshutdown(s, "No free RADIUS sessions.", CDN_UNAVAILABLE, TERM_SERVICE_UNAVAILABLE); | |
113 | 113 | } |
114 | 114 | } |
115 | 115 | else |
151 | 151 | { |
152 | 152 | LOG(1, s, t, "Short CHAP %u bytes\n", l); |
153 | 153 | STAT(tunnel_rx_errors); |
154 | sessionshutdown(s, "Short CHAP packet.", 3, 0); | |
154 | sessionshutdown(s, "Short CHAP packet.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
155 | 155 | return; |
156 | 156 | } |
157 | 157 | |
159 | 159 | { |
160 | 160 | LOG(1, s, t, "Length mismatch CHAP %u/%u\n", hl, l); |
161 | 161 | STAT(tunnel_rx_errors); |
162 | sessionshutdown(s, "CHAP length mismatch.", 3, 0); | |
162 | sessionshutdown(s, "CHAP length mismatch.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
163 | 163 | return; |
164 | 164 | } |
165 | 165 | l = hl; |
168 | 168 | { |
169 | 169 | LOG(1, s, t, "Unexpected CHAP response code %d\n", *p); |
170 | 170 | STAT(tunnel_rx_errors); |
171 | sessionshutdown(s, "CHAP length mismatch.", 3, 0); | |
171 | sessionshutdown(s, "CHAP length mismatch.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
172 | return; | |
173 | } | |
174 | ||
175 | if (session[s].ppp.phase != Authenticate) | |
176 | { | |
177 | LOG(2, s, t, "CHAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase)); | |
172 | 178 | return; |
173 | 179 | } |
174 | 180 | |
176 | 182 | if (!r) |
177 | 183 | { |
178 | 184 | LOG(3, s, t, "Unexpected CHAP message\n"); |
179 | return; | |
180 | } | |
181 | ||
182 | if (session[s].ppp.phase != Authenticate) | |
183 | { | |
184 | LOG(2, s, t, "CHAP ignored in %s phase\n", ppp_phase(session[s].ppp.phase)); | |
185 | ||
186 | // Some modems (Netgear DM602, possibly others) persist in using CHAP even | |
187 | // after ACKing our ConfigReq for PAP. | |
188 | if (sess_local[s].lcp_authtype == AUTHPAP && config->radius_authtypes & AUTHCHAP) | |
189 | { | |
190 | sess_local[s].lcp_authtype = AUTHCHAP; | |
191 | sendchap(s, t); | |
192 | } | |
185 | 193 | return; |
186 | 194 | } |
187 | 195 | |
189 | 197 | { |
190 | 198 | LOG(1, s, t, "Wrong CHAP response ID %d (should be %d) (%d)\n", p[1], radius[r].id, r); |
191 | 199 | STAT(tunnel_rx_errors); |
192 | sessionshutdown(s, "Unexpected CHAP response ID.", 3, 0); | |
200 | sessionshutdown(s, "Unexpected CHAP response ID.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
193 | 201 | return; |
194 | 202 | } |
195 | 203 | |
197 | 205 | { |
198 | 206 | LOG(1, s, t, "Bad CHAP response length %d\n", l < 5 ? -1 : p[4]); |
199 | 207 | STAT(tunnel_rx_errors); |
200 | sessionshutdown(s, "Bad CHAP response length.", 3, 0); | |
208 | sessionshutdown(s, "Bad CHAP response length.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
201 | 209 | return; |
202 | 210 | } |
203 | 211 | |
207 | 215 | { |
208 | 216 | LOG(1, s, t, "CHAP user too long %d\n", l - 16); |
209 | 217 | STAT(tunnel_rx_errors); |
210 | sessionshutdown(s, "CHAP username too long.", 3, 0); | |
218 | sessionshutdown(s, "CHAP username too long.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
211 | 219 | return; |
212 | 220 | } |
213 | 221 | |
813 | 821 | |
814 | 822 | default: |
815 | 823 | LOG(2, s, t, "LCP: remote sent %s for type %u?\n", ppp_code(*p), type); |
816 | sessionshutdown(s, "Unable to negotiate LCP.", 3, 0); | |
824 | sessionshutdown(s, "Unable to negotiate LCP.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
817 | 825 | return; |
818 | 826 | } |
819 | 827 | x -= length; |
822 | 830 | |
823 | 831 | if (!authtype) |
824 | 832 | { |
825 | sessionshutdown(s, "Unsupported authentication.", 3, 0); | |
833 | sessionshutdown(s, "Unsupported authentication.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
826 | 834 | return; |
827 | 835 | } |
828 | 836 | |
869 | 877 | } |
870 | 878 | else if (*p == TerminateReq) |
871 | 879 | { |
872 | *p = TerminateAck; // close | |
880 | switch (session[s].ppp.lcp) | |
881 | { | |
882 | case Closed: | |
883 | case Stopped: | |
884 | case Closing: | |
885 | case Stopping: | |
886 | case RequestSent: | |
887 | case AckReceived: | |
888 | case AckSent: | |
889 | break; | |
890 | ||
891 | case Opened: | |
892 | lcp_restart(s); | |
893 | zero_restart_count(s, lcp); | |
894 | change_state(s, lcp, Closing); | |
895 | break; | |
896 | ||
897 | default: | |
898 | LOG(2, s, t, "LCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.lcp)); | |
899 | return; | |
900 | } | |
901 | ||
902 | *p = TerminateAck; // send ack | |
873 | 903 | q = makeppp(b, sizeof(b), p, l, s, t, PPPLCP); |
874 | 904 | if (!q) return; |
875 | 905 | |
877 | 907 | if (config->debug > 3) dumplcp(q, l); |
878 | 908 | |
879 | 909 | tunnelsend(b, l + (q - b), t); // send it |
880 | sessionshutdown(s, "Remote end closed connection.", 3, 0); | |
881 | } | |
882 | else if (*p == TerminateAck) | |
883 | { | |
884 | sessionshutdown(s, "Connection closed.", 3, 0); | |
885 | 910 | } |
886 | 911 | else if (*p == ProtocolRej) |
887 | 912 | { |
966 | 991 | CSTAT(processipcp); |
967 | 992 | |
968 | 993 | LOG_HEX(5, "IPCP", p, l); |
969 | if (l < 5) | |
994 | if (l < 4) | |
970 | 995 | { |
971 | 996 | LOG(1, s, t, "Short IPCP %d bytes\n", l); |
972 | 997 | STAT(tunnel_rx_errors); |
1038 | 1063 | q = ppp_conf_nak(s, b, sizeof(b), PPPIPCP, &response, q, p, o, (uint8_t *) &addr, sizeof(addr)); |
1039 | 1064 | if (!q || (q != oq && *response == ConfigRej)) |
1040 | 1065 | { |
1041 | sessionshutdown(s, "Can't negotiate IPCP.", 3, 0); | |
1066 | sessionshutdown(s, "Can't negotiate IPCP.", CDN_ADMIN_DISC, TERM_USER_ERROR); | |
1042 | 1067 | return; |
1043 | 1068 | } |
1044 | 1069 | } |
1152 | 1177 | } |
1153 | 1178 | else if (*p == TerminateReq) |
1154 | 1179 | { |
1155 | *p = TerminateAck; | |
1156 | q = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP); | |
1180 | switch (session[s].ppp.ipcp) | |
1181 | { | |
1182 | case Closed: | |
1183 | case Stopped: | |
1184 | case Closing: | |
1185 | case Stopping: | |
1186 | case RequestSent: | |
1187 | case AckReceived: | |
1188 | case AckSent: | |
1189 | break; | |
1190 | ||
1191 | case Opened: | |
1192 | zero_restart_count(s, ipcp); | |
1193 | change_state(s, ipcp, Closing); | |
1194 | break; | |
1195 | ||
1196 | default: | |
1197 | LOG(2, s, t, "IPCP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ipcp)); | |
1198 | return; | |
1199 | } | |
1200 | ||
1201 | *p = TerminateAck; // send ack | |
1202 | q = makeppp(b, sizeof(b), p, l, s, t, PPPIPCP); | |
1157 | 1203 | if (!q) return; |
1204 | ||
1158 | 1205 | LOG(3, s, t, "IPCP: send %s\n", ppp_code(*q)); |
1159 | tunnelsend(b, l + (q - b), t); | |
1160 | change_state(s, ipcp, Stopped); | |
1206 | tunnelsend(b, l + (q - b), t); // send it | |
1161 | 1207 | } |
1162 | 1208 | else if (*p != CodeRej) |
1163 | 1209 | { |
1352 | 1398 | } |
1353 | 1399 | else if (*p == TerminateReq) |
1354 | 1400 | { |
1355 | *p = TerminateAck; | |
1401 | switch (session[s].ppp.ipv6cp) | |
1402 | { | |
1403 | case Closed: | |
1404 | case Stopped: | |
1405 | case Closing: | |
1406 | case Stopping: | |
1407 | case RequestSent: | |
1408 | case AckReceived: | |
1409 | case AckSent: | |
1410 | break; | |
1411 | ||
1412 | case Opened: | |
1413 | zero_restart_count(s, ipv6cp); | |
1414 | change_state(s, ipv6cp, Closing); | |
1415 | break; | |
1416 | ||
1417 | default: | |
1418 | LOG(2, s, t, "IPV6CP: ignoring %s in state %s\n", ppp_code(*p), ppp_state(session[s].ppp.ipv6cp)); | |
1419 | return; | |
1420 | } | |
1421 | ||
1422 | *p = TerminateAck; // send ack | |
1356 | 1423 | q = makeppp(b, sizeof(b), p, l, s, t, PPPIPV6CP); |
1357 | 1424 | if (!q) return; |
1425 | ||
1358 | 1426 | LOG(3, s, t, "IPV6CP: send %s\n", ppp_code(*q)); |
1359 | tunnelsend(b, l + (q - b), t); | |
1360 | change_state(s, ipv6cp, Stopped); | |
1427 | tunnelsend(b, l + (q - b), t); // send it | |
1361 | 1428 | } |
1362 | 1429 | else if (*p != CodeRej) |
1363 | 1430 | { |
1756 | 1823 | radius[r].retry = backoff(radius[r].try++); |
1757 | 1824 | if (radius[r].try > 5) |
1758 | 1825 | { |
1759 | sessionshutdown(s, "CHAP timeout.", 3, 0); | |
1826 | sessionshutdown(s, "CHAP timeout.", CDN_ADMIN_DISC, TERM_REAUTHENTICATION_FAILURE); | |
1760 | 1827 | STAT(tunnel_tx_errors); |
1761 | 1828 | return ; |
1762 | 1829 | } |
0 | 0 | // L2TPNS Radius Stuff |
1 | 1 | |
2 | char const *cvs_id_radius = "$Id: radius.c,v 1.47 2005/12/19 06:18:13 bodea Exp $"; | |
2 | char const *cvs_id_radius = "$Id: radius.c,v 1.49 2006/04/13 11:14:35 bodea Exp $"; | |
3 | 3 | |
4 | 4 | #include <time.h> |
5 | 5 | #include <stdio.h> |
157 | 157 | if (s) |
158 | 158 | { |
159 | 159 | if (state == RADIUSAUTH) |
160 | sessionshutdown(s, "RADIUS timeout.", 3, 0); | |
160 | sessionshutdown(s, "RADIUS timeout.", CDN_ADMIN_DISC, TERM_REAUTHENTICATION_FAILURE); | |
161 | 161 | else |
162 | 162 | { |
163 | 163 | LOG(1, s, session[s].tunnel, "RADIUS timeout, but in state %s so don't timeout session\n", |
247 | 247 | p += p[1]; |
248 | 248 | } |
249 | 249 | } |
250 | else if (state == RADIUSSTART || state == RADIUSSTOP || state == RADIUSINTERIM) | |
251 | { // accounting | |
250 | else // accounting | |
251 | { | |
252 | 252 | *p = 40; // accounting type |
253 | 253 | p[1] = 6; |
254 | 254 | *(uint32_t *) (p + 2) = htonl(state - RADIUSSTART + 1); // start=1, stop=2, interim=3 |
303 | 303 | p[1] = 6; |
304 | 304 | *(uint32_t *) (p + 2) = htonl(session[s].cout_wrap); |
305 | 305 | p += p[1]; |
306 | ||
307 | if (state == RADIUSSTOP && radius[r].term_cause) | |
308 | { | |
309 | *p = 49; // acct-terminate-cause | |
310 | p[1] = 6; | |
311 | *(uint32_t *) (p + 2) = htonl(radius[r].term_cause); | |
312 | p += p[1]; | |
313 | ||
314 | if (radius[r].term_msg) | |
315 | { | |
316 | *p = 26; // vendor-specific | |
317 | *(uint32_t *) (p + 2) = htonl(9); // Cisco | |
318 | p[6] = 1; // Cisco-AVPair | |
319 | p[7] = 2 + sprintf((char *) p + 8, "disc-cause-ext=%s", radius[r].term_msg); | |
320 | p[1] = p[7] + 6; | |
321 | p += p[1]; | |
322 | } | |
323 | } | |
306 | 324 | } |
307 | 325 | |
308 | 326 | { |
784 | 802 | |
785 | 803 | extern int daefd; |
786 | 804 | |
787 | void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) | |
805 | void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen, struct in_addr *local) | |
788 | 806 | { |
789 | 807 | int i, r_code, r_id, length, attribute_length; |
790 | 808 | uint8_t *packet, attribute; |
993 | 1011 | LOG(3, s, t, " DAE Disconnect %d (%s)\n", s, session[s].user); |
994 | 1012 | r_code = DisconnectACK; |
995 | 1013 | |
996 | sessionshutdown(s, "Requested by PoD", 3, 0); // disconnect session | |
1014 | sessionshutdown(s, "Requested by PoD", CDN_ADMIN_DISC, TERM_ADMIN_RESET); // disconnect session | |
997 | 1015 | break; |
998 | 1016 | |
999 | 1017 | case CoARequest: // Change of Authorization |
1062 | 1080 | LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code), r_id); |
1063 | 1081 | |
1064 | 1082 | // send DAE response |
1065 | if (sendto(daefd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *) addr, alen) < 0) | |
1083 | if (sendtofrom(daefd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *) addr, alen, local) < 0) | |
1066 | 1084 | LOG(0, 0, 0, "Error sending DAE response packet: %s\n", strerror(errno)); |
1067 | 1085 | } |
4 | 4 | |
5 | 5 | /* session control */ |
6 | 6 | |
7 | char const *cvs_id = "$Id: sessionctl.c,v 1.4 2005/10/11 09:04:53 bodea Exp $"; | |
7 | char const *cvs_id = "$Id: sessionctl.c,v 1.5 2006/04/13 11:14:35 bodea Exp $"; | |
8 | 8 | |
9 | 9 | int plugin_api_version = PLUGIN_API_VERSION; |
10 | 10 | static struct pluginfuncs *f = 0; |
57 | 57 | reason = "Requested by administrator."; |
58 | 58 | |
59 | 59 | if (data->argv[0][0] == 'd') |
60 | f->sessionshutdown(session, reason, 3, 0); | |
60 | f->sessionshutdown(session, reason, CDN_ADMIN_DISC, TERM_ADMIN_RESET); | |
61 | 61 | else |
62 | 62 | f->sessionkill(session, reason); |
63 | 63 |
0 | 0 | /* Misc util functions */ |
1 | 1 | |
2 | char const *cvs_id_util = "$Id: util.c,v 1.13 2005/09/19 00:29:12 bodea Exp $"; | |
2 | char const *cvs_id_util = "$Id: util.c,v 1.14 2006/04/05 01:45:57 bodea Exp $"; | |
3 | 3 | |
4 | 4 | #include <unistd.h> |
5 | 5 | #include <errno.h> |
19 | 19 | // to use |
20 | 20 | char *fmtaddr(in_addr_t addr, int n) |
21 | 21 | { |
22 | static char addrs[4][16]; | |
23 | struct in_addr in; | |
22 | static char addrs[4][16]; | |
23 | struct in_addr in; | |
24 | 24 | |
25 | if (n < 0 || n >= 4) return ""; | |
26 | in.s_addr = addr; | |
27 | return strcpy(addrs[n], inet_ntoa(in)); | |
25 | if (n < 0 || n >= 4) | |
26 | return ""; | |
27 | ||
28 | in.s_addr = addr; | |
29 | return strcpy(addrs[n], inet_ntoa(in)); | |
28 | 30 | } |
29 | 31 | |
30 | 32 | void *shared_malloc(unsigned int size) |
31 | 33 | { |
32 | void * p; | |
33 | p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0); | |
34 | void * p; | |
35 | p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0); | |
34 | 36 | |
35 | if (p == MAP_FAILED) | |
36 | p = NULL; | |
37 | if (p == MAP_FAILED) | |
38 | p = NULL; | |
37 | 39 | |
38 | return p; | |
40 | return p; | |
39 | 41 | } |
40 | 42 | |
41 | 43 | extern int forked; |
44 | 46 | |
45 | 47 | pid_t fork_and_close() |
46 | 48 | { |
47 | pid_t pid = fork(); | |
48 | int i; | |
49 | pid_t pid = fork(); | |
50 | int i; | |
49 | 51 | |
50 | if (pid) | |
51 | return pid; | |
52 | if (pid) | |
53 | return pid; | |
52 | 54 | |
53 | forked++; | |
54 | if (config->scheduler_fifo) | |
55 | forked++; | |
56 | if (config->scheduler_fifo) | |
57 | { | |
58 | struct sched_param params = {0}; | |
59 | params.sched_priority = 0; | |
60 | if (sched_setscheduler(0, SCHED_OTHER, ¶ms)) | |
55 | 61 | { |
56 | struct sched_param params = {0}; | |
57 | params.sched_priority = 0; | |
58 | if (sched_setscheduler(0, SCHED_OTHER, ¶ms)) | |
59 | { | |
60 | LOG(0, 0, 0, "Error setting scheduler to OTHER after fork: %s\n", strerror(errno)); | |
61 | LOG(0, 0, 0, "This is probably really really bad.\n"); | |
62 | } | |
62 | LOG(0, 0, 0, "Error setting scheduler to OTHER after fork: %s\n", strerror(errno)); | |
63 | LOG(0, 0, 0, "This is probably really really bad.\n"); | |
63 | 64 | } |
65 | } | |
64 | 66 | |
65 | signal(SIGPIPE, SIG_DFL); | |
66 | signal(SIGCHLD, SIG_DFL); | |
67 | signal(SIGHUP, SIG_DFL); | |
68 | signal(SIGUSR1, SIG_DFL); | |
69 | signal(SIGQUIT, SIG_DFL); | |
70 | signal(SIGKILL, SIG_DFL); | |
71 | signal(SIGTERM, SIG_DFL); | |
67 | signal(SIGPIPE, SIG_DFL); | |
68 | signal(SIGCHLD, SIG_DFL); | |
69 | signal(SIGHUP, SIG_DFL); | |
70 | signal(SIGUSR1, SIG_DFL); | |
71 | signal(SIGQUIT, SIG_DFL); | |
72 | signal(SIGKILL, SIG_DFL); | |
73 | signal(SIGTERM, SIG_DFL); | |
72 | 74 | |
73 | // Close sockets | |
74 | if (clifd != -1) close(clifd); | |
75 | if (cluster_sockfd != -1) close(cluster_sockfd); | |
76 | if (tunfd != -1) close(tunfd); | |
77 | if (udpfd != -1) close(udpfd); | |
78 | if (controlfd != -1) close(controlfd); | |
79 | if (daefd != -1) close(daefd); | |
80 | if (snoopfd != -1) close(snoopfd); | |
81 | if (ifrfd != -1) close(ifrfd); | |
82 | if (ifr6fd != -1) close(ifr6fd); | |
83 | if (rand_fd != -1) close(rand_fd); | |
84 | if (epollfd != -1) close(epollfd); | |
75 | // Close sockets | |
76 | if (clifd != -1) close(clifd); | |
77 | if (cluster_sockfd != -1) close(cluster_sockfd); | |
78 | if (tunfd != -1) close(tunfd); | |
79 | if (udpfd != -1) close(udpfd); | |
80 | if (controlfd != -1) close(controlfd); | |
81 | if (daefd != -1) close(daefd); | |
82 | if (snoopfd != -1) close(snoopfd); | |
83 | if (ifrfd != -1) close(ifrfd); | |
84 | if (ifr6fd != -1) close(ifr6fd); | |
85 | if (rand_fd != -1) close(rand_fd); | |
86 | if (epollfd != -1) close(epollfd); | |
85 | 87 | |
86 | for (i = 0; radfds && i < RADIUS_FDS; i++) | |
87 | close(radfds[i]); | |
88 | for (i = 0; radfds && i < RADIUS_FDS; i++) | |
89 | close(radfds[i]); | |
90 | ||
88 | 91 | #ifdef BGP |
89 | for (i = 0; i < BGP_NUM_PEERS; i++) | |
90 | if (bgp_peers[i].sock != -1) | |
91 | close(bgp_peers[i].sock); | |
92 | for (i = 0; i < BGP_NUM_PEERS; i++) | |
93 | if (bgp_peers[i].sock != -1) | |
94 | close(bgp_peers[i].sock); | |
92 | 95 | #endif /* BGP */ |
93 | 96 | |
94 | return pid; | |
97 | return pid; | |
95 | 98 | } |
99 | ||
100 | ssize_t recvfromto(int s, void *buf, size_t len, int flags, | |
101 | struct sockaddr *from, socklen_t *fromlen, struct in_addr *toaddr) | |
102 | { | |
103 | ssize_t r; | |
104 | struct msghdr msg; | |
105 | struct cmsghdr *cmsg; | |
106 | struct iovec vec; | |
107 | char cbuf[128]; | |
108 | ||
109 | memset(&msg, 0, sizeof(msg)); | |
110 | msg.msg_name = from; | |
111 | msg.msg_namelen = *fromlen; | |
112 | ||
113 | vec.iov_base = buf; | |
114 | vec.iov_len = len; | |
115 | msg.msg_iov = &vec; | |
116 | msg.msg_iovlen = 1; | |
117 | msg.msg_flags = 0; | |
118 | ||
119 | msg.msg_control = cbuf; | |
120 | msg.msg_controllen = sizeof(cbuf); | |
121 | ||
122 | if ((r = recvmsg(s, &msg, flags)) < 0) | |
123 | return r; | |
124 | ||
125 | if (fromlen) | |
126 | *fromlen = msg.msg_namelen; | |
127 | ||
128 | memset(toaddr, 0, sizeof(*toaddr)); | |
129 | for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) | |
130 | { | |
131 | if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) | |
132 | { | |
133 | struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg); | |
134 | memcpy(toaddr, &i->ipi_addr, sizeof(*toaddr)); | |
135 | break; | |
136 | } | |
137 | } | |
138 | ||
139 | return r; | |
140 | } | |
141 | ||
142 | ssize_t sendtofrom(int s, void const *buf, size_t len, int flags, | |
143 | struct sockaddr const *to, socklen_t tolen, struct in_addr const *from) | |
144 | { | |
145 | struct msghdr msg; | |
146 | struct cmsghdr *cmsg; | |
147 | struct iovec vec; | |
148 | struct in_pktinfo pktinfo; | |
149 | char cbuf[CMSG_SPACE(sizeof(pktinfo))]; | |
150 | ||
151 | memset(&msg, 0, sizeof(msg)); | |
152 | msg.msg_name = (struct sockaddr *) to; | |
153 | msg.msg_namelen = tolen; | |
154 | ||
155 | vec.iov_base = (void *) buf; | |
156 | vec.iov_len = len; | |
157 | msg.msg_iov = &vec; | |
158 | msg.msg_iovlen = 1; | |
159 | msg.msg_flags = 0; | |
160 | ||
161 | msg.msg_control = cbuf; | |
162 | msg.msg_controllen = sizeof(cbuf); | |
163 | ||
164 | cmsg = CMSG_FIRSTHDR(&msg); | |
165 | cmsg->cmsg_level = SOL_IP; | |
166 | cmsg->cmsg_type = IP_PKTINFO; | |
167 | cmsg->cmsg_len = CMSG_LEN(sizeof(pktinfo)); | |
168 | ||
169 | memset(&pktinfo, 0, sizeof(pktinfo)); | |
170 | memcpy(&pktinfo.ipi_spec_dst, from, sizeof(*from)); | |
171 | memcpy(CMSG_DATA(cmsg), &pktinfo, sizeof(pktinfo)); | |
172 | ||
173 | return sendmsg(s, &msg, flags); | |
174 | } |
3 | 3 | char *fmtaddr(in_addr_t addr, int n); |
4 | 4 | void *shared_malloc(unsigned int size); |
5 | 5 | pid_t fork_and_close(void); |
6 | ssize_t sendtofrom(int s, void const *buf, size_t len, int flags, | |
7 | struct sockaddr const *to, socklen_t tolen, struct in_addr const *from); | |
8 | ||
9 | ssize_t recvfromto(int s, void *buf, size_t len, int flags, | |
10 | struct sockaddr *from, socklen_t *fromlen, struct in_addr *toaddr); | |
6 | 11 | |
7 | 12 | #endif /* __UTIL_H__ */ |