+ // Filter-Id
+ char *filter = (char *) p + 2;
+ int l = p[1] - 2;
+ char *suffix;
+ int f;
+ uint8_t *fp = 0;
+
+ LOG(3, s, session[s].tunnel, " Radius reply contains Filter-Id \"%.*s\"\n", l, filter);
+ if ((suffix = memchr(filter, '.', l)))
+ {
+ int b = suffix - filter;
+ if (l - b == 3 && !memcmp("in", suffix+1, 2))
+ fp = &session[s].filter_in;
+ else if (l - b == 4 && !memcmp("out", suffix+1, 3))
+ fp = &session[s].filter_out;
+
+ l = b;
+ }
+
+ if (!fp)
+ {
+ LOG(3, s, session[s].tunnel, " Invalid filter\n");
+ continue;
+ }
+
+ if ((f = find_filter(filter, l)) < 0 || !*ip_filters[f].name)
+ {
+ LOG(3, s, session[s].tunnel, " Unknown filter\n");
+ }
+ else
+ {
+ *fp = f + 1;
+ ip_filters[f].used++;
+ }
+ }
+ 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)
+ {
+ LOG(3, s, session[s].tunnel,
+ " Radius reply contains route for %s/%d\n",
+ n, prefixlen);
+ session[s].ipv6route = r6;
+ session[s].ipv6prefixlen = prefixlen;
+ }
+ }
+ else if (*p == 123)
+ {
+ // Delegated-IPv6-Prefix
+ if ((p[1] > 4) && (p[3] > 0) && (p[3] <= 128))
+ {
+ char ipv6addr[INET6_ADDRSTRLEN];
+ memcpy(&session[s].ipv6route, &p[4], p[1] - 4);
+ session[s].ipv6prefixlen = p[3];
+ LOG(3, s, session[s].tunnel, " Radius reply contains Delegated IPv6 Prefix %s/%d\n",
+ inet_ntop(AF_INET6, &session[s].ipv6route, ipv6addr, INET6_ADDRSTRLEN), session[s].ipv6prefixlen);
+ }
+ }
+ 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);
+ }