+ else if (*p == 27)
+ {
+ // Session-Timeout
+ if (p[1] < 6) continue;
+ session[s].session_timeout = ntohl(*(uint32_t *)(p + 2));
+ LOG(3, s, session[s].tunnel, " Radius reply contains Session-Timeout = %u\n", session[s].session_timeout);
+ if(!session[s].session_timeout && config->kill_timedout_sessions)
+ sessionshutdown(s, "Session timeout is zero", CDN_ADMIN_DISC, 0);
+ }
+ else if (*p == 28)
+ {
+ // Idle-Timeout
+ if (p[1] < 6) continue;
+ session[s].idle_timeout = ntohl(*(uint32_t *)(p + 2));
+ LOG(3, s, session[s].tunnel, " Radius reply contains Idle-Timeout = %u\n", session[s].idle_timeout);
+ }
+ else if (*p == 99)
+ {
+ // Framed-IPv6-Route
+ struct in6_addr r6;
+ int prefixlen;
+ uint8_t *n = p + 2;
+ uint8_t *e = p + p[1];
+ uint8_t *m = memchr(n, '/', e - n);
+
+ *m++ = 0;
+ inet_pton(AF_INET6, (char *) n, &r6);
+
+ prefixlen = 0;
+ while (m < e && isdigit(*m)) {
+ prefixlen = prefixlen * 10 + *m++ - '0';
+ }
+
+ if (prefixlen)
+ {
+ if (routes6 == MAXROUTE6)
+ {
+ LOG(1, s, session[s].tunnel, " Too many IPv6 routes\n");
+ }
+ else
+ {
+ LOG(3, s, session[s].tunnel, " Radius reply contains route for %s/%d\n", n, prefixlen);
+ session[s].route6[routes6].ipv6route = r6;
+ session[s].route6[routes6].ipv6prefixlen = prefixlen;
+ routes6++;
+ }
+ }
+ }
+ else if (*p == 123)
+ {
+ // Delegated-IPv6-Prefix
+ if ((p[1] > 4) && (p[3] > 0) && (p[3] <= 128))
+ {
+ char ipv6addr[INET6_ADDRSTRLEN];
+
+ if (routes6 == MAXROUTE6)
+ {
+ LOG(1, s, session[s].tunnel, " Too many IPv6 routes\n");
+ }
+ else
+ {
+ memcpy(&session[s].route6[routes6].ipv6route, &p[4], p[1] - 4);
+ session[s].route6[routes6].ipv6prefixlen = p[3];
+ LOG(3, s, session[s].tunnel, " Radius reply contains Delegated IPv6 Prefix %s/%d\n",
+ inet_ntop(AF_INET6, &session[s].route6[routes6].ipv6route, ipv6addr, INET6_ADDRSTRLEN), session[s].route6[routes6].ipv6prefixlen);
+ routes6++;
+ }
+ }
+ }
+ else if (*p == 168)
+ {
+ // Framed-IPv6-Address
+ if (p[1] == 18)
+ {
+ char ipv6addr[INET6_ADDRSTRLEN];
+ memcpy(&session[s].ipv6address, &p[2], 16);
+ LOG(3, s, session[s].tunnel, " Radius reply contains Framed-IPv6-Address %s\n", inet_ntop(AF_INET6, &session[s].ipv6address, ipv6addr, INET6_ADDRSTRLEN));
+ }
+ }
+ else if (*p == 25)
+ {
+ // Class
+ if (p[1] < 3) continue;
+ session[s].classlen = p[1] - 2;
+ if (session[s].classlen > MAXCLASS)
+ session[s].classlen = MAXCLASS;
+ memcpy(session[s].class, p + 2, session[s].classlen);
+ }
+ else if (*p == 64)
+ {
+ // Tunnel-Type
+ if (p[1] != 6) continue;
+ tag = p[2];
+ LOG(3, s, session[s].tunnel, " Radius reply Tunnel-Type:%d %d\n",
+ tag, ntohl(*(uint32_t *)(p + 2)) & 0xFFFFFF);
+ // Fill context
+ lac_set_rad_tag_tunnel_type(tag, ntohl(*(uint32_t *)(p + 2)) & 0xFFFFFF);
+ /* Request open tunnel to remote LNS*/
+ OpentunnelReq = 1;
+ }
+ else if (*p == 65)
+ {
+ // Tunnel-Medium-Type
+ if (p[1] < 6) continue;
+ tag = p[2];
+ LOG(3, s, session[s].tunnel, " Radius reply Tunnel-Medium-Type:%d %d\n",
+ tag, ntohl(*(uint32_t *)(p + 2)) & 0xFFFFFF);
+ // Fill context
+ lac_set_rad_tag_tunnel_medium_type(tag, ntohl(*(uint32_t *)(p + 2)) & 0xFFFFFF);
+ }
+ else if (*p == 67)
+ {
+ // Tunnel-Server-Endpoint
+ if (p[1] < 3) continue;
+ tag = p[2];
+ //If the Tag field is greater than 0x1F,
+ // it SHOULD be interpreted as the first byte of the following String field.
+ memset(strtemp, 0, 256);
+ if (tag > 0x1F)
+ {
+ tag = 0;
+ memcpy(strtemp, (p + 2), p[1]-2);
+ }
+ else
+ memcpy(strtemp, (p + 3), p[1]-3);
+
+ LOG(3, s, session[s].tunnel, " Radius reply Tunnel-Server-Endpoint:%d %s\n", tag, strtemp);
+ // Fill context
+ lac_set_rad_tag_tunnel_serv_endpt(tag, (char *) strtemp);
+ }
+ else if (*p == 69)
+ {
+ // Tunnel-Password
+ size_t lentemp;
+
+ if (p[1] < 5) continue;
+ tag = p[2];
+
+ memset(strtemp, 0, 256);
+ lentemp = p[1]-3;
+ memcpy(strtemp, (p + 3), lentemp);
+ if (!rad_tunnel_pwdecode(strtemp, &lentemp, config->radiussecret, radius[r].auth))
+ {
+ LOG_HEX(3, "Error Decode Tunnel-Password, Dump Radius reponse:", p, p[1]);
+ continue;
+ }
+
+ LOG(3, s, session[s].tunnel, " Radius reply Tunnel-Password:%d %s\n", tag, strtemp);
+ if (strlen((char *) strtemp) > 63)
+ {
+ LOG(1, s, session[s].tunnel, "tunnel password is too long (>63)\n");
+ continue;
+ }
+ // Fill context
+ lac_set_rad_tag_tunnel_password(tag, (char *) strtemp);
+ }
+ else if (*p == 82)
+ {
+ // Tunnel-Assignment-Id
+ if (p[1] < 3) continue;
+ tag = p[2];
+ //If the Tag field is greater than 0x1F,
+ // it SHOULD be interpreted as the first byte of the following String field.
+ memset(strtemp, 0, 256);
+ if (tag > 0x1F)
+ {
+ tag = 0;
+ memcpy(strtemp, (p + 2), p[1]-2);
+ }
+ else
+ memcpy(strtemp, (p + 3), p[1]-3);
+
+ LOG(3, s, session[s].tunnel, " Radius reply Tunnel-Assignment-Id:%d %s\n", tag, strtemp);
+ // Fill context
+ lac_set_rad_tag_tunnel_assignment_id(tag, (char *) strtemp);
+ }