New upstream version 3.0.21+dfsg
Bernhard Schmidt
4 years ago
41 | 41 | files for more detailed copyright statements. |
42 | 42 | |
43 | 43 | |
44 | Copyright (C) 1999-2019 The FreeRADIUS Server Project | |
44 | Copyright (C) 1999-2020 The FreeRADIUS Server Project | |
45 | 45 | |
46 | 46 | Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Alan DeKok |
47 | 47 | <aland@deployingradius.com> |
32 | 32 | # |
33 | 33 | ifneq "$(MAKECMDGOALS)" "deb" |
34 | 34 | ifneq "$(MAKECMDGOALS)" "rpm" |
35 | ifeq "$(findstring docker,$(MAKECMDGOALS))" "" | |
36 | ifeq "$(findstring crossbuild,$(MAKECMDGOALS))" "" | |
35 | 37 | $(if $(wildcard Make.inc),,$(error Missing 'Make.inc' Run './configure [options]' and retry)) |
36 | 38 | |
37 | 39 | include Make.inc |
40 | endif | |
41 | endif | |
38 | 42 | endif |
39 | 43 | endif |
40 | 44 | |
51 | 55 | # And over-ride all of the other magic. |
52 | 56 | ifneq "$(MAKECMDGOALS)" "deb" |
53 | 57 | ifneq "$(MAKECMDGOALS)" "rpm" |
58 | ifeq "$(findstring docker,$(MAKECMDGOALS))" "" | |
59 | ifeq "$(findstring crossbuild,$(MAKECMDGOALS))" "" | |
54 | 60 | include scripts/boiler.mk |
61 | endif | |
62 | endif | |
55 | 63 | endif |
56 | 64 | endif |
57 | 65 | |
282 | 290 | # high-level targets |
283 | 291 | .PHONY: dist-check |
284 | 292 | dist-check: redhat/freeradius.spec suse/freeradius.spec debian/changelog |
285 | @if [ `grep ^Version: redhat/freeradius.spec | sed 's/.*://;s/ //'` != "$(RADIUSD_VERSION_STRING)" ]; then \ | |
286 | cat redhat/freeradius.spec | sed 's/^Version: .*/Version: $(RADIUSD_VERSION_STRING)/' > redhat/.foo; \ | |
293 | @if [ `grep ^Version: redhat/freeradius.spec | sed 's/.*://;s/ //g'` != "$(RADIUSD_VERSION_STRING)" ]; then \ | |
294 | cat redhat/freeradius.spec | sed 's/^Version:.*/Version: $(RADIUSD_VERSION_STRING)/' > redhat/.foo; \ | |
287 | 295 | mv redhat/.foo redhat/freeradius.spec; \ |
288 | 296 | echo redhat/freeradius.spec 'Version' needs to be updated; \ |
289 | 297 | exit 1; \ |
290 | 298 | fi |
291 | @if [ `grep ^Version: suse/freeradius.spec | sed 's/.*://;s/ //'` != "$(RADIUSD_VERSION_STRING)" ]; then \ | |
292 | cat suse/freeradius.spec | sed 's/^Version: .*/Version: $(RADIUSD_VERSION_STRING)/' > suse/.foo; \ | |
299 | @if [ `grep ^Version: suse/freeradius.spec | sed 's/.*://;s/ //g'` != "$(RADIUSD_VERSION_STRING)" ]; then \ | |
300 | cat suse/freeradius.spec | sed 's/^Version: .*/Version: $(RADIUSD_VERSION_STRING)/' > suse/.foo; \ | |
293 | 301 | mv suse/.foo suse/freeradius.spec; \ |
294 | 302 | echo suse/freeradius.spec 'Version' needs to be updated; \ |
295 | 303 | exit 1; \ |
296 | 304 | fi |
297 | @if [ `head -n 1 debian/changelog | sed 's/.*(//;s/-0).*//;s/-1).*//;s/\+.*//'` != "$(RADIUSD_VERSION_STRING)" ]; then \ | |
305 | @if [ `head -n 1 doc/ChangeLog | awk '/^FreeRADIUS/{print $$2}'` != "$(RADIUSD_VERSION_STRING)" ]; then \ | |
306 | echo doc/ChangeLog needs to be updated; \ | |
307 | exit 1; \ | |
308 | fi | |
309 | @if [ `head -n 1 debian/changelog | sed 's/.*(//;s/-0).*//;s/-1).*//;s/\+.*//'` != "$(RADIUSD_VERSION_STRING)" ]; then \ | |
298 | 310 | echo debian/changelog needs to be updated; \ |
299 | 311 | exit 1; \ |
300 | 312 | fi |
301 | 313 | |
302 | 314 | dist: dist-check freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2 |
303 | 315 | |
304 | dist-sign: freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz.sig freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2.sig | |
316 | dist-sign: dist-check freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz.sig freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2.sig | |
305 | 317 | |
306 | 318 | dist-publish: freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz.sig freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz.sig freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2 freeradius-server-$(RADIUSD_VERSION_STRING).tar.gz.sig freeradius-server-$(RADIUSD_VERSION_STRING).tar.bz2.sig |
307 | 319 | scp $^ freeradius.org@ftp.freeradius.org:public_ftp |
314 | 326 | @echo "git tag release_`echo $(RADIUSD_VERSION_STRING) | tr .- __`" |
315 | 327 | |
316 | 328 | # |
317 | # Docker-related targets | |
318 | # | |
319 | .PHONY: docker | |
320 | docker: | |
321 | docker build scripts/docker/ubuntu18 --build-arg=release=release_`echo $(RADIUSD_VERSION_STRING) | tr .- __` -t freeradius/freeradius-server:$(RADIUSD_VERSION_STRING) | |
322 | docker build scripts/docker/alpine --build-arg=release=release_`echo $(RADIUSD_VERSION_STRING) | tr .- __` -t freeradius/freeradius-server:$(RADIUSD_VERSION_STRING)-alpine | |
323 | ||
324 | .PHONY: docker-push | |
325 | docker-push: docker | |
326 | docker push freeradius/freeradius-server:$(RADIUSD_VERSION_STRING) | |
327 | docker push freeradius/freeradius-server:$(RADIUSD_VERSION_STRING)-alpine | |
328 | ||
329 | .PHONY: docker-tag-latest | |
330 | docker-tag-latest: docker | |
331 | docker tag freeradius/freeradius-server:$(RADIUSD_VERSION_STRING) freeradius/freeradius-server:latest | |
332 | docker tag freeradius/freeradius-server:$(RADIUSD_VERSION_STRING)-alpine freeradius/freeradius-server:latest-alpine | |
333 | ||
334 | .PHONY: docker-push-latest | |
335 | docker-push-latest: docker-push docker-tag-latest | |
336 | docker push freeradius/freeradius-server:latest | |
337 | docker push freeradius/freeradius-server:latest-alpine | |
338 | ||
339 | .PHONY: docker-publish | |
340 | docker-publish: docker-push-latest | |
329 | # Docker-related targets (main docker images and crossbuild) | |
330 | # | |
331 | ifneq "$(findstring docker,$(MAKECMDGOALS))" "" | |
332 | include scripts/docker/docker.mk | |
333 | endif | |
334 | ||
335 | ifneq "$(findstring crossbuild,$(MAKECMDGOALS))" "" | |
336 | include scripts/crossbuild/crossbuild.mk | |
337 | endif | |
341 | 338 | |
342 | 339 | # |
343 | 340 | # Build a debian package |
8779 | 8779 | sys/event.h \ |
8780 | 8780 | sys/fcntl.h \ |
8781 | 8781 | sys/prctl.h \ |
8782 | sys/procctl.h \ | |
8782 | 8783 | sys/ptrace.h \ |
8783 | 8784 | sys/resource.h \ |
8784 | 8785 | sys/security.h \ |
1150 | 1150 | sys/event.h \ |
1151 | 1151 | sys/fcntl.h \ |
1152 | 1152 | sys/prctl.h \ |
1153 | sys/procctl.h \ | |
1153 | 1154 | sys/ptrace.h \ |
1154 | 1155 | sys/resource.h \ |
1155 | 1156 | sys/security.h \ |
0 | FreeRADIUS 3.0.21 Tue 24 Mar 2020 12:00:00 EDT urgency=low | |
1 | Feature improvements | |
2 | * New stored procedure for allocating IPs with PostgreSQL. | |
3 | Rates of 1500 IPs per second are now possible. | |
4 | See raddb/mods-config/sql/ippool/postgresql/procedure.sql | |
5 | Patch from Terry Burton. | |
6 | * Add SQL IP pool support for Microsoft SQL Server | |
7 | See raddb/mods-config/sql/ippool/mssql/ | |
8 | Patch from Terry Burton. | |
9 | * Added RCNTEC dictionary. Closes #3168. | |
10 | * Added Pica8 dictionary. Closes #3179. | |
11 | * Add TLS-Client-Cert-Valid-Since attribute holding notBefore date. | |
12 | Patch from Boris Lytochkin. Fixes #3157. | |
13 | * Generate attributes containing unknown OIDs. | |
14 | See raddb/sites-available/tls. Patch from Boris Lytochkin. | |
15 | * Update the WiMAX dictionary. | |
16 | * Added ability to rlm_python(Python2) show a stacktrace from errors. #2979 | |
17 | * Add WiFi Alliance Policy OIDs. See raddb/certs/xpextensions | |
18 | Patch from Stefan Winter. | |
19 | * radmin now shows coa stats, too. | |
20 | * Sample schema extensions for summarizing data in SQL. | |
21 | See mods-config/sql/main/*/process-radacct.sql | |
22 | Many patches from Terry Burton. | |
23 | * Update dictionary.aerohive, dictionary.fortinet, | |
24 | dictionary.arista and dictionary.erx | |
25 | * Added VAS Experts dictionary. | |
26 | * Many updates to RPM and jenkins builds from Matthew Newton | |
27 | * Added %C (time now in seconds) and %c (microsecond component of now) | |
28 | back-ported from the "master" branch. | |
29 | * Add reload capability to systemd unit file in Debian and RedHat. | |
30 | * Increase timestamp precision in postauth to maximum supported by each | |
31 | database and simplify (and make more consistent between drivers) the | |
32 | timestamps in SQL queries by using expansions. | |
33 | Patches from Terry Burton. | |
34 | * Option to set dictionary path in raduat script. Patch from Terry Burton. | |
35 | ||
36 | Bug fixes | |
37 | * Various fixes found by PVS-Studio. | |
38 | * Set permissions of certificates in bootstrap shell script. | |
39 | Fixes #3132. | |
40 | * Increase the 'nasportid' SQL field for 'varchar(32)'. #3141 | |
41 | * Skip processing proxy reply if there are no home servers | |
42 | available. | |
43 | * Update SQLite IPPool queries. Fixes #3177 | |
44 | Patch from Terry Burton. | |
45 | * rlm_sql_unixodbc fixes. Patches from Terry Burton. Fixes #2822 | |
46 | * Fixes when building with LibreSSL. Patch from Nathan Owens. | |
47 | * Fix the rlm_python3 build. Note that this module is experimental. #3183 | |
48 | * The rlm_python should append the 'python_path' paths in 'sys.path', | |
49 | It fixes the expected behavior to use the existing Python modules. | |
50 | Fixes #3180 | |
51 | * Fix rlm_python to print the script errors properly. | |
52 | * Bound total query time for PostgreSQL. Fixes #3253 | |
53 | * Many fixes to Oracle sqlippool. It now does 500 IPs per second | |
54 | without any tuning. Fixes #3270. | |
55 | * Reference sqlippool by it's correct name. Fixes #3272 | |
56 | * Revert 3.0.20 patch which caused crashes on duplicate clients. | |
57 | * Update WiMAX-MSK attribute. Fixes #3280. | |
58 | * Fix crash when trying to access non-existant regex capture group. | |
59 | * Use timestamps (request or server) rather than SQL NOW() in | |
60 | accounting queries so that these are stable when replayed from a | |
61 | file buffer. | |
62 | Patches from Terry Burton. | |
63 | ||
0 | 64 | FreeRADIUS 3.0.20 Thu 14 Nov 2019 12:00:00 EDT urgency=medium |
1 | 65 | Feature improvements |
2 | 66 | * Add Jenkins continuous integration. Fixes #2620. |
53 | 53 | Print packet headers only, not contents. |
54 | 54 | .IP \-p\ \fIport\fP |
55 | 55 | \tListen for packets on port. |
56 | .IP \-r\ \fIresponse-filter\fP | |
56 | .IP \-r\ \fIattribute-filter\fP | |
57 | 57 | RADIUS attribute request filter. |
58 | .IP \-R\ \fIrequest-filter\fP | |
58 | .IP \-R\ \fIattribute-filter\fP | |
59 | 59 | RADIUS attribute response filter. |
60 | 60 | .IP \-s\ \fIsecret\fP |
61 | 61 | RADIUS secret. |
41 | 41 | |
42 | 42 | if [ ! -f server.key ]; then |
43 | 43 | openssl req -new -out server.csr -keyout server.key -config ./server.cnf || exit 1 |
44 | chmod g+r server.key | |
44 | 45 | fi |
45 | 46 | |
46 | 47 | if [ ! -f ca.key ]; then |
61 | 62 | |
62 | 63 | if [ ! -f server.p12 ]; then |
63 | 64 | openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12 -passin pass:`grep output_password server.cnf | sed 's/.*=//;s/^ *//'` -passout pass:`grep output_password server.cnf | sed 's/.*=//;s/^ *//'` || exit 1 |
65 | chmod g+r server.p12 | |
64 | 66 | fi |
65 | 67 | |
66 | 68 | if [ ! -f server.pem ]; then |
67 | 69 | openssl pkcs12 -in server.p12 -out server.pem -passin pass:`grep output_password server.cnf | sed 's/.*=//;s/^ *//'` -passout pass:`grep output_password server.cnf | sed 's/.*=//;s/^ *//'` || exit 1 |
68 | 70 | openssl verify -CAfile ca.pem server.pem || exit 1 |
71 | chmod g+r server.pem | |
69 | 72 | fi |
70 | 73 | |
71 | 74 | if [ ! -f ca.der ]; then |
74 | 77 | |
75 | 78 | if [ ! -f client.key ]; then |
76 | 79 | openssl req -new -out client.csr -keyout client.key -config ./client.cnf |
80 | chmod g+r client.key | |
77 | 81 | fi |
78 | 82 | |
79 | 83 | if [ ! -f client.crt ]; then |
13 | 13 | extendedKeyUsage = 1.3.6.1.5.5.7.3.1 |
14 | 14 | crlDistributionPoints = URI:http://www.example.com/example_ca.crl |
15 | 15 | |
16 | # Enterprise Wi-Fi clients from 2020 onwards which have the | |
17 | # Wi-Fi Certified WPA3 Release 2 (December 2019) certification | |
18 | # honour the following two policies for enhanced security | |
19 | # posture regarding certificate validation: | |
20 | # | |
21 | # https://www.wi-fi.org/discover-wi-fi/security | |
22 | # | |
23 | # Adding the 'Trust Override Disabled - STRICT' policy means that | |
24 | # the client device is not allowed to request and accept ad-hoc | |
25 | # trust decisions from the user ("Is this the certificate you | |
26 | # expect here?") and instead aborts authentication until the | |
27 | # device has been properly configured using out-of-band means | |
28 | # with all the details needed to verify the certificate (i.e. | |
29 | # either the tuple (CA, server name) or the literal server cert). | |
30 | # | |
31 | # Adding the 'Trust Override Disabled - TOFU' policy means that | |
32 | # the client device is allowed to ask the end user for such an | |
33 | # override exactly once, when first connecting to an unknown | |
34 | # network. Once the network is known and the trust decision made, | |
35 | # any other certificate that is presented and would require | |
36 | # another override is rejected and authentication aborted. | |
37 | # | |
38 | # Both of these policies provide a protection against rogue | |
39 | # authentication servers in that they make sure configurations | |
40 | # on end user devices are sufficient to identify the genuine | |
41 | # server. | |
42 | # | |
43 | # The difference is that the TOFU policy allows a leap of faith | |
44 | # on first sight of a network ONCE - very much comparable to | |
45 | # how SSH establishes trust in a new host. This adds convenience | |
46 | # for end users who did not bother to configure their devices | |
47 | # beforehand, but adds an element of uncertainty in that the | |
48 | # attacker could be present on that first contact with the network. | |
49 | # | |
50 | # Network administrators who consider the TOFU leap of faith | |
51 | # unacceptable should choose STRICT; everyone else gains security | |
52 | # by choosing TOFU without giving up on convenience for their | |
53 | # end users. | |
54 | # | |
55 | # For completeness, it is also possible to include none of the | |
56 | # two to stay with the "anything goes" that was the situation | |
57 | # prior to Wi-Fi Certified WPA3 Release December 2019. | |
58 | # | |
59 | # This is the 'Trust Override Disabled - STRICT' policy. | |
60 | #certificatePolicies = 1.3.6.1.4.1.40808.1.3.1 | |
61 | # This is the 'Trust Override Disabled - TOFU' policy. | |
62 | certificatePolicies = 1.3.6.1.4.1.40808.1.3.2 | |
63 | ||
16 | 64 | # |
17 | 65 | # Add this to the PKCS#7 keybag attributes holding the client's private key |
18 | 66 | # for machine authentication. |
12 | 12 | # item is GLOBAL TO THE SERVER. That is, you cannot have two |
13 | 13 | # instances of the python module, each with a different path. |
14 | 14 | # |
15 | # python_path="/path/to/python/files:/another_path/to/python_files/" | |
15 | # python_path="${modconfdir}/${.:name}:/path/to/python/files:/another_path/to/python_files/" | |
16 | 16 | |
17 | 17 | module = example |
18 | 18 |
12 | 12 | # item is GLOBAL TO THE SERVER. That is, you cannot have two |
13 | 13 | # instances of the python module, each with a different path. |
14 | 14 | # |
15 | # python_path="/path/to/python/files:/another_path/to/python_files/" | |
15 | # python_path="${modconfdir}/${.:name}:/another_path/to/python_files" | |
16 | 16 | |
17 | 17 | module = example |
18 | 18 |
10 | 10 | # Host where the redis server is located. |
11 | 11 | # We recommend using ONLY 127.0.0.1 ! |
12 | 12 | server = 127.0.0.1 |
13 | ||
14 | # Select the Redis logical database having the specified zero-based numeric index. | |
15 | # database = 0 | |
13 | 16 | |
14 | 17 | # The default port. |
15 | 18 | port = 6379 |
55 | 55 | # rlm_sql_freetds |
56 | 56 | # rlm_sql_iodbc |
57 | 57 | # rlm_sql_unixodbc |
58 | # rlm_sql_mongo | |
59 | 58 | # |
60 | 59 | driver = "rlm_sql_null" |
61 | 60 | # driver = "rlm_sql_${dialect}" |
246 | 245 | # connection pool, use "pool = name" instead of a "pool" |
247 | 246 | # section. e.g. |
248 | 247 | # |
249 | # sql1 { | |
248 | # sql sql1 { | |
250 | 249 | # ... |
251 | 250 | # pool { |
252 | 251 | # ... |
254 | 253 | # } |
255 | 254 | # |
256 | 255 | # # sql2 will use the connection pool from sql1 |
257 | # sql2 { | |
256 | # sql sql2 { | |
258 | 257 | # ... |
259 | 258 | # pool = sql1 |
260 | 259 | # } |
149 | 149 | # an already existing name-value pair. |
150 | 150 | # |
151 | 151 | |
152 | # | |
153 | # Set up different IP address pools for the terminal servers. | |
154 | # Note that the "+" behind the IP address means that this is the "base" | |
155 | # IP address. The Port-Id (S0, S1 etc) will be added to it. | |
156 | # | |
157 | #DEFAULT Service-Type == Framed-User, Huntgroup-Name == "alphen" | |
158 | # Framed-IP-Address = 192.0.2.32+, | |
159 | # Fall-Through = Yes | |
160 | ||
161 | #DEFAULT Service-Type == Framed-User, Huntgroup-Name == "delft" | |
162 | # Framed-IP-Address = 198.51.100.32+, | |
163 | # Fall-Through = Yes | |
164 | ||
165 | # | |
166 | 152 | # Sample defaults for all framed connections. |
167 | 153 | # |
168 | 154 | #DEFAULT Service-Type == Framed-User |
2 | 2 | # ippool/mongo/queries.conf -- Mongo queries for rlm_sqlippool |
3 | 3 | # |
4 | 4 | # $Id$ |
5 | ||
6 | # | |
7 | # The IP Pool queries expect a result like: | |
8 | # | |
9 | # { | |
10 | # pool_key: "bob" | |
11 | # pool_name: "my_pool" | |
12 | # expiry_time: xxx | |
13 | # value: "192.168.1.1" | |
14 | # } | |
15 | # | |
16 | # i.e. the results are in "value", and not "framed_ip_address". | |
17 | # | |
18 | # When using dynamic expansions such as "%{sql:... mongo query ...}", | |
19 | # Mongo uses a lot of curly brackets, {..}. Any closing braces have | |
20 | # to be escaped as %}. Sorry, that is a limitation of the FreeRADIUS | |
21 | # parser. | |
22 | # | |
5 | 23 | |
6 | 24 | # |
7 | 25 | # TBD |
19 | 37 | 'query': {' \ |
20 | 38 | '$and': [ \ |
21 | 39 | { \ |
22 | 'pool_name': '{Control:Pool-Name}' \ | |
40 | 'pool_name': '%{control:Pool-Name}' \ | |
23 | 41 | }, \ |
24 | 42 | { \ |
25 | 43 | 'nas_ip': '%{Nas-IP-Address}' \ |
0 | -- | |
1 | -- A stored procedure to reallocate a user's previous address, otherwise | |
2 | -- provide a free address. | |
3 | -- | |
4 | -- Using this SP reduces the usual set dialogue of queries to a single | |
5 | -- query: | |
6 | -- | |
7 | -- BEGIN TRAN; "SELECT FOR UPDATE"; UPDATE; COMMIT TRAN; -> EXEC sp | |
8 | -- | |
9 | -- The stored procedure is executed on an database instance within a single | |
10 | -- round trip which often leads to reduced deadlocking and significant | |
11 | -- performance improvements especially on multi-master clusters, perhaps even | |
12 | -- by an order of magnitude or more. | |
13 | -- | |
14 | -- To use this stored procedure the corresponding queries.conf statements must | |
15 | -- be configured as follows: | |
16 | -- | |
17 | -- allocate_begin = "" | |
18 | -- allocate_find = "\ | |
19 | -- EXEC fr_allocate_previous_or_new_framedipaddress \ | |
20 | -- @v_pool_name = '%{control:${pool_name}}', \ | |
21 | -- @v_username = '%{User-Name}', \ | |
22 | -- @v_callingstationid = '%{Calling-Station-Id}', \ | |
23 | -- @v_nasipaddress = '%{NAS-IP-Address}', \ | |
24 | -- @v_pool_key = '${pool_key}', \ | |
25 | -- @v_lease_duration = ${lease_duration} \ | |
26 | -- " | |
27 | -- allocate_update = "" | |
28 | -- allocate_commit = "" | |
29 | -- | |
30 | ||
31 | CREATE INDEX UserName_CallingStationId ON radippool(pool_name,UserName,CallingStationId) | |
32 | GO | |
33 | ||
34 | CREATE OR ALTER PROCEDURE fr_allocate_previous_or_new_framedipaddress | |
35 | @v_pool_name VARCHAR(64), | |
36 | @v_username VARCHAR(64), | |
37 | @v_callingstationid VARCHAR(64), | |
38 | @v_nasipaddress VARCHAR(15), | |
39 | @v_pool_key VARCHAR(64), | |
40 | @v_lease_duration INT | |
41 | AS | |
42 | BEGIN | |
43 | ||
44 | -- MS SQL lacks a "SELECT FOR UPDATE" statement, and its table | |
45 | -- hints do not provide a direct means to implement the row-level | |
46 | -- read lock needed to guarentee that concurrent queries do not | |
47 | -- select the same Framed-IP-Address for allocation to distinct | |
48 | -- users. | |
49 | -- | |
50 | -- The "WITH cte AS ( SELECT ... ) UPDATE cte ... OUTPUT INTO" | |
51 | -- patterns in this procedure body compensate by wrapping | |
52 | -- the SELECT in a synthetic UPDATE which locks the row. | |
53 | ||
54 | DECLARE @r_address_tab TABLE(id VARCHAR(15)); | |
55 | DECLARE @r_address VARCHAR(15); | |
56 | ||
57 | BEGIN TRAN; | |
58 | ||
59 | -- Reissue an existing IP address lease when re-authenticating a session | |
60 | -- | |
61 | WITH cte AS ( | |
62 | SELECT TOP(1) FramedIPAddress | |
63 | FROM radippool | |
64 | WHERE pool_name = @v_pool_name | |
65 | AND expiry_time > CURRENT_TIMESTAMP | |
66 | AND UserName = @v_username | |
67 | AND CallingStationId = @v_callingstationid | |
68 | ) | |
69 | UPDATE cte WITH (rowlock, readpast) | |
70 | SET FramedIPAddress = FramedIPAddress | |
71 | OUTPUT INSERTED.FramedIPAddress INTO @r_address_tab; | |
72 | SELECT @r_address = id FROM @r_address_tab; | |
73 | ||
74 | -- Reissue an user's previous IP address, provided that the lease is | |
75 | -- available (i.e. enable sticky IPs) | |
76 | -- | |
77 | -- When using this SELECT you should delete the one above. You must also | |
78 | -- set allocate_clear = "" in queries.conf to persist the associations | |
79 | -- for expired leases. | |
80 | -- | |
81 | -- WITH cte AS ( | |
82 | -- SELECT TOP(1) FramedIPAddress | |
83 | -- FROM radippool | |
84 | -- WHERE pool_name = @v_pool_name | |
85 | -- AND UserName = @v_username | |
86 | -- AND CallingStationId = @v_callingstationid | |
87 | -- ) | |
88 | -- UPDATE cte WITH (rowlock, readpast) | |
89 | -- SET FramedIPAddress = FramedIPAddress | |
90 | -- OUTPUT INSERTED.FramedIPAddress INTO @r_address_tab; | |
91 | -- SELECT @r_address = id FROM @r_address_tab; | |
92 | ||
93 | -- If we didn't reallocate a previous address then pick the least | |
94 | -- recently used address from the pool which maximises the likelihood | |
95 | -- of re-assigning the other addresses to their recent user | |
96 | -- | |
97 | IF @r_address IS NULL | |
98 | BEGIN | |
99 | WITH cte AS ( | |
100 | SELECT TOP(1) FramedIPAddress | |
101 | FROM radippool | |
102 | WHERE pool_name = @v_pool_name | |
103 | AND ( expiry_time < CURRENT_TIMESTAMP OR expiry_time IS NULL ) | |
104 | ORDER BY | |
105 | expiry_time | |
106 | ) | |
107 | UPDATE cte WITH (rowlock, readpast) | |
108 | SET FramedIPAddress = FramedIPAddress | |
109 | OUTPUT INSERTED.FramedIPAddress INTO @r_address_tab; | |
110 | SELECT @r_address = id FROM @r_address_tab; | |
111 | END | |
112 | ||
113 | -- Return nothing if we failed to allocated an address | |
114 | -- | |
115 | IF @r_address IS NULL | |
116 | BEGIN | |
117 | COMMIT TRAN; | |
118 | RETURN; | |
119 | END | |
120 | ||
121 | -- Update the pool having allocated an IP address | |
122 | -- | |
123 | UPDATE radippool | |
124 | SET | |
125 | NASIPAddress = @v_nasipaddress, | |
126 | pool_key = @v_pool_key, | |
127 | CallingStationId = @v_callingstationid, | |
128 | UserName = @v_username, | |
129 | expiry_time = DATEADD(SECOND,@v_lease_duration,CURRENT_TIMESTAMP) | |
130 | WHERE framedipaddress = @r_address; | |
131 | ||
132 | COMMIT TRAN; | |
133 | ||
134 | -- Return the address that we allocated | |
135 | SELECT @r_address; | |
136 | ||
137 | END | |
138 | GO |
0 | # -*- text -*- | |
1 | # | |
2 | # ippool/mssql/queries.conf -- MSSQL queries for rlm_sqlippool | |
3 | # | |
4 | # $Id$ | |
5 | ||
6 | # MSSQL-specific syntax | |
7 | allocate_begin = "BEGIN TRAN" | |
8 | allocate_commit = "COMMIT TRAN" | |
9 | ||
10 | # | |
11 | # This series of queries allocates an IP address | |
12 | # | |
13 | #allocate_clear = "\ | |
14 | # UPDATE ${ippool_table} \ | |
15 | # SET \ | |
16 | # NASIPAddress = '', \ | |
17 | # pool_key = 0, \ | |
18 | # CallingStationId = '', \ | |
19 | # UserName = '', \ | |
20 | # expiry_time = NULL \ | |
21 | # WHERE pool_key = '${pool_key}'" | |
22 | ||
23 | # | |
24 | # (Note: If your pool_key is set to Calling-Station-Id and not NAS-Port | |
25 | # then you may wish to delete the "AND nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' | |
26 | # from the WHERE clause) | |
27 | # | |
28 | allocate_clear = "\ | |
29 | UPDATE ${ippool_table} \ | |
30 | SET \ | |
31 | NASIPAddress = '', \ | |
32 | pool_key = 0, \ | |
33 | CallingStationID = '', \ | |
34 | UserName = '', \ | |
35 | expiry_time = NULL \ | |
36 | WHERE expiry_time <= DATEADD(SECOND,-1,CURRENT_TIMESTAMP) \ | |
37 | AND NASIPAddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
38 | ||
39 | # | |
40 | # The ORDER BY clause of this query tries to allocate the same IP-address | |
41 | # which user had last session... | |
42 | # | |
43 | allocate_find = "\ | |
44 | WITH cte AS ( \ | |
45 | SELECT TOP(1) FramedIPAddress FROM ${ippool_table} \ | |
46 | WHERE pool_name = '%{control:${pool_name}}' \ | |
47 | AND ( expiry_time < CURRENT_TIMESTAMP OR expiry_time IS NULL ) \ | |
48 | OR ( NASIPAddress = '%{NAS-IP-Address}' AND pool_key = '${pool_key}' ) \ | |
49 | ORDER BY \ | |
50 | CASE WHEN UserName = '%{User-Name}' THEN 0 ELSE 1 END, \ | |
51 | CASE WHEN CallingStationId = '%{Calling-Station-Id}' THEN 0 ELSE 1 END, \ | |
52 | expiry_time \ | |
53 | ) \ | |
54 | UPDATE cte WITH (rowlock, readpast) \ | |
55 | SET FramedIPAddress = FramedIPAddress \ | |
56 | OUTPUT INSERTED.FramedIPAddress" | |
57 | ||
58 | # | |
59 | # If you prefer to allocate a random IP address every time, use this query instead. | |
60 | # Note: This is very slow if you have a lot of free IPs. | |
61 | # | |
62 | #allocate_find = "\ | |
63 | # WITH cte AS ( \ | |
64 | # SELECT TOP(1) FramedIPAddress FROM ${ippool_table} \ | |
65 | # WHERE pool_name = '%{control:${pool_name}}' \ | |
66 | # AND ( \ | |
67 | # expiry_time < CURRENT_TIMESTAMP OR expiry_time IS NULL \ | |
68 | # ) \ | |
69 | # ORDER BY \ | |
70 | # newid() \ | |
71 | # ) \ | |
72 | # UPDATE cte WITH (rowlock, readpast) \ | |
73 | # SET FramedIPAddress = FramedIPAddress \ | |
74 | # OUTPUT INSERTED.FramedIPAddress" | |
75 | ||
76 | # | |
77 | # If an IP could not be allocated, check to see if the pool exists or not | |
78 | # This allows the module to differentiate between a full pool and no pool | |
79 | # Note: If you are not running redundant pool modules this query may be | |
80 | # commented out to save running this query every time an ip is not allocated. | |
81 | # | |
82 | pool_check = "\ | |
83 | SELECT TOP(1) id \ | |
84 | FROM ${ippool_table} \ | |
85 | WHERE pool_name='%{control:${pool_name}}'" | |
86 | ||
87 | # | |
88 | # This is the final IP Allocation query, which saves the allocated ip details. | |
89 | # | |
90 | allocate_update = "\ | |
91 | UPDATE ${ippool_table} \ | |
92 | SET \ | |
93 | NASIPAddress = '%{NAS-IP-Address}', pool_key = '${pool_key}', \ | |
94 | CallingStationId = '%{Calling-Station-Id}', \ | |
95 | UserName = '%{User-Name}', expiry_time = DATEADD(SECOND,${lease_duration},CURRENT_TIMESTAMP) \ | |
96 | WHERE FramedIPAddress = '%I'" | |
97 | ||
98 | # | |
99 | # Use a stored procedure to find AND allocate the address. Read and customise | |
100 | # `procedure.sql` in this directory to determine the optimal configuration. | |
101 | # | |
102 | #allocate_begin = "" | |
103 | #allocate_find = "\ | |
104 | # EXEC fr_allocate_previous_or_new_framedipaddress \ | |
105 | # @v_pool_name = '%{control:${pool_name}}', \ | |
106 | # @v_username = '%{User-Name}', \ | |
107 | # @v_callingstationid = '%{Calling-Station-Id}', \ | |
108 | # @v_nasipaddress = '%{NAS-IP-Address}', \ | |
109 | # @v_pool_key = '${pool_key}', \ | |
110 | # @v_lease_duration = ${lease_duration} \ | |
111 | # " | |
112 | #allocate_update = "" | |
113 | #allocate_commit = "" | |
114 | ||
115 | # | |
116 | # This series of queries frees an IP number when an accounting START record arrives. | |
117 | # | |
118 | start_update = "\ | |
119 | UPDATE ${ippool_table} \ | |
120 | SET \ | |
121 | expiry_time = DATEADD(SECOND,${lease_duration},CURRENT_TIMESTAMP) \ | |
122 | WHERE NASIPAddress = '%{NAS-IP-Address}' \ | |
123 | AND pool_key = '${pool_key}' \ | |
124 | AND UserName = '%{User-Name}' \ | |
125 | AND CallingStationId = '%{Calling-Station-Id}' \ | |
126 | AND FramedIPAddress = '%{${attribute_name}}'" | |
127 | ||
128 | # | |
129 | # Free an IP when an accounting STOP record arrives | |
130 | # | |
131 | stop_clear = "\ | |
132 | UPDATE ${ippool_table} \ | |
133 | SET \ | |
134 | NASIPAddress = '', \ | |
135 | pool_key = 0, \ | |
136 | CallingStationId = '', \ | |
137 | UserName = '', \ | |
138 | expiry_time = NULL \ | |
139 | WHERE NASIPAddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
140 | AND pool_key = '${pool_key}' \ | |
141 | AND UserName = '%{User-Name}' \ | |
142 | AND CallingStationId = '%{Calling-Station-Id}' \ | |
143 | AND FramedIPAddress = '%{${attribute_name}}'" | |
144 | ||
145 | # | |
146 | # Update the expiry time for an IP when an accounting ALIVE record arrives | |
147 | # | |
148 | alive_update = "\ | |
149 | UPDATE ${ippool_table} \ | |
150 | SET \ | |
151 | expiry_time = DATEADD(SECOND,${lease_duration},CURRENT_TIMESTAMP) \ | |
152 | WHERE NASIPAddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ | |
153 | AND pool_key = '${pool_key}' \ | |
154 | AND UserName = '%{User-Name}' \ | |
155 | AND CallingStationId = '%{Calling-Station-Id}' \ | |
156 | AND FramedIPAddress = '%{${attribute_name}}'" | |
157 | ||
158 | # | |
159 | # Frees all IPs allocated to a NAS when an accounting ON record arrives | |
160 | # | |
161 | on_clear = "\ | |
162 | UPDATE ${ippool_table} \ | |
163 | SET \ | |
164 | NASIPAddress = '', \ | |
165 | pool_key = 0, \ | |
166 | CallingStationId = '', \ | |
167 | UserName = '', \ | |
168 | expiry_time = NULL \ | |
169 | WHERE NASIPAddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" | |
170 | ||
171 | # | |
172 | # Frees all IPs allocated to a NAS when an accounting OFF record arrives | |
173 | # | |
174 | off_clear = "\ | |
175 | UPDATE ${ippool_table} \ | |
176 | SET \ | |
177 | NASIPAddress = '', \ | |
178 | pool_key = 0, \ | |
179 | CallingStationId = '', \ | |
180 | UserName = '', \ | |
181 | expiry_time = NULL \ | |
182 | WHERE NASIPAddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" |
0 | -- | |
1 | -- Table structure for table 'radippool' | |
2 | -- | |
3 | CREATE TABLE radippool ( | |
4 | id int IDENTITY (1,1) NOT NULL, | |
5 | pool_name varchar(30) NOT NULL, | |
6 | FramedIPAddress varchar(15) NOT NULL default '', | |
7 | NASIPAddress varchar(15) NOT NULL default '', | |
8 | CalledStationId VARCHAR(32) NOT NULL, | |
9 | CallingStationId VARCHAR(30) NOT NULL, | |
10 | expiry_time DATETIME NULL default NULL, | |
11 | UserName varchar(64) NOT NULL default '', | |
12 | pool_key varchar(30) NOT NULL default '', | |
13 | PRIMARY KEY (id) | |
14 | ) | |
15 | GO | |
16 | ||
17 | CREATE INDEX poolname_expire ON radippool(pool_name, expiry_time) | |
18 | GO | |
19 | ||
20 | CREATE INDEX FramedIPAddress ON radippool(FramedIPAddress) | |
21 | GO | |
22 | ||
23 | CREATE INDEX NASIPAddress_poolkey_FramedIPAddress ON radippool(NASIPAddress, pool_key, FramedIPAddress) | |
24 | GO |
16 | 16 | -- |
17 | 17 | -- allocate_begin = "" |
18 | 18 | -- allocate_find = "\ |
19 | -- CALL sp_allocate_previous_or_new_framedipaddress( \ | |
19 | -- CALL fr_allocate_previous_or_new_framedipaddress( \ | |
20 | 20 | -- '%{control:${pool_name}}', \ |
21 | 21 | -- '%{User-Name}', \ |
22 | 22 | -- '%{Calling-Station-Id}', \ |
32 | 32 | |
33 | 33 | DELIMITER $$ |
34 | 34 | |
35 | DROP PROCEDURE IF EXISTS sp_allocate_previous_or_new_framedipaddress; | |
36 | CREATE PROCEDURE sp_allocate_previous_or_new_framedipaddress ( | |
35 | DROP PROCEDURE IF EXISTS fr_allocate_previous_or_new_framedipaddress; | |
36 | CREATE PROCEDURE fr_allocate_previous_or_new_framedipaddress ( | |
37 | 37 | IN v_pool_name VARCHAR(64), |
38 | 38 | IN v_username VARCHAR(64), |
39 | 39 | IN v_callingstationid VARCHAR(64), |
113 | 113 | nasipaddress = '%{NAS-IP-Address}', pool_key = '${pool_key}', \ |
114 | 114 | callingstationid = '%{Calling-Station-Id}', \ |
115 | 115 | username = '%{User-Name}', expiry_time = NOW() + INTERVAL ${lease_duration} SECOND \ |
116 | WHERE framedipaddress = '%I' | |
116 | WHERE framedipaddress = '%I'" | |
117 | 117 | |
118 | 118 | # |
119 | 119 | # Use a stored procedure to find AND allocate the address. Read and customise |
121 | 121 | # |
122 | 122 | #allocate_begin = "" |
123 | 123 | #allocate_find = "\ |
124 | # CALL sp_allocate_previous_or_new_framedipaddress( \ | |
124 | # CALL fr_allocate_previous_or_new_framedipaddress( \ | |
125 | 125 | # '%{control:${pool_name}}', \ |
126 | 126 | # '%{User-Name}', \ |
127 | 127 | # '%{Calling-Station-Id}', \ |
0 | -- | |
1 | -- A stored procedure to reallocate a user's previous address, otherwise | |
2 | -- provide a free address. | |
3 | -- | |
4 | -- Using this SP reduces the usual set dialogue of queries to a single | |
5 | -- query: | |
6 | -- | |
7 | -- BEGIN; SELECT FOR UPDATE; UPDATE; COMMIT; -> SELECT sp() FROM dual | |
8 | -- | |
9 | -- The stored procedure is executed on an database instance within a single | |
10 | -- round trip which often leads to reduced deadlocking and significant | |
11 | -- performance improvements especially on multi-master clusters, perhaps even | |
12 | -- by an order of magnitude or more. | |
13 | -- | |
14 | -- To use this stored procedure the corresponding queries.conf statements must | |
15 | -- be configured as follows: | |
16 | -- | |
17 | -- allocate_begin = "" | |
18 | -- allocate_find = "\ | |
19 | -- SELECT fr_allocate_previous_or_new_framedipaddress( \ | |
20 | -- '%{control:${pool_name}}', \ | |
21 | -- '%{User-Name}', \ | |
22 | -- '%{%{Calling-Station-Id}:-0}', \ | |
23 | -- '%{NAS-IP-Address}', \ | |
24 | -- '${pool_key}', \ | |
25 | -- ${lease_duration} \ | |
26 | -- ) FROM dual" | |
27 | -- allocate_update = "" | |
28 | -- allocate_commit = "" | |
29 | -- | |
30 | ||
31 | CREATE OR REPLACE FUNCTION fr_allocate_previous_or_new_framedipaddress ( | |
32 | v_pool_name IN VARCHAR2, | |
33 | v_username IN VARCHAR2, | |
34 | v_callingstationid IN VARCHAR2, | |
35 | v_nasipaddress IN VARCHAR2, | |
36 | v_pool_key IN VARCHAR2, | |
37 | v_lease_duration IN INTEGER | |
38 | ) | |
39 | RETURN varchar2 IS | |
40 | PRAGMA AUTONOMOUS_TRANSACTION; | |
41 | r_address varchar2(15); | |
42 | BEGIN | |
43 | ||
44 | -- Reissue an existing IP address lease when re-authenticating a session | |
45 | -- | |
46 | BEGIN | |
47 | SELECT framedipaddress INTO r_address FROM radippool WHERE id IN ( | |
48 | SELECT id FROM ( | |
49 | SELECT * | |
50 | FROM radippool | |
51 | WHERE pool_name = v_pool_name | |
52 | AND expiry_time > current_timestamp | |
53 | AND username = v_username | |
54 | AND callingstationid = v_callingstationid | |
55 | ) WHERE ROWNUM <= 1 | |
56 | ) FOR UPDATE SKIP LOCKED; | |
57 | EXCEPTION | |
58 | WHEN NO_DATA_FOUND THEN | |
59 | r_address := NULL; | |
60 | END; | |
61 | ||
62 | -- Reissue an user's previous IP address, provided that the lease is | |
63 | -- available (i.e. enable sticky IPs) | |
64 | -- | |
65 | -- When using this SELECT you should delete the one above. You must also | |
66 | -- set allocate_clear = "" in queries.conf to persist the associations | |
67 | -- for expired leases. | |
68 | -- | |
69 | -- BEGIN | |
70 | -- SELECT framedipaddress INTO r_address FROM radippool WHERE id IN ( | |
71 | -- SELECT id FROM ( | |
72 | -- SELECT * | |
73 | -- FROM radippool | |
74 | -- WHERE pool_name = v_pool_name | |
75 | -- AND username = v_username | |
76 | -- AND callingstationid = v_callingstationid | |
77 | -- ) WHERE ROWNUM <= 1 | |
78 | -- ) FOR UPDATE SKIP LOCKED; | |
79 | -- EXCEPTION | |
80 | -- WHEN NO_DATA_FOUND THEN | |
81 | -- r_address := NULL; | |
82 | -- END; | |
83 | ||
84 | -- If we didn't reallocate a previous address then pick the least | |
85 | -- recently used address from the pool which maximises the likelihood | |
86 | -- of re-assigning the other addresses to their recent user | |
87 | -- | |
88 | IF r_address IS NULL THEN | |
89 | BEGIN | |
90 | SELECT framedipaddress INTO r_address FROM radippool WHERE id IN ( | |
91 | SELECT id FROM ( | |
92 | SELECT * | |
93 | FROM radippool | |
94 | WHERE pool_name = v_pool_name | |
95 | AND expiry_time < CURRENT_TIMESTAMP | |
96 | ORDER BY expiry_time | |
97 | ) WHERE ROWNUM <= 1 | |
98 | ) FOR UPDATE SKIP LOCKED; | |
99 | EXCEPTION | |
100 | WHEN NO_DATA_FOUND THEN | |
101 | r_address := NULL; | |
102 | END; | |
103 | END IF; | |
104 | ||
105 | -- Return nothing if we failed to allocated an address | |
106 | -- | |
107 | IF r_address IS NULL THEN | |
108 | COMMIT; | |
109 | RETURN r_address; | |
110 | END IF; | |
111 | ||
112 | -- Update the pool having allocated an IP address | |
113 | -- | |
114 | UPDATE radippool | |
115 | SET | |
116 | nasipaddress = v_nasipaddress, | |
117 | pool_key = v_pool_key, | |
118 | callingstationid = v_callingstationid, | |
119 | username = v_username, | |
120 | expiry_time = CURRENT_TIMESTAMP + v_lease_duration * INTERVAL '1' SECOND(1) | |
121 | WHERE framedipaddress = r_address; | |
122 | ||
123 | -- Return the address that we allocated | |
124 | COMMIT; | |
125 | RETURN r_address; | |
126 | ||
127 | END; | |
128 | / |
0 | CREATE OR REPLACE FUNCTION msqlippool(user varchar2, pool varchar2) | |
1 | RETURN varchar2 IS | |
2 | ||
3 | PRAGMA AUTONOMOUS_TRANSACTION; | |
4 | ip_temp varchar2(20); | |
5 | BEGIN | |
6 | ||
7 | -- If the user's pool is dynamic, get an ipaddress (oldest one) from the corresponding pool | |
8 | ||
9 | if pool = 'Dynamic' then | |
10 | select framedipaddress into ip_temp from (select framedipaddress from radippool where expiry_time < current_timestamp and pool_name = pool ORDER BY expiry_time) where rownum = 1; | |
11 | return (ip_temp); | |
12 | ||
13 | -- Else, then get the static ipaddress for that user from the corresponding pool | |
14 | ||
15 | else | |
16 | select framedipaddress into ip_temp from radippool where username = user and pool_name = pool; | |
17 | return (ip_temp); | |
18 | end if; | |
19 | ||
20 | exception | |
21 | ||
22 | -- This block is executed if there's no free ipaddresses or no static ip assigned to the user | |
23 | ||
24 | when NO_DATA_FOUND then | |
25 | if pool = 'Dynamic' then | |
26 | return(''); -- so sqlippool can log it on radius.log | |
27 | end if; | |
28 | ||
29 | -- Else, grabs a free IP from the static pool and saves it in radippool so the user will always get the same IP the next time | |
30 | ||
31 | select framedipaddress into ip_temp from (select framedipaddress from radippool where expiry_time < current_timestamp and username is null and pool_name = pool) where rownum = 1; | |
32 | UPDATE radippool SET username = user where framedipaddress = ip_temp; | |
33 | commit; | |
34 | return (ip_temp); | |
35 | ||
36 | when others | |
37 | then return('Oracle Exception'); | |
38 | ||
39 | END; | |
40 | / |
16 | 16 | # to the user that they had last session... |
17 | 17 | # |
18 | 18 | allocate_find = "\ |
19 | SELECT framedipaddress \ | |
20 | FROM ${ippool_table} \ | |
21 | WHERE pool_name = '%{control:${pool_name}}' \ | |
22 | AND ( \ | |
23 | expiry_time < current_timestamp \ | |
24 | OR ( nasipaddress = '%{NAS-IP-Address}' AND pool_key = '${pool_key}' ) \ | |
25 | ) \ | |
26 | AND rownum <= 1 \ | |
27 | ORDER BY \ | |
28 | (username <> '%{SQL-User-Name}'), \ | |
29 | (callingstationid <> '%{Calling-Station-Id}'), \ | |
30 | expiry_time \ | |
31 | FOR UPDATE" | |
19 | SELECT framedipaddress FROM ${ippool_table} WHERE id IN ( \ | |
20 | SELECT id FROM ( \ | |
21 | SELECT * \ | |
22 | FROM ${ippool_table} \ | |
23 | WHERE pool_name = '%{control:${pool_name}}' \ | |
24 | AND ( \ | |
25 | expiry_time < current_timestamp \ | |
26 | OR ( nasipaddress = '%{NAS-IP-Address}' AND pool_key = '${pool_key}' ) \ | |
27 | ) \ | |
28 | ORDER BY \ | |
29 | DECODE(username,'%{SQL-User-Name}',2,1), \ | |
30 | DECODE(callingstationid,'%{%{Calling-Station-Id}:-0}',2,1), \ | |
31 | expiry_time \ | |
32 | ) WHERE ROWNUM <= 1 \ | |
33 | ) FOR UPDATE" | |
32 | 34 | |
33 | 35 | # |
34 | 36 | # The above query again, but with SKIP LOCKED. This requires Oracle > 11g. |
35 | 37 | # It may work in 9i and 10g, but is not documented, so YMMV. |
36 | 38 | # |
37 | 39 | #allocate_find = "\ |
38 | # SELECT framedipaddress \ | |
39 | # FROM ${ippool_table} \ | |
40 | # WHERE pool_name = '%{control:${pool_name}}' \ | |
41 | # AND expiry_time < current_timestamp \ | |
42 | # AND rownum <= 1 \ | |
43 | # ORDER BY \ | |
44 | # (username <> '%{SQL-User-Name}'), \ | |
45 | # (callingstationid <> '%{Calling-Station-Id}'), \ | |
46 | # expiry_time \ | |
47 | # FOR UPDATE SKIP LOCKED" | |
48 | ||
49 | # | |
50 | # This function is available if you want to use multiple pools | |
51 | # | |
52 | #allocate_find = "\ | |
53 | # SELECT msqlippool('%{SQL-User-Name}','%{control:${pool_name}}') \ | |
54 | # FROM dual" | |
40 | # SELECT framedipaddress FROM ${ippool_table} WHERE id IN ( \ | |
41 | # SELECT id FROM ( \ | |
42 | # SELECT * \ | |
43 | # FROM ${ippool_table} \ | |
44 | # WHERE pool_name = '%{control:${pool_name}}' \ | |
45 | # AND ( \ | |
46 | # expiry_time < current_timestamp \ | |
47 | # OR ( nasipaddress = '%{NAS-IP-Address}' AND pool_key = '${pool_key}' ) \ | |
48 | # ) \ | |
49 | # ORDER BY \ | |
50 | # DECODE(username,'%{SQL-User-Name}',2,1), \ | |
51 | # DECODE(callingstationid,'%{%{Calling-Station-Id}:-0}',2,1), \ | |
52 | # expiry_time \ | |
53 | # ) WHERE ROWNUM <= 1 \ | |
54 | # ) FOR UPDATE SKIP LOCKED" | |
55 | 55 | |
56 | 56 | # |
57 | 57 | # If you prefer to allocate a random IP address every time, use this query instead |
58 | 58 | # Note: This is very slow if you have a lot of free IPs. |
59 | 59 | # |
60 | 60 | #allocate_find = "\ |
61 | # SELECT framedipaddress \ | |
62 | # FROM ${ippool_table} \ | |
63 | # WHERE pool_name = '%{control:${pool_name}}' \ | |
64 | # AND expiry_time < current_timestamp \ | |
65 | # AND rownum <= 1 \ | |
66 | # ORDER BY RANDOM() \ | |
67 | # FOR UPDATE" | |
61 | # SELECT framedipaddress FROM ${ippool_table} WHERE id IN ( \ | |
62 | # SELECT id FROM ( \ | |
63 | # SELECT * \ | |
64 | # FROM ${ippool_table} \ | |
65 | # WHERE pool_name = '%{control:${pool_name}}' \ | |
66 | # AND expiry_time < current_timestamp \ | |
67 | # ORDER BY DBMS_RANDOM.VALUE \ | |
68 | # ) WHERE ROWNUM <= 1 \ | |
69 | # ) FOR UPDATE" | |
68 | 70 | |
69 | 71 | # |
70 | 72 | # The above query again, but with SKIP LOCKED. This requires Oracle > 11g. |
71 | 73 | # It may work in 9i and 10g, but is not documented, so YMMV. |
72 | 74 | # |
73 | 75 | #allocate_find = "\ |
74 | # SELECT framedipaddress \ | |
75 | # FROM ${ippool_table} \ | |
76 | # WHERE pool_name = '%{control:${pool_name}}' \ | |
77 | # AND expiry_time < current_timestamp \ | |
78 | # AND rownum <= 1 \ | |
79 | # ORDER BY RANDOM() \ | |
80 | # FOR UPDATE SKIP LOCKED" | |
76 | # SELECT framedipaddress FROM ${ippool_table} WHERE id IN ( \ | |
77 | # SELECT id FROM (\ | |
78 | # SELECT * \ | |
79 | # FROM ${ippool_table} \ | |
80 | # WHERE pool_name = '%{control:${pool_name}}' \ | |
81 | # AND expiry_time < current_timestamp \ | |
82 | # ORDER BY DBMS_RANDOM.VALUE \ | |
83 | # ) WHERE ROWNUM <= 1 \ | |
84 | # ) FOR UPDATE SKIP LOCKED" | |
81 | 85 | |
82 | 86 | # |
83 | 87 | # If an IP could not be allocated, check to see whether the pool exists or not |
103 | 107 | SET \ |
104 | 108 | nasipaddress = '%{NAS-IP-Address}', \ |
105 | 109 | pool_key = '${pool_key}', \ |
106 | callingstationid = '%{Calling-Station-Id}', \ | |
110 | callingstationid = '%{%{Calling-Station-Id}:-0}', \ | |
107 | 111 | username = '%{SQL-User-Name}', \ |
108 | 112 | expiry_time = current_timestamp + INTERVAL '${lease_duration}' second(1) \ |
109 | 113 | WHERE framedipaddress = '%I'" |
121 | 125 | allocate_clear = "\ |
122 | 126 | UPDATE ${ippool_table} \ |
123 | 127 | SET \ |
124 | nasipaddress = '', \ | |
125 | pool_key = 0, \ | |
126 | callingstationid = '', \ | |
127 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ | |
128 | WHERE pool_key = '${pool_key}'" | |
128 | nasipaddress = '0', \ | |
129 | pool_key = '0', \ | |
130 | callingstationid = '0', \ | |
131 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ | |
132 | WHERE nasipaddress = '%{NAS-IP-Address}' \ | |
133 | AND pool_key = '${pool_key}'" | |
134 | ||
135 | ||
136 | # | |
137 | # Use a stored procedure to find AND allocate the address. Read and customise | |
138 | # `procedure.sql` in this directory to determine the optimal configuration. | |
139 | # | |
140 | #allocate_begin = "" | |
141 | #allocate_find = "\ | |
142 | # SELECT fr_allocate_previous_or_new_framedipaddress( \ | |
143 | # '%{control:${pool_name}}', \ | |
144 | # '%{SQL-User-Name}', \ | |
145 | # '%{%{Calling-Station-Id}:-0}', \ | |
146 | # '%{NAS-IP-Address}', \ | |
147 | # '${pool_key}', \ | |
148 | # '${lease_duration}' \ | |
149 | # )" | |
150 | #allocate_update = "" | |
151 | #allocate_commit = "" | |
129 | 152 | |
130 | 153 | # |
131 | 154 | # This query extends an IP address lease by "lease_duration" when an accounting |
144 | 167 | stop_clear = "\ |
145 | 168 | UPDATE ${ippool_table} \ |
146 | 169 | SET \ |
147 | nasipaddress = '', \ | |
148 | pool_key = 0, \ | |
149 | callingstationid = '', \ | |
170 | nasipaddress = '0', \ | |
171 | pool_key = '0', \ | |
172 | callingstationid = '0', \ | |
150 | 173 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ |
151 | 174 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}' \ |
152 | 175 | AND pool_key = '${pool_key}' \ |
153 | 176 | AND username = '%{SQL-User-Name}' \ |
154 | AND callingstationid = '%{Calling-Station-Id}'" | |
177 | AND callingstationid = '%{%{Calling-Station-Id}:-0}' \ | |
178 | AND framedipaddress = '%{${attribute_name}}'" | |
155 | 179 | |
156 | 180 | # |
157 | 181 | # This query extends an IP address lease by "lease_duration" when an accounting |
165 | 189 | AND pool_key = '${pool_key}' \ |
166 | 190 | AND framedipaddress = '%{${attribute_name}}' \ |
167 | 191 | AND username = '%{SQL-User-Name}' \ |
168 | AND callingstationid = '%{Calling-Station-Id}'" | |
192 | AND callingstationid = '%{%{Calling-Station-Id}:-0}'" | |
169 | 193 | |
170 | 194 | # |
171 | 195 | # This query frees all IP addresses allocated to a NAS when an |
174 | 198 | on_clear = "\ |
175 | 199 | UPDATE ${ippool_table} \ |
176 | 200 | SET \ |
177 | nasipaddress = '', \ | |
178 | pool_key = 0, \ | |
179 | callingstationid = '', \ | |
201 | nasipaddress = '0', \ | |
202 | pool_key = '0', \ | |
203 | callingstationid = '0', \ | |
180 | 204 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ |
181 | 205 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" |
182 | 206 | |
187 | 211 | off_clear = "\ |
188 | 212 | UPDATE ${ippool_table} \ |
189 | 213 | SET \ |
190 | nasipaddress = '', \ | |
191 | pool_key = 0, \ | |
192 | callingstationid = '', \ | |
214 | nasipaddress = '0', \ | |
215 | pool_key = '0', \ | |
216 | callingstationid = '0', \ | |
193 | 217 | expiry_time = current_timestamp - INTERVAL '1' second(1) \ |
194 | 218 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" |
0 | 0 | CREATE TABLE radippool ( |
1 | 1 | id INT PRIMARY KEY, |
2 | 2 | pool_name VARCHAR(30) NOT NULL, |
3 | framedipaddress VARCHAR(30) NOT NULL, | |
4 | nasipaddress VARCHAR(30) NOT NULL, | |
5 | pool_key INT NOT NULL, | |
6 | CalledStationId VARCHAR(64), | |
3 | framedipaddress VARCHAR(15) NOT NULL, | |
4 | nasipaddress VARCHAR(15) NOT NULL, | |
5 | pool_key VARCHAR(30) NOT NULL, | |
6 | CalledStationId VARCHAR(64) NOT NULL, | |
7 | 7 | CallingStationId VARCHAR(64) NOT NULL, |
8 | 8 | expiry_time timestamp(0) NOT NULL, |
9 | username VARCHAR(100) | |
9 | username VARCHAR(64) | |
10 | 10 | ); |
11 | 11 | |
12 | CREATE INDEX radippool_poolname_ipaadr ON radippool (pool_name, framedipaddress); | |
13 | 12 | CREATE INDEX radippool_poolname_expire ON radippool (pool_name, expiry_time); |
14 | CREATE INDEX radippool_nasipaddr_key ON radippool (nasipaddress, pool_key); | |
15 | CREATE INDEX radippool_nasipaddr_calling ON radippool (nasipaddress, callingstationid); | |
13 | CREATE INDEX radippool_framedipaddress ON radippool (framedipaddress); | |
14 | CREATE INDEX radippool_nasip_poolkey_ipaddress ON radippool (nasipaddress, pool_key, framedipaddress); | |
16 | 15 | |
17 | 16 | CREATE SEQUENCE radippool_seq START WITH 1 INCREMENT BY 1; |
18 | 17 |
0 | 0 | -- |
1 | -- Use the following indexes and function if using the stored procedure to | |
2 | -- find the previously used address. | |
1 | -- A stored procedure to reallocate a user's previous address, otherwise | |
2 | -- provide a free address. | |
3 | 3 | -- |
4 | -- You may wish to set the ORDER BY expiry_time to DESC for the first two | |
5 | -- queries in order to assign the address that the user had most recently, | |
6 | -- instead of assigning the oldest address the user had used. | |
4 | -- Using this SP reduces the usual set dialogue of queries to a single | |
5 | -- query: | |
6 | -- | |
7 | -- START TRANSACTION; SELECT FOR UPDATE; UPDATE; COMMIT; -> SELECT sp() | |
8 | -- | |
9 | -- The stored procedure is executed on an database instance within a single | |
10 | -- round trip which often leads to reduced deadlocking and significant | |
11 | -- performance improvements especially on multi-master clusters, perhaps even | |
12 | -- by an order of magnitude or more. | |
13 | -- | |
14 | -- To use this stored procedure the corresponding queries.conf statements must | |
15 | -- be configured as follows: | |
16 | -- | |
17 | -- allocate_begin = "" | |
18 | -- allocate_find = "\ | |
19 | -- SELECT fr_allocate_previous_or_new_framedipaddress( \ | |
20 | -- '%{control:${pool_name}}', \ | |
21 | -- '%{User-Name}', \ | |
22 | -- '%{Calling-Station-Id}', \ | |
23 | -- '%{NAS-IP-Address}', \ | |
24 | -- '${pool_key}', \ | |
25 | -- ${lease_duration} \ | |
26 | -- )" | |
27 | -- allocate_update = "" | |
28 | -- allocate_commit = "" | |
7 | 29 | -- |
8 | 30 | |
9 | CREATE INDEX radippool_pool_name ON radippool USING btree (pool_name); | |
10 | CREATE INDEX radippool_username ON radippool USING btree (username); | |
11 | CREATE INDEX radippool_callingstationid ON radippool USING btree (callingstationid); | |
31 | CREATE INDEX radippool_poolname_username_callingstationid ON radippool(pool_name,username,callingstationid); | |
12 | 32 | |
13 | CREATE OR REPLACE FUNCTION find_previous_or_new_framedipaddress ( | |
33 | CREATE OR REPLACE FUNCTION fr_allocate_previous_or_new_framedipaddress ( | |
14 | 34 | v_pool_name VARCHAR(64), |
15 | 35 | v_username VARCHAR(64), |
16 | v_callingstationid VARCHAR(64) | |
36 | v_callingstationid VARCHAR(64), | |
37 | v_nasipaddress VARCHAR(16), | |
38 | v_pool_key VARCHAR(64), | |
39 | v_lease_duration INT | |
17 | 40 | ) |
18 | 41 | RETURNS inet |
19 | 42 | LANGUAGE plpgsql |
21 | 44 | DECLARE |
22 | 45 | r_address inet; |
23 | 46 | BEGIN |
47 | ||
48 | -- Reissue an existing IP address lease when re-authenticating a session | |
49 | -- | |
24 | 50 | SELECT framedipaddress INTO r_address |
25 | 51 | FROM radippool |
26 | WHERE radippool.pool_name = v_pool_name | |
27 | AND radippool.expiry_time < 'now'::timestamp(0) | |
28 | AND radippool.username = v_username | |
29 | AND radippool.callingstationid = v_callingstationid | |
30 | ORDER BY expiry_time | |
52 | WHERE pool_name = v_pool_name | |
53 | AND expiry_time > NOW() | |
54 | AND username = v_username | |
55 | AND callingstationid = v_callingstationid | |
31 | 56 | LIMIT 1 |
32 | 57 | FOR UPDATE SKIP LOCKED; |
33 | IF r_address IS NOT NULL THEN | |
58 | ||
59 | -- Reissue an user's previous IP address, provided that the lease is | |
60 | -- available (i.e. enable sticky IPs) | |
61 | -- | |
62 | -- When using this SELECT you should delete the one above. You must also | |
63 | -- set allocate_clear = "" in queries.conf to persist the associations | |
64 | -- for expired leases. | |
65 | -- | |
66 | -- SELECT framedipaddress INTO r_address | |
67 | -- FROM radippool | |
68 | -- WHERE pool_name = v_pool_name | |
69 | -- AND username = v_username | |
70 | -- AND callingstationid = v_callingstationid | |
71 | -- LIMIT 1 | |
72 | -- FOR UPDATE SKIP LOCKED; | |
73 | ||
74 | -- If we didn't reallocate a previous address then pick the least | |
75 | -- recently used address from the pool which maximises the likelihood | |
76 | -- of re-assigning the other addresses to their recent user | |
77 | -- | |
78 | IF r_address IS NULL THEN | |
79 | SELECT framedipaddress INTO r_address | |
80 | FROM radippool | |
81 | WHERE pool_name = v_pool_name | |
82 | AND expiry_time < NOW() | |
83 | ORDER BY | |
84 | expiry_time | |
85 | LIMIT 1 | |
86 | FOR UPDATE SKIP LOCKED; | |
87 | END IF; | |
88 | ||
89 | -- Return nothing if we failed to allocated an address | |
90 | -- | |
91 | IF r_address IS NULL THEN | |
34 | 92 | RETURN r_address; |
35 | 93 | END IF; |
36 | SELECT framedipaddress INTO r_address | |
37 | FROM radippool | |
38 | WHERE radippool.pool_name = v_pool_name | |
39 | AND radippool.expiry_time < 'now'::timestamp(0) | |
40 | AND radippool.username = v_username | |
41 | ORDER BY expiry_time | |
42 | LIMIT 1 | |
43 | FOR UPDATE SKIP LOCKED; | |
44 | IF r_address IS NOT NULL THEN | |
45 | RETURN r_address; | |
46 | END IF; | |
47 | SELECT framedipaddress INTO r_address | |
48 | FROM radippool | |
49 | WHERE radippool.pool_name = v_pool_name | |
50 | AND radippool.expiry_time < 'now'::timestamp(0) | |
51 | ORDER BY expiry_time | |
52 | LIMIT 1 | |
53 | FOR UPDATE SKIP LOCKED; | |
94 | ||
95 | -- Update the pool having allocated an IP address | |
96 | -- | |
97 | UPDATE radippool | |
98 | SET | |
99 | nasipaddress = v_nasipaddress, | |
100 | pool_key = v_pool_key, | |
101 | callingstationid = v_callingstationid, | |
102 | username = v_username, | |
103 | expiry_time = NOW() + v_lease_duration * interval '1 sec' | |
104 | WHERE framedipaddress = r_address; | |
105 | ||
106 | -- Return the address that we allocated | |
54 | 107 | RETURN r_address; |
108 | ||
55 | 109 | END |
56 | 110 | $$; |
39 | 39 | # FOR UPDATE SKIP LOCKED" |
40 | 40 | |
41 | 41 | # |
42 | # Use a stored procedure to find the address. This requires PostgreSQL >= 9.5 as | |
43 | # SKIP LOCKED is used. See `procedure.sql` in this directory for the | |
44 | # indices and stored procedure used by this query. | |
45 | # | |
46 | # The "NO LOAD BALANCE" comment is included here to indicate to a PgPool | |
47 | # system that this needs to be a write transaction. PgPool itself cannot | |
48 | # detect this from the statement alone. If you are using PgPool and do not | |
49 | # have this comment, the query may go to a read only server, and will fail. | |
50 | # This has no negative effect if you are not using PgPool. | |
51 | # | |
52 | # allocate_find = "\ | |
53 | # /*NO LOAD BALANCE*/ \ | |
54 | # SELECT find_previous_or_new_framedipaddress( \ | |
55 | # '%{control:${pool_name}}', \ | |
56 | # '%{SQL-User-Name}', \ | |
57 | # '%{Calling-Station-Id}' \ | |
58 | # )" | |
59 | ||
60 | # | |
61 | 42 | # If you prefer to allocate a random IP address every time, use this query instead |
62 | 43 | # Note: This is very slow if you have a lot of free IPs. |
63 | 44 | # |
125 | 106 | AND pool_key = '${pool_key}'" |
126 | 107 | |
127 | 108 | # |
109 | # Use a stored procedure to find AND allocate the address. Read and customise | |
110 | # `procedure.sql` in this directory to determine the optimal configuration. | |
111 | # | |
112 | # This requires PostgreSQL >= 9.5 as SKIP LOCKED is used. | |
113 | # | |
114 | # The "NO LOAD BALANCE" comment is included here to indicate to a PgPool | |
115 | # system that this needs to be a write transaction. PgPool itself cannot | |
116 | # detect this from the statement alone. If you are using PgPool and do not | |
117 | # have this comment, the query may go to a read only server, and will fail. | |
118 | # This has no negative effect if you are not using PgPool. | |
119 | # | |
120 | #allocate_begin = "" | |
121 | #allocate_find = "\ | |
122 | # /*NO LOAD BALANCE*/ \ | |
123 | # SELECT fr_allocate_previous_or_new_framedipaddress( \ | |
124 | # '%{control:${pool_name}}', \ | |
125 | # '%{SQL-User-Name}', \ | |
126 | # '%{Calling-Station-Id}', \ | |
127 | # '%{NAS-IP-Address}', \ | |
128 | # '${pool_key}', \ | |
129 | # '${lease_duration}' \ | |
130 | # )" | |
131 | #allocate_update = "" | |
132 | #allocate_commit = "" | |
133 | ||
134 | # | |
128 | 135 | # This query extends an IP address lease by "lease_duration" when an accounting |
129 | 136 | # START record arrives |
130 | 137 | # |
2 | 2 | # ippool/sqlite/queries.conf -- SQLite queries for rlm_sqlippool |
3 | 3 | # |
4 | 4 | # $Id$ |
5 | ||
6 | # | |
7 | # SQLite does not implement SELECT FOR UPDATE which is normally used to place | |
8 | # an exclusive lock over rows to prevent the same address from being | |
9 | # concurrently selected for allocation to multiple users. | |
10 | # | |
11 | # The most granular read-blocking lock that SQLite has is an exclusive lock | |
12 | # over the database, so that's what we use. All locking in SQLite is performed | |
13 | # over the entire database and we perform a row update for any IP that we | |
14 | # allocate, requiring an exclusive lock. Taking the exclusive lock from the | |
15 | # start of the transaction (even if it were not required to guard the SELECT) | |
16 | # is actually quicker than if we deferred it causing SQLite to "upgrade" the | |
17 | # automatic shared lock for the transaction to an exclusive lock for the | |
18 | # subsequent UPDATE. | |
19 | # | |
20 | allocate_begin = "BEGIN EXCLUSIVE" | |
21 | allocate_commit = "COMMIT" | |
5 | 22 | |
6 | 23 | # |
7 | 24 | # This series of queries allocates an IP address |
47 | 64 | (username <> '%{User-Name}'), \ |
48 | 65 | (callingstationid <> '%{Calling-Station-Id}'), \ |
49 | 66 | expiry_time \ |
50 | LIMIT 1 \ | |
51 | FOR UPDATE" | |
67 | LIMIT 1" | |
52 | 68 | |
53 | 69 | # |
54 | 70 | # If you prefer to allocate a random IP address every time, i |
62 | 78 | # WHERE pool_name = '%{control:${pool_name}}' \ |
63 | 79 | # AND expiry_time IS NULL \ |
64 | 80 | # ORDER BY RAND() \ |
65 | # LIMIT 1 \ | |
66 | # FOR UPDATE" | |
81 | # LIMIT 1" | |
67 | 82 | |
68 | 83 | # |
69 | 84 | # If an IP could not be allocated, check to see if the pool exists or not |
88 | 103 | callingstationid = '%{Calling-Station-Id}', \ |
89 | 104 | username = '%{User-Name}', \ |
90 | 105 | expiry_time = datetime(strftime('%%s', 'now') + ${lease_duration}, 'unixepoch') \ |
91 | WHERE framedipaddress = '%I' | |
106 | WHERE framedipaddress = '%I'" | |
92 | 107 | |
93 | 108 | # |
94 | # This series of queries frees an IP number when an accounting START record arrives | |
109 | # Free an IP when an accounting START record arrives | |
95 | 110 | # |
96 | 111 | start_update = "\ |
97 | 112 | UPDATE ${ippool_table} \ |
104 | 119 | AND framedipaddress = '%{${attribute_name}}'" |
105 | 120 | |
106 | 121 | # |
107 | # This series of queries frees an IP number when an accounting STOP record arrives | |
122 | # Free an IP when an accounting STOP record arrives | |
108 | 123 | # |
109 | 124 | stop_clear = "\ |
110 | 125 | UPDATE ${ippool_table} \ |
121 | 136 | AND framedipaddress = '%{${attribute_name}}'" |
122 | 137 | |
123 | 138 | # |
124 | # This series of queries frees an IP number when an accounting | |
125 | # ALIVE record arrives | |
139 | # Update the expiry time for an IP when an accounting ALIVE record arrives | |
126 | 140 | # |
127 | 141 | alive_update = "\ |
128 | 142 | UPDATE ${ippool_table} \ |
135 | 149 | AND framedipaddress = '%{${attribute_name}}'" |
136 | 150 | |
137 | 151 | # |
138 | # This series of queries frees the IP numbers allocate to a | |
139 | # NAS when an accounting ON record arrives | |
152 | # Frees all IPs allocated to a NAS when an accounting ON record arrives | |
140 | 153 | # |
141 | 154 | on_clear = "\ |
142 | 155 | UPDATE ${ippool_table} \ |
149 | 162 | WHERE nasipaddress = '%{%{Nas-IP-Address}:-%{Nas-IPv6-Address}}'" |
150 | 163 | |
151 | 164 | # |
152 | # This series of queries frees the IP numbers allocate to a | |
153 | # NAS when an accounting OFF record arrives | |
165 | # Frees all IPs allocated to a NAS when an accounting OFF record arrives | |
154 | 166 | # |
155 | 167 | off_clear = "\ |
156 | 168 | UPDATE ${ippool_table} \ |
54 | 54 | # { "attribute" : "ClearText-Password", "value" : "pwd1", "op" : ":=" } |
55 | 55 | # { "attribute" : "Cache-TTL", "value" : 1000, "op" : ":=" } |
56 | 56 | # |
57 | authorize_check_query = "db.mobiles.aggregate([ \ | |
57 | authorize_check_query = "db.${authcheck_table}.aggregate([ \ | |
58 | 58 | { \ |
59 | 59 | '$match': { \ |
60 | 60 | 'calling_station_id': '%{Calling-Station-id}', \ |
0 | # -*- text -*- | |
1 | # | |
2 | # main/mssql/process-radacct.sql -- Schema extensions for processing radacct entries | |
3 | # | |
4 | # $Id$ | |
5 | ||
6 | -- --------------------------------- | |
7 | -- - Per-user data usage over time - | |
8 | -- --------------------------------- | |
9 | -- | |
10 | -- An extension to the standard schema to hold per-user data usage statistics | |
11 | -- for arbitrary periods. | |
12 | -- | |
13 | -- The data_usage_by_period table is populated by periodically calling the | |
14 | -- fr_new_data_usage_period stored procedure. | |
15 | -- | |
16 | -- This table can be queried in various ways to produce reports of aggregate | |
17 | -- data use over time. For example, if the fr_new_data_usage_period SP is | |
18 | -- invoked one per day just after midnight, to produce usage data with daily | |
19 | -- granularity, then a reasonably accurate monthly bandwidth summary for a | |
20 | -- given user could be obtained with: | |
21 | -- | |
22 | -- SELECT | |
23 | -- FORMAT(period_start, 'yyyy-MMMM') AS month, | |
24 | -- SUM(acctinputoctets)/1000/1000/1000 AS GB_in, | |
25 | -- SUM(acctoutputoctets)/1000/1000/1000 AS GB_out | |
26 | -- FROM | |
27 | -- data_usage_by_period | |
28 | -- WHERE | |
29 | -- username='bob' AND | |
30 | -- period_end <> 0 | |
31 | -- GROUP BY | |
32 | -- FORMAT(period_start, 'yyyy-MMMM'); | |
33 | -- | |
34 | -- +----------------+----------+-----------+ | |
35 | -- | month | GB_in | GB_out | | |
36 | -- +----------------+----------+-----------+ | |
37 | -- | 2019-July | 5.782279 | 50.545664 | | |
38 | -- | 2019-August | 4.230543 | 48.523096 | | |
39 | -- | 2019-September | 4.847360 | 48.631835 | | |
40 | -- | 2019-October | 6.456763 | 51.686231 | | |
41 | -- | 2019-November | 6.362537 | 52.385710 | | |
42 | -- | 2019-December | 4.301524 | 50.762240 | | |
43 | -- | 2020-January | 5.436280 | 49.067775 | | |
44 | -- +----------------+----------+-----------+ | |
45 | -- | |
46 | CREATE TABLE data_usage_by_period ( | |
47 | username VARCHAR(64) NOT NULL, | |
48 | period_start DATETIME NOT NULL, | |
49 | period_end DATETIME NOT NULL, | |
50 | acctinputoctets NUMERIC(19), | |
51 | acctoutputoctets NUMERIC(19), | |
52 | PRIMARY KEY (username, period_start) | |
53 | ); | |
54 | GO | |
55 | ||
56 | CREATE INDEX idx_data_usage_by_period_period_end ON data_usage_by_period(period_end); | |
57 | GO | |
58 | ||
59 | -- | |
60 | -- Stored procedure that when run with some arbitrary frequency, say | |
61 | -- once per day by cron, will process the recent radacct entries to extract | |
62 | -- time-windowed data containing acct{input,output}octets ("data usage") per | |
63 | -- username, per period. | |
64 | -- | |
65 | -- Each invocation will create new rows in the data_usage_by_period tables | |
66 | -- containing the data used by each user since the procedure was last invoked. | |
67 | -- The intervals do not need to be identical but care should be taken to | |
68 | -- ensure that the start/end of each period aligns well with any intended | |
69 | -- reporting intervals. | |
70 | -- | |
71 | -- It can be invoked by running: | |
72 | -- | |
73 | -- EXEC fr_new_data_usage_period; | |
74 | -- | |
75 | -- | |
76 | CREATE OR ALTER PROCEDURE fr_new_data_usage_period | |
77 | AS | |
78 | BEGIN | |
79 | ||
80 | DECLARE @v_start DATETIME; | |
81 | DECLARE @v_end DATETIME; | |
82 | ||
83 | SELECT @v_start = COALESCE(MAX(period_start), CAST('1970-01-01' AS DATETIME)) FROM data_usage_by_period; | |
84 | SELECT @v_end = CAST(CURRENT_TIMESTAMP AS DATETIME2(0)); | |
85 | ||
86 | BEGIN TRAN; | |
87 | ||
88 | -- | |
89 | -- Add the data usage for the sessions that were active in the current | |
90 | -- period to the table. Include all sessions that finished since the start | |
91 | -- of this period as well as those still ongoing. | |
92 | -- | |
93 | MERGE INTO data_usage_by_period d | |
94 | USING ( | |
95 | SELECT | |
96 | username, | |
97 | @v_start AS period_start, | |
98 | @v_end AS period_end, | |
99 | SUM(acctinputoctets) AS acctinputoctets, | |
100 | SUM(acctoutputoctets) AS acctoutputoctets | |
101 | FROM | |
102 | radacct | |
103 | WHERE | |
104 | acctstoptime > @v_start OR | |
105 | acctstoptime=0 | |
106 | GROUP BY | |
107 | username | |
108 | ) s | |
109 | ON ( d.username = s.username AND d.period_start = s.period_start ) | |
110 | WHEN MATCHED THEN | |
111 | UPDATE SET | |
112 | acctinputoctets = d.acctinputoctets + s.acctinputoctets, | |
113 | acctoutputoctets = d.acctoutputoctets + s.acctoutputoctets, | |
114 | period_end = @v_end | |
115 | WHEN NOT MATCHED THEN | |
116 | INSERT | |
117 | (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
118 | VALUES | |
119 | (s.username, s.period_start, s.period_end, s.acctinputoctets, s.acctoutputoctets); | |
120 | ||
121 | -- | |
122 | -- Create an open-ended "next period" for all ongoing sessions and carry a | |
123 | -- negative value of their data usage to avoid double-accounting when we | |
124 | -- process the next period. Their current data usage has already been | |
125 | -- allocated to the current and possibly previous periods. | |
126 | -- | |
127 | -- MSSQL doesn't allow a DATETIME to be NULL so we use "0" (1900-01-01) to | |
128 | -- indicate the open-ended interval. | |
129 | -- | |
130 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
131 | SELECT * | |
132 | FROM ( | |
133 | SELECT | |
134 | username, | |
135 | DATEADD(ss,1,@v_end) AS period_start, | |
136 | 0 AS period_end, | |
137 | 0 - SUM(acctinputoctets) AS acctinputoctets, | |
138 | 0 - SUM(acctoutputoctets) AS acctoutputoctets | |
139 | FROM | |
140 | radacct | |
141 | WHERE | |
142 | acctstoptime=0 | |
143 | GROUP BY | |
144 | username | |
145 | ) s; | |
146 | ||
147 | COMMIT; | |
148 | ||
149 | END | |
150 | GO |
24 | 24 | #sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-none}}" |
25 | 25 | # |
26 | 26 | sql_user_name = "%{User-Name}" |
27 | ||
28 | ####################################################################### | |
29 | # Query config: Event-Timestamp | |
30 | ####################################################################### | |
31 | # event_timestamp_epoch is the basis for the time inserted into | |
32 | # accounting records. Typically this will be the Event-Timestamp of the | |
33 | # accounting request, which is usually provided by a NAS. | |
34 | # | |
35 | # Uncomment the next line, if you want the timestamp to be based on the | |
36 | # request reception time recorded by this server, for example if you | |
37 | # distrust the provided Event-Timestamp. | |
38 | #event_timestamp_epoch = "%l" | |
39 | ||
40 | event_timestamp_epoch = "%{%{integer:Event-Timestamp}:-%l}" | |
41 | ||
42 | # event_timestamp is the SQL snippet for converting an epoch timestamp | |
43 | # to an SQL date. | |
44 | ||
45 | event_timestamp = "DATEADD(SS, ${event_timestamp_epoch}, '19700101')" | |
27 | 46 | |
28 | 47 | ####################################################################### |
29 | 48 | # Authorization Queries |
106 | 125 | query = "\ |
107 | 126 | UPDATE ${....acct_table1} \ |
108 | 127 | SET \ |
109 | AcctStopTime='%S', \ | |
110 | AcctSessionTime=unix_timestamp('%S') - \ | |
111 | unix_timestamp(AcctStartTime), \ | |
128 | AcctStopTime=${....event_timestamp}, \ | |
129 | AcctSessionTime=${....event_timestamp_epoch} - \ | |
130 | DATEDIFF(SS, '1970-01-01', AcctStartTime), \ | |
112 | 131 | AcctTerminateCause='%{%{Acct-Terminate-Cause}:-NAS-Reboot}', \ |
113 | 132 | AcctStopDelay = %{%{Acct-Delay-Time}:-0} \ |
114 | 133 | WHERE AcctStopTime = 0 \ |
115 | 134 | AND NASIPAddress = '%{NAS-IP-Address}' \ |
116 | AND AcctStartTime <= '%S'" | |
135 | AND AcctStartTime <= ${....event_timestamp}" | |
117 | 136 | } |
118 | 137 | |
119 | 138 | accounting-off { |
231 | 250 | '%{NAS-IP-Address}', \ |
232 | 251 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
233 | 252 | '%{NAS-Port-Type}', \ |
234 | '%S', \ | |
253 | ${....event_timestamp}, \ | |
235 | 254 | '0', \ |
236 | 255 | '%{Acct-Authentic}', \ |
237 | 256 | '%{Connect-Info}', \ |
285 | 304 | query = "\ |
286 | 305 | UPDATE ${....acct_table1} \ |
287 | 306 | SET \ |
288 | AcctStartTime = '%S', \ | |
307 | AcctStartTime = ${....event_timestamp}, \ | |
289 | 308 | AcctStartDelay = '%{%{Acct-Delay-Time}:-0}', \ |
290 | 309 | ConnectInfo_start = '%{Connect-Info}' \ |
291 | 310 | WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ |
390 | 409 | query = "\ |
391 | 410 | UPDATE ${....acct_table2} \ |
392 | 411 | SET \ |
393 | AcctStopTime = '%S', \ | |
412 | AcctStopTime = ${....event_timestamp}, \ | |
394 | 413 | AcctSessionTime = '%{Acct-Session-Time}', \ |
395 | 414 | AcctInputOctets = convert(bigint, '%{%{Acct-Input-Gigawords}:-0}' * POWER(2.0, 32)) | '%{%{Acct-Input-Octets}:-0}', \ |
396 | 415 | AcctOutputOctets = convert(bigint, '%{%{Acct-Output-Gigawords}:-0}' * POWER(2.0, 32)) | '%{%{Acct-Output-Octets}:-0}', \ |
436 | 455 | '%{NAS-IP-Address}', \ |
437 | 456 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
438 | 457 | '%{NAS-Port-Type}', \ |
439 | '%S', \ | |
458 | ${....event_timestamp}, \ | |
440 | 459 | '%{Acct-Session-Time}', \ |
441 | 460 | '%{Acct-Authentic}', \ |
442 | 461 | '', \ |
506 | 525 | # Write SQL queries to a logfile. This is potentially useful for bulk inserts |
507 | 526 | # when used with the rlm_sql_null driver. |
508 | 527 | # logfile = ${logdir}/post-auth.sql |
528 | ||
529 | query = "\ | |
530 | INSERT INTO ${..postauth_table} \ | |
531 | (userName, pass, reply, authdate) \ | |
532 | VALUES(\ | |
533 | '%{User-Name}', \ | |
534 | '%{%{User-Password}:-CHAP-PASSWORD}', \ | |
535 | '%{reply:Packet-Type}', \ | |
536 | '%S.%{expr:%M / 1000}')" | |
509 | 537 | } |
0 | /*************************************************************************** | |
1 | * $Id$ * | |
2 | * * | |
3 | * db_mssql.sql * | |
4 | * * | |
5 | * Database schema for MSSQL server * | |
6 | * * | |
7 | * To load: * | |
8 | * isql -S db_ip_addr -d db_name -U db_login -P db_passwd -i db_mssql.sql * | |
9 | * * | |
10 | * Based on: db_mysql.sql (Mike Machado <mike@innercite.com>) * | |
11 | * * | |
12 | * Dmitri Ageev <d_ageev@ortcc.ru> * | |
13 | ***************************************************************************/ | |
14 | ||
15 | /****** Object: Table [radacct] Script Date: 26.03.02 16:55:17 ******/ | |
0 | -- $Id$d$ | |
1 | -- | |
2 | -- schela.sql rlm_sql - FreeRADIUS SQL Module | |
3 | -- | |
4 | -- Database schema for MSSQL rlm_sql module | |
5 | -- | |
6 | -- To load: | |
7 | -- isql -S db_ip_addr -d db_name -U db_login -P db_passwd -i db_mssql.sql | |
8 | -- | |
9 | -- Based on: db_mysql.sql (Mike Machado <mike@innercite.com>) | |
10 | -- | |
11 | -- Dmitri Ageev <d_ageev@ortcc.ru> | |
12 | -- | |
13 | ||
14 | ||
15 | -- | |
16 | -- Table structure for table 'radacct' | |
17 | -- | |
18 | ||
16 | 19 | CREATE TABLE [radacct] ( |
17 | [RadAcctId] [numeric](21, 0) IDENTITY (1, 1) NOT NULL , | |
18 | [AcctSessionId] [varchar] (64) DEFAULT ('') FOR [AcctSessionId], | |
19 | [AcctUniqueId] [varchar] (32) DEFAULT ('') FOR [AcctUniqueId], | |
20 | [UserName] [varchar] (64) DEFAULT ('') FOR [UserName], | |
21 | [Realm] [varchar] (64) DEFAULT ('') FOR [Realm], | |
22 | [NASIPAddress] [varchar] (15) DEFAULT ('') FOR [NASIPAddress], | |
23 | [NASPortId] [varchar] (15) NULL , | |
24 | [NASPortType] [varchar] (32) NULL , | |
25 | [AcctStartTime] [datetime] NOT NULL , | |
26 | [AcctStopTime] [datetime] NOT NULL , | |
27 | [AcctSessionTime] [bigint] NULL , | |
28 | [AcctAuthentic] [varchar] (32) NULL , | |
29 | [ConnectInfo_start] [varchar] (32) DEFAULT (null) FOR [ConnectInfo_start], | |
30 | [ConnectInfo_stop] [varchar] (32) DEFAULT (null) FOR [ConnectInfo_stop], | |
31 | [AcctInputOctets] [bigint] NULL , | |
32 | [AcctOutputOctets] [bigint] NULL , | |
33 | [CalledStationId] [varchar] (30) DEFAULT ('') FOR [CalledStationId], | |
34 | [CallingStationId] [varchar] (30) DEFAULT ('') FOR [CallingStationId], | |
35 | [AcctTerminateCause] [varchar] (32) DEFAULT ('') FOR [AcctTerminateCause], | |
36 | [ServiceType] [varchar] (32) NULL , | |
37 | [FramedProtocol] [varchar] (32) NULL , | |
38 | [FramedIPAddress] [varchar] (15) DEFAULT ('') FOR [FramedIPAddress], | |
39 | [FramedIPv6Address] [varchar] (45) DEFAULT ('') FOR [FramedIPv6Address], | |
40 | [FramedIPv6Prefix] [varchar] (45) DEFAULT ('') FOR [FramedIPv6Prefix], | |
41 | [FramedInterfaceId] [varchar] (44) DEFAULT ('') FOR [FramedInterfaceId], | |
42 | [DelegatedIPv6Prefix] [varchar] (45) DEFAULT ('') FOR [DelegatedIPv6Prefix], | |
43 | [XAscendSessionSvrKey] [varchar] (10) DEFAULT (null) FOR [XAscendSessionSvrKey], | |
44 | [AcctStartDelay] [int] NULL , | |
20 | [RadAcctId] [numeric](21, 0) IDENTITY (1, 1) NOT NULL, | |
21 | [AcctSessionId] [varchar] (64) NOT NULL, | |
22 | [AcctUniqueId] [varchar] (32) NOT NULL, | |
23 | [UserName] [varchar] (64) NOT NULL, | |
24 | [GroupName] [varchar] (64) NOT NULL, | |
25 | [Realm] [varchar] (64) NOT NULL, | |
26 | [NASIPAddress] [varchar] (15) NOT NULL, | |
27 | [NASPortId] [varchar] (15) NULL, | |
28 | [NASPortType] [varchar] (32) NULL, | |
29 | [AcctStartTime] [datetime] NOT NULL, | |
30 | [AcctStopTime] [datetime] NOT NULL, | |
31 | [AcctSessionTime] [bigint] NULL, | |
32 | [AcctAuthentic] [varchar] (32) NULL, | |
33 | [ConnectInfo_start] [varchar] (32) NULL, | |
34 | [ConnectInfo_stop] [varchar] (32) NULL, | |
35 | [AcctInputOctets] [bigint] NULL, | |
36 | [AcctOutputOctets] [bigint] NULL, | |
37 | [CalledStationId] [varchar] (30) NOT NULL, | |
38 | [CallingStationId] [varchar] (30) NOT NULL, | |
39 | [AcctTerminateCause] [varchar] (32) NOT NULL, | |
40 | [ServiceType] [varchar] (32) NULL, | |
41 | [FramedProtocol] [varchar] (32) NULL, | |
42 | [FramedIPAddress] [varchar] (15) NOT NULL, | |
43 | [FramedIPv6Address] [varchar] (45) NOT NULL, | |
44 | [FramedIPv6Prefix] [varchar] (45) NOT NULL, | |
45 | [FramedInterfaceId] [varchar] (44) NOT NULL, | |
46 | [DelegatedIPv6Prefix] [varchar] (45) NOT NULL, | |
47 | [AcctStartDelay] [int] NULL, | |
45 | 48 | [AcctStopDelay] [int] NULL |
46 | 49 | ) ON [PRIMARY] |
47 | GO | |
48 | ||
49 | /****** Object: Table [radcheck] Script Date: 26.03.02 16:55:17 ******/ | |
50 | CREATE TABLE [radcheck] ( | |
51 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
52 | [UserName] [varchar] (64) NOT NULL , | |
53 | [Attribute] [varchar] (32) NOT NULL , | |
54 | [Value] [varchar] (253) NOT NULL , | |
55 | [op] [char] (2) NULL | |
56 | ) ON [PRIMARY] | |
57 | GO | |
58 | ||
59 | /****** Object: Table [radgroupcheck] Script Date: 26.03.02 16:55:17 ******/ | |
60 | CREATE TABLE [radgroupcheck] ( | |
61 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
62 | [GroupName] [varchar] (64) NOT NULL , | |
63 | [Attribute] [varchar] (32) NOT NULL , | |
64 | [Value] [varchar] (253) NOT NULL , | |
65 | [op] [char] (2) NULL | |
66 | ) ON [PRIMARY] | |
67 | GO | |
68 | ||
69 | /****** Object: Table [radgroupreply] Script Date: 26.03.02 16:55:17 ******/ | |
70 | CREATE TABLE [radgroupreply] ( | |
71 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
72 | [GroupName] [varchar] (64) NOT NULL , | |
73 | [Attribute] [varchar] (32) NOT NULL , | |
74 | [Value] [varchar] (253) NOT NULL , | |
75 | [op] [char] (2) NULL , | |
76 | [prio] [int] NOT NULL | |
77 | ) ON [PRIMARY] | |
78 | GO | |
79 | ||
80 | /****** Object: Table [radreply] Script Date: 26.03.02 16:55:18 ******/ | |
81 | CREATE TABLE [radreply] ( | |
82 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
83 | [UserName] [varchar] (64) NOT NULL , | |
84 | [Attribute] [varchar] (32) NOT NULL , | |
85 | [Value] [varchar] (253) NOT NULL , | |
86 | [op] [char] (2) NULL | |
87 | ) ON [PRIMARY] | |
88 | GO | |
89 | ||
90 | /****** Object: Table [radusergroup] Script Date: 26.03.02 16:55:18 ******/ | |
91 | CREATE TABLE [radusergroup] ( | |
92 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
93 | [UserName] [varchar] (64) NOT NULL , | |
94 | [GroupName] [varchar] (64) NULL , | |
95 | [Priority] [int] NULL | |
96 | ) ON [PRIMARY] | |
97 | GO | |
98 | ||
99 | /****** Object: Table [radusergroup] Script Date: 16.04.08 19:44:11 ******/ | |
100 | CREATE TABLE [radpostauth] ( | |
101 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
102 | [userName] [varchar] (64) NOT NULL , | |
103 | [pass] [varchar] (64) NOT NULL , | |
104 | [reply] [varchar] (32) NOT NULL , | |
105 | [authdate] [datetime] NOT NULL | |
106 | ) | |
107 | 50 | GO |
108 | 51 | |
109 | 52 | ALTER TABLE [radacct] WITH NOCHECK ADD |
135 | 78 | CONSTRAINT [DF_radacct_DelegatedIPv6Prefix] DEFAULT ('') FOR [DelegatedIPv6Prefix], |
136 | 79 | CONSTRAINT [DF_radacct_AcctStartDelay] DEFAULT (null) FOR [AcctStartDelay], |
137 | 80 | CONSTRAINT [DF_radacct_AcctStopDelay] DEFAULT (null) FOR [AcctStopDelay], |
138 | CONSTRAINT [PK_radacct] PRIMARY KEY NONCLUSTERED | |
81 | CONSTRAINT [PK_radacct] PRIMARY KEY NONCLUSTERED | |
139 | 82 | ( |
140 | 83 | [RadAcctId] |
141 | ) ON [PRIMARY] | |
84 | ) ON [PRIMARY] | |
85 | GO | |
86 | ||
87 | CREATE INDEX [UserName] ON [radacct]([UserName]) ON [PRIMARY] | |
88 | GO | |
89 | ||
90 | CREATE INDEX [FramedIPAddress] ON [radacct]([FramedIPAddress]) ON [PRIMARY] | |
91 | GO | |
92 | ||
93 | CREATE INDEX [FramedIPv6Address] ON [radacct]([FramedIPv6Address]) ON [PRIMARY] | |
94 | GO | |
95 | ||
96 | CREATE INDEX [FramedIPv6Prefix] ON [radacct]([FramedIPv6Prefix]) ON [PRIMARY] | |
97 | GO | |
98 | ||
99 | CREATE INDEX [FramedInterfaceId] ON [radacct]([FramedInterfaceId]) ON [PRIMARY] | |
100 | GO | |
101 | ||
102 | CREATE INDEX [DelegatedIPv6Prefix] ON [radacct]([DelegatedIPv6Prefix]) ON [PRIMARY] | |
103 | GO | |
104 | ||
105 | CREATE INDEX [AcctSessionId] ON [radacct]([AcctSessionId]) ON [PRIMARY] | |
106 | GO | |
107 | ||
108 | CREATE UNIQUE INDEX [AcctUniqueId] ON [radacct]([AcctUniqueId]) ON [PRIMARY] | |
109 | GO | |
110 | ||
111 | CREATE INDEX [AcctStartTime] ON [radacct]([AcctStartTime]) ON [PRIMARY] | |
112 | GO | |
113 | ||
114 | CREATE INDEX [AcctStopTime] ON [radacct]([AcctStopTime]) ON [PRIMARY] | |
115 | GO | |
116 | ||
117 | CREATE INDEX [NASIPAddress] ON [radacct]([NASIPAddress]) ON [PRIMARY] | |
118 | GO | |
119 | ||
120 | /* For use by onoff */ | |
121 | CREATE INDEX [RadacctBulkClose] ON [radacct]([NASIPAddress],[AcctStartTime]) WHERE [AcctStopTime] IS NULL ON [PRIMARY] | |
122 | GO | |
123 | ||
124 | ||
125 | -- | |
126 | -- Table structure for table 'radacct' | |
127 | -- | |
128 | ||
129 | CREATE TABLE [radcheck] ( | |
130 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
131 | [UserName] [varchar] (64) NOT NULL , | |
132 | [Attribute] [varchar] (32) NOT NULL , | |
133 | [Value] [varchar] (253) NOT NULL , | |
134 | [op] [char] (2) NULL | |
135 | ) ON [PRIMARY] | |
142 | 136 | GO |
143 | 137 | |
144 | 138 | ALTER TABLE [radcheck] WITH NOCHECK ADD |
146 | 140 | CONSTRAINT [DF_radcheck_Attribute] DEFAULT ('') FOR [Attribute], |
147 | 141 | CONSTRAINT [DF_radcheck_Value] DEFAULT ('') FOR [Value], |
148 | 142 | CONSTRAINT [DF_radcheck_op] DEFAULT (null) FOR [op], |
149 | CONSTRAINT [PK_radcheck] PRIMARY KEY NONCLUSTERED | |
150 | ( | |
151 | [id] | |
152 | ) ON [PRIMARY] | |
143 | CONSTRAINT [PK_radcheck] PRIMARY KEY NONCLUSTERED | |
144 | ( | |
145 | [id] | |
146 | ) ON [PRIMARY] | |
147 | GO | |
148 | ||
149 | CREATE INDEX [UserName] ON [radcheck]([UserName]) ON [PRIMARY] | |
150 | GO | |
151 | ||
152 | ||
153 | -- | |
154 | -- Table structure for table 'radacct' | |
155 | -- | |
156 | ||
157 | CREATE TABLE [radgroupcheck] ( | |
158 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
159 | [GroupName] [varchar] (64) NOT NULL , | |
160 | [Attribute] [varchar] (32) NOT NULL , | |
161 | [Value] [varchar] (253) NOT NULL , | |
162 | [op] [char] (2) NULL | |
163 | ) ON [PRIMARY] | |
153 | 164 | GO |
154 | 165 | |
155 | 166 | ALTER TABLE [radgroupcheck] WITH NOCHECK ADD |
157 | 168 | CONSTRAINT [DF_radgroupcheck_Attribute] DEFAULT ('') FOR [Attribute], |
158 | 169 | CONSTRAINT [DF_radgroupcheck_Value] DEFAULT ('') FOR [Value], |
159 | 170 | CONSTRAINT [DF_radgroupcheck_op] DEFAULT (null) FOR [op], |
160 | CONSTRAINT [PK_radgroupcheck] PRIMARY KEY NONCLUSTERED | |
161 | ( | |
162 | [id] | |
163 | ) ON [PRIMARY] | |
171 | CONSTRAINT [PK_radgroupcheck] PRIMARY KEY NONCLUSTERED | |
172 | ( | |
173 | [id] | |
174 | ) ON [PRIMARY] | |
175 | GO | |
176 | ||
177 | CREATE INDEX [GroupName] ON [radgroupcheck]([GroupName]) ON [PRIMARY] | |
178 | GO | |
179 | ||
180 | ||
181 | -- | |
182 | -- Table structure for table 'radacct' | |
183 | -- | |
184 | ||
185 | CREATE TABLE [radgroupreply] ( | |
186 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
187 | [GroupName] [varchar] (64) NOT NULL , | |
188 | [Attribute] [varchar] (32) NOT NULL , | |
189 | [Value] [varchar] (253) NOT NULL , | |
190 | [op] [char] (2) NULL , | |
191 | [prio] [int] NOT NULL | |
192 | ) ON [PRIMARY] | |
164 | 193 | GO |
165 | 194 | |
166 | 195 | ALTER TABLE [radgroupreply] WITH NOCHECK ADD |
169 | 198 | CONSTRAINT [DF_radgroupreply_Value] DEFAULT ('') FOR [Value], |
170 | 199 | CONSTRAINT [DF_radgroupreply_op] DEFAULT (null) FOR [op], |
171 | 200 | CONSTRAINT [DF_radgroupreply_prio] DEFAULT (0) FOR [prio], |
172 | CONSTRAINT [PK_radgroupreply] PRIMARY KEY NONCLUSTERED | |
173 | ( | |
174 | [id] | |
175 | ) ON [PRIMARY] | |
201 | CONSTRAINT [PK_radgroupreply] PRIMARY KEY NONCLUSTERED | |
202 | ( | |
203 | [id] | |
204 | ) ON [PRIMARY] | |
205 | GO | |
206 | ||
207 | CREATE INDEX [GroupName] ON [radgroupreply]([GroupName]) ON [PRIMARY] | |
208 | GO | |
209 | ||
210 | ||
211 | -- | |
212 | -- Table structure for table 'radacct' | |
213 | -- | |
214 | ||
215 | CREATE TABLE [radreply] ( | |
216 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
217 | [UserName] [varchar] (64) NOT NULL , | |
218 | [Attribute] [varchar] (32) NOT NULL , | |
219 | [Value] [varchar] (253) NOT NULL , | |
220 | [op] [char] (2) NULL | |
221 | ) ON [PRIMARY] | |
176 | 222 | GO |
177 | 223 | |
178 | 224 | ALTER TABLE [radreply] WITH NOCHECK ADD |
180 | 226 | CONSTRAINT [DF_radreply_Attribute] DEFAULT ('') FOR [Attribute], |
181 | 227 | CONSTRAINT [DF_radreply_Value] DEFAULT ('') FOR [Value], |
182 | 228 | CONSTRAINT [DF_radreply_op] DEFAULT (null) FOR [op], |
183 | CONSTRAINT [PK_radreply] PRIMARY KEY NONCLUSTERED | |
184 | ( | |
185 | [id] | |
186 | ) ON [PRIMARY] | |
229 | CONSTRAINT [PK_radreply] PRIMARY KEY NONCLUSTERED | |
230 | ( | |
231 | [id] | |
232 | ) ON [PRIMARY] | |
233 | GO | |
234 | ||
235 | CREATE INDEX [UserName] ON [radreply]([UserName]) ON [PRIMARY] | |
236 | GO | |
237 | ||
238 | ||
239 | -- | |
240 | -- Table structure for table 'radacct' | |
241 | -- | |
242 | ||
243 | CREATE TABLE [radusergroup] ( | |
244 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
245 | [UserName] [varchar] (64) NOT NULL , | |
246 | [GroupName] [varchar] (64) NULL , | |
247 | [Priority] [int] NULL | |
248 | ) ON [PRIMARY] | |
187 | 249 | GO |
188 | 250 | |
189 | 251 | ALTER TABLE [radusergroup] WITH NOCHECK ADD |
190 | 252 | CONSTRAINT [DF_radusergroup_UserName] DEFAULT ('') FOR [UserName], |
191 | 253 | CONSTRAINT [DF_radusergroup_GroupName] DEFAULT ('') FOR [GroupName], |
192 | CONSTRAINT [PK_radusergroup] PRIMARY KEY NONCLUSTERED | |
193 | ( | |
194 | [id] | |
195 | ) ON [PRIMARY] | |
254 | CONSTRAINT [PK_radusergroup] PRIMARY KEY NONCLUSTERED | |
255 | ( | |
256 | [id] | |
257 | ) ON [PRIMARY] | |
258 | GO | |
259 | ||
260 | CREATE INDEX [UserName] ON [radusergroup]([UserName]) ON [PRIMARY] | |
261 | GO | |
262 | ||
263 | ||
264 | -- | |
265 | -- Table structure for table 'radacct' | |
266 | -- | |
267 | ||
268 | CREATE TABLE [radpostauth] ( | |
269 | [id] [int] IDENTITY (1, 1) NOT NULL , | |
270 | [userName] [varchar] (64) NOT NULL , | |
271 | [pass] [varchar] (64) NOT NULL , | |
272 | [reply] [varchar] (32) NOT NULL , | |
273 | [authdate] [datetime] NOT NULL | |
274 | ) | |
196 | 275 | GO |
197 | 276 | |
198 | 277 | ALTER TABLE [radpostauth] WITH NOCHECK ADD |
205 | 284 | [id] |
206 | 285 | ) ON [PRIMARY] |
207 | 286 | GO |
208 | ||
209 | CREATE INDEX [UserName] ON [radacct]([UserName]) ON [PRIMARY] | |
210 | GO | |
211 | ||
212 | CREATE INDEX [FramedIPAddress] ON [radacct]([FramedIPAddress]) ON [PRIMARY] | |
213 | GO | |
214 | ||
215 | CREATE INDEX [FramedIPv6Address] ON [radacct]([FramedIPv6Address]) ON [PRIMARY] | |
216 | GO | |
217 | ||
218 | CREATE INDEX [FramedIPv6Prefix] ON [radacct]([FramedIPv6Prefix]) ON [PRIMARY] | |
219 | GO | |
220 | ||
221 | CREATE INDEX [FramedInterfaceId] ON [radacct]([FramedInterfaceId]) ON [PRIMARY] | |
222 | GO | |
223 | ||
224 | CREATE INDEX [DelegatedIPv6Prefix] ON [radacct]([DelegatedIPv6Prefix]) ON [PRIMARY] | |
225 | GO | |
226 | ||
227 | CREATE INDEX [AcctSessionId] ON [radacct]([AcctSessionId]) ON [PRIMARY] | |
228 | GO | |
229 | ||
230 | CREATE UNIQUE INDEX [AcctUniqueId] ON [radacct]([AcctUniqueId]) ON [PRIMARY] | |
231 | GO | |
232 | ||
233 | CREATE INDEX [AcctStartTime] ON [radacct]([AcctStartTime]) ON [PRIMARY] | |
234 | GO | |
235 | ||
236 | CREATE INDEX [AcctStopTime] ON [radacct]([AcctStopTime]) ON [PRIMARY] | |
237 | GO | |
238 | ||
239 | CREATE INDEX [NASIPAddress] ON [radacct]([NASIPAddress]) ON [PRIMARY] | |
240 | GO | |
241 | ||
242 | CREATE INDEX [UserName] ON [radcheck]([UserName]) ON [PRIMARY] | |
243 | GO | |
244 | ||
245 | CREATE INDEX [GroupName] ON [radgroupcheck]([GroupName]) ON [PRIMARY] | |
246 | GO | |
247 | ||
248 | CREATE INDEX [GroupName] ON [radgroupreply]([GroupName]) ON [PRIMARY] | |
249 | GO | |
250 | ||
251 | CREATE INDEX [UserName] ON [radreply]([UserName]) ON [PRIMARY] | |
252 | GO | |
253 | ||
254 | CREATE INDEX [UserName] ON [radusergroup]([UserName]) ON [PRIMARY] | |
255 | GO |
0 | # -*- text -*- | |
1 | # | |
2 | # main/mysql/process-radacct.sql -- Schema extensions for processing radacct entries | |
3 | # | |
4 | # $Id$ | |
5 | ||
6 | -- --------------------------------- | |
7 | -- - Per-user data usage over time - | |
8 | -- --------------------------------- | |
9 | -- | |
10 | -- An extension to the standard schema to hold per-user data usage statistics | |
11 | -- for arbitrary periods. | |
12 | -- | |
13 | -- The data_usage_by_period table is populated by periodically calling the | |
14 | -- fr_new_data_usage_period stored procedure. | |
15 | -- | |
16 | -- This table can be queried in various ways to produce reports of aggregate | |
17 | -- data use over time. For example, if the fr_new_data_usage_period SP is | |
18 | -- invoked one per day just after midnight, to produce usage data with daily | |
19 | -- granularity, then a reasonably accurate monthly bandwidth summary for a | |
20 | -- given user could be obtained with: | |
21 | -- | |
22 | -- SELECT | |
23 | -- DATE_FORMAT(period_start, '%Y-%M') AS month, | |
24 | -- SUM(acctinputoctets)/1000/1000/1000 AS GB_in, | |
25 | -- SUM(acctoutputoctets)/1000/1000/1000 AS GB_out | |
26 | -- FROM | |
27 | -- data_usage_by_period | |
28 | -- WHERE | |
29 | -- username='bob' AND | |
30 | -- period_end IS NOT NULL | |
31 | -- GROUP BY | |
32 | -- YEAR(period_start), MONTH(period_start); | |
33 | -- | |
34 | -- +----------------+----------------+-----------------+ | |
35 | -- | month | GB_in | GB_out | | |
36 | -- +----------------+----------------+-----------------+ | |
37 | -- | 2019-July | 5.782279230000 | 50.545664820000 | | |
38 | -- | 2019-August | 4.230543340000 | 48.523096420000 | | |
39 | -- | 2019-September | 4.847360590000 | 48.631835480000 | | |
40 | -- | 2019-October | 6.456763250000 | 51.686231930000 | | |
41 | -- | 2019-November | 6.362537730000 | 52.385710570000 | | |
42 | -- | 2019-December | 4.301524440000 | 50.762240270000 | | |
43 | -- | 2020-January | 5.436280540000 | 49.067775280000 | | |
44 | -- +----------------+----------------+-----------------+ | |
45 | -- 7 rows in set (0.000 sec) | |
46 | -- | |
47 | CREATE TABLE data_usage_by_period ( | |
48 | username VARCHAR(64), | |
49 | period_start DATETIME, | |
50 | period_end DATETIME, | |
51 | acctinputoctets BIGINT(20), | |
52 | acctoutputoctets BIGINT(20), | |
53 | PRIMARY KEY (username,period_start) | |
54 | ); | |
55 | CREATE INDEX idx_data_usage_by_period_period_start ON data_usage_by_period (period_start); | |
56 | ||
57 | ||
58 | -- | |
59 | -- Stored procedure that when run with some arbitrary frequency, say | |
60 | -- once per day by cron, will process the recent radacct entries to extract | |
61 | -- time-windowed data containing acct{input,output}octets ("data usage") per | |
62 | -- username, per period. | |
63 | -- | |
64 | -- Each invocation will create new rows in the data_usage_by_period tables | |
65 | -- containing the data used by each user since the procedure was last invoked. | |
66 | -- The intervals do not need to be identical but care should be taken to | |
67 | -- ensure that the start/end of each period aligns well with any intended | |
68 | -- reporting intervals. | |
69 | -- | |
70 | -- It can be invoked by running: | |
71 | -- | |
72 | -- CALL fr_new_data_usage_period(); | |
73 | -- | |
74 | -- | |
75 | DELIMITER $$ | |
76 | ||
77 | DROP PROCEDURE IF EXISTS fr_new_data_usage_period; | |
78 | CREATE PROCEDURE fr_new_data_usage_period () | |
79 | BEGIN | |
80 | ||
81 | DECLARE v_start DATETIME; | |
82 | DECLARE v_end DATETIME; | |
83 | ||
84 | SELECT IFNULL(MAX(period_start), FROM_UNIXTIME(0)) INTO v_start FROM data_usage_by_period; | |
85 | SELECT NOW() INTO v_end; | |
86 | ||
87 | START TRANSACTION; | |
88 | ||
89 | -- | |
90 | -- Add the data usage for the sessions that were active in the current | |
91 | -- period to the table. Include all sessions that finished since the start | |
92 | -- of this period as well as those still ongoing. | |
93 | -- | |
94 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
95 | SELECT * | |
96 | FROM ( | |
97 | SELECT | |
98 | username, | |
99 | v_start, | |
100 | v_end, | |
101 | SUM(acctinputoctets) AS acctinputoctets, | |
102 | SUM(acctoutputoctets) AS acctoutputoctets | |
103 | FROM | |
104 | radacct | |
105 | WHERE | |
106 | acctstoptime > v_start OR | |
107 | acctstoptime IS NULL | |
108 | GROUP BY | |
109 | username | |
110 | ) AS s | |
111 | ON DUPLICATE KEY UPDATE | |
112 | acctinputoctets = data_usage_by_period.acctinputoctets + s.acctinputoctets, | |
113 | acctoutputoctets = data_usage_by_period.acctoutputoctets + s.acctoutputoctets, | |
114 | period_end = v_end; | |
115 | ||
116 | -- | |
117 | -- Create an open-ended "next period" for all ongoing sessions and carry a | |
118 | -- negative value of their data usage to avoid double-accounting when we | |
119 | -- process the next period. Their current data usage has already been | |
120 | -- allocated to the current and possibly previous periods. | |
121 | -- | |
122 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
123 | SELECT * | |
124 | FROM ( | |
125 | SELECT | |
126 | username, | |
127 | DATE_ADD(v_end, INTERVAL 1 SECOND), | |
128 | NULL, | |
129 | 0 - SUM(acctinputoctets), | |
130 | 0 - SUM(acctoutputoctets) | |
131 | FROM | |
132 | radacct | |
133 | WHERE | |
134 | acctstoptime IS NULL | |
135 | GROUP BY | |
136 | username | |
137 | ) AS s; | |
138 | ||
139 | COMMIT; | |
140 | ||
141 | END$$ | |
142 | ||
143 | DELIMITER ; |
47 | 47 | #sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}" |
48 | 48 | # |
49 | 49 | sql_user_name = "%{User-Name}" |
50 | ||
51 | ####################################################################### | |
52 | # Query config: Event-Timestamp | |
53 | ####################################################################### | |
54 | # event_timestamp_epoch is the basis for the time inserted into | |
55 | # accounting records. Typically this will be the Event-Timestamp of the | |
56 | # accounting request, which is usually provided by a NAS. | |
57 | # | |
58 | # Uncomment the next line, if you want the timestamp to be based on the | |
59 | # request reception time recorded by this server, for example if you | |
60 | # distrust the provided Event-Timestamp. | |
61 | #event_timestamp_epoch = "%l" | |
62 | ||
63 | event_timestamp_epoch = "%{%{integer:Event-Timestamp}:-%l}" | |
64 | ||
65 | # event_timestamp is the SQL snippet for converting an epoch timestamp | |
66 | # to an SQL date. | |
67 | ||
68 | event_timestamp = "FROM_UNIXTIME(${event_timestamp_epoch})" | |
50 | 69 | |
51 | 70 | ####################################################################### |
52 | 71 | # Default profile |
227 | 246 | query = "\ |
228 | 247 | UPDATE ${....acct_table1} \ |
229 | 248 | SET \ |
230 | acctstoptime = FROM_UNIXTIME(\ | |
231 | %{integer:Event-Timestamp}), \ | |
232 | acctsessiontime = '%{integer:Event-Timestamp}' \ | |
249 | acctstoptime = ${....event_timestamp}, \ | |
250 | acctsessiontime = '${....event_timestamp_epoch}' \ | |
233 | 251 | - UNIX_TIMESTAMP(acctstarttime), \ |
234 | 252 | acctterminatecause = '%{%{Acct-Terminate-Cause}:-NAS-Reboot}' \ |
235 | 253 | WHERE acctstoptime IS NULL \ |
236 | 254 | AND nasipaddress = '%{NAS-IP-Address}' \ |
237 | AND acctstarttime <= FROM_UNIXTIME(\ | |
238 | %{integer:Event-Timestamp})" | |
255 | AND acctstarttime <= ${....event_timestamp}" | |
239 | 256 | } |
240 | 257 | |
241 | 258 | accounting-off { |
261 | 278 | '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \ |
262 | 279 | NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \ |
263 | 280 | '%{NAS-Port-Type}', \ |
264 | FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
281 | ${....event_timestamp}, \ | |
265 | 282 | NULL, \ |
266 | 283 | NULL, \ |
267 | 284 | 0, \ |
272 | 289 | 0, \ |
273 | 290 | '%{Called-Station-Id}', \ |
274 | 291 | '%{Calling-Station-Id}', \ |
275 | NULL, \ | |
292 | '', \ | |
276 | 293 | '%{Service-Type}', \ |
277 | 294 | NULL, \ |
278 | 295 | '', \ |
283 | 300 | |
284 | 301 | query = "\ |
285 | 302 | UPDATE ${....acct_table1} SET \ |
286 | AcctStartTime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
287 | AcctUpdateTime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
303 | AcctStartTime = ${....event_timestamp}, \ | |
304 | AcctUpdateTime = ${....event_timestamp}, \ | |
288 | 305 | ConnectInfo_start = '%{Connect-Info}', \ |
289 | 306 | AcctSessionId = '%{Acct-Session-Id}' \ |
290 | 307 | WHERE UserName = '%{SQL-User-Name}' \ |
309 | 326 | '%{NAS-IP-Address}', \ |
310 | 327 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
311 | 328 | '%{NAS-Port-Type}', \ |
312 | FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
313 | FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
329 | ${....event_timestamp}, \ | |
330 | ${....event_timestamp}, \ | |
314 | 331 | NULL, \ |
315 | 332 | '0', \ |
316 | 333 | '%{Acct-Authentic}', \ |
352 | 369 | framedipv6prefix = '%{Framed-IPv6-Prefix}', \ |
353 | 370 | framedinterfaceid = '%{Framed-Interface-Id}', \ |
354 | 371 | delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ |
355 | AcctStartTime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
356 | AcctUpdateTime = FROM_UNIXTIME(%{integer:Event-Timestamp}) \ | |
372 | AcctStartTime = ${....event_timestamp}, \ | |
373 | AcctUpdateTime = ${....event_timestamp} \ | |
357 | 374 | WHERE UserName = '%{SQL-User-Name}' \ |
358 | 375 | AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \ |
359 | 376 | AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \ |
366 | 383 | # |
367 | 384 | query = "\ |
368 | 385 | UPDATE ${....acct_table1} SET \ |
369 | acctstarttime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
370 | acctupdatetime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
386 | acctstarttime = ${....event_timestamp}, \ | |
387 | acctupdatetime = ${....event_timestamp}, \ | |
371 | 388 | connectinfo_start = '%{Connect-Info}' \ |
372 | 389 | WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" |
373 | 390 | |
383 | 400 | UPDATE ${....acct_table1} \ |
384 | 401 | SET \ |
385 | 402 | acctupdatetime = (@acctupdatetime_old:=acctupdatetime), \ |
386 | acctupdatetime = FROM_UNIXTIME(\ | |
387 | %{integer:Event-Timestamp}), \ | |
388 | acctinterval = %{integer:Event-Timestamp} - \ | |
403 | acctupdatetime = ${....event_timestamp}, \ | |
404 | acctinterval = ${....event_timestamp_epoch} - \ | |
389 | 405 | UNIX_TIMESTAMP(@acctupdatetime_old), \ |
390 | 406 | framedipaddress = '%{Framed-IP-Address}', \ |
391 | 407 | framedipv6address = '%{Framed-IPv6-Address}', \ |
414 | 430 | '%{NAS-IP-Address}', \ |
415 | 431 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
416 | 432 | '%{NAS-Port-Type}', \ |
417 | FROM_UNIXTIME(%{integer:Event-Timestamp} - %{%{Acct-Session-Time}:-0}), \ | |
418 | FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
433 | FROM_UNIXTIME(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \ | |
434 | ${....event_timestamp}, \ | |
419 | 435 | NULL, \ |
420 | 436 | %{%{Acct-Session-Time}:-NULL}, \ |
421 | 437 | '%{Acct-Authentic}', \ |
457 | 473 | framedipv6prefix = '%{Framed-IPv6-Prefix}', \ |
458 | 474 | framedinterfaceid = '%{Framed-Interface-Id}', \ |
459 | 475 | delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ |
460 | AcctUpdateTime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
476 | AcctUpdateTime = ${....event_timestamp}, \ | |
461 | 477 | AcctSessionTime = %{%{Acct-Session-Time}:-NULL}, \ |
462 | 478 | AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \ |
463 | 479 | << 32 | '%{%{Acct-Input-Octets}:-0}', \ |
477 | 493 | # |
478 | 494 | query = "\ |
479 | 495 | UPDATE ${....acct_table2} SET \ |
480 | acctstoptime = FROM_UNIXTIME(\ | |
481 | %{integer:Event-Timestamp}), \ | |
496 | acctstoptime = ${....event_timestamp}, \ | |
482 | 497 | acctsessiontime = %{%{Acct-Session-Time}:-NULL}, \ |
483 | 498 | acctinputoctets = '%{%{Acct-Input-Gigawords}:-0}' \ |
484 | 499 | << 32 | '%{%{Acct-Input-Octets}:-0}', \ |
503 | 518 | '%{NAS-IP-Address}', \ |
504 | 519 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
505 | 520 | '%{NAS-Port-Type}', \ |
506 | FROM_UNIXTIME(%{integer:Event-Timestamp} - %{%{Acct-Session-Time}:-0}), \ | |
507 | FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
508 | FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
521 | FROM_UNIXTIME(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \ | |
522 | ${....event_timestamp}, \ | |
523 | ${....event_timestamp}, \ | |
509 | 524 | %{%{Acct-Session-Time}:-NULL}, \ |
510 | 525 | '%{Acct-Authentic}', \ |
511 | 526 | '', \ |
546 | 561 | framedipv6prefix = '%{Framed-IPv6-Prefix}', \ |
547 | 562 | framedinterfaceid = '%{Framed-Interface-Id}', \ |
548 | 563 | delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ |
549 | AcctStopTime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
550 | AcctUpdateTime = FROM_UNIXTIME(%{integer:Event-Timestamp}), \ | |
564 | AcctStopTime = ${....event_timestamp}, \ | |
565 | AcctUpdateTime = ${....event_timestamp}, \ | |
551 | 566 | AcctSessionTime = %{Acct-Session-Time}, \ |
552 | 567 | AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \ |
553 | 568 | << 32 | '%{%{Acct-Input-Octets}:-0}', \ |
591 | 606 | '%{SQL-User-Name}', \ |
592 | 607 | '%{%{User-Password}:-%{Chap-Password}}', \ |
593 | 608 | '%{reply:Packet-Type}', \ |
594 | '%S')" | |
609 | '%S.%M')" | |
595 | 610 | } |
20 | 20 | username varchar(64) NOT NULL default '', |
21 | 21 | realm varchar(64) default '', |
22 | 22 | nasipaddress varchar(15) NOT NULL default '', |
23 | nasportid varchar(15) default NULL, | |
23 | nasportid varchar(32) default NULL, | |
24 | 24 | nasporttype varchar(32) default NULL, |
25 | 25 | acctstarttime datetime NULL default NULL, |
26 | 26 | acctupdatetime datetime NULL default NULL, |
131 | 131 | # |
132 | 132 | # Table structure for table 'radpostauth' |
133 | 133 | # |
134 | # Note: MySQL versions since 5.6.4 support fractional precision timestamps | |
135 | # which we use here. Replace the authdate definition with the following | |
136 | # if your software is too old: | |
137 | # | |
138 | # authdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | |
139 | # | |
134 | 140 | CREATE TABLE IF NOT EXISTS radpostauth ( |
135 | 141 | id int(11) NOT NULL auto_increment, |
136 | 142 | username varchar(64) NOT NULL default '', |
137 | 143 | pass varchar(64) NOT NULL default '', |
138 | 144 | reply varchar(32) NOT NULL default '', |
139 | authdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
145 | authdate timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), | |
140 | 146 | PRIMARY KEY (id), |
141 | 147 | KEY username (username(32)) |
142 | 148 | ) ENGINE = INNODB; |
22 | 22 | username varchar(64) NOT NULL default '', |
23 | 23 | realm varchar(64) default '', |
24 | 24 | nasipaddress varchar(15) NOT NULL default '', |
25 | nasportid varchar(15) default NULL, | |
25 | nasportid varchar(32) default NULL, | |
26 | 26 | nasporttype varchar(32) default NULL, |
27 | 27 | acctstarttime datetime NULL default NULL, |
28 | 28 | acctupdatetime datetime NULL default NULL, |
137 | 137 | username varchar(64) NOT NULL default '', |
138 | 138 | pass varchar(64) NOT NULL default '', |
139 | 139 | reply varchar(32) NOT NULL default '', |
140 | authdate timestamp NOT NULL, | |
140 | authdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), | |
141 | 141 | PRIMARY KEY (id) |
142 | 142 | ) ENGINE=ndbcluster; |
0 | # -*- text -*- | |
1 | # | |
2 | # main/oracle/process-radacct.sql -- Schema extensions for processing radacct entries | |
3 | # | |
4 | # $Id$ | |
5 | ||
6 | -- --------------------------------- | |
7 | -- - Per-user data usage over time - | |
8 | -- --------------------------------- | |
9 | -- | |
10 | -- An extension to the standard schema to hold per-user data usage statistics | |
11 | -- for arbitrary periods. | |
12 | -- | |
13 | -- The data_usage_by_period table is populated by periodically calling the | |
14 | -- fr_new_data_usage_period stored procedure. | |
15 | -- | |
16 | -- This table can be queried in various ways to produce reports of aggregate | |
17 | -- data use over time. For example, if the fr_new_data_usage_period SP is | |
18 | -- invoked one per day just after midnight, to produce usage data with daily | |
19 | -- granularity, then a reasonably accurate monthly bandwidth summary for a | |
20 | -- given user could be obtained with: | |
21 | -- | |
22 | -- SELECT | |
23 | -- MIN(TO_CHAR(period_start, 'YYYY-Month')) AS month, | |
24 | -- SUM(acctinputoctets)/1000/1000/1000 AS GB_in, | |
25 | -- SUM(acctoutputoctets)/1000/1000/1000 AS GB_out | |
26 | -- FROM | |
27 | -- data_usage_by_period | |
28 | -- WHERE | |
29 | -- username='bob' AND | |
30 | -- period_end IS NOT NULL | |
31 | -- GROUP BY | |
32 | -- TRUNC(period_start,'month'); | |
33 | -- | |
34 | -- +----------------+----------------+-----------------+ | |
35 | -- | MONTH | GB_IN | GB_OUT | | |
36 | -- +----------------+----------------+-----------------+ | |
37 | -- | 2019-July | 5.782279230000 | 50.545664820000 | | |
38 | -- | 2019-August | 4.230543340000 | 48.523096420000 | | |
39 | -- | 2019-September | 4.847360590000 | 48.631835480000 | | |
40 | -- | 2019-October | 6.456763250000 | 51.686231930000 | | |
41 | -- | 2019-November | 6.362537730000 | 52.385710570000 | | |
42 | -- | 2019-December | 4.301524440000 | 50.762240270000 | | |
43 | -- | 2020-January | 5.436280540000 | 49.067775280000 | | |
44 | -- +----------------+----------------+-----------------+ | |
45 | -- | |
46 | CREATE TABLE data_usage_by_period ( | |
47 | id NUMBER GENERATED BY DEFAULT AS IDENTITY, | |
48 | username VARCHAR(64) NOT NULL, | |
49 | period_start TIMESTAMP WITH TIME ZONE NOT NULL, | |
50 | period_end TIMESTAMP WITH TIME ZONE, | |
51 | acctinputoctets NUMERIC(19), | |
52 | acctoutputoctets NUMERIC(19), | |
53 | PRIMARY KEY (id) | |
54 | ); | |
55 | CREATE UNIQUE INDEX idx_data_usage_by_period_username_period_start ON data_usage_by_period (username,period_start); | |
56 | CREATE INDEX idx_data_usage_by_period_period_start ON data_usage_by_period (period_start); | |
57 | ||
58 | -- | |
59 | -- Stored procedure that when run with some arbitrary frequency, say | |
60 | -- once per day by cron, will process the recent radacct entries to extract | |
61 | -- time-windowed data containing acct{input,output}octets ("data usage") per | |
62 | -- username, per period. | |
63 | -- | |
64 | -- Each invocation will create new rows in the data_usage_by_period tables | |
65 | -- containing the data used by each user since the procedure was last invoked. | |
66 | -- The intervals do not need to be identical but care should be taken to | |
67 | -- ensure that the start/end of each period aligns well with any intended | |
68 | -- reporting intervals. | |
69 | -- | |
70 | -- It can be invoked by running: | |
71 | -- | |
72 | -- CALL fr_new_data_usage_period(); | |
73 | -- | |
74 | -- | |
75 | CREATE OR REPLACE PROCEDURE fr_new_data_usage_period | |
76 | AS | |
77 | v_start TIMESTAMP WITH TIME ZONE; | |
78 | v_end TIMESTAMP WITH TIME ZONE; | |
79 | BEGIN | |
80 | ||
81 | SELECT COALESCE(MAX(period_start), TO_DATE('1970-01-01','YYYY-MM-DD')) INTO v_start FROM data_usage_by_period; | |
82 | SELECT CAST(CURRENT_TIMESTAMP AS DATE) INTO v_end FROM dual; | |
83 | ||
84 | BEGIN | |
85 | ||
86 | -- | |
87 | -- Add the data usage for the sessions that were active in the current | |
88 | -- period to the table. Include all sessions that finished since the start | |
89 | -- of this period as well as those still ongoing. | |
90 | -- | |
91 | MERGE INTO data_usage_by_period d | |
92 | USING ( | |
93 | SELECT | |
94 | username, | |
95 | MIN(v_start) period_start, | |
96 | MIN(v_end) period_end, | |
97 | SUM(acctinputoctets) AS acctinputoctets, | |
98 | SUM(acctoutputoctets) AS acctoutputoctets | |
99 | FROM | |
100 | radacct | |
101 | WHERE | |
102 | acctstoptime > v_start OR | |
103 | acctstoptime IS NULL | |
104 | GROUP BY | |
105 | username | |
106 | ) s | |
107 | ON ( d.username = s.username AND d.period_start = s.period_start ) | |
108 | WHEN MATCHED THEN | |
109 | UPDATE SET | |
110 | acctinputoctets = d.acctinputoctets + s.acctinputoctets, | |
111 | acctoutputoctets = d.acctoutputoctets + s.acctoutputoctets, | |
112 | period_end = v_end | |
113 | WHEN NOT MATCHED THEN | |
114 | INSERT | |
115 | (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
116 | VALUES | |
117 | (s.username, s.period_start, s.period_end, s.acctinputoctets, s.acctoutputoctets); | |
118 | ||
119 | -- | |
120 | -- Create an open-ended "next period" for all ongoing sessions and carry a | |
121 | -- negative value of their data usage to avoid double-accounting when we | |
122 | -- process the next period. Their current data usage has already been | |
123 | -- allocated to the current and possibly previous periods. | |
124 | -- | |
125 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
126 | SELECT * | |
127 | FROM ( | |
128 | SELECT | |
129 | username, | |
130 | v_end + NUMTODSINTERVAL(1,'SECOND'), | |
131 | NULL, | |
132 | 0 - SUM(acctinputoctets), | |
133 | 0 - SUM(acctoutputoctets) | |
134 | FROM | |
135 | radacct | |
136 | WHERE | |
137 | acctstoptime IS NULL | |
138 | GROUP BY | |
139 | username | |
140 | ) s; | |
141 | ||
142 | END; | |
143 | ||
144 | END; | |
145 | / |
19 | 19 | #sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}" |
20 | 20 | # |
21 | 21 | sql_user_name = "%{User-Name}" |
22 | ||
23 | ####################################################################### | |
24 | # Query config: Event-Timestamp | |
25 | ####################################################################### | |
26 | # event_timestamp_epoch is the basis for the time inserted into | |
27 | # accounting records. Typically this will be the Event-Timestamp of the | |
28 | # accounting request, which is provided by a NAS. | |
29 | # | |
30 | # Uncomment the next line, if you want the timestamp to be based on the | |
31 | # request reception time recorded by this server, for example if you | |
32 | # distrust the provided Event-Timestamp. | |
33 | #event_timestamp_epoch = "%l" | |
34 | ||
35 | event_timestamp_epoch = "%{%{integer:Event-Timestamp}:-%l}" | |
36 | ||
37 | # event_timestamp is the SQL snippet for converting an epoch timestamp | |
38 | # to an SQL date. | |
39 | ||
40 | event_timestamp = "TO_DATE('1970-01-01','YYYY-MM-DD') + NUMTODSINTERVAL(${event_timestamp_epoch},'SECOND')" | |
22 | 41 | |
23 | 42 | ####################################################################### |
24 | 43 | # Default profile |
182 | 201 | query = "\ |
183 | 202 | UPDATE ${....acct_table1} \ |
184 | 203 | SET \ |
185 | AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \ | |
186 | AcctSessionTime = round((TO_DATE('%S','yyyy-mm-dd hh24:mi:ss') - \ | |
204 | AcctStopTime = ${....event_timestamp}, \ | |
205 | AcctSessionTime = ROUND((${....event_timestamp} - \ | |
187 | 206 | TO_DATE(TO_CHAR(acctstarttime, 'yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss'))*86400), \ |
188 | 207 | AcctTerminateCause='%{%{Acct-Terminate-Cause}:-NAS-Reboot}', \ |
189 | 208 | AcctStopDelay = %{%{Acct-Delay-Time}:-0} \ |
190 | 209 | WHERE AcctStopTime IS NULL \ |
191 | 210 | AND NASIPAddress = '%{NAS-IP-Address}' \ |
192 | AND AcctStartTime <= TO_DATE('%S','yyyy-mm-dd hh24:mi:ss')" | |
211 | AND AcctStartTime <= ${....event_timestamp}" | |
193 | 212 | } |
194 | 213 | |
195 | 214 | accounting-off { |
311 | 330 | '%{NAS-IP-Address}', \ |
312 | 331 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
313 | 332 | '%{NAS-Port-Type}', \ |
314 | TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \ | |
333 | ${....event_timestamp}, \ | |
315 | 334 | NULL, \ |
316 | 335 | '0', \ |
317 | 336 | '%{Acct-Authentic}', \ |
367 | 386 | query = "\ |
368 | 387 | UPDATE ${....acct_table1} \ |
369 | 388 | SET \ |
370 | AcctStartTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \ | |
389 | AcctStartTime = ${....event_timestamp}, \ | |
371 | 390 | AcctStartDelay = '%{%{Acct-Delay-Time}:-0}', \ |
372 | 391 | ConnectInfo_start = '%{Connect-Info}' \ |
373 | 392 | WHERE AcctUniqueId = '%{Acct-Unique-Session-ID}' \ |
487 | 506 | query = "\ |
488 | 507 | UPDATE ${....acct_table2} \ |
489 | 508 | SET \ |
490 | AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \ | |
509 | AcctStopTime = ${....event_timestamp}, \ | |
491 | 510 | AcctSessionTime = '%{Acct-Session-Time}', \ |
492 | 511 | AcctInputOctets = '%{Acct-Input-Octets}' + \ |
493 | 512 | ('%{%{Acct-Input-Gigawords}:-0}' * 4294967296), \ |
539 | 558 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
540 | 559 | '%{NAS-Port-Type}', \ |
541 | 560 | NULL, \ |
542 | TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), \ | |
561 | ${....event_timestamp}, \ | |
543 | 562 | '%{Acct-Session-Time}', \ |
544 | 563 | '%{Acct-Authentic}', \ |
545 | 564 | '', \ |
620 | 639 | '%{User-Name}', \ |
621 | 640 | '%{%{User-Password}:-%{Chap-Password}}', \ |
622 | 641 | '%{reply:Packet-Type}', \ |
623 | TO_TIMESTAMP('%S','YYYY-MM-DDHH24:MI:SS'))" | |
642 | TO_TIMESTAMP('%S.%M','YYYY-MM-DDHH24:MI:SS.FF'))" | |
624 | 643 | } |
158 | 158 | UserName VARCHAR(64) NOT NULL, |
159 | 159 | Pass VARCHAR(64), |
160 | 160 | Reply VARCHAR(64), |
161 | AuthDate DATE | |
161 | AuthDate TIMESTAMP(6) WITH TIME ZONE | |
162 | 162 | ); |
163 | 163 | |
164 | 164 | CREATE SEQUENCE radpostauth_seq START WITH 1 INCREMENT BY 1; |
171 | 171 | SELECT radpostauth_seq.nextval into :new.id from dual; |
172 | 172 | end if; |
173 | 173 | if (:new.AuthDate is null) then |
174 | select sysdate into :new.AuthDate from dual; | |
174 | select systimestamp into :new.AuthDate from dual; | |
175 | 175 | end if; |
176 | 176 | END; |
177 | 177 |
0 | # -*- text -*- | |
1 | # | |
2 | # main/postgresql/process-radacct.sql -- Schema extensions for processing radacct entries | |
3 | # | |
4 | # $Id$ | |
5 | ||
6 | -- --------------------------------- | |
7 | -- - Per-user data usage over time - | |
8 | -- --------------------------------- | |
9 | -- | |
10 | -- An extension to the standard schema to hold per-user data usage statistics | |
11 | -- for arbitrary periods. | |
12 | -- | |
13 | -- The data_usage_by_period table is populated by periodically calling the | |
14 | -- fr_new_data_usage_period stored procedure. | |
15 | -- | |
16 | -- This table can be queried in various ways to produce reports of aggregate | |
17 | -- data use over time. For example, if the fr_new_data_usage_period SP is | |
18 | -- invoked one per day just after midnight, to produce usage data with daily | |
19 | -- granularity, then a reasonably accurate monthly bandwidth summary for a | |
20 | -- given user could be obtained by queriing this table with: | |
21 | -- | |
22 | -- SELECT | |
23 | -- TO_CHAR(CURRENT_TIMESTAMP, 'YYYY-Month') AS month, | |
24 | -- TRUNC(SUM(acctinputoctets)/1000/1000/1000,9) AS gb_in, | |
25 | -- TRUNC(SUM(acctoutputoctets)/1000/1000/1000,9) AS gb_out | |
26 | -- FROM | |
27 | -- data_usage_by_period | |
28 | -- WHERE | |
29 | -- username='bob' AND | |
30 | -- period_end IS NOT NULL | |
31 | -- GROUP BY | |
32 | -- month; | |
33 | -- | |
34 | -- month | gb_in | gb_out | |
35 | -- ----------------+-------------+-------------- | |
36 | -- 2019-July | 5.782279231 | 50.545664824 | |
37 | -- 2019-August | 4.230543344 | 48.523096424 | |
38 | -- 2019-September | 4.847360599 | 48.631835488 | |
39 | -- 2019-October | 6.456763254 | 51.686231937 | |
40 | -- 2019-November | 6.362537735 | 52.385710572 | |
41 | -- 2019-December | 4.301524442 | 50.762240277 | |
42 | -- 2020-January | 5.436280545 | 49.067775286 | |
43 | -- (7 rows) | |
44 | -- | |
45 | CREATE TABLE data_usage_by_period ( | |
46 | username text, | |
47 | period_start timestamp with time zone, | |
48 | period_end timestamp with time zone, | |
49 | acctinputoctets bigint, | |
50 | acctoutputoctets bigint | |
51 | ); | |
52 | ALTER TABLE data_usage_by_period ADD CONSTRAINT data_usage_by_period_pkey PRIMARY KEY (username, period_start); | |
53 | ||
54 | ||
55 | -- | |
56 | -- Stored procedure that when run with some arbitrary frequency, say | |
57 | -- once per day by cron, will process the recent radacct entries to extract | |
58 | -- time-windowed data containing acct{input,output}octets ("data usage") per | |
59 | -- username, per period. | |
60 | -- | |
61 | -- Each invocation will create new rows in the data_usage_by_period tables | |
62 | -- containing the data used by each user since the procedure was last invoked. | |
63 | -- The intervals do not need to be identical but care should be taken to | |
64 | -- ensure that the start/end of each period aligns well with any intended | |
65 | -- reporting intervals. | |
66 | -- | |
67 | -- It can be invoked by running: | |
68 | -- | |
69 | -- SELECT fr_new_data_usage_period(); | |
70 | -- | |
71 | -- | |
72 | CREATE OR REPLACE FUNCTION fr_new_data_usage_period () | |
73 | RETURNS void | |
74 | LANGUAGE plpgsql | |
75 | AS $$ | |
76 | DECLARE v_start timestamp; | |
77 | DECLARE v_end timestamp; | |
78 | BEGIN | |
79 | ||
80 | SELECT COALESCE(MAX(period_start), TO_TIMESTAMP(0)) INTO v_start FROM data_usage_by_period; | |
81 | SELECT DATE_TRUNC('second',CURRENT_TIMESTAMP) INTO v_end; | |
82 | ||
83 | -- | |
84 | -- Add the data usage for the sessions that were active in the current | |
85 | -- period to the table. Include all sessions that finished since the start | |
86 | -- of this period as well as those still ongoing. | |
87 | -- | |
88 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
89 | SELECT * | |
90 | FROM ( | |
91 | SELECT | |
92 | username, | |
93 | v_start, | |
94 | v_end, | |
95 | SUM(acctinputoctets) AS acctinputoctets, | |
96 | SUM(acctoutputoctets) AS acctoutputoctets | |
97 | FROM | |
98 | radacct | |
99 | WHERE | |
100 | acctstoptime > v_start OR | |
101 | acctstoptime IS NULL | |
102 | GROUP BY | |
103 | username | |
104 | ) AS s | |
105 | ON CONFLICT ON CONSTRAINT data_usage_by_period_pkey | |
106 | DO UPDATE | |
107 | SET | |
108 | acctinputoctets = data_usage_by_period.acctinputoctets + EXCLUDED.acctinputoctets, | |
109 | acctoutputoctets = data_usage_by_period.acctoutputoctets + EXCLUDED.acctoutputoctets, | |
110 | period_end = v_end; | |
111 | ||
112 | -- | |
113 | -- Create an open-ended "next period" for all ongoing sessions and carry a | |
114 | -- negative value of their data usage to avoid double-accounting when we | |
115 | -- process the next period. Their current data usage has already been | |
116 | -- allocated to the current and possibly previous periods. | |
117 | -- | |
118 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
119 | SELECT * | |
120 | FROM ( | |
121 | SELECT | |
122 | username, | |
123 | v_end + INTERVAL '1 SECOND', | |
124 | NULL::timestamp, | |
125 | 0 - SUM(acctinputoctets), | |
126 | 0 - SUM(acctoutputoctets) | |
127 | FROM | |
128 | radacct | |
129 | WHERE | |
130 | acctstoptime IS NULL | |
131 | GROUP BY | |
132 | username | |
133 | ) AS s; | |
134 | ||
135 | END | |
136 | $$; |
37 | 37 | #sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-none}}" |
38 | 38 | |
39 | 39 | sql_user_name = "%{User-Name}" |
40 | ||
41 | ####################################################################### | |
42 | # Query config: Event-Timestamp | |
43 | ####################################################################### | |
44 | # event_timestamp_epoch is the basis for the time inserted into | |
45 | # accounting records. Typically this will be the Event-Timestamp of the | |
46 | # accounting request, which is usually provided by a NAS. | |
47 | # | |
48 | # Uncomment the next line, if you want the timestamp to be based on the | |
49 | # request reception time recorded by this server, for example if you | |
50 | # distrust the provided Event-Timestamp. | |
51 | #event_timestamp_epoch = "%l" | |
52 | ||
53 | event_timestamp_epoch = "%{%{integer:Event-Timestamp}:-%l}" | |
54 | ||
55 | # event_timestamp is the SQL snippet for converting an epoch timestamp | |
56 | # to an SQL date. | |
57 | ||
58 | event_timestamp = "TO_TIMESTAMP(${event_timestamp_epoch})" | |
40 | 59 | |
41 | 60 | ####################################################################### |
42 | 61 | # Default profile |
263 | 282 | query = "\ |
264 | 283 | UPDATE ${....acct_table1} \ |
265 | 284 | SET \ |
266 | AcctStopTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
267 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
268 | AcctSessionTime = (%{integer:Event-Timestamp} - EXTRACT(EPOCH FROM(AcctStartTime))), \ | |
285 | AcctStopTime = ${....event_timestamp}, \ | |
286 | AcctUpdateTime = ${....event_timestamp}, \ | |
287 | AcctSessionTime = (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime))), \ | |
269 | 288 | AcctTerminateCause = '%{%{Acct-Terminate-Cause}:-NAS-Reboot}' \ |
270 | 289 | WHERE AcctStopTime IS NULL \ |
271 | 290 | AND NASIPAddress= '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \ |
272 | AND AcctStartTime <= '%S'::timestamp" | |
291 | AND AcctStartTime <= ${....event_timestamp}" | |
273 | 292 | } |
274 | 293 | |
275 | 294 | accounting-off { |
295 | 314 | '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \ |
296 | 315 | NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \ |
297 | 316 | '%{NAS-Port-Type}', \ |
298 | TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
317 | ${....event_timestamp}, \ | |
299 | 318 | NULL, \ |
300 | 319 | NULL, \ |
301 | 320 | 0, \ |
318 | 337 | query = "\ |
319 | 338 | UPDATE ${....acct_table1} \ |
320 | 339 | SET \ |
321 | AcctStartTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
322 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
340 | AcctStartTime = ${....event_timestamp}, \ | |
341 | AcctUpdateTime = ${....event_timestamp}, \ | |
323 | 342 | ConnectInfo_start = '%{Connect-Info}', \ |
324 | 343 | AcctSessionId = '%{Acct-Session-Id}' \ |
325 | 344 | WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \ |
338 | 357 | '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \ |
339 | 358 | NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \ |
340 | 359 | '%{NAS-Port-Type}', \ |
341 | TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
342 | TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
360 | ${....event_timestamp}, \ | |
361 | ${....event_timestamp}, \ | |
343 | 362 | NULL, \ |
344 | 363 | 0, \ |
345 | 364 | '%{Acct-Authentic}', \ |
360 | 379 | ON CONFLICT (AcctUniqueId) \ |
361 | 380 | DO UPDATE \ |
362 | 381 | SET \ |
363 | AcctStartTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
364 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
382 | AcctStartTime = ${....event_timestamp}, \ | |
383 | AcctUpdateTime = ${....event_timestamp}, \ | |
365 | 384 | ConnectInfo_start = '%{Connect-Info}' \ |
366 | 385 | WHERE ${....acct_table1}.AcctUniqueId = '%{Acct-Unique-Session-Id}' \ |
367 | 386 | AND ${....acct_table1}.AcctStopTime IS NULL" |
389 | 408 | FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ |
390 | 409 | FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ |
391 | 410 | DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ |
392 | AcctStartTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
393 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}) \ | |
411 | AcctStartTime = ${....event_timestamp}, \ | |
412 | AcctUpdateTime = ${....event_timestamp} \ | |
394 | 413 | WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}' \ |
395 | 414 | AND AcctStopTime IS NULL" |
396 | 415 | |
398 | 417 | query = "\ |
399 | 418 | UPDATE ${....acct_table1} \ |
400 | 419 | SET \ |
401 | AcctStartTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
402 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
420 | AcctStartTime = ${....event_timestamp}, \ | |
421 | AcctUpdateTime = ${....event_timestamp}, \ | |
403 | 422 | ConnectInfo_start = '%{Connect-Info}' \ |
404 | 423 | WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" |
405 | 424 | } |
414 | 433 | FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ |
415 | 434 | DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ |
416 | 435 | AcctSessionTime = %{%{Acct-Session-Time}:-NULL}, \ |
417 | AcctInterval = (%{integer:Event-Timestamp} - EXTRACT(EPOCH FROM (COALESCE(AcctUpdateTime, AcctStartTime)))), \ | |
418 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
436 | AcctInterval = (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM (COALESCE(AcctUpdateTime, AcctStartTime)))), \ | |
437 | AcctUpdateTime = ${....event_timestamp}, \ | |
419 | 438 | AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \ |
420 | 439 | '%{%{Acct-Input-Octets}:-0}'::bigint), \ |
421 | 440 | AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \ |
434 | 453 | '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \ |
435 | 454 | NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \ |
436 | 455 | '%{NAS-Port-Type}', \ |
437 | TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
438 | TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
456 | ${....event_timestamp}, \ | |
457 | ${....event_timestamp}, \ | |
439 | 458 | NULL, \ |
440 | 459 | %{%{Acct-Session-Time}:-NULL}, \ |
441 | 460 | '%{Acct-Authentic}', \ |
481 | 500 | FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ |
482 | 501 | FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ |
483 | 502 | DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ |
484 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
485 | AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \ | |
486 | (%{integer:Event-Timestamp} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
503 | AcctUpdateTime = ${....event_timestamp}, \ | |
504 | AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, | |
505 | (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
487 | 506 | AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \ |
488 | 507 | '%{%{Acct-Input-Octets}:-0}'::bigint), \ |
489 | 508 | AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \ |
496 | 515 | query = "\ |
497 | 516 | UPDATE ${....acct_table2} \ |
498 | 517 | SET \ |
499 | AcctStopTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
500 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
518 | AcctStopTime = ${....event_timestamp}, \ | |
519 | AcctUpdateTime = ${....event_timestamp}, \ | |
501 | 520 | AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \ |
502 | (%{integer:Event-Timestamp} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
521 | (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
503 | 522 | AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \ |
504 | 523 | '%{%{Acct-Input-Octets}:-0}'::bigint), \ |
505 | 524 | AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \ |
525 | 544 | '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \ |
526 | 545 | NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \ |
527 | 546 | '%{NAS-Port-Type}', \ |
528 | TO_TIMESTAMP(%{integer:Event-Timestamp} - %{%{Acct-Session-Time}:-0}), \ | |
529 | TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
530 | TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
547 | TO_TIMESTAMP(${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \ | |
548 | ${....event_timestamp}, \ | |
549 | ${....event_timestamp}, \ | |
531 | 550 | NULLIF('%{Acct-Session-Time}', '')::bigint, \ |
532 | 551 | '%{Acct-Authentic}', \ |
533 | 552 | '%{Connect-Info}', \ |
572 | 591 | FramedIPv6Prefix = NULLIF('%{Framed-IPv6-Prefix}', '')::inet, \ |
573 | 592 | FramedInterfaceId = NULLIF('%{Framed-Interface-Id}', ''), \ |
574 | 593 | DelegatedIPv6Prefix = NULLIF('%{Delegated-IPv6-Prefix}', '')::inet, \ |
575 | AcctStopTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
576 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
594 | AcctStopTime = ${....event_timestamp}, \ | |
595 | AcctUpdateTime = ${....event_timestamp}, \ | |
577 | 596 | AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \ |
578 | (%{integer:Event-Timestamp} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
597 | (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
579 | 598 | AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \ |
580 | 599 | '%{%{Acct-Input-Octets}:-0}'::bigint), \ |
581 | 600 | AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \ |
589 | 608 | query = "\ |
590 | 609 | UPDATE ${....acct_table2} \ |
591 | 610 | SET \ |
592 | AcctStopTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
593 | AcctUpdateTime = TO_TIMESTAMP(%{integer:Event-Timestamp}), \ | |
611 | AcctStopTime = ${....event_timestamp}, \ | |
612 | AcctUpdateTime = ${....event_timestamp}, \ | |
594 | 613 | AcctSessionTime = COALESCE(%{%{Acct-Session-Time}:-NULL}, \ |
595 | (%{integer:Event-Timestamp} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
614 | (${....event_timestamp_epoch} - EXTRACT(EPOCH FROM(AcctStartTime)))), \ | |
596 | 615 | AcctInputOctets = (('%{%{Acct-Input-Gigawords}:-0}'::bigint << 32) + \ |
597 | 616 | '%{%{Acct-Input-Octets}:-0}'::bigint), \ |
598 | 617 | AcctOutputOctets = (('%{%{Acct-Output-Gigawords}:-0}'::bigint << 32) + \ |
635 | 654 | '%{User-Name}', \ |
636 | 655 | '%{%{User-Password}:-%{Chap-Password}}', \ |
637 | 656 | '%{reply:Packet-Type}', \ |
638 | NOW())" | |
657 | '%S.%M')" | |
639 | 658 | } |
0 | #!/bin/sh | |
1 | # | |
2 | # main/sqlite/process-radacct-refresh.sh -- Schema extensions and script for processing radacct entries | |
3 | # | |
4 | # $Id$ | |
5 | ||
6 | # | |
7 | # See process-radacct-schema.sql for details. | |
8 | # | |
9 | ||
10 | if [ "$#" -ne 1 ]; then | |
11 | echo "Usage: process-radacct-refresh.sh SQLITE_DB_FILE" 2>&1 | |
12 | exit 1 | |
13 | fi | |
14 | ||
15 | if [ ! -r "$1" ]; then | |
16 | echo "The SQLite database must exist: $1" 1>&2 | |
17 | exit 1 | |
18 | fi | |
19 | ||
20 | cat <<EOF | sqlite3 "$1" | |
21 | ||
22 | -- | |
23 | -- SQLite doesn't have a concept of session variables so we fake it. | |
24 | -- | |
25 | DROP TABLE IF EXISTS vars; | |
26 | CREATE TEMPORARY TABLE vars ( | |
27 | key text, | |
28 | value text, | |
29 | PRIMARY KEY (key) | |
30 | ); | |
31 | ||
32 | INSERT INTO vars SELECT 'v_start', COALESCE(MAX(period_start), DATETIME(0, 'unixepoch')) FROM data_usage_by_period; | |
33 | INSERT INTO vars SELECT 'v_end', CURRENT_TIMESTAMP; | |
34 | ||
35 | ||
36 | -- | |
37 | -- Make of copy of the sessions that were active during this period to | |
38 | -- avoid having to execute a potentially long transaction that might hold a | |
39 | -- global database lock. | |
40 | -- | |
41 | DROP TABLE IF EXISTS radacct_sessions; | |
42 | CREATE TEMPORARY TABLE radacct_sessions ( | |
43 | username text, | |
44 | acctstarttime datetime, | |
45 | acctstoptime datetime, | |
46 | acctinputoctets bigint, | |
47 | acctoutputoctets bigint | |
48 | ); | |
49 | CREATE INDEX temp.idx_radacct_sessions_username ON radacct_sessions(username); | |
50 | CREATE INDEX temp.idx_radacct_sessions_acctstoptime ON radacct_sessions(acctstoptime); | |
51 | ||
52 | INSERT INTO radacct_sessions | |
53 | SELECT | |
54 | username, | |
55 | acctstarttime, | |
56 | acctstoptime, | |
57 | acctinputoctets, | |
58 | acctoutputoctets | |
59 | FROM | |
60 | radacct | |
61 | WHERE | |
62 | acctstoptime > (SELECT value FROM vars WHERE key='v_start') OR | |
63 | acctstoptime IS NULL; | |
64 | ||
65 | ||
66 | -- | |
67 | -- Add the data usage for the sessions that were active in the current | |
68 | -- period to the table. Include all sessions that finished since the start | |
69 | -- of this period as well as those still ongoing. | |
70 | -- | |
71 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
72 | SELECT | |
73 | username, | |
74 | (SELECT value FROM vars WHERE key='v_start'), | |
75 | (SELECT value FROM vars WHERE key='v_end'), | |
76 | SUM(acctinputoctets) AS acctinputoctets, | |
77 | SUM(acctoutputoctets) AS acctoutputoctets | |
78 | FROM | |
79 | radacct_sessions | |
80 | GROUP BY | |
81 | username | |
82 | ON CONFLICT(username,period_start) DO UPDATE | |
83 | SET | |
84 | acctinputoctets = data_usage_by_period.acctinputoctets + EXCLUDED.acctinputoctets, | |
85 | acctoutputoctets = data_usage_by_period.acctoutputoctets + EXCLUDED.acctoutputoctets, | |
86 | period_end = (SELECT value FROM vars WHERE key='v_end'); | |
87 | ||
88 | -- | |
89 | -- Create an open-ended "next period" for all ongoing sessions and carry a | |
90 | -- negative value of their data usage to avoid double-accounting when we | |
91 | -- process the next period. Their current data usage has already been | |
92 | -- allocated to the current and possibly previous periods. | |
93 | -- | |
94 | INSERT INTO data_usage_by_period (username, period_start, period_end, acctinputoctets, acctoutputoctets) | |
95 | SELECT | |
96 | username, | |
97 | (SELECT DATETIME(value, '+1 seconds') FROM vars WHERE key='v_end'), | |
98 | NULL, | |
99 | 0 - SUM(acctinputoctets), | |
100 | 0 - SUM(acctoutputoctets) | |
101 | FROM | |
102 | radacct_sessions | |
103 | WHERE | |
104 | acctstoptime IS NULL | |
105 | GROUP BY | |
106 | username; | |
107 | ||
108 | DROP TABLE vars; | |
109 | DROP TABLE radacct_sessions; | |
110 | ||
111 | EOF |
0 | # -*- text -*- | |
1 | # | |
2 | # main/sqlite/process-radacct.sql -- Schema extensions and script for processing radacct entries | |
3 | # | |
4 | # $Id$ | |
5 | ||
6 | -- --------------------------------- | |
7 | -- - Per-user data usage over time - | |
8 | -- --------------------------------- | |
9 | -- | |
10 | -- An extension to the standard schema to hold per-user data usage statistics | |
11 | -- for arbitrary periods. | |
12 | -- | |
13 | -- The data_usage_by_period table is populated by periodically calling the | |
14 | -- process-radacct-refresh.sh script. | |
15 | -- | |
16 | -- This table can be queried in various ways to produce reports of aggregate | |
17 | -- data use over time. For example, if the refresh script is invoked once per | |
18 | -- day just after midnight, to produce usage data with daily granularity, then | |
19 | -- a reasonably accurate monthly bandwidth summary for a given user could be | |
20 | -- obtained by queriing this table with: | |
21 | -- | |
22 | -- SELECT | |
23 | -- STRFTIME('%Y-%m',CURRENT_TIMESTAMP) AS month, | |
24 | -- SUM(acctinputoctets)*1.0/1000/1000/1000 AS gb_in, | |
25 | -- SUM(acctoutputoctets)*1.0/1000/1000/1000 AS gb_out | |
26 | -- FROM | |
27 | -- data_usage_by_period | |
28 | -- WHERE | |
29 | -- username='bob' AND | |
30 | -- period_end IS NOT NULL | |
31 | -- GROUP BY | |
32 | -- month; | |
33 | -- | |
34 | -- 2019-07|5.782279231|50.545664824 | |
35 | -- 2019-08|4.230543344|48.523096424 | |
36 | -- 2019-09|4.847360599|48.631835488 | |
37 | -- 2019-10|6.456763254|51.686231937 | |
38 | -- 2019-11|6.362537735|52.385710572 | |
39 | -- 2019-12|4.301524442|50.762240277 | |
40 | -- 2020-01|5.436280545|49.067775286 | |
41 | -- | |
42 | CREATE TABLE data_usage_by_period ( | |
43 | username text, | |
44 | period_start datetime, | |
45 | period_end datetime, | |
46 | acctinputoctets bigint, | |
47 | acctoutputoctets bigint, | |
48 | PRIMARY KEY (username, period_start) | |
49 | ); | |
50 | CREATE INDEX idx_data_usage_by_period_period_start ON data_usage_by_period(period_start); |
24 | 24 | #sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}" |
25 | 25 | # |
26 | 26 | sql_user_name = "%{User-Name}" |
27 | ||
28 | ####################################################################### | |
29 | # Query config: Event-Timestamp | |
30 | ####################################################################### | |
31 | # event_timestamp_epoch is the basis for the time inserted into | |
32 | # accounting records. Typically this will be the Event-Timestamp of the | |
33 | # accounting request, which is usually provided by a NAS. | |
34 | # | |
35 | # Uncomment the next line, if you want the timestamp to be based on the | |
36 | # request reception time recorded by this server, for example if you | |
37 | # distrust the provided Event-Timestamp. | |
38 | #event_timestamp_epoch = "%l" | |
39 | ||
40 | event_timestamp_epoch = "%{%{integer:Event-Timestamp}:-%l}" | |
41 | ||
42 | # event_timestamp is the SQL snippet for converting an epoch timestamp | |
43 | # to an SQL date. | |
44 | ||
45 | event_timestamp = "${event_timestamp_epoch}" | |
46 | ||
47 | # NOTE: Recent SQLite versions allow proper arithmetic with dates | |
48 | # stored as strings including comparison using an index, so we keep | |
49 | # these variables differentiated in preparation for switching away from | |
50 | # integer storage. | |
27 | 51 | |
28 | 52 | ####################################################################### |
29 | 53 | # Default profile |
221 | 245 | query = "\ |
222 | 246 | UPDATE ${....acct_table1} \ |
223 | 247 | SET \ |
224 | acctstoptime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
248 | acctstoptime = ${....event_timestamp}, \ | |
225 | 249 | acctsessiontime = \ |
226 | (%{%{integer:Event-Timestamp}:-strftime('%%s', 'now')} \ | |
227 | - strftime('%%s', acctstarttime)), \ | |
250 | (${....event_timestamp_epoch} \ | |
251 | - acctstarttime), \ | |
228 | 252 | acctterminatecause = '%{Acct-Terminate-Cause}' \ |
229 | 253 | WHERE acctstoptime IS NULL \ |
230 | 254 | AND nasipaddress = '%{NAS-IP-Address}' \ |
231 | AND acctstarttime <= %{integer:Event-Timestamp}" | |
255 | AND acctstarttime <= ${....event_timestamp}" | |
232 | 256 | } |
233 | 257 | |
234 | 258 | accounting-off { |
254 | 278 | '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}', \ |
255 | 279 | NULLIF('%{%{NAS-Port-ID}:-%{NAS-Port}}', ''), \ |
256 | 280 | '%{NAS-Port-Type}', \ |
257 | %{%{integer:Event-Timestamp}:-date('now')}, \ | |
281 | ${....event_timestamp}, \ | |
258 | 282 | NULL, \ |
259 | 283 | NULL, \ |
260 | 284 | 0, \ |
276 | 300 | |
277 | 301 | query = "\ |
278 | 302 | UPDATE ${....acct_table1} SET \ |
279 | AcctStartTime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
280 | AcctUpdateTime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
303 | AcctStartTime = ${....event_timestamp}, \ | |
304 | AcctUpdateTime = ${....event_timestamp}, \ | |
281 | 305 | ConnectInfo_start = '%{Connect-Info}', \ |
282 | 306 | AcctSessionId = '%{Acct-Session-Id}' \ |
283 | 307 | WHERE UserName = '%{SQL-User-Name}' \ |
302 | 326 | '%{NAS-IP-Address}', \ |
303 | 327 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
304 | 328 | '%{NAS-Port-Type}', \ |
305 | %{%{integer:Event-Timestamp}:-date('now')}, \ | |
306 | %{%{integer:Event-Timestamp}:-date('now')}, \ | |
329 | ${....event_timestamp}, \ | |
330 | ${....event_timestamp}, \ | |
307 | 331 | NULL, \ |
308 | 332 | '0', \ |
309 | 333 | '%{Acct-Authentic}', \ |
345 | 369 | framedipv6prefix = '%{Framed-IPv6-Prefix}', \ |
346 | 370 | framedinterfaceid = '%{Framed-Interface-Id}', \ |
347 | 371 | delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ |
348 | AcctStartTime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
349 | AcctUpdateTime = %{%{integer:Event-Timestamp}:-date('now')} \ | |
372 | AcctStartTime = ${....event_timestamp}, \ | |
373 | AcctUpdateTime = ${....event_timestamp} \ | |
350 | 374 | WHERE UserName = '%{SQL-User-Name}' \ |
351 | 375 | AND NASIPAddress = '%{%{NAS-IPv6-Address}:-%{NAS-IP-Address}}' \ |
352 | 376 | AND NASPortId = '%{%{NAS-Port-ID}:-%{NAS-Port}}' \ |
359 | 383 | # |
360 | 384 | query = "\ |
361 | 385 | UPDATE ${....acct_table1} SET \ |
362 | acctstarttime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
363 | acctupdatetime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
386 | acctstarttime = ${....event_timestamp}, \ | |
387 | acctupdatetime = ${....event_timestamp}, \ | |
364 | 388 | connectinfo_start = '%{Connect-Info}' \ |
365 | 389 | WHERE AcctUniqueId = '%{Acct-Unique-Session-Id}'" |
366 | 390 | } |
374 | 398 | query = "\ |
375 | 399 | UPDATE ${....acct_table1} \ |
376 | 400 | SET \ |
377 | acctupdatetime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
401 | acctupdatetime = ${....event_timestamp}, \ | |
378 | 402 | acctinterval = 0, \ |
379 | 403 | framedipaddress = '%{Framed-IP-Address}', \ |
380 | 404 | framedipv6address = '%{Framed-IPv6-Address}', \ |
403 | 427 | '%{NAS-IP-Address}', \ |
404 | 428 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
405 | 429 | '%{NAS-Port-Type}', \ |
406 | (%{%{integer:Event-Timestamp}:-strftime('%%s', 'now')} - %{%{Acct-Session-Time}:-0}), \ | |
407 | %{%{integer:Event-Timestamp}:-date('now')}, \ | |
430 | (${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \ | |
431 | ${....event_timestamp}, \ | |
408 | 432 | NULL, \ |
409 | 433 | %{%{Acct-Session-Time}:-NULL}, \ |
410 | 434 | '%{Acct-Authentic}', \ |
448 | 472 | framedipv6prefix = '%{Framed-IPv6-Prefix}', \ |
449 | 473 | framedinterfaceid = '%{Framed-Interface-Id}', \ |
450 | 474 | delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ |
451 | AcctUpdateTime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
475 | AcctUpdateTime = ${....event_timestamp}, \ | |
452 | 476 | AcctSessionTime = %{%{Acct-Session-Time}:-NULL}, \ |
453 | 477 | AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \ |
454 | 478 | << 32 | '%{%{Acct-Input-Octets}:-0}', \ |
468 | 492 | # |
469 | 493 | query = "\ |
470 | 494 | UPDATE ${....acct_table2} SET \ |
471 | acctstoptime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
495 | acctstoptime = ${....event_timestamp}, \ | |
472 | 496 | acctsessiontime = %{%{Acct-Session-Time}:-NULL}, \ |
473 | 497 | acctinputoctets = %{%{Acct-Input-Gigawords}:-0} \ |
474 | 498 | << 32 | %{%{Acct-Input-Octets}:-0}, \ |
493 | 517 | '%{NAS-IP-Address}', \ |
494 | 518 | '%{%{NAS-Port-ID}:-%{NAS-Port}}', \ |
495 | 519 | '%{NAS-Port-Type}', \ |
496 | (%{%{integer:Event-Timestamp}:-strftime('%%s', 'now')} - %{%{Acct-Session-Time}:-0}), \ | |
497 | %{%{integer:Event-Timestamp}:-date('now')}, \ | |
498 | %{%{integer:Event-Timestamp}:-date('now')}, \ | |
520 | (${....event_timestamp_epoch} - %{%{Acct-Session-Time}:-0}), \ | |
521 | ${....event_timestamp}, \ | |
522 | ${....event_timestamp}, \ | |
499 | 523 | %{%{Acct-Session-Time}:-NULL}, \ |
500 | 524 | '%{Acct-Authentic}', \ |
501 | 525 | '', \ |
538 | 562 | framedipv6prefix = '%{Framed-IPv6-Prefix}', \ |
539 | 563 | framedinterfaceid = '%{Framed-Interface-Id}', \ |
540 | 564 | delegatedipv6prefix = '%{Delegated-IPv6-Prefix}', \ |
541 | AcctStopTime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
542 | AcctUpdateTime = %{%{integer:Event-Timestamp}:-date('now')}, \ | |
565 | AcctStopTime = ${....event_timestamp}, \ | |
566 | AcctUpdateTime = ${....event_timestamp}, \ | |
543 | 567 | AcctSessionTime = %{%{Acct-Session-Time}:-NULL}, \ |
544 | 568 | AcctInputOctets = '%{%{Acct-Input-Gigawords}:-0}' \ |
545 | 569 | << 32 | '%{%{Acct-Input-Octets}:-0}', \ |
583 | 607 | '%{SQL-User-Name}', \ |
584 | 608 | '%{%{User-Password}:-%{Chap-Password}}', \ |
585 | 609 | '%{reply:Packet-Type}', \ |
586 | '%S')" | |
610 | '%S.%M')" | |
587 | 611 | } |
16 | 16 | username varchar(64) NOT NULL default '', |
17 | 17 | realm varchar(64) default '', |
18 | 18 | nasipaddress varchar(15) NOT NULL default '', |
19 | nasportid varchar(15) default NULL, | |
19 | nasportid varchar(32) default NULL, | |
20 | 20 | nasporttype varchar(32) default NULL, |
21 | 21 | acctstarttime datetime NULL default NULL, |
22 | 22 | acctupdatetime datetime NULL default NULL, |
637 | 637 | # sradutmp |
638 | 638 | |
639 | 639 | # Return an address to the IP Pool when we see a stop record. |
640 | # main_pool | |
640 | # sqlippool | |
641 | 641 | |
642 | 642 | # |
643 | 643 | # Log traffic to an SQL database. |
726 | 726 | &reply: += &session-state: |
727 | 727 | } |
728 | 728 | |
729 | # Get an address from the IP Pool. | |
730 | # main_pool | |
729 | # Refresh leases when we see a start or alive. Return an address to | |
730 | # the IP Pool when we see a stop record. | |
731 | # sqlippool | |
731 | 732 | |
732 | 733 | |
733 | 734 | # Create the CUI value and add the attribute to Access-Accept. |
768 | 769 | # you will need to define the WiMAX NAI, usually via |
769 | 770 | # |
770 | 771 | # update request { |
771 | # WiMAX-MN-NAI = "%{User-Name}" | |
772 | # &WiMAX-MN-NAI = "%{User-Name}" | |
772 | 773 | # } |
773 | 774 | # |
774 | 775 | # If you want various keys to be calculated, you will need to |
777 | 778 | # taken from the cryptographic calculations. e.g. |
778 | 779 | # |
779 | 780 | # update reply { |
780 | # WiMAX-FA-RK-Key = 0x00 | |
781 | # WiMAX-MSK = "%{EAP-MSK}" | |
781 | # &WiMAX-FA-RK-Key = 0x00 | |
782 | # &WiMAX-MSK = "%{reply:EAP-MSK}" | |
782 | 783 | # } |
783 | 784 | # |
784 | 785 | # You may want to delete the MS-MPPE-*-Keys from the reply, |
23 | 23 | # |
24 | 24 | # Will return "yes" if the connection has TLS enabled. It will |
25 | 25 | # return "no" if TLS is not enabled for a particular listen section. |
26 | # | |
27 | # A number of TLS-Client-Cert-.. attributes holds X509v3 extensions | |
28 | # data, attributes named the way OpenSSL names them. It is possible | |
29 | # to extract data for an extension not known to OpenSSL by defining | |
30 | # a custom string attribute which contains extension OID in it's | |
31 | # name after 'TLS-Client-Cert-' prefix. E.g.: | |
32 | # | |
33 | # ATTRIBUTE TLS-Client-Cert-1.3.6.1.4.1.311.21.7 3002 string | |
34 | # | |
35 | # which will yield something simmilar to: | |
36 | # | |
37 | # (0) eap_tls: TLS - Creating attributes from certificate OIDs | |
38 | # (0) eap_tls: TLS-Client-Cert-1.3.6.1.4.1.311.21.7 += "0x302e06" | |
39 | # ... | |
26 | 40 | # |
27 | 41 | ###################################################################### |
28 | 42 |
27 | 27 | |
28 | 28 | Summary: High-performance and highly configurable free RADIUS server |
29 | 29 | Name: freeradius |
30 | Version: 3.0.20 | |
30 | Version: 3.0.21 | |
31 | 31 | Release: 1%{?dist} |
32 | 32 | License: GPLv2+ and LGPLv2+ |
33 | 33 | Group: System Environment/Daemons |
266 | 266 | %endif |
267 | 267 | %endif |
268 | 268 | |
269 | %if %{?el6:0}%{!?el6:1} | |
269 | 270 | %package redis |
270 | 271 | Summary: Redis support for FreeRADIUS |
271 | 272 | Group: System Environment/Daemons |
275 | 276 | |
276 | 277 | %description redis |
277 | 278 | This plugin provides Redis support for the FreeRADIUS server project. |
279 | %endif | |
278 | 280 | |
279 | 281 | %package rest |
280 | 282 | Summary: REST support for FreeRADIUS |
730 | 732 | # freetds |
731 | 733 | %dir %attr(750,root,radiusd) %{_sysconfdir}/raddb/mods-config/sql/main/mssql |
732 | 734 | %attr(640,root,radiusd) %config(noreplace) %{_sysconfdir}/raddb/mods-config/sql/main/mssql/* |
735 | %dir %attr(750,root,radiusd) %{_sysconfdir}/raddb/mods-config/sql/ippool/mssql | |
736 | %attr(640,root,radiusd) %config(noreplace) %{_sysconfdir}/raddb/mods-config/sql/ippool/mssql/* | |
733 | 737 | # oracle |
734 | 738 | %if %{?_with_rlm_sql_oracle:1}%{!?_with_rlm_sql_oracle:0} |
735 | 739 | %dir %attr(750,root,radiusd) %{_sysconfdir}/raddb/mods-config/sql |
797 | 801 | %defattr(-,root,root) |
798 | 802 | %{_libdir}/freeradius/rlm_sql_unixodbc.so |
799 | 803 | |
804 | %if %{?el6:0}%{!?el6:1} | |
800 | 805 | %files redis |
801 | 806 | %defattr(-,root,root) |
802 | 807 | %{_libdir}/freeradius/rlm_redis.so |
803 | 808 | %{_libdir}/freeradius/rlm_rediswho.so |
809 | %endif | |
804 | 810 | |
805 | 811 | %files rest |
806 | 812 | %defattr(-,root,root) |
29 | 29 | ExecStart=/usr/sbin/radiusd -f $FREERADIUS_OPTIONS |
30 | 30 | Restart=on-failure |
31 | 31 | RestartSec=5 |
32 | ExecReload=/usr/sbin/radiusd $FREERADIUS_OPTIONS -Cxm -lstdout | |
33 | ExecReload=/bin/kill -HUP $MAINPID | |
32 | 34 | |
33 | 35 | # Don't elevate privileges after starting |
34 | 36 | NoNewPrivileges=true |
0 | # Crossbuild | |
1 | ||
2 | ## Summary | |
3 | ||
4 | The "crossbuild" system is a way to build FreeRADIUS for multiple | |
5 | different operating systems, using Docker. | |
6 | ||
7 | The primary purpose is for developers to easily test FreeRADIUS on | |
8 | different systems. | |
9 | ||
10 | ||
11 | ## Common Usage | |
12 | ||
13 | The systems supported can be listed with | |
14 | ||
15 | make crossbuild.info | |
16 | ||
17 | A reminder of the make targets may be seen with | |
18 | ||
19 | make crossbuild.help | |
20 | ||
21 | To make all the known systems (this may take quite a while, at | |
22 | least on the first run): | |
23 | ||
24 | make crossbuild | |
25 | ||
26 | or for the most common systems (Debian, Ubuntu, CentOS): | |
27 | ||
28 | make crossbuild.common | |
29 | ||
30 | ||
31 | ## General operation | |
32 | ||
33 | The system works by building and then starting up Docker | |
34 | containers for the systems. When a build is triggered (either | |
35 | generally, as above, or for a specific OS) the current git commits | |
36 | are copied into the image and then `make test` run. | |
37 | ||
38 | The Docker containers are left running, and may be stopped with | |
39 | ||
40 | make crossbuild.down | |
41 | ||
42 | The system tries to be as efficient as possible, so will not | |
43 | rebuild from scratch every time. | |
44 | ||
45 | ||
46 | ## Global make targets | |
47 | ||
48 | The following targets will operate on the crossbuild system | |
49 | globally, or on all images (unless otherwise stated): | |
50 | ||
51 | ||
52 | ### `make crossbuild` | |
53 | ||
54 | Create all docker images (if required), start them, build and test | |
55 | FreeRADIUS. | |
56 | ||
57 | ||
58 | ### `make crossbuild.common` | |
59 | ||
60 | As `make crossbuild`, but only build and test the most common | |
61 | systems. | |
62 | ||
63 | ||
64 | ### `make crossbuild.info` | |
65 | ||
66 | List all systems, together with the expected state. See | |
67 | `crossbuild.reset`. | |
68 | ||
69 | ||
70 | ### `make crossbuild.down` | |
71 | ||
72 | Stop all containers. | |
73 | ||
74 | ||
75 | ### `make crossbuild.reset` | |
76 | ||
77 | If containers are stopped or started outside Docker, crossbuild | |
78 | may get confused. This will clear the internal state which should | |
79 | try and start everything from be beginning again. | |
80 | ||
81 | ||
82 | ### `make crossbuild.clean` | |
83 | ||
84 | Bring down all containers, clear state. This is a general "tidy | |
85 | up". | |
86 | ||
87 | ||
88 | ### `make crossbuild.wipe` | |
89 | ||
90 | Don't just stop, but destroy all crossbuild docker images. This | |
91 | will mean they need to be recreated again upon next use. | |
92 | ||
93 | ||
94 | ## Per-image make targets | |
95 | ||
96 | The following make targets may be used on a per-image basis: | |
97 | ||
98 | * `make crossbuild.IMAGE`: build and test image | |
99 | * `make crossbuild.IMAGE.log`: show latest build log | |
100 | * `make crossbuild.IMAGE.up`: start container | |
101 | * `make crossbuild.IMAGE.down`: stop container | |
102 | * `make crossbuild.IMAGE.sh`: shell in container | |
103 | * `make crossbuild.IMAGE.refresh`: push latest commits into container | |
104 | * `make crossbuild.IMAGE.clean`: stop container and tidy up | |
105 | * `make crossbuild.IMAGE.wipe`: remove Docker image | |
106 | ||
107 | For example, `make crossbuild.debian10` to create, build and test | |
108 | FreeRADIUS on Debian 10. `make crossbuild.debian10.down` will then | |
109 | stop the container. | |
110 | ||
111 | ||
112 | ## Docker image and container names | |
113 | ||
114 | Docker images will be created with names in the form: | |
115 | ||
116 | freeradius-build/debian10 | |
117 | ||
118 | whil containers will have names like: | |
119 | ||
120 | fr-crossbuild-debian10 | |
121 |
0 | # | |
1 | # Include crossbuild targets, to test building on lots of | |
2 | # different OSes. Uses Docker. | |
3 | # | |
4 | ifeq ($(shell which docker 2> /dev/null),) | |
5 | .PHONY: crossbuild crossbuild.help | |
6 | crossbuild crossbuild.help : | |
7 | @echo crossbuild requires Docker to be installed | |
8 | else | |
9 | ||
10 | # | |
11 | # Short list of common builds | |
12 | # | |
13 | CB_COMMON:=centos7 debian10 ubuntu18 | |
14 | ||
15 | # Where the docker directories are | |
16 | DT:=scripts/crossbuild/docker | |
17 | ||
18 | # Where to put stamp files (subdirectory of where this makefile is) | |
19 | DD:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))/build | |
20 | ||
21 | # List of all the docker images (sorted for "crossbuild.info") | |
22 | CB_IMAGES:=$(sort $(patsubst $(DT)/%,%,$(wildcard $(DT)/*))) | |
23 | ||
24 | # Location of the .git dir (may be different for e.g. submodules) | |
25 | GITDIR:=$(shell perl -MCwd -e 'print Cwd::abs_path shift' $$(git rev-parse --git-dir)) | |
26 | ||
27 | CB_CPREFIX:=fr-crossbuild- | |
28 | CB_IPREFIX:=freeradius-build | |
29 | ||
30 | # | |
31 | # This Makefile is included in-line, and not via the "boilermake" | |
32 | # wrapper. But it's still useful to use the same process for | |
33 | # seeing commands that are run. | |
34 | # | |
35 | ifeq "${VERBOSE}" "" | |
36 | Q=@ | |
37 | else | |
38 | Q= | |
39 | endif | |
40 | ||
41 | # | |
42 | # Enter here: This builds everything | |
43 | # | |
44 | .PHONY: crossbuild crossbuild.common | |
45 | crossbuild: crossbuild.info $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}) | |
46 | crossbuild.common: crossbuild.info $(foreach IMG,${CB_COMMON},crossbuild.${IMG}) | |
47 | ||
48 | # | |
49 | # Dump out some useful information on what images we're going to test | |
50 | # | |
51 | .PHONY: crossbuild.info crossbuild.info_header crossbuild.help | |
52 | crossbuild.info: crossbuild.info_header $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.status) | |
53 | @echo Common images: $(CB_COMMON) | |
54 | ||
55 | crossbuild.info_header: | |
56 | @echo Images: | |
57 | ||
58 | crossbuild.help: crossbuild.info | |
59 | @echo "" | |
60 | @echo "Make targets:" | |
61 | @echo " crossbuild - build and test all images" | |
62 | @echo " crossbuild.common - build and test common images" | |
63 | @echo " crossbuild.info - list images" | |
64 | @echo " crossbuild.down - stop all containers" | |
65 | @echo " crossbuild.reset - remove cache of docker state" | |
66 | @echo " crossbuild.clean - down and reset all targets" | |
67 | @echo " crossbuild.wipe - destroy all crossbuild Docker images" | |
68 | @echo "" | |
69 | @echo "Per-image targets:" | |
70 | @echo " crossbuild.IMAGE - build and test image <IMAGE>" | |
71 | @echo " crossbuild.IMAGE.log - show latest build log" | |
72 | @echo " crossbuild.IMAGE.up - start container" | |
73 | @echo " crossbuild.IMAGE.down - stop container" | |
74 | @echo " crossbuild.IMAGE.sh - shell in container" | |
75 | @echo " crossbuild.IMAGE.refresh - push latest commits into container" | |
76 | @echo " crossbuild.IMAGE.reset - remove cache of docker state" | |
77 | @echo " crossbuild.IMAGE.clean - stop container and tidy up" | |
78 | @echo " crossbuild.IMAGE.wipe - remove Docker image" | |
79 | ||
80 | # | |
81 | # Remove stamp files, so that we try and create images again | |
82 | # | |
83 | crossbuild.reset: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.reset) | |
84 | ||
85 | # | |
86 | # Stop all containers | |
87 | # | |
88 | crossbuild.down: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.down) | |
89 | ||
90 | # | |
91 | # Clean up: stop all containers, do a reset | |
92 | # | |
93 | crossbuild.clean: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.clean) | |
94 | ||
95 | # | |
96 | # Remove all images | |
97 | # | |
98 | crossbuild.wipe: $(foreach IMG,${CB_IMAGES},crossbuild.${IMG}.wipe) | |
99 | ||
100 | # | |
101 | # Define rules for building a particular image | |
102 | # | |
103 | define CROSSBUILD_IMAGE_RULE | |
104 | # | |
105 | # Show status (based on stamp files) | |
106 | # | |
107 | .PHONY: crossbuild.${1}.status | |
108 | crossbuild.${1}.status: | |
109 | ${Q}echo -n "`echo \" ${1} \" | cut -c 1-20`" | |
110 | ${Q}if [ -e "$(DD)/stamp-up.${1}" ]; then echo "running"; \ | |
111 | elif [ -e "$(DD)/stamp-image.${1}" ]; then echo "built"; \ | |
112 | else echo "-"; fi | |
113 | # | |
114 | # Build the docker image | |
115 | # | |
116 | $(DD)/stamp-image.${1}: | |
117 | ${Q}echo "BUILD ${1} ($(CB_IPREFIX)/${1}) > $(DD)/build.${1}" | |
118 | ${Q}docker build $(DT)/${1} -f $(DT)/${1}/Dockerfile -t $(CB_IPREFIX)/${1} >$(DD)/build.${1} 2>&1 | |
119 | ${Q}touch $(DD)/stamp-image.${1} | |
120 | ||
121 | # | |
122 | # Start up the docker container | |
123 | # | |
124 | .PHONY: $(DD)/docker.up.${1} | |
125 | $(DD)/docker.up.${1}: $(DD)/stamp-image.${1} | |
126 | ${Q}echo "START ${1} ($(CB_CPREFIX)${1})" | |
127 | ${Q}docker container inspect $(CB_CPREFIX)${1} >/dev/null 2>&1 || \ | |
128 | docker run -d --rm \ | |
129 | --privileged --cap-add=ALL \ | |
130 | --mount=type=bind,source="$(GITDIR)",destination=/srv/src,ro \ | |
131 | --name $(CB_CPREFIX)${1} $(CB_IPREFIX)/${1} \ | |
132 | /bin/sh -c 'while true; do sleep 60; done' >/dev/null | |
133 | ||
134 | $(DD)/stamp-up.${1}: $(DD)/docker.up.${1} | |
135 | ${Q}touch $(DD)/stamp-up.${1} | |
136 | ||
137 | .PHONY: crossbuild.${1}.up | |
138 | crossbuild.${1}.up: $(DD)/stamp-up.${1} | |
139 | ||
140 | # | |
141 | # Run tests in the container | |
142 | # | |
143 | .PHONY: $(DD)/docker.refresh.${1} | |
144 | $(DD)/docker.refresh.${1}: $(DD)/stamp-up.${1} | |
145 | ${Q}echo "REFRESH ${1}" | |
146 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c 'rsync -a /srv/src/ /srv/local-src/' | |
147 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c 'git config -f /srv/local-src/config core.bare true' | |
148 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c 'git config -f /srv/local-src/config --unset core.worktree || true' | |
149 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '[ -d /srv/build ] || git clone /srv/local-src /srv/build' | |
150 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '(cd /srv/build && git pull --rebase)' | |
151 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '[ -e /srv/build/config.log ] || echo CONFIGURE ${1}' | |
152 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '[ -e /srv/build/config.log ] || (cd /srv/build && ./configure -C)' > $(DD)/configure.${1} 2>&1 | |
153 | ||
154 | .PHONY: $(DD)/docker.run.${1} | |
155 | $(DD)/docker.run.${1}: $(DD)/docker.refresh.${1} | |
156 | ${Q}echo "TEST ${1} > $(DD)/log.${1}" | |
157 | ${Q}docker container exec $(CB_CPREFIX)${1} sh -c '(cd /srv/build && make && make test)' > $(DD)/log.${1} 2>&1 || echo FAIL ${1} | |
158 | ||
159 | # | |
160 | # Stop the docker container | |
161 | # | |
162 | .PHONY: crossbuild.${1}.down | |
163 | crossbuild.${1}.down: | |
164 | @echo STOP ${1} | |
165 | ${Q}docker container kill $(CB_CPREFIX)${1} || true | |
166 | @rm -f $(DD)/stamp-up.${1} | |
167 | ||
168 | .PHONY: crossbuild.${1}.clean | |
169 | crossbuild.${1}.clean: crossbuild.${1}.down crossbuild.${1}.reset | |
170 | ||
171 | # | |
172 | # Shell into container. cd to root first (will always succeed), | |
173 | # then try to change to build dir, which might not exist, then | |
174 | # run bash. (Default cwd is the wrong freeradius source in | |
175 | # /usr/local, which would be confusing) | |
176 | # | |
177 | .PHONY: crossbuild.${1}.sh | |
178 | crossbuild.${1}.sh: crossbuild.${1}.up | |
179 | ${Q}docker exec -it $(CB_CPREFIX)${1} sh -c 'cd / ; cd /srv/build 2>/dev/null; bash' || true | |
180 | ||
181 | # | |
182 | # Show last build logs. Try and use the most sensible pager. | |
183 | # | |
184 | .PHONY: crossbuild.${1}.log | |
185 | crossbuild.${1}.log: | |
186 | @if which less >/dev/null; then \ | |
187 | less +G $(DD)/log.${1};\ | |
188 | elif which more >/dev/null; then \ | |
189 | more $(DD)/log.${1};\ | |
190 | else cat $(DD)/log.${1}; fi | |
191 | ||
192 | # | |
193 | # Tidy up stamp files. This means on next run we'll do | |
194 | # everything. Required if e.g. system has been rebooted, so | |
195 | # containers are stopped, but the stamp file still exists. | |
196 | # | |
197 | .PHONY: crossbuild.${1}.reset | |
198 | crossbuild.${1}.reset: | |
199 | ${Q}echo RESET ${1} | |
200 | ${Q}rm -f $(DD)/stamp-up.${1} | |
201 | ${Q}rm -f $(DD)/stamp-image.${1} | |
202 | ||
203 | # | |
204 | # Clean down images. Means on next run we'll rebuild the | |
205 | # container (rather than just starting it). | |
206 | # | |
207 | .PHONY: crossbuild.${1}.wipe | |
208 | crossbuild.${1}.wipe: | |
209 | ${Q}echo CLEAN ${1} | |
210 | ${Q}docker image rm $(CB_IPREFIX)/${1} >/dev/null 2>&1 || true | |
211 | ${Q}rm -f $(DD)/stamp-image.${1} | |
212 | ||
213 | # | |
214 | # Refresh git repository within the docker image | |
215 | # | |
216 | .PHONY: crossbuild.${1}.refresh | |
217 | crossbuild.${1}.refresh: $(DD)/docker.refresh.${1} | |
218 | ||
219 | # | |
220 | # Run the build test | |
221 | # | |
222 | .PHONY: crossbuild.${1} | |
223 | crossbuild.${1}: $(DD)/docker.run.${1} | |
224 | ||
225 | endef | |
226 | ||
227 | # | |
228 | # Add all the image building rules | |
229 | # | |
230 | $(foreach IMAGE,$(CB_IMAGES),\ | |
231 | $(eval $(call CROSSBUILD_IMAGE_RULE,$(IMAGE)))) | |
232 | ||
233 | ||
234 | # if docker is defined | |
235 | endif |
0 | FROM centos:centos7 | |
1 | ||
2 | # | |
3 | # Install devtools like make and git and the EPEL | |
4 | # repository for freetds and hiredis | |
5 | # | |
6 | RUN yum update -y | |
7 | RUN yum install -y rpmdevtools openssl epel-release git yum-utils rsync | |
8 | ||
9 | # | |
10 | # Install GCC that has the requisite support for C11 keywords and atomics | |
11 | # | |
12 | RUN yum install -y centos-release-scl | |
13 | RUN yum install -y devtoolset-8-gcc devtoolset-8-gcc-c++ | |
14 | ENV CC=/opt/rh/devtoolset-8/root/usr/bin/gcc | |
15 | ||
16 | # | |
17 | # Remove the CentOS-SCLo repo which is apparently not valid? | |
18 | # See: https://bugs.centos.org/view.php?id=14773 | |
19 | # | |
20 | RUN rm /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo | |
21 | RUN rm /etc/yum.repos.d/CentOS-SCLo-scl.repo | |
22 | ||
23 | # | |
24 | # Documentation build dependecies | |
25 | # | |
26 | ||
27 | # - doxygen & JSON.pm | |
28 | RUN yum install -y doxygen graphviz perl-JSON | |
29 | # - antora (npm needed) | |
30 | RUN curl -sL https://rpm.nodesource.com/setup_8.x | bash - | |
31 | RUN yum install -y nodejs | |
32 | RUN npm i -g @antora/cli@2.1 @antora/site-generator-default@2.1 | |
33 | # - pandoc | |
34 | RUN curl -o - -L $(curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | grep "browser_download_url.*tar.gz" | cut -d '"' -f 4) | tar xzvf - -C /tmp/ | |
35 | RUN mv /tmp/pandoc-*/bin/* /usr/local/bin | |
36 | # - asciidoctor | |
37 | RUN yum install -y rubygems-devel | |
38 | RUN gem install asciidoctor | |
39 | ||
40 | # | |
41 | # Setup a src dir in /usr/local | |
42 | # | |
43 | RUN mkdir -p /usr/local/src/repositories | |
44 | WORKDIR /usr/local/src/repositories | |
45 | ||
46 | # | |
47 | # Use LTB's openldap packages intead of the distribution version to avoid linking against NSS | |
48 | # | |
49 | RUN echo $'[ltb-project]\n\ | |
50 | name=LTB project packages\n\ | |
51 | baseurl=https://ltb-project.org/rpm/$releasever/$basearch\n\ | |
52 | enabled=1\n\ | |
53 | gpgcheck=1\n\ | |
54 | gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-LTB-project'\ | |
55 | > /etc/yum.repos.d/ltb-project.repo | |
56 | RUN rpm --import https://ltb-project.org/lib/RPM-GPG-KEY-LTB-project | |
57 | ||
58 | # | |
59 | # Shallow clone the FreeRADIUS source | |
60 | # | |
61 | WORKDIR /usr/local/src/repositories | |
62 | ARG source=https://github.com/FreeRADIUS/freeradius-server.git | |
63 | RUN git clone --depth 1 --no-single-branch ${source} | |
64 | ||
65 | # | |
66 | # Install build dependencies for all branches from v3 onwards | |
67 | # | |
68 | WORKDIR freeradius-server | |
69 | RUN for i in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin 2>/dev/null | sed -e 's#origin/##' | egrep "^(v[3-9]*\.[0-9x]*\.x|master)$");\ | |
70 | do \ | |
71 | git checkout $i; \ | |
72 | [ -e redhat/freeradius.spec ] && yum-builddep -y redhat/freeradius.spec; \ | |
73 | done | |
74 | ||
75 | # | |
76 | # Which is required by fixture setup utilities | |
77 | # | |
78 | RUN yum install -y which | |
79 | ||
80 | # | |
81 | # Explicitly install libnl3-devel which is required for the EAP tests | |
82 | # | |
83 | RUN yum install -y libnl3-devel | |
84 | ||
85 | # | |
86 | # Create the RPM build tree | |
87 | # | |
88 | ENV BUILDDIR=/root/rpmbuild | |
89 | RUN rpmdev-setuptree |
0 | FROM debian:buster | |
1 | ||
2 | ARG gccver=8 | |
3 | ARG clangver=8 | |
4 | ARG osname=buster | |
5 | ||
6 | ARG DEBIAN_FRONTEND=noninteractive | |
7 | ||
8 | # | |
9 | # Install add-apt-repository | |
10 | # | |
11 | RUN apt-get update && \ | |
12 | apt-get install -y software-properties-common gnupg2 procps && \ | |
13 | apt-get clean && \ | |
14 | rm -r /var/lib/apt/lists/* | |
15 | ||
16 | # For clang | |
17 | RUN add-apt-repository -y "deb http://apt.llvm.org/${osname}/ llvm-toolchain-${osname}-${clangver} main" && \ | |
18 | apt-key adv --fetch-keys http://apt.llvm.org/llvm-snapshot.gpg.key | |
19 | ||
20 | RUN apt-get update && \ | |
21 | # Development utilities | |
22 | apt-get install -y devscripts equivs git quilt rsync && \ | |
23 | # Compilers | |
24 | apt-get install -y g++-${gccver} llvm-${clangver} clang-${clangver} lldb-${clangver} && \ | |
25 | # eapol_test dependencies | |
26 | apt-get install -y libnl-3-dev libnl-genl-3-dev | |
27 | ||
28 | # | |
29 | # Documentation build dependecies | |
30 | # | |
31 | ||
32 | # - doxygen & JSON.pm | |
33 | RUN apt-get install -y doxygen graphviz libjson-perl | |
34 | # - antora (npm needed) | |
35 | RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - | |
36 | RUN apt-get install -y nodejs | |
37 | RUN npm i -g @antora/cli@2.1 @antora/site-generator-default@2.1 | |
38 | # - pandoc | |
39 | WORKDIR /tmp | |
40 | RUN curl -OL $(curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | grep "browser_download_url.*deb" | cut -d '"' -f 4) | |
41 | RUN apt-get install -y ./pandoc-*.deb | |
42 | # - asciidoctor | |
43 | RUN apt-get install -y ruby-dev | |
44 | RUN gem install asciidoctor | |
45 | ||
46 | # set default things | |
47 | RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${gccver} 50 \ | |
48 | --slave /usr/bin/g++ g++ /usr/bin/g++-${gccver} && \ | |
49 | update-alternatives --config gcc | |
50 | ||
51 | RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${clangver} 60 && \ | |
52 | update-alternatives --config clang | |
53 | ||
54 | RUN update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-${clangver} 60 && \ | |
55 | update-alternatives --config lldb | |
56 | ||
57 | ||
58 | # | |
59 | # Setup a src dir in /usr/local | |
60 | # | |
61 | RUN mkdir -p /usr/local/src/repositories | |
62 | WORKDIR /usr/local/src/repositories | |
63 | ||
64 | ||
65 | # | |
66 | # Shallow clone the FreeRADIUS source | |
67 | # | |
68 | WORKDIR /usr/local/src/repositories | |
69 | ARG source=https://github.com/FreeRADIUS/freeradius-server.git | |
70 | RUN git clone --depth 1 --no-single-branch ${source} | |
71 | ||
72 | ||
73 | # | |
74 | # Install build dependencies for all v3 branches | |
75 | # | |
76 | WORKDIR freeradius-server | |
77 | RUN for i in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin 2>/dev/null | sed -e 's#origin/##' | egrep "^v3\..*\.x");\ | |
78 | do \ | |
79 | git checkout $i; \ | |
80 | if [ -e ./debian/control.in ] ; then \ | |
81 | debian/rules debian/control ; \ | |
82 | fi ; \ | |
83 | echo Installing dependencies for $i ; \ | |
84 | mk-build-deps debian/control ; \ | |
85 | apt-get --no-install-recommends -y -V install ./freeradius-build-deps*.deb || true ; \ | |
86 | apt-get -y -f remove freeradius-build-deps libiodbc2-dev || true ; \ | |
87 | rm ./freeradius-build-deps*.deb ; \ | |
88 | done |
0 | FROM debian:jessie | |
1 | ||
2 | ARG gccver=4.9 | |
3 | ARG clangver=5.0 | |
4 | ARG osname=jessie | |
5 | ||
6 | ARG DEBIAN_FRONTEND=noninteractive | |
7 | ||
8 | # | |
9 | # Install add-apt-repository | |
10 | # | |
11 | RUN apt-get update && \ | |
12 | apt-get install -y software-properties-common && \ | |
13 | apt-get clean && \ | |
14 | rm -r /var/lib/apt/lists/* | |
15 | ||
16 | # Requires GCC-4.9 as it has support for C11 keywords and atomics | |
17 | ||
18 | # For clang | |
19 | RUN add-apt-repository -y "deb http://apt.llvm.org/${osname}/ llvm-toolchain-${osname}-${clangver} main" && \ | |
20 | apt-key adv --fetch-keys http://apt.llvm.org/llvm-snapshot.gpg.key | |
21 | ||
22 | RUN apt-get update && \ | |
23 | # Development utilities | |
24 | apt-get install -y devscripts equivs git quilt rsync && \ | |
25 | # Compilers | |
26 | apt-get install -y g++-${gccver} llvm-${clangver} clang-${clangver} lldb-${clangver} && \ | |
27 | # eapol_test dependencies | |
28 | apt-get install -y libnl-3-dev libnl-genl-3-dev | |
29 | ||
30 | # | |
31 | # Documentation build dependecies | |
32 | # | |
33 | ||
34 | # - doxygen & JSON.pm | |
35 | RUN apt-get install -y doxygen graphviz libjson-perl | |
36 | # - antora (npm needed) | |
37 | RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - | |
38 | RUN apt-get install -y nodejs | |
39 | RUN npm i -g @antora/cli@2.1 @antora/site-generator-default@2.1 | |
40 | # - pandoc | |
41 | WORKDIR /tmp | |
42 | RUN curl -OL $(curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | grep "browser_download_url.*deb" | cut -d '"' -f 4) | |
43 | RUN dpkg -i ./pandoc-*.deb | |
44 | RUN apt-get install -fy | |
45 | # - asciidoctor | |
46 | RUN apt-get install -y ruby | |
47 | RUN gem install asciidoctor | |
48 | ||
49 | # set default things | |
50 | RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${gccver} 50 \ | |
51 | --slave /usr/bin/g++ g++ /usr/bin/g++-${gccver} && \ | |
52 | update-alternatives --config gcc | |
53 | ||
54 | RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${clangver} 60 && \ | |
55 | update-alternatives --config clang | |
56 | ||
57 | RUN update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-${clangver} 60 && \ | |
58 | update-alternatives --config lldb | |
59 | ||
60 | ||
61 | # | |
62 | # Setup a src dir in /usr/local | |
63 | # | |
64 | RUN mkdir -p /usr/local/src/repositories | |
65 | WORKDIR /usr/local/src/repositories | |
66 | ||
67 | # | |
68 | # Shallow clone the FreeRADIUS source | |
69 | # | |
70 | ARG source=https://github.com/FreeRADIUS/freeradius-server.git | |
71 | RUN git clone --depth 1 --no-single-branch ${source} | |
72 | ||
73 | # | |
74 | # Install build dependencies for all branches from v3 onwards | |
75 | # | |
76 | WORKDIR freeradius-server | |
77 | RUN for i in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin 2>/dev/null | sed -e 's#origin/##' | egrep "^(v[3-9]*\.[0-9x]*\.x|master)$");\ | |
78 | do \ | |
79 | git checkout $i; \ | |
80 | if [ -e ./debian/control.in ] ; then debian/rules debian/control ; fi ; echo 'y' | mk-build-deps -irt'apt-get -yV' debian/control ; \ | |
81 | done |
0 | FROM debian:stretch | |
1 | ||
2 | ARG gccver=6 | |
3 | ARG clangver=5.0 | |
4 | ARG osname=stretch | |
5 | ||
6 | ARG DEBIAN_FRONTEND=noninteractive | |
7 | ||
8 | # | |
9 | # Install add-apt-repository | |
10 | # | |
11 | RUN apt-get update && \ | |
12 | apt-get install -y software-properties-common gnupg2 && \ | |
13 | apt-get clean && \ | |
14 | rm -r /var/lib/apt/lists/* | |
15 | ||
16 | # Stretch uses GCC-6.3 by default, so it doesn't need to be updated to get C11 functionality. | |
17 | ||
18 | # For clang | |
19 | RUN add-apt-repository -y "deb http://apt.llvm.org/${osname}/ llvm-toolchain-${osname}-${clangver} main" && \ | |
20 | apt-key adv --fetch-keys http://apt.llvm.org/llvm-snapshot.gpg.key | |
21 | ||
22 | RUN apt-get update && \ | |
23 | # Development utilities | |
24 | apt-get install -y devscripts equivs git quilt rsync && \ | |
25 | # Compilers | |
26 | apt-get install -y g++-${gccver} llvm-${clangver} clang-${clangver} lldb-${clangver} && \ | |
27 | # eapol_test dependencies | |
28 | apt-get install -y libnl-3-dev libnl-genl-3-dev | |
29 | ||
30 | # | |
31 | # Documentation build dependecies | |
32 | # | |
33 | ||
34 | # - doxygen & JSON.pm | |
35 | RUN apt-get install -y doxygen graphviz libjson-perl | |
36 | # - antora (npm needed) | |
37 | RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - | |
38 | RUN apt-get install -y npm | |
39 | RUN npm i -g @antora/cli@2.1 @antora/site-generator-default@2.1 | |
40 | # - pandoc | |
41 | WORKDIR /tmp | |
42 | RUN curl -OL $(curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | grep "browser_download_url.*deb" | cut -d '"' -f 4) | |
43 | RUN apt-get install -y ./pandoc-*.deb | |
44 | # - asciidoctor | |
45 | RUN apt-get install -y ruby-dev | |
46 | RUN gem install asciidoctor | |
47 | ||
48 | # set default things | |
49 | RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${gccver} 50 \ | |
50 | --slave /usr/bin/g++ g++ /usr/bin/g++-${gccver} && \ | |
51 | update-alternatives --config gcc | |
52 | ||
53 | RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${clangver} 60 && \ | |
54 | update-alternatives --config clang | |
55 | ||
56 | RUN update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-${clangver} 60 && \ | |
57 | update-alternatives --config lldb | |
58 | ||
59 | ||
60 | # | |
61 | # Setup a src dir in /usr/local | |
62 | # | |
63 | RUN mkdir -p /usr/local/src/repositories | |
64 | WORKDIR /usr/local/src/repositories | |
65 | ||
66 | ||
67 | # | |
68 | # Shallow clone the FreeRADIUS source | |
69 | # | |
70 | WORKDIR /usr/local/src/repositories | |
71 | ARG source=https://github.com/FreeRADIUS/freeradius-server.git | |
72 | RUN git clone --depth 1 --no-single-branch ${source} | |
73 | ||
74 | # | |
75 | # Install build dependencies for all branches from v3 onwards | |
76 | # | |
77 | WORKDIR freeradius-server | |
78 | RUN for i in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin 2>/dev/null | sed -e 's#origin/##' | egrep "^(v[3-9]*\.[0-9x]*\.x|master)$");\ | |
79 | do \ | |
80 | git checkout $i; \ | |
81 | if [ -e ./debian/control.in ] ; then debian/rules debian/control ; fi ; echo 'y' | mk-build-deps -irt'apt-get -yV' debian/control ; \ | |
82 | done |
0 | ||
1 | Build source image | |
2 | ||
3 | docker build . -f Dockerfile.source -t freeradius:debian9-source | |
4 | ||
5 | Then either build and run jenkins image | |
6 | ||
7 | docker build . -f Dockerfile.jenkins -t freeradius:debian9-jenkins | |
8 | docker run -d -p 2222:22 freeradius:debian9-jenkins | |
9 | ||
10 | or build and run the server | |
11 | ||
12 | docker build . -t freeradius:debian9 | |
13 | docker run -d -p 1812:1812/udp -p 1813:1813/udp freeradius:debian9 | |
14 |
0 | FROM ubuntu:16.04 | |
1 | ||
2 | ARG gccver=4.9 | |
3 | ARG clangver=5.0 | |
4 | ARG osname=xenial | |
5 | ||
6 | ARG DEBIAN_FRONTEND=noninteractive | |
7 | ||
8 | # | |
9 | # Install add-apt-repository | |
10 | # | |
11 | RUN apt-get update && \ | |
12 | apt-get install -y software-properties-common python-software-properties && \ | |
13 | apt-get clean && \ | |
14 | rm -r /var/lib/apt/lists/* | |
15 | ||
16 | # Requires GCC-4.9 as it has support for C11 keywords and atomics | |
17 | ||
18 | # For clang | |
19 | RUN add-apt-repository -y "deb http://apt.llvm.org/${osname}/ llvm-toolchain-${osname}-${clangver} main" && \ | |
20 | apt-key adv --fetch-keys http://apt.llvm.org/llvm-snapshot.gpg.key && \ | |
21 | # For GCC | |
22 | add-apt-repository -y ppa:ubuntu-toolchain-r/test | |
23 | ||
24 | RUN apt-get update && \ | |
25 | # Development utilities | |
26 | apt-get install -y devscripts equivs git quilt rsync && \ | |
27 | # Compilers | |
28 | apt-get install -y g++-${gccver} llvm-${clangver} clang-${clangver} lldb-${clangver} && \ | |
29 | # eapol_test dependencies | |
30 | apt-get install -y libnl-3-dev libnl-genl-3-dev | |
31 | ||
32 | # | |
33 | # Documentation build dependecies | |
34 | # | |
35 | ||
36 | # - doxygen & JSON.pm | |
37 | RUN apt-get install -y doxygen graphviz libjson-perl | |
38 | # - antora (npm needed) | |
39 | RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - | |
40 | RUN apt-get install -y nodejs | |
41 | RUN npm i -g @antora/cli@2.1 @antora/site-generator-default@2.1 | |
42 | # - pandoc | |
43 | WORKDIR /tmp | |
44 | RUN curl -OL $(curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | grep "browser_download_url.*deb" | cut -d '"' -f 4) | |
45 | RUN apt-get install -y ./pandoc-*.deb | |
46 | # - asciidoctor | |
47 | RUN apt-get install -y ruby-dev | |
48 | RUN gem install asciidoctor | |
49 | ||
50 | # set default things | |
51 | RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${gccver} 50 \ | |
52 | --slave /usr/bin/g++ g++ /usr/bin/g++-${gccver} && \ | |
53 | update-alternatives --config gcc | |
54 | ||
55 | RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${clangver} 60 && \ | |
56 | update-alternatives --config clang | |
57 | ||
58 | RUN update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-${clangver} 60 && \ | |
59 | update-alternatives --config lldb | |
60 | ||
61 | ||
62 | # | |
63 | # Setup a src dir in /usr/local | |
64 | # | |
65 | RUN mkdir -p /usr/local/src/repositories | |
66 | WORKDIR /usr/local/src/repositories | |
67 | ||
68 | ||
69 | # | |
70 | # Shallow clone the FreeRADIUS source | |
71 | # | |
72 | WORKDIR /usr/local/src/repositories | |
73 | ARG source=https://github.com/FreeRADIUS/freeradius-server.git | |
74 | RUN git clone --depth 1 --no-single-branch ${source} | |
75 | ||
76 | # | |
77 | # Install build dependencies for all branches from v3 onwards | |
78 | # | |
79 | WORKDIR freeradius-server | |
80 | RUN for i in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin 2>/dev/null | sed -e 's#origin/##' | egrep "^(v[3-9]*\.[0-9x]*\.x|master)$");\ | |
81 | do \ | |
82 | git checkout $i; \ | |
83 | if [ -e ./debian/control.in ] ; then debian/rules debian/control ; fi ; echo 'y' | mk-build-deps -irt'apt-get -yV' debian/control ; \ | |
84 | done |
0 | FROM ubuntu:18.04 | |
1 | ||
2 | ARG gccver=4.9 | |
3 | ARG clangver=5.0 | |
4 | ARG osname=bionic | |
5 | ||
6 | ARG DEBIAN_FRONTEND=noninteractive | |
7 | ||
8 | # | |
9 | # Install add-apt-repository | |
10 | # | |
11 | RUN apt-get update && \ | |
12 | apt-get install -y software-properties-common && \ | |
13 | apt-get clean && \ | |
14 | rm -r /var/lib/apt/lists/* | |
15 | ||
16 | RUN apt-get update && \ | |
17 | # Development utilities | |
18 | apt-get install -y devscripts equivs git quilt rsync && \ | |
19 | # Compilers | |
20 | apt-get install -y g++ llvm clang lldb && \ | |
21 | # eapol_test dependencies | |
22 | apt-get install -y libnl-3-dev libnl-genl-3-dev | |
23 | ||
24 | # | |
25 | # Documentation build dependecies | |
26 | # | |
27 | ||
28 | # - doxygen & JSON.pm | |
29 | RUN apt-get install -y doxygen graphviz libjson-perl | |
30 | # - antora (npm needed) | |
31 | RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - | |
32 | RUN apt-get install -y nodejs | |
33 | RUN npm i -g @antora/cli@2.1 @antora/site-generator-default@2.1 | |
34 | # - pandoc | |
35 | WORKDIR /tmp | |
36 | RUN curl -OL $(curl -s https://api.github.com/repos/jgm/pandoc/releases/latest | grep "browser_download_url.*deb" | cut -d '"' -f 4) | |
37 | RUN apt-get install -y ./pandoc-*.deb | |
38 | # - asciidoctor | |
39 | RUN apt-get install -y ruby-dev | |
40 | RUN gem install asciidoctor | |
41 | ||
42 | # | |
43 | # Setup a src dir in /usr/local | |
44 | # | |
45 | RUN mkdir -p /usr/local/src/repositories | |
46 | WORKDIR /usr/local/src/repositories | |
47 | ||
48 | ||
49 | # | |
50 | # Shallow clone the FreeRADIUS source | |
51 | # | |
52 | WORKDIR /usr/local/src/repositories | |
53 | ARG source=https://github.com/FreeRADIUS/freeradius-server.git | |
54 | RUN git clone --depth 1 --no-single-branch ${source} | |
55 | ||
56 | # | |
57 | # Install build dependencies for all branches from v3 onwards | |
58 | # | |
59 | WORKDIR freeradius-server | |
60 | RUN for i in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin 2>/dev/null | sed -e 's#origin/##' | egrep "^(v[3-9]*\.[0-9x]*\.x|master)$");\ | |
61 | do \ | |
62 | git checkout $i; \ | |
63 | if [ -e ./debian/control.in ] ; then debian/rules debian/control ; fi ; echo 'y' | mk-build-deps -irt'apt-get -yV' debian/control ; \ | |
64 | done |
0 | # | |
1 | # Docker-related targets | |
2 | # | |
3 | # Intended for internal use to publish Docker images to docker hub. Likely need to run | |
4 | # "docker login" before any push commands. | |
5 | # | |
6 | # Examples: | |
7 | # | |
8 | # Publish to Dockerhub "freeradius-server" | |
9 | # make DOCKER_VERSION=3.0.20 DOCKER_BUILD_ARGS="--no-cache" docker-publish | |
10 | # | |
11 | # Build and push "freeradius-dev" image to Dockerhub (e.g. CI on every commit): | |
12 | # make DOCKER_VERSION=latest DOCKER_COMMIT=v3.0.x DOCKER_TAG="freeradius-dev" DOCKER_BUILD_ARGS="--no-cache" docker-push | |
13 | # | |
14 | # Push to local repository: | |
15 | # make DOCKER_VERSION=3.0.20 DOCKER_TAG="our-freeradius-build" DOCKER_REGISTRY="docker.somewhere.example" docker-publish | |
16 | # | |
17 | # See what is going to happen: | |
18 | # make Q=": " ... | |
19 | # | |
20 | # | |
21 | # Variables: | |
22 | # | |
23 | # Which version to tag as, e.g. "3.0.20". If this is not an actual release | |
24 | # version, DOCKER_COMMIT _must_ also be set. | |
25 | DOCKER_VERSION := $(RADIUSD_VERSION_STRING) | |
26 | # | |
27 | # Commit hash/tag/branch to build, will be taken from VERSION above if not overridden, e.g. "release_3_0_20" | |
28 | DOCKER_COMMIT := release_$(shell echo $(DOCKER_VERSION) | tr .- __) | |
29 | # | |
30 | # Build args, most likely "--no-cache" | |
31 | DOCKER_BUILD_ARGS := | |
32 | # | |
33 | # Tag name, likely "freeradius-server" for releases, or "freeradius-dev" for nightlies. | |
34 | DOCKER_TAG := freeradius-server | |
35 | # | |
36 | # Repository name | |
37 | DOCKER_REPO := freeradius | |
38 | # | |
39 | # Registry to push to | |
40 | DOCKER_REGISTRY := | |
41 | # | |
42 | ||
43 | ifneq "$(DOCKER_REPO)" "" | |
44 | override DOCKER_REPO := $(DOCKER_REPO)/ | |
45 | endif | |
46 | ||
47 | ifneq "$(DOCKER_REGISTRY)" "" | |
48 | override DOCKER_REGISTRY := $(DOCKER_REGISTRY)/ | |
49 | endif | |
50 | ||
51 | ||
52 | .PHONY: docker | |
53 | docker: | |
54 | @echo Building $(DOCKER_COMMIT) | |
55 | $(Q)docker build $(DOCKER_BUILD_ARGS) scripts/docker/ubuntu18 --build-arg=release=$(DOCKER_COMMIT) -t $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):$(DOCKER_VERSION) | |
56 | $(Q)docker build $(DOCKER_BUILD_ARGS) scripts/docker/alpine --build-arg=release=$(DOCKER_COMMIT) -t $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):$(DOCKER_VERSION)-alpine | |
57 | ||
58 | .PHONY: docker-push | |
59 | docker-push: docker | |
60 | $(Q)docker push $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):$(DOCKER_VERSION) | |
61 | $(Q)docker push $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):$(DOCKER_VERSION)-alpine | |
62 | ||
63 | .PHONY: docker-tag-latest | |
64 | docker-tag-latest: docker | |
65 | $(Q)docker tag $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):$(DOCKER_VERSION) $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):latest | |
66 | $(Q)docker tag $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):$(DOCKER_VERSION)-alpine $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):latest-alpine | |
67 | ||
68 | .PHONY: docker-push-latest | |
69 | docker-push-latest: docker-push docker-tag-latest | |
70 | $(Q)docker push $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):latest | |
71 | $(Q)docker push $(DOCKER_REGISTRY)$(DOCKER_REPO)$(DOCKER_TAG):latest-alpine | |
72 | ||
73 | .PHONY: docker-publish | |
74 | docker-publish: docker-push-latest |
0 | def platforms = ["ubuntu14", "ubuntu16", "ubuntu18", "centos7", "centos8", "debian8", "debian9", "debian10"] | |
0 | def platforms = ["ubuntu14", "ubuntu16", "ubuntu18", "centos6", "centos7", "centos8", "debian8", "debian9", "debian10"] | |
1 | 1 | def server_dir = "freeradius-server" |
2 | 2 | def artifacts = 'build-number, **/*.changes, **/*.buildinfo, **/*.deb, **/*.rpm' |
3 | 3 |
63 | 63 | */ |
64 | 64 | |
65 | 65 | node { |
66 | cleanWs(patterns: [[pattern: '**/*.deb , **/*.changes , **/*.buildinfo , **/*.rpm', type: 'INCLUDE']]) | |
66 | def server_dir = "freeradius-server" | |
67 | 67 | |
68 | def server_dir = "freeradius-server" | |
68 | sh 'find . -type f \\( -name "*.deb" -o -name "*.changes" -o -name "*.buildinfo" -o -name "*.rpm" \\) -delete' | |
69 | 69 | |
70 | 70 | checkout([ |
71 | 71 | $class: 'GitSCM', |
36 | 36 | # |
37 | 37 | # Install build dependencies |
38 | 38 | # |
39 | # RUN [ -e redhat/freeradius.spec ] && yum-builddep -y redhat/freeradius.spec | |
39 | RUN [ -e redhat/freeradius.spec ] && yum-builddep -y redhat/freeradius.spec | |
40 | 40 |
176 | 176 | #endif |
177 | 177 | |
178 | 178 | #ifndef CC |
179 | #define CC "gcc" | |
179 | #define CC "clang" | |
180 | 180 | #endif |
181 | 181 | |
182 | 182 | #ifndef CXX |
184 | 184 | #endif |
185 | 185 | |
186 | 186 | #ifndef LINK_C |
187 | #define LINK_C "gcc" | |
187 | #define LINK_C "clang" | |
188 | 188 | #endif |
189 | 189 | |
190 | 190 | #ifndef LINK_CXX |
412 | 412 | |
413 | 413 | out = malloc(size); |
414 | 414 | if (!out) { |
415 | ERROR("Failed allocating %zu bytes, OOM", size); | |
415 | ERROR("Failed allocating %zu bytes, OOM\n", size); | |
416 | 416 | exit(1); |
417 | 417 | } |
418 | 418 | |
1052 | 1052 | |
1053 | 1053 | newext = strrchr(newarg, '.'); |
1054 | 1054 | if (!newext) { |
1055 | ERROR("Library path does not have an extension"); | |
1055 | ERROR("Library path does not have an extension\n"); | |
1056 | 1056 | free(newarg); |
1057 | 1057 | |
1058 | 1058 | return NULL; |
1144 | 1144 | strcpy(newarg + newpathlen, arg + pathlen); |
1145 | 1145 | ext = strrchr(newarg, '.'); |
1146 | 1146 | if (!ext) { |
1147 | ERROR("Error: Library path does not have an extension"); | |
1147 | ERROR("Error: Library path does not have an extension\n"); | |
1148 | 1148 | free(newarg); |
1149 | 1149 | |
1150 | 1150 | return NULL; |
2222 | 2222 | { |
2223 | 2223 | char *l, libpath[PATH_MAX]; |
2224 | 2224 | |
2225 | if (!cmd->arglist->num) { | |
2226 | ERROR("No command to execute.\n"); | |
2227 | rv = 1; | |
2228 | ||
2229 | goto finish; | |
2230 | } | |
2231 | ||
2225 | 2232 | if (strlen(cmd->arglist->vals[0]) >= PATH_MAX) { |
2226 | ERROR("Libpath too long no buffer space"); | |
2233 | ERROR("Libpath too long no buffer space\n"); | |
2227 | 2234 | rv = 1; |
2228 | 2235 | |
2229 | 2236 | goto finish; |
2273 | 2280 | } |
2274 | 2281 | |
2275 | 2282 | if ((strlen(dirname) + 1 + sizeof(entry->d_name)) >= sizeof(fullname)) { |
2276 | ERROR("Dirname too long, out of buffer space"); | |
2283 | ERROR("Dirname too long, out of buffer space\n"); | |
2277 | 2284 | |
2278 | 2285 | (void) closedir(dir); |
2279 | 2286 | return; |
317 | 317 | args+=" -t \"$timeout\"" |
318 | 318 | args+=" -r \"$retries\"" |
319 | 319 | args+=" -p \"$parallel\"" |
320 | args+=" -D \"$DICTPATH\"" | |
320 | 321 | args+=" \"$target\"" |
321 | 322 | args+=" auto" |
322 | 323 | args+=" \"$secret\"" |
323 | 324 | |
324 | DEBUG "Executing: radclient $args" | |
325 | eval radclient $args; ret=$? | |
325 | DEBUG "Executing: $RADCLIENT $args" | |
326 | eval $RADCLIENT $args; ret=$? | |
326 | 327 | INFO "(Parallelised tests)" |
327 | 328 | INFO "" |
328 | 329 | |
346 | 347 | args+=" -t \"$timeout\"" |
347 | 348 | args+=" -r \"$retries\"" |
348 | 349 | args+=" -p 1" |
350 | args+=" -D \"$DICTPATH\"" | |
349 | 351 | args+=" \"$target\"" |
350 | 352 | args+=" auto" |
351 | 353 | args+=" \"$secret\"" |
352 | 354 | |
353 | DEBUG "Executing: radclient $args" | |
354 | eval radclient $args; ret=$? | |
355 | DEBUG "Executing: $RADCLIENT $args" | |
356 | eval $RADCLIENT $args; ret=$? | |
355 | 357 | INFO "(Serialised tests)" |
356 | 358 | |
357 | 359 | if [ $ret -ne 0 ]; then |
251 | 251 | $INCLUDE dictionary.motorola |
252 | 252 | $INCLUDE dictionary.motorola.wimax |
253 | 253 | $INCLUDE dictionary.navini |
254 | $INCLUDE dictionary.net | |
254 | 255 | $INCLUDE dictionary.netscreen |
255 | 256 | $INCLUDE dictionary.networkphysics |
256 | 257 | $INCLUDE dictionary.nexans |
263 | 264 | $INCLUDE dictionary.patton |
264 | 265 | $INCLUDE dictionary.perle |
265 | 266 | $INCLUDE dictionary.pfsense |
267 | $INCLUDE dictionary.pica8 | |
266 | 268 | $INCLUDE dictionary.propel |
267 | 269 | $INCLUDE dictionary.prosoft |
268 | 270 | $INCLUDE dictionary.proxim |
269 | 271 | $INCLUDE dictionary.purewave |
270 | 272 | $INCLUDE dictionary.quiconnect |
271 | 273 | $INCLUDE dictionary.quintum |
274 | $INCLUDE dictionary.rcntec | |
272 | 275 | $INCLUDE dictionary.redcreek |
273 | 276 | $INCLUDE dictionary.riverbed |
274 | 277 | $INCLUDE dictionary.riverstone |
301 | 304 | $INCLUDE dictionary.usr |
302 | 305 | $INCLUDE dictionary.utstarcom |
303 | 306 | $INCLUDE dictionary.valemount |
307 | $INCLUDE dictionary.vasexperts | |
304 | 308 | $INCLUDE dictionary.verizon |
305 | 309 | $INCLUDE dictionary.versanet |
306 | 310 | $INCLUDE dictionary.walabi |
1 | 1 | # Copyright (C) 2019 The FreeRADIUS Server project and contributors |
2 | 2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 |
3 | 3 | # |
4 | # Aerohive | |
4 | # Aerohive (now Extreme Networks, Inc.) | |
5 | 5 | # |
6 | 6 | # $Id$ |
7 | 7 | # |
8 | 8 | VENDOR Aerohive 26928 |
9 | 9 | |
10 | 10 | BEGIN-VENDOR Aerohive |
11 | #BEGIN-VENDOR Extreme | |
11 | 12 | |
13 | # Source: http://docs.aerohive.com/330000/docs/help/english/ng/Content/reference/docs/radius-dictionary.htm | |
14 | # Last-updated-date 25-October-2017 | |
15 | # Extreme supports a small set of Vendor-Specific-Attributes for | |
16 | # administrative access to HiveManager Classic, and a different set | |
17 | # of Vendor-Specific-Attributes for HiveOS. Both are documented in | |
18 | # this file. | |
19 | ||
20 | # Most customer will wish to import this file in it’s entirety into | |
21 | # their local RADIUS data store. | |
22 | ||
23 | # Beginning of HiveManager Classic VSAs | |
12 | 24 | # The following ATTRIBUTE and VALUE definitions are required. |
13 | 25 | ATTRIBUTE AH-HM-Admin-Group-Id 1 integer |
14 | 26 | VALUE AH-HM-Admin-Group-Id Read-Only-Admin 0 |
18 | 30 | # The following is an example of an admin group that you can define. |
19 | 31 | #VALUE AH-HM-Admin-Group-Id Admin-Group100 100 |
20 | 32 | |
33 | # End of HiveManager Classic VSAs | |
34 | # Beginning of HiveOS VSAs | |
35 | ||
36 | ATTRIBUTE Extreme-User-Vlan 1 integer | |
37 | ATTRIBUTE Extreme-Libsip-Patron-Info 3 octets encrypt=2 | |
38 | ATTRIBUTE Extreme-Libsip-Action 4 integer | |
39 | ATTRIBUTE Extreme-Libsip-Additional-Message 5 octets | |
40 | ATTRIBUTE Extreme-User-Profile-Attribute 6 integer | |
41 | ATTRIBUTE Extreme-Data-Usage-Limit 7 octets | |
42 | ATTRIBUTE Extreme-AVPair 8 string | |
43 | ATTRIBUTE Extreme-Radius-Code 9 integer | |
44 | ATTRIBUTE Extreme-PPSK-Request 201 octets | |
45 | ATTRIBUTE Extreme-PPSK-PMK 202 octets | |
46 | ATTRIBUTE Extreme-IDM-Message 203 integer | |
47 | ATTRIBUTE Extreme-NT-Identity 204 integer | |
48 | ATTRIBUTE Extreme-User-Language 205 string | |
49 | ATTRIBUTE Extreme-Time-Zone-Offset 207 integer | |
50 | ATTRIBUTE Extreme-Daylight-Saving-Offset 208 integer | |
51 | ATTRIBUTE Extreme-Client-Monitor-Session 209 octets | |
52 | ATTRIBUTE Extreme-Client-Monitor-Problem 210 integer | |
53 | ATTRIBUTE Extreme-IDM-Redirect-URL 211 string | |
54 | ATTRIBUTE Extreme-MGT-MAC-Address 212 string | |
55 | ATTRIBUTE Extreme-Auth-Source 213 integer | |
56 | ||
57 | # | |
58 | # Integer Translations | |
59 | # | |
60 | ||
61 | # Extreme-Libsip-Action Values | |
62 | VALUE Extreme-Libsip-Action Permit 0 | |
63 | VALUE Extreme-Libsip-Action Restricted 1 | |
64 | VALUE Extreme-Libsip-Action Deny 2 | |
65 | ||
66 | # Extreme-Radius-Code Values | |
67 | VALUE Extreme-Radius-Code Disconnect-Request 1 | |
68 | VALUE Extreme-Radius-Code COA-Request 2 | |
69 | ||
70 | # Extreme-Auth-Source | |
71 | VALUE Extreme-Auth-Source Service 1 | |
72 | VALUE Extreme-Auth-Source Non-Service 2 | |
73 | ||
21 | 74 | END-VENDOR Aerohive |
0 | 0 | # -*- text -*- |
1 | # Copyright (C) 2019 The FreeRADIUS Server project and contributors | |
1 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors | |
2 | 2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 |
3 | # | |
3 | # Version $Id$ | |
4 | 4 | ############################################################################## |
5 | 5 | # |
6 | 6 | # Arista VSAs |
7 | # https://eos.arista.com/common-aaa-requirements/ | |
7 | 8 | # |
8 | 9 | ############################################################################## |
9 | 10 | |
14 | 15 | ATTRIBUTE Arista-User-Priv-Level 2 integer |
15 | 16 | ATTRIBUTE Arista-User-Role 3 string |
16 | 17 | ATTRIBUTE Arista-CVP-Role 4 string |
18 | ATTRIBUTE Arista-Command 5 string | |
19 | ATTRIBUTE Arista-WebAuth 6 integer | |
20 | ATTRIBUTE Arista-BlockMac 7 string | |
21 | ATTRIBUTE Arista-UnblockMac 8 string | |
22 | ATTRIBUTE Arista-PortFlap 9 integer | |
23 | ||
24 | VALUE Arista-WebAuth start 0 | |
25 | VALUE Arista-WebAuth complete 1 | |
17 | 26 | |
18 | 27 | END-VENDOR Arista |
0 | 0 | # -*- text -*- |
1 | # Copyright (C) 2019 The FreeRADIUS Server project and contributors | |
1 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors | |
2 | 2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 |
3 | # Version $Id$ | |
3 | 4 | # |
4 | 5 | # Version: $Id$ |
5 | 6 | # |
41 | 42 | ATTRIBUTE Aruba-WorkSpace-App-Name 31 string |
42 | 43 | ATTRIBUTE Aruba-Mdps-Provisioning-Settings 32 string |
43 | 44 | ATTRIBUTE Aruba-Mdps-Device-Profile 33 string |
44 | ||
45 | 45 | ATTRIBUTE Aruba-AP-IP-Address 34 ipaddr |
46 | ||
47 | 46 | ATTRIBUTE Aruba-AirGroup-Shared-Group 35 string |
48 | 47 | ATTRIBUTE Aruba-User-Group 36 string |
49 | 48 | ATTRIBUTE Aruba-Network-SSO-Token 37 string |
50 | 49 | ATTRIBUTE Aruba-AirGroup-Version 38 integer |
51 | ||
50 | ATTRIBUTE Aruba-Auth-SurvMethod 39 integer | |
52 | 51 | ATTRIBUTE Aruba-Port-Bounce-Host 40 integer |
53 | 52 | |
54 | 53 | ATTRIBUTE Aruba-Calea-Server-Ip 41 ipaddr |
55 | ||
56 | 54 | ATTRIBUTE Aruba-Admin-Path 42 string |
57 | 55 | ATTRIBUTE Aruba-Captive-Portal-URL 43 string |
58 | 56 | ATTRIBUTE Aruba-MPSK-Passphrase 44 octets encrypt=2 |
59 | 57 | ATTRIBUTE Aruba-ACL-Server-Query-Info 45 string |
60 | 58 | ATTRIBUTE Aruba-Command-String 46 string |
59 | ATTRIBUTE Aruba-Network-Profile 47 string | |
60 | ATTRIBUTE Aruba-Admin-Device-Group 48 string | |
61 | ATTRIBUTE Aruba-PoE-Priority 49 integer | |
62 | ATTRIBUTE Aruba-Port-Auth-Mode 50 integer | |
63 | ||
64 | ATTRIBUTE Aruba-NAS-Filter-Rule 51 string | |
65 | ATTRIBUTE Aruba-QoS-Trust-Mode 52 integer | |
66 | ATTRIBUTE Aruba-UBT-Gateway-Role 53 string | |
67 | ATTRIBUTE Aruba-Gateway-Zone 54 string | |
61 | 68 | |
62 | 69 | VALUE Aruba-AirGroup-Device-Type Personal-Device 1 |
63 | 70 | VALUE Aruba-AirGroup-Device-Type Shared-Device 2 |
66 | 73 | VALUE Aruba-AirGroup-Version AirGroup-v1 1 |
67 | 74 | VALUE Aruba-AirGroup-Version AirGroup-v2 2 |
68 | 75 | |
76 | VALUE Aruba-PoE-Priority Critical 0 | |
77 | VALUE Aruba-PoE-Priority High 1 | |
78 | VALUE Aruba-PoE-Priority Low 2 | |
79 | ||
80 | VALUE Aruba-Port-Auth-Mode Infrastructure-Mode 1 | |
81 | VALUE Aruba-Port-Auth-Mode Client-Mode 2 | |
82 | ||
83 | VALUE Aruba-QoS-Trust-Mode DSCP 0 | |
84 | VALUE Aruba-QoS-Trust-Mode QoS 1 | |
85 | VALUE Aruba-QoS-Trust-Mode None 2 | |
86 | ||
69 | 87 | END-VENDOR Aruba |
0 | 0 | # -*- text -*- |
1 | # Copyright (C) 2019 The FreeRADIUS Server project and contributors | |
1 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors | |
2 | 2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 |
3 | # Version $Id$ | |
3 | 4 | # |
4 | 5 | # Juniper's (was Unisphere's) broadband RAS |
5 | 6 | # From Terje Krogdahl <tekr@nextra.com> |
227 | 228 | ATTRIBUTE ERX-Client-Profile-Name 174 string |
228 | 229 | ATTRIBUTE ERX-Redirect-GW-Address 175 ipaddr |
229 | 230 | ATTRIBUTE ERX-APN-Name 176 string |
231 | ATTRIBUTE ERX-Cos-Shaping-Rate 177 string | |
230 | 232 | |
231 | 233 | ATTRIBUTE ERX-Service-Volume-Gigawords 179 integer |
232 | 234 | ATTRIBUTE ERX-Update-Service 180 string |
258 | 260 | ATTRIBUTE ERX-DHCPv6-Header 209 octets |
259 | 261 | ATTRIBUTE ERX-Acct-Request-Reason 210 integer |
260 | 262 | |
263 | ATTRIBUTE ERX-Inner-Tag-Protocol-Id 211 octets | |
264 | ATTRIBUTE ERX-Routing-Services 212 integer | |
265 | ATTRIBUTE ERX-Interface-Set-Targeting-Weight 213 integer | |
266 | ATTRIBUTE ERX-Interface-Targeting-Weight 214 integer | |
267 | ATTRIBUTE ERX-Hybrid-Access-DSL-Downstream-Speed 216 integer | |
268 | ATTRIBUTE ERX-Hybrid-Access-LTE-Downstream-Speed 217 integer | |
269 | ||
270 | ATTRIBUTE ERX-PON-Access-Type 219 integer | |
271 | ATTRIBUTE ERX-ONT-ONU-Average-Data-Rate-Downstream 220 integer | |
272 | ATTRIBUTE ERX-ONT-ONU-Peak-Data-Rate-Downstream 221 integer | |
273 | ATTRIBUTE ERX-ONT-ONU-Maximum-Data-Rate-Upstream 222 integer | |
274 | ATTRIBUTE ERX-ONT-ONU-Assured-Data-Rate-Upstream 223 integer | |
275 | ATTRIBUTE ERX-PON-Tree-Maximum-Data-Rate-Upstream 224 integer | |
276 | ATTRIBUTE ERX-PON-Tree-Maximum-Data-Rate-Downstream 225 integer | |
277 | ||
278 | ATTRIBUTE ERX-Expected-Throughput-Upstream 226 integer | |
279 | ATTRIBUTE ERX-Expected-Throughput-Downstream 227 integer | |
280 | ATTRIBUTE ERX-Attainable-Expected-Throughput-Upstream 228 integer | |
281 | ATTRIBUTE ERX-Attainable-Expected-Throughput-Downstream 229 integer | |
282 | ATTRIBUTE ERX-Gamma-Data-Rate-Upstream 230 integer | |
283 | ATTRIBUTE ERX-Gamma-Data-Rate-Downstream 231 integer | |
284 | ATTRIBUTE ERX-Attainable-Gamma-Data-Rate-Upstream 232 integer | |
285 | ATTRIBUTE ERX-Attainable-Gamma-Data-Rate-Downstream 233 integer | |
286 | ||
261 | 287 | # |
262 | 288 | # Values Attribute Name Number |
263 | 289 | # |
392 | 418 | VALUE ERX-Acct-Request-Reason Address-Assignment-Change 512 |
393 | 419 | VALUE ERX-Acct-Request-Reason CoA-Complete 1024 |
394 | 420 | |
421 | VALUE ERX-Routing-Services disabled 0 | |
422 | VALUE ERX-Routing-Services enabled 1 | |
423 | ||
424 | VALUE ERX-PON-Access-Type Other 0 | |
425 | VALUE ERX-PON-Access-Type GPON 1 | |
426 | VALUE ERX-PON-Access-Type XG-PON1 2 | |
427 | VALUE ERX-PON-Access-Type TWDM-PON 3 | |
428 | VALUE ERX-PON-Access-Type XGS-PON 4 | |
429 | VALUE ERX-PON-Access-Type WDM-PON 5 | |
430 | VALUE ERX-PON-Access-Type UNKNOWN 7 | |
431 | ||
395 | 432 | END-VENDOR ERX |
4 | 4 | ############################################################################## |
5 | 5 | # |
6 | 6 | # Fortinet's VSA's |
7 | # As posted to the list by Richie Lee. | |
7 | # | |
8 | # 2019-0502 | |
8 | 9 | # |
9 | 10 | # $Id$ |
10 | 11 | # |
23 | 24 | ATTRIBUTE Fortinet-Client-IPv6-Address 4 octets |
24 | 25 | ATTRIBUTE Fortinet-Interface-Name 5 string |
25 | 26 | ATTRIBUTE Fortinet-Access-Profile 6 string |
26 | ||
27 | # | |
28 | # Integer Translations | |
29 | # | |
27 | ATTRIBUTE Fortinet-SSID 7 string | |
28 | ATTRIBUTE Fortinet-AP-Name 8 string | |
29 | ATTRIBUTE Fortinet-FAC-Auth-Status 11 string | |
30 | ATTRIBUTE Fortinet-FAC-Token-ID 12 string | |
31 | ATTRIBUTE Fortinet-FAC-Challenge-Code 15 string | |
32 | ATTRIBUTE Fortinet-Webfilter-Category-Allow 16 octets | |
33 | ATTRIBUTE Fortinet-Webfilter-Category-Block 17 octets | |
34 | ATTRIBUTE Fortinet-Webfilter-Category-Monitor 18 octets | |
35 | ATTRIBUTE Fortinet-AppCtrl-Category-Allow 19 octets | |
36 | ATTRIBUTE Fortinet-AppCtrl-Category-Block 20 octets | |
37 | ATTRIBUTE Fortinet-AppCtrl-Risk-Allow 21 octets | |
38 | ATTRIBUTE Fortinet-AppCtrl-Risk-Block 22 octets | |
39 | ATTRIBUTE Fortinet-WirelessController-Device-MAC 23 ether | |
40 | ATTRIBUTE Fortinet-WirelessController-WTP-ID 24 string | |
41 | ATTRIBUTE Fortinet-WirelessController-Assoc-Time 25 date | |
42 | ATTRIBUTE Fortinet-FortiWAN-AVPair 26 string | |
43 | ATTRIBUTE Fortinet-FDD-Access-Profile 30 string | |
44 | ATTRIBUTE Fortinet-FDD-Trusted-Hosts 31 string | |
45 | ATTRIBUTE Fortinet-FDD-SPP-Name 32 string | |
46 | ATTRIBUTE Fortinet-FDD-Is-System-Admin 33 string | |
47 | ATTRIBUTE Fortinet-FDD-Is-SPP-Admin 34 string | |
48 | ATTRIBUTE Fortinet-FDD-SPP-Policy-Group 35 string | |
49 | ATTRIBUTE Fortinet-FDD-Allow-API-Access 36 string | |
50 | ATTRIBUTE Fortinet-Fpc-User-Role 40 string | |
51 | ATTRIBUTE Fortinet-Tenant-Identification 41 string | |
30 | 52 | |
31 | 53 | END-VENDOR Fortinet |
524 | 524 | ATTRIBUTE TLS-Cert-Subject-Alt-Name-Email 1915 string |
525 | 525 | ATTRIBUTE TLS-Cert-Subject-Alt-Name-Dns 1916 string |
526 | 526 | ATTRIBUTE TLS-Cert-Subject-Alt-Name-Upn 1917 string |
527 | # 1918 - 1919: reserved for future cert attributes | |
527 | ATTRIBUTE TLS-Cert-Valid-Since 1918 string | |
528 | # 1919: reserved for future cert attribute | |
528 | 529 | ATTRIBUTE TLS-Client-Cert-Serial 1920 string |
529 | 530 | ATTRIBUTE TLS-Client-Cert-Expiration 1921 string |
530 | 531 | ATTRIBUTE TLS-Client-Cert-Issuer 1922 string |
540 | 541 | ATTRIBUTE TLS-Client-Cert-Subject-Alt-Name-Upn 1932 string |
541 | 542 | ATTRIBUTE TLS-PSK-Identity 1933 string |
542 | 543 | ATTRIBUTE TLS-Client-Cert-X509v3-Extended-Key-Usage-OID 1936 string |
543 | ||
544 | # 1937 - 1939: reserved for future cert attributes | |
544 | ATTRIBUTE TLS-Client-Cert-Valid-Since 1937 string | |
545 | ||
546 | # 1938 - 1939: reserved for future cert attributes | |
545 | 547 | |
546 | 548 | # 1940 - 1949: reserved for TLS session caching, mostly in 4.0 |
547 | 549 |
0 | # -*- text -*- | |
1 | # Copyright (C) 2019 The FreeRADIUS Server project and contributors | |
2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 | |
3 | # | |
4 | # From https://support.sonus.net/display/UXDOC50/Vendor+Specific+Attributes+Reference | |
5 | ||
6 | VENDOR NET 177 | |
7 | ||
8 | BEGIN-VENDOR NET | |
9 | ||
10 | # MSC/Media related attributes | |
11 | ATTRIBUTE NET-Fwd-Flow-In-Realm 11 string # unsupported | |
12 | ATTRIBUTE NET-Fwd-Flow-In-Src-Addr 12 string | |
13 | ATTRIBUTE NET-Fwd-Flow-In-Src-Port 13 integer | |
14 | ATTRIBUTE NET-Fwd-Flow-In-Dst-Addr 14 string | |
15 | ATTRIBUTE NET-Fwd-Flow-In-Dst-Port 15 integer | |
16 | ATTRIBUTE NET-Fwd-Flow-Out-Realm 16 string # unsupported | |
17 | ATTRIBUTE NET-Fwd-Flow-Out-Src-Addr 17 string | |
18 | ATTRIBUTE NET-Fwd-Flow-Out-Src-Port 18 integer | |
19 | ATTRIBUTE NET-Fwd-Flow-Out-Dst-Addr 19 string | |
20 | ATTRIBUTE NET-Fwd-Flow-Out-Dst-Port 20 integer | |
21 | ATTRIBUTE NET-Bwd-Flow-In-Realm 21 string # unsupported | |
22 | ATTRIBUTE NET-Bwd-Flow-In-Src-Addr 22 string | |
23 | ATTRIBUTE NET-Bwd-Flow-In-Src-Port 23 integer | |
24 | ATTRIBUTE NET-Bwd-Flow-In-Dst-Addr 24 string | |
25 | ATTRIBUTE NET-Bwd-Flow-In-Dst-Port 25 integer | |
26 | ATTRIBUTE NET-Bwd-Flow-Out-Realm 26 string # unsupported | |
27 | ATTRIBUTE NET-Bwd-Flow-Out-Src-Addr 27 string | |
28 | ATTRIBUTE NET-Bwd-Flow-Out-Src-Port 28 integer | |
29 | ATTRIBUTE NET-Bwd-Flow-Out-Dst-Addr 29 string | |
30 | ATTRIBUTE NET-Bwd-Flow-Out-Dst-Port 30 integer | |
31 | ATTRIBUTE NET-Fwd-Flow-Media-Type 31 string | |
32 | ATTRIBUTE NET-Fwd-Flow-PTime 32 integer | |
33 | ATTRIBUTE NET-Fwd-Octets 33 integer | |
34 | ATTRIBUTE NET-Fwd-Packets 34 integer | |
35 | ATTRIBUTE NET-Fwd-RTCP-Packets-Lost 35 integer # future | |
36 | ATTRIBUTE NET-Fwd-RTCP-Avg-Jitter 36 integer # future | |
37 | ATTRIBUTE NET-Fwd-RTP-Avg-Latency 37 integer | |
38 | ATTRIBUTE NET-Fwd-RTCP-MaxJitter 38 integer # future | |
39 | ATTRIBUTE NET-Fwd-RTP-MaxLatency 39 integer | |
40 | ATTRIBUTE NET-Fwd-RTP-Packets-Lost 40 integer | |
41 | ATTRIBUTE NET-Fwd-RTP-Avg-Jitter 41 integer | |
42 | ATTRIBUTE NET-Fwd-RTP-MaxJitter 42 integer | |
43 | ATTRIBUTE NET-Bwd-Octets 43 integer | |
44 | ATTRIBUTE NET-Bwd-Packets 44 integer | |
45 | ATTRIBUTE NET-Bwd-RTCP-Packets-Lost 45 integer # future | |
46 | ATTRIBUTE NET-Bwd-RTCP-Avg-Jitter 46 integer # future | |
47 | ATTRIBUTE NET-Bwd-RTP-Avg-Latency 47 integer | |
48 | ATTRIBUTE NET-Bwd-RTCP-MaxJitter 48 integer # future | |
49 | ATTRIBUTE NET-Bwd-RTP-MaxLatency 49 integer | |
50 | ATTRIBUTE NET-Bwd-RTP-Packets-Lost 50 integer | |
51 | ATTRIBUTE NET-Bwd-RTP-Avg-Jitter 51 integer | |
52 | ATTRIBUTE NET-Bwd-RTP-MaxJitter 52 integer | |
53 | ||
54 | # Generic Session and Signaling Group related metrics | |
55 | ATTRIBUTE NET-Session-Ingress-CallId 60 integer | |
56 | ATTRIBUTE NET-Session-Egress-CallId 61 integer | |
57 | ATTRIBUTE NET-Session-Generic-Id 62 integer | |
58 | ATTRIBUTE NET-Routing-Table-Number 63 integer | |
59 | ATTRIBUTE NET-Ingress-Signaling-Group 64 integer | |
60 | ATTRIBUTE NET-Egress-Signaling-Group 65 integer | |
61 | ATTRIBUTE NET-Primary-Routing-Number 66 string | |
62 | ATTRIBUTE NET-Egress-Final-Routing-Num 67 string | |
63 | ATTRIBUTE NET-Ingress-Channel-Number 68 integer | |
64 | ATTRIBUTE NET-Egress-Channel-Number 69 integer | |
65 | ATTRIBUTE NET-Call-Type 70 integer | |
66 | ATTRIBUTE NET-Call-Origin 71 integer | |
67 | ATTRIBUTE NET-Calling-Number 72 string | |
68 | ATTRIBUTE NET-Called-Number 73 string | |
69 | ATTRIBUTE NET-Calling-Name 74 string | |
70 | ATTRIBUTE NET-Disconnect-Cause 75 integer | |
71 | ATTRIBUTE NET-Abort-Cause 76 integer | |
72 | ATTRIBUTE NET-Ingress-Channel-Id 77 string | |
73 | ATTRIBUTE NET-Egress-Channel-Id 78 string | |
74 | ATTRIBUTE NET-Call-Priority 79 string | |
75 | ||
76 | # Generic Call related attributes | |
77 | ATTRIBUTE NET-Call-Number-Type 90 string | |
78 | ATTRIBUTE NET-Call-Plan 91 string | |
79 | ATTRIBUTE NET-Original-Called-Number 92 string | |
80 | ATTRIBUTE NET-Original-Called-Type 93 string | |
81 | ATTRIBUTE NET-Original-Called-Plan 94 string | |
82 | ATTRIBUTE NET-Called-Name 95 string | |
83 | ATTRIBUTE NET-Namespace 96 string | |
84 | ATTRIBUTE NET-Precedence 97 string | |
85 | ATTRIBUTE NET-Presentation 98 string | |
86 | ATTRIBUTE NET-Screening 99 string | |
87 | ATTRIBUTE NET-Transfer-Capability 100 string | |
88 | ATTRIBUTE NET-Transfer-Mode 101 string | |
89 | ATTRIBUTE NET-Transfer-Rate 102 string | |
90 | ATTRIBUTE NET-User-Rate 103 string | |
91 | ||
92 | # Generic time related attributes | |
93 | ATTRIBUTE NET-Setup-Time 110 string | |
94 | ATTRIBUTE NET-Alert-Time 111 string | |
95 | ATTRIBUTE NET-Connect-Time 112 string | |
96 | ATTRIBUTE NET-Disconnect-Time 113 string | |
97 | ATTRIBUTE NET-Inbound-Seize-Time 114 string | |
98 | ATTRIBUTE NET-Outbound-Seize-Time 115 string | |
99 | ATTRIBUTE NET-Call-Duration 116 integer | |
100 | ATTRIBUTE NET-Post-Dial-Delay 117 integer | |
101 | ATTRIBUTE NET-Disconnect-Initiator 118 integer | |
102 | ||
103 | # SIP related | |
104 | ATTRIBUTE NET-P-Asserted-ID 130 string | |
105 | ATTRIBUTE NET-SIP-Diversion 131 string | |
106 | ATTRIBUTE NET-Ingress-Local-Addr 132 string | |
107 | ATTRIBUTE NET-Ingress-Remote-Addr 133 string | |
108 | ATTRIBUTE NET-Egress-Local-Addr 134 string | |
109 | ATTRIBUTE NET-Egress-Remote-Addr 135 string | |
110 | ATTRIBUTE NET-Ingress-Net-Interface-Id 136 integer | |
111 | ATTRIBUTE NET-Egress-Net-Interface-Id 137 integer | |
112 | ATTRIBUTE NET-Refer-Call-Transfer-Id 138 string | |
113 | ATTRIBUTE NET-Session-Forked-Call-Id 139 string | |
114 | ATTRIBUTE NET-Redirect-Number 140 string | |
115 | ATTRIBUTE NET-Redirect-Ip-Address 141 string | |
116 | ATTRIBUTE NET-Session-Ingress-Realm 142 string | |
117 | ATTRIBUTE NET-Session-Egress-Realm 143 string | |
118 | ATTRIBUTE NET-Ingress-Signaling-Port-Num 144 integer | |
119 | ATTRIBUTE NET-Egress-Signaling-Port-Num 145 integer | |
120 | ATTRIBUTE NET-Transport-Type 146 integer | |
121 | ATTRIBUTE NET-P-Preferred-ID 147 string | |
122 | ATTRIBUTE NET-Replaced-Header 148 string | |
123 | ||
124 | # Generic parameters | |
125 | ATTRIBUTE NET-Firmware-Version 160 string | |
126 | ATTRIBUTE NET-Local-Time-Zone 161 string | |
127 | ATTRIBUTE NET-Gw-Id 162 string | |
128 | ATTRIBUTE NET-Time-And-Day 163 string | |
129 | ATTRIBUTE NET-Log-Time 164 string | |
130 | ||
131 | END-VENDOR NET |
0 | # -*- text -*- | |
1 | # Copyright (C) 2019 The FreeRADIUS Server project and contributors | |
2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 | |
3 | # Version $Id$ | |
4 | # | |
5 | # Pica8 RADIUS attributes | |
6 | # For general information please visit: | |
7 | # http://www.pica8.com | |
8 | # | |
9 | ||
10 | VENDOR Pica8 35098 | |
11 | ||
12 | BEGIN-VENDOR Pica8 | |
13 | ||
14 | ATTRIBUTE Pica8-AVPair 1 string | |
15 | ATTRIBUTE Pica8-IP-Downloadable-ACL-Rule 2 string | |
16 | ATTRIBUTE Pica8-IP-Downloadable-ACL-Name 3 string | |
17 | ATTRIBUTE Pica8-Redirect-URL 4 string | |
18 | ||
19 | END-VENDOR Pica8 |
0 | # -*- text -*- | |
1 | # Copyright (C) 2019 The FreeRADIUS Server project and contributors | |
2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 | |
3 | # Version $Id$ | |
4 | ########################################################### | |
5 | # Resilient Cloud Network Technologies (RCNTEC) | |
6 | # Dictionary for RCNTEC's RPCM hardware, https://rpcm.pro | |
7 | # Contributed by Sergey Minakov <ser@rcntec.com> | |
8 | # | |
9 | # | |
10 | ########################################################### | |
11 | ||
12 | VENDOR RCNTEC 46235 | |
13 | BEGIN-VENDOR RCNTEC | |
14 | ||
15 | ATTRIBUTE RCNTEC-RPCM-Group 1 string | |
16 | ATTRIBUTE RCNTEC-RPCM-Session-Expire 2 integer | |
17 | ||
18 | END-VENDOR RCNTEC |
0 | # -*- text -*- | |
1 | # Copyright (C) 2020 The FreeRADIUS Server project and contributors | |
2 | # This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0 | |
3 | # Version $Id$ | |
4 | # | |
5 | # VAS Experts dictionary | |
6 | # | |
7 | VENDOR VasExperts 43823 | |
8 | ||
9 | BEGIN-VENDOR VasExperts | |
10 | ||
11 | ATTRIBUTE VasExperts-Policing-Profile 1 string | |
12 | ATTRIBUTE VasExperts-Service-Profile 2 string | |
13 | ATTRIBUTE VasExperts-Enable-Service 3 string | |
14 | ATTRIBUTE VasExperts-Multi-IP-User 4 integer | |
15 | ATTRIBUTE VasExperts-UserName 5 string | |
16 | ATTRIBUTE VasExperts-Service-Type 6 integer | |
17 | ATTRIBUTE VasExperts-Restrict-User 7 integer | |
18 | ATTRIBUTE VasExperts-Enable-Interconnect 8 integer | |
19 | ATTRIBUTE VasExperts-OutVLAN 9 integer | |
20 | ATTRIBUTE VasExperts-Command-Code 10 integer # CoA command code | |
21 | ATTRIBUTE VasExperts-OutMAC 11 string | |
22 | ||
23 | VALUE VasExperts-Service-Type Auth 0 # L3-authorization, known IP | |
24 | VALUE VasExperts-Service-Type DHCP 1 # DHCP | |
25 | VALUE VasExperts-Service-Type PAP 2 # PAP authorization | |
26 | VALUE VasExperts-Service-Type CHAP 3 # CHAP authorization | |
27 | VALUE VasExperts-Service-Type MS_CHAPv2 4 # MS-CHAPv2 authorization | |
28 | VALUE VasExperts-Service-Type MAC_QinQ 5 # MAC/QinQ authorization | |
29 | VALUE VasExperts-Service-Type ARP 6 # ARP | |
30 | VALUE VasExperts-Service-Type DHCPv6 7 # DHCPv6 | |
31 | ||
32 | VALUE VasExperts-Command-Code Check-Acct 1 # Check Accounting session for Framed-IP-Address | |
33 | ||
34 | # Accounting | |
35 | ATTRIBUTE VasExperts-Acct-Traffic-Class-Name 16 string | |
36 | ATTRIBUTE VasExperts-Acct-Traffic-Class-Input-Octets 17 integer64 | |
37 | ATTRIBUTE VasExperts-Acct-Traffic-Class-Output-Octets 18 integer64 | |
38 | ATTRIBUTE VasExperts-Acct-Traffic-Class-Input-Packets 19 integer64 | |
39 | ATTRIBUTE VasExperts-Acct-Traffic-Class-Output-Packets 20 integer64 | |
40 | ATTRIBUTE VasExperts-NAT-IP 21 ipaddr # NAT 1:1 white address | |
41 | ||
42 | # DHCP -> Radius attributes | |
43 | ATTRIBUTE VasExperts-DHCP-Hostname 32 octets # DHCP Opt12 | |
44 | ATTRIBUTE VasExperts-DHCP-ClientId 33 octets # DHCP Opt61 | |
45 | ATTRIBUTE VasExperts-DHCP-ClassId 34 octets # DHCP Opt60 | |
46 | ATTRIBUTE VasExperts-DHCP-RelayInfo 35 octets # DHCP Opt82 | |
47 | ATTRIBUTE VasExperts-DHCP-ClientIP 36 ipaddr # DHCP Opt50 | |
48 | ATTRIBUTE VasExperts-DHCP-Request 37 integer | |
49 | ATTRIBUTE VasExperts-DHCP-RelayRemoteId 38 octets # DHCP Opt82 subopt 2 | |
50 | ATTRIBUTE VasExperts-DHCP-RelayCircuitId 39 octets # DHCP Opt82 subopt 1 | |
51 | ||
52 | VALUE VasExperts-DHCP-Request Discover 0 | |
53 | VALUE VasExperts-DHCP-Request Inform 1 | |
54 | VALUE VasExperts-DHCP-Request Request 2 | |
55 | ||
56 | # Radius -> DHCP (Access-Accept, Access-Reject) | |
57 | ATTRIBUTE VasExperts-DHCP-Option 40 octets # Any DHCP option in binary form | |
58 | ATTRIBUTE VasExperts-DHCP-DNS 41 ipaddr # DNS IP address | |
59 | ATTRIBUTE VasExperts-DHCP-Gateway 42 ipaddr # Gateway IP address | |
60 | ATTRIBUTE VasExperts-BOOTP-SName 43 string # BOOTP SName | |
61 | ATTRIBUTE VasExperts-BOOTP-File 44 string # BOOTP File | |
62 | ATTRIBUTE VasExperts-DHCP-Option-IP 45 string # IPv4 option: "opt:192.168.6.90", for example: "42:192.168.6.90" | |
63 | ATTRIBUTE VasExperts-DHCP-Option-Num 46 string # Numeric option: "opt:1500", for example: "58:3600" | |
64 | ATTRIBUTE VasExperts-DHCP-Option-String 47 string # String option: "opt:text", for example: "56:Hello from DHCP!" | |
65 | ATTRIBUTE VasExperts-DHCP-Option-Bin 48 string # Binary option in hex form: "opt:xxxxxxxx", for example: "58:100E" | |
66 | ||
67 | ATTRIBUTE VasExperts-ARP-SourceIP 60 ipaddr # ARP source IP | |
68 | ATTRIBUTE VasExperts-ARP-TargetIP 61 ipaddr # ARP target IP | |
69 | ||
70 | # DHCPv6 -> Radius attributes | |
71 | ATTRIBUTE VasExperts-DHCPv6-Request 70 integer # DHCPv6 request type | |
72 | ATTRIBUTE VasExperts-DHCPv6-UserClass 71 octets # DHCPv6 User Class option | |
73 | ATTRIBUTE VasExperts-DHCPv6-VendorClass 72 octets # DHCPv6 Vendor Class option | |
74 | ATTRIBUTE VasExperts-DHCPv6-RemoteId 73 octets # DHCPv6 RemoteId option [RFC 4649] | |
75 | ATTRIBUTE VasExperts-DHCPv6-SubsId 74 octets # DHCPv6 SubscriberId option [RFC 4580] | |
76 | ATTRIBUTE VasExperts-DHCPv6-Delegated 75 integer # DHCPv6 flag: (1) - CPE requests delegated prefix, (0) - does not | |
77 | ||
78 | # Radius -> DHCPv6 attributes | |
79 | ATTRIBUTE VasExperts-DHCP-Option-IPv6 80 string # IPv6 option: "opt:2001:fde3::709", for example: "22:2001:fde3::709" | |
80 | ATTRIBUTE VasExperts-DHCP-Option-IPv6-Prefix 81 string # IPv6 prefix option: "opt:2001:fde3/64" | |
81 | ATTRIBUTE VasExperts-DHCP6-Option-Num 82 string # DHCPv6 numeric option: "opt:1500", for example: "58:3600" | |
82 | ATTRIBUTE VasExperts-DHCP6-Option-String 83 string # DHCPv6 string option: "opt:text", for example: "56:Hello from DHCP!" | |
83 | ATTRIBUTE VasExperts-DHCP6-Option-Bin 84 string # DHCPv6 binary option in hex form: "opt:xxxxxxxx", for example: "58:100E" | |
84 | ||
85 | VALUE VasExperts-DHCPv6-Request Solicit 1 | |
86 | VALUE VasExperts-DHCPv6-Request Request 3 | |
87 | VALUE VasExperts-DHCPv6-Request Renew 5 | |
88 | VALUE VasExperts-DHCPv6-Request Rebind 6 | |
89 | ||
90 | # Attributes 250 - 255 are dedicated to the customer's private use and are not used (ignored) by pcrf | |
91 | ||
92 | END-VENDOR VasExperts |
66 | 66 | ATTRIBUTE WiMAX-Accounting-Capabilities 1.2 byte |
67 | 67 | ATTRIBUTE WiMAX-Hotlining-Capabilities 1.3 byte |
68 | 68 | ATTRIBUTE WiMAX-Idle-Mode-Notification-Cap 1.4 byte |
69 | ATTRIBUTE WiMAX-ASN-IP-Service-Capabilities 1.5 byte | |
70 | ATTRIBUTE WiMAX-VCSN-IP-Service-Capabilities 1.6 byte | |
71 | ATTRIBUTE WiMAX-Authorized-IP-Services 1.7 byte | |
72 | ATTRIBUTE WiMAX-Authorized-Anchor-Locations 1.8 byte | |
73 | ATTRIBUTE WiMAX-ASN-Ethernet-Service-Capabilities 1.9 byte | |
74 | ATTRIBUTE WiMAX-VCSN-Ethernet-Service-Capabilities 1.10 byte | |
75 | ATTRIBUTE WiMAX-Authorized-Ethernet-Services 1.11 byte | |
69 | 76 | |
70 | 77 | # This is really a bitmap |
71 | 78 | VALUE WiMAX-Accounting-Capabilities No-Accounting 0 |
81 | 88 | |
82 | 89 | VALUE WiMAX-Idle-Mode-Notification-Cap Not-Supported 0 |
83 | 90 | VALUE WiMAX-Idle-Mode-Notification-Cap Supported 1 |
91 | ||
92 | VALUE WiMAX-ASN-IP-Service-Capabilities DHCP-Relay 1 | |
93 | VALUE WiMAX-ASN-IP-Service-Capabilities DHCP-Proxy 2 | |
94 | VALUE WiMAX-ASN-IP-Service-Capabilities FA 4 | |
95 | VALUE WiMAX-ASN-IP-Service-Capabilities PMIP-Client 8 | |
96 | ||
97 | VALUE WiMAX-ASN-Ethernet-Service-Capabilities eAFF-IPv4-Transport 1 | |
98 | VALUE WiMAX-ASN-Ethernet-Service-Capabilities eAFF-IPv6-Transport 2 | |
99 | VALUE WiMAX-ASN-Ethernet-Service-Capabilities eFA 4 | |
100 | ||
101 | VALUE WiMAX-VCSN-Ethernet-Service-Capabilities eCFF-IPv4-Transport 1 | |
102 | VALUE WiMAX-VCSN-Ethernet-Service-Capabilities eCFF-IPv6-Transport 2 | |
103 | VALUE WiMAX-VCSN-Ethernet-Service-Capabilities eHAv4 4 | |
104 | VALUE WiMAX-VCSN-Ethernet-Service-Capabilities eHAv6 8 | |
84 | 105 | |
85 | 106 | ATTRIBUTE WiMAX-Device-Authentication-Indicator 2 byte |
86 | 107 | ATTRIBUTE WiMAX-GMT-Timezone-offset 3 signed |
502 | 502 | |
503 | 503 | /* Define to 1 if you have the <sys/prctl.h> header file. */ |
504 | 504 | #undef HAVE_SYS_PRCTL_H |
505 | ||
506 | /* Define to 1 if you have the <sys/procctl.h> header file. */ | |
507 | #undef HAVE_SYS_PROCCTL_H | |
505 | 508 | |
506 | 509 | /* Define to 1 if you have the <sys/ptrace.h> header file. */ |
507 | 510 | #undef HAVE_SYS_PTRACE_H |
12 | 12 | #define SRADUTMP LOGDIR "/sradutmp" |
13 | 13 | #define RADWTMP LOGDIR "/radwtmp" |
14 | 14 | #define SRADWTMP LOGDIR "/sradwtmp" |
15 | ||
16 | #ifdef __APPLE__ | |
17 | # define LT_SHREXT ".dylib" | |
18 | #elif defined (WIN32) | |
19 | # define LT_SHREXT ".dll" | |
20 | #else | |
21 | # define LT_SHREXT ".so" | |
22 | #endif |
415 | 415 | int rad_expand_xlat(REQUEST *request, char const *cmd, |
416 | 416 | int max_argc, char const *argv[], bool can_fail, |
417 | 417 | size_t argv_buflen, char *argv_buf); |
418 | void rad_tv_sub(struct timeval const *end, struct timeval const *start, struct timeval *elapsed); | |
418 | 419 | |
419 | 420 | void verify_request(char const *file, int line, REQUEST *request); /* only for special debug builds */ |
420 | 421 | void rad_mode_to_str(char out[10], mode_t mode); |
39 | 39 | |
40 | 40 | #ifdef HAVE_SYS_PRCTL_H |
41 | 41 | # include <sys/prctl.h> |
42 | #endif | |
43 | ||
44 | #ifdef HAVE_SYS_PROCCTL_H | |
45 | # include <sys/procctl.h> | |
42 | 46 | #endif |
43 | 47 | |
44 | 48 | #ifdef HAVE_SYS_PTRACE_H |
246 | 250 | return ret; |
247 | 251 | } |
248 | 252 | } |
253 | #elif defined(HAVE_SYS_PROCCTL_H) | |
254 | static int fr_get_debug_state(void) | |
255 | { | |
256 | int status; | |
257 | ||
258 | if (procctl(P_PID, getpid(), PROC_TRACE_STATUS, &status) == -1) { | |
259 | fr_strerror_printf("Cannot get dumpable flag: procctl(PROC_TRACE_STATUS) failed: %s", fr_syserror(errno)); | |
260 | return DEBUG_STATE_UNKNOWN; | |
261 | } | |
262 | ||
263 | /* | |
264 | * As FreeBSD docs say about "PROC_TRACE_STATUS": | |
265 | * | |
266 | * Returns the current tracing status for the specified process in the | |
267 | * integer variable pointed to by data. If tracing is disabled, data | |
268 | * is set to -1. If tracing is enabled, but no debugger is attached by | |
269 | * the ptrace(2) syscall, data is set to 0. If a debugger is attached, | |
270 | * data is set to the pid of the debugger process. | |
271 | */ | |
272 | if (status <= 0) return DEBUG_STATE_NOT_ATTACHED; | |
273 | ||
274 | return DEBUG_STATE_ATTACHED; | |
275 | } | |
249 | 276 | #else |
250 | 277 | static int fr_get_debug_state(void) |
251 | 278 | { |
473 | 500 | |
474 | 501 | return 0; |
475 | 502 | } |
503 | #elif defined(HAVE_SYS_PROCCTL_H) | |
504 | static int fr_set_dumpable_flag(bool dumpable) | |
505 | { | |
506 | int mode = dumpable ? PROC_TRACE_CTL_ENABLE : PROC_TRACE_CTL_DISABLE; | |
507 | ||
508 | if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &mode) == -1) { | |
509 | fr_strerror_printf("Cannot re-enable core dumps: procctl(PROC_TRACE_CTL) failed: %s", | |
510 | fr_syserror(errno)); | |
511 | return -1; | |
512 | } | |
513 | ||
514 | return 0; | |
515 | } | |
476 | 516 | #else |
477 | 517 | static int fr_set_dumpable_flag(UNUSED bool dumpable) |
478 | 518 | { |
499 | 539 | * Linux is crazy and prctl sometimes returns 2 for disabled |
500 | 540 | */ |
501 | 541 | if (ret != 1) return 0; |
542 | return 1; | |
543 | } | |
544 | #elif defined(HAVE_SYS_PROCCTL_H) | |
545 | static int fr_get_dumpable_flag(void) | |
546 | { | |
547 | int status; | |
548 | ||
549 | if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &status) == -1) { | |
550 | fr_strerror_printf("Cannot get dumpable flag: procctl(PROC_TRACE_CTL) failed: %s", fr_syserror(errno)); | |
551 | return -1; | |
552 | } | |
553 | ||
554 | /* | |
555 | * There are a few different kinds of disabled, but only | |
556 | * one ENABLE. | |
557 | */ | |
558 | if (status != PROC_TRACE_CTL_ENABLE) return 0; | |
559 | ||
502 | 560 | return 1; |
503 | 561 | } |
504 | 562 | #else |
2535 | 2535 | * BEGIN-VENDOR foo format=Foo-Encapsulation-Attr |
2536 | 2536 | */ |
2537 | 2537 | if (argc > 2) { |
2538 | if (strncmp(argv[2], "format=", 7) != 0) { | |
2538 | if ((strncmp(argv[2], "format=", 7) != 0) && | |
2539 | (strncmp(argv[2], "parent=", 7) != 0)) { | |
2539 | 2540 | fr_strerror_printf( |
2540 | 2541 | "dict_init: %s[%d]: Invalid format %s", |
2541 | 2542 | fn, line, argv[2]); |
100 | 100 | } |
101 | 101 | |
102 | 102 | if ((str[0] >= 0xf1) && /* 6 */ |
103 | (str[1] <= 0xf3) && | |
103 | (str[0] <= 0xf3) && | |
104 | 104 | (str[1] >= 0x80) && |
105 | 105 | (str[1] <= 0xbf) && |
106 | 106 | (str[2] >= 0x80) && |
209 | 209 | * to the global client list. |
210 | 210 | */ |
211 | 211 | subcs = cf_section_sub_find(cs, "listen"); |
212 | if (!subcs) goto global_clients; | |
212 | if (!subcs) { | |
213 | DEBUG("No 'listen' section in virtual server %s. Adding client to global client list", | |
214 | client->server); | |
215 | goto global_clients; | |
216 | } | |
213 | 217 | |
214 | 218 | /* |
215 | 219 | * If the client list already exists, use that. |
285 | 289 | } |
286 | 290 | |
287 | 291 | ERROR("Failed to add duplicate client %s", client->shortname); |
288 | client_free(client); | |
289 | 292 | return false; |
290 | 293 | } |
291 | 294 | #undef namecmp |
294 | 297 | * Other error adding client: likely is fatal. |
295 | 298 | */ |
296 | 299 | if (!rbtree_insert(clients->trees[client->ipaddr.prefix], client)) { |
297 | client_free(client); | |
298 | 300 | return false; |
299 | 301 | } |
300 | 302 |
2672 | 2672 | #ifdef WITH_STATS |
2673 | 2673 | static fr_command_table_t command_table_stats[] = { |
2674 | 2674 | { "client", FR_READ, |
2675 | "stats client [auth/acct] <ipaddr> [udp|tcp] [listen <ipaddr> <port>] " | |
2675 | "stats client [auth/acct/coa] <ipaddr> [udp|tcp] [listen <ipaddr> <port>] " | |
2676 | 2676 | "- show statistics for given client, or for all clients (auth or acct)", |
2677 | 2677 | command_stats_client, NULL }, |
2678 | 2678 |
122 | 122 | char const *filename; |
123 | 123 | CONF_SECTION *cs; |
124 | 124 | struct stat buf; |
125 | bool from_dir; | |
125 | 126 | } cf_file_t; |
126 | 127 | |
127 | 128 | CONF_SECTION *root_config = NULL; |
328 | 329 | if (stat(filename, &my_file.buf) < 0) goto error; |
329 | 330 | |
330 | 331 | file = rbtree_finddata(tree, &my_file); |
331 | if (file) return 0; | |
332 | if (file && !file->from_dir) return 0; | |
332 | 333 | } |
333 | 334 | |
334 | 335 | DEBUG2("including configuration file %s", filename); |
43 | 43 | #endif |
44 | 44 | |
45 | 45 | #define MAX_ARGV (256) |
46 | ||
47 | #define USEC 1000000 | |
48 | static void tv_sub(struct timeval *end, struct timeval *start, | |
49 | struct timeval *elapsed) | |
50 | { | |
51 | elapsed->tv_sec = end->tv_sec - start->tv_sec; | |
52 | if (elapsed->tv_sec > 0) { | |
53 | elapsed->tv_sec--; | |
54 | elapsed->tv_usec = USEC; | |
55 | } else { | |
56 | elapsed->tv_usec = 0; | |
57 | } | |
58 | elapsed->tv_usec += end->tv_usec; | |
59 | elapsed->tv_usec -= start->tv_usec; | |
60 | ||
61 | if (elapsed->tv_usec >= USEC) { | |
62 | elapsed->tv_usec -= USEC; | |
63 | elapsed->tv_sec++; | |
64 | } | |
65 | } | |
66 | ||
67 | 46 | |
68 | 47 | /** Start a process |
69 | 48 | * |
426 | 405 | FD_SET(fd, &fds); |
427 | 406 | |
428 | 407 | gettimeofday(&when, NULL); |
429 | tv_sub(&when, &start, &elapsed); | |
408 | rad_tv_sub(&when, &start, &elapsed); | |
430 | 409 | if (elapsed.tv_sec >= timeout) goto too_long; |
431 | 410 | |
432 | 411 | when.tv_sec = timeout; |
433 | 412 | when.tv_usec = 0; |
434 | tv_sub(&when, &elapsed, &wake); | |
413 | rad_tv_sub(&when, &elapsed, &wake); | |
435 | 414 | |
436 | 415 | rcode = select(fd + 1, &fds, NULL, NULL, &wake); |
437 | 416 | if (rcode == 0) { |
426 | 426 | } |
427 | 427 | |
428 | 428 | if (len < sizeof(buffer)) { |
429 | len += vsnprintf(buffer + len, sizeof(buffer) - len - 1, msg, ap); | |
429 | vsnprintf(buffer + len, sizeof(buffer) - len - 1, msg, ap); | |
430 | len += strlen(buffer + len); | |
430 | 431 | } |
431 | 432 | |
432 | 433 | /* |
94 | 94 | #define RTLD_LOCAL (0) |
95 | 95 | #endif |
96 | 96 | |
97 | #ifdef __APPLE__ | |
98 | # define LT_SHREXT ".dylib" | |
99 | #elif defined (WIN32) | |
100 | # define LT_SHREXT ".dll" | |
101 | #else | |
102 | # define LT_SHREXT ".so" | |
103 | #endif | |
104 | ||
105 | 97 | /** Check if the magic number in the module matches the one in the library |
106 | 98 | * |
107 | 99 | * This is used to detect potential ABI issues caused by running with modules which |
56 | 56 | rad_assert(bufsize > 0); |
57 | 57 | |
58 | 58 | next: |
59 | rad_assert(p < end); | |
60 | ||
59 | 61 | if (!c) { |
62 | p[0] = '\0'; | |
63 | return 0; | |
64 | } | |
65 | ||
66 | /* | |
67 | * Don't overflow the output buffer. | |
68 | */ | |
69 | if ((end - p) < 2) { | |
60 | 70 | p[0] = '\0'; |
61 | 71 | return 0; |
62 | 72 | } |
69 | 79 | case COND_TYPE_EXISTS: |
70 | 80 | rad_assert(c->data.vpt != NULL); |
71 | 81 | if (c->cast) { |
72 | len = snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types, | |
73 | c->cast->type, "??")); | |
74 | p += len; | |
82 | snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types, | |
83 | c->cast->type, "??")); | |
84 | p += strlen(p); | |
75 | 85 | } |
76 | 86 | |
77 | 87 | len = tmpl_prints(p, end - p, c->data.vpt, NULL); |
84 | 94 | *(p++) = '['; /* for extra-clear debugging */ |
85 | 95 | #endif |
86 | 96 | if (c->cast) { |
87 | len = snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types, | |
88 | c->cast->type, "??")); | |
89 | p += len; | |
97 | snprintf(p, end - p, "<%s>", fr_int2str(dict_attr_types, | |
98 | c->cast->type, "??")); | |
99 | p += strlen(p); | |
90 | 100 | } |
91 | 101 | |
92 | 102 | len = map_prints(p, end - p, c->data.map); |
2473 | 2473 | } |
2474 | 2474 | |
2475 | 2475 | old_server = request->server; |
2476 | rad_assert(request->home_server != NULL); | |
2477 | 2476 | |
2478 | 2477 | /* |
2479 | 2478 | * If the home server is virtual, just run pre_proxy from |
2480 | 2479 | * that section. |
2481 | 2480 | */ |
2482 | if (request->home_server->server) { | |
2481 | if (request->home_server && request->home_server->server) { | |
2483 | 2482 | request->server = request->home_server->server; |
2484 | 2483 | |
2485 | 2484 | } else { |
3180 | 3179 | } |
3181 | 3180 | |
3182 | 3181 | old_server = request->server; |
3183 | rad_assert(request->home_server != NULL); | |
3184 | 3182 | |
3185 | 3183 | /* |
3186 | 3184 | * If the home server is virtual, just run pre_proxy from |
3187 | 3185 | * that section. |
3188 | 3186 | */ |
3189 | if (request->home_server->server) { | |
3187 | if (request->home_server && request->home_server->server) { | |
3190 | 3188 | request->server = request->home_server->server; |
3191 | 3189 | |
3192 | 3190 | } else { |
123 | 123 | if (!cap) { |
124 | 124 | RDEBUG4("No subcapture data found"); |
125 | 125 | *out = NULL; |
126 | return 1; | |
126 | return -1; | |
127 | 127 | } |
128 | 128 | |
129 | 129 | ret = pcre_get_substring(cap->value, (int *)cap->rxmatch, (int)cap->nmatch, num, &p); |
181 | 181 | if (!cap) { |
182 | 182 | RDEBUG4("No subcapture data found"); |
183 | 183 | *out = NULL; |
184 | return 1; | |
184 | return -1; | |
185 | 185 | } |
186 | 186 | |
187 | 187 | ret = pcre_get_named_substring(cap->preg->compiled, cap->value, |
57 | 57 | #endif |
58 | 58 | #endif |
59 | 59 | |
60 | static void tv_sub(struct timeval *end, struct timeval *start, | |
61 | struct timeval *elapsed) | |
62 | { | |
63 | elapsed->tv_sec = end->tv_sec - start->tv_sec; | |
64 | if (elapsed->tv_sec > 0) { | |
65 | elapsed->tv_sec--; | |
66 | elapsed->tv_usec = USEC; | |
67 | } else { | |
68 | elapsed->tv_usec = 0; | |
69 | } | |
70 | elapsed->tv_usec += end->tv_usec; | |
71 | elapsed->tv_usec -= start->tv_usec; | |
72 | ||
73 | if (elapsed->tv_usec >= USEC) { | |
74 | elapsed->tv_usec -= USEC; | |
75 | elapsed->tv_sec++; | |
76 | } | |
77 | } | |
78 | ||
79 | 60 | static void stats_time(fr_stats_t *stats, struct timeval *start, |
80 | 61 | struct timeval *end) |
81 | 62 | { |
85 | 66 | if ((start->tv_sec == 0) || (end->tv_sec == 0) || |
86 | 67 | (end->tv_sec < start->tv_sec)) return; |
87 | 68 | |
88 | tv_sub(end, start, &diff); | |
69 | rad_tv_sub(end, start, &diff); | |
89 | 70 | |
90 | 71 | if (diff.tv_sec >= 10) { |
91 | 72 | stats->elapsed[7]++; |
1564 | 1564 | return 0; |
1565 | 1565 | } |
1566 | 1566 | |
1567 | #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) | |
1567 | #if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) | |
1568 | 1568 | static SSL_SESSION *cbtls_get_session(SSL *ssl, unsigned char *data, int len, int *copy) |
1569 | 1569 | #else |
1570 | 1570 | static SSL_SESSION *cbtls_get_session(SSL *ssl, const unsigned char *data, int len, int *copy) |
2064 | 2064 | /* |
2065 | 2065 | * For creating certificate attributes. |
2066 | 2066 | */ |
2067 | static char const *cert_attr_names[8][2] = { | |
2067 | static char const *cert_attr_names[9][2] = { | |
2068 | 2068 | { "TLS-Client-Cert-Serial", "TLS-Cert-Serial" }, |
2069 | 2069 | { "TLS-Client-Cert-Expiration", "TLS-Cert-Expiration" }, |
2070 | 2070 | { "TLS-Client-Cert-Subject", "TLS-Cert-Subject" }, |
2072 | 2072 | { "TLS-Client-Cert-Common-Name", "TLS-Cert-Common-Name" }, |
2073 | 2073 | { "TLS-Client-Cert-Subject-Alt-Name-Email", "TLS-Cert-Subject-Alt-Name-Email" }, |
2074 | 2074 | { "TLS-Client-Cert-Subject-Alt-Name-Dns", "TLS-Cert-Subject-Alt-Name-Dns" }, |
2075 | { "TLS-Client-Cert-Subject-Alt-Name-Upn", "TLS-Cert-Subject-Alt-Name-Upn" } | |
2075 | { "TLS-Client-Cert-Subject-Alt-Name-Upn", "TLS-Cert-Subject-Alt-Name-Upn" }, | |
2076 | { "TLS-Client-Cert-Valid-Since", "TLS-Cert-Valid-Since" } | |
2076 | 2077 | }; |
2077 | 2078 | |
2078 | 2079 | #define FR_TLS_SERIAL (0) |
2083 | 2084 | #define FR_TLS_SAN_EMAIL (5) |
2084 | 2085 | #define FR_TLS_SAN_DNS (6) |
2085 | 2086 | #define FR_TLS_SAN_UPN (7) |
2087 | #define FR_TLS_VALID_SINCE (8) | |
2086 | 2088 | |
2087 | 2089 | /* |
2088 | 2090 | * Before trusting a certificate, you must make sure that the |
2210 | 2212 | memcpy(buf, (char*) asn_time->data, asn_time->length); |
2211 | 2213 | buf[asn_time->length] = '\0'; |
2212 | 2214 | vp = fr_pair_make(talloc_ctx, certs, cert_attr_names[FR_TLS_EXPIRATION][lookup], buf, T_OP_SET); |
2215 | rdebug_pair(L_DBG_LVL_2, request, vp, NULL); | |
2216 | } | |
2217 | ||
2218 | /* | |
2219 | * Get the Valid Since Date | |
2220 | */ | |
2221 | buf[0] = '\0'; | |
2222 | asn_time = X509_get_notBefore(client_cert); | |
2223 | if (certs && (lookup <= 1) && asn_time && | |
2224 | (asn_time->length < (int) sizeof(buf))) { | |
2225 | memcpy(buf, (char*) asn_time->data, asn_time->length); | |
2226 | buf[asn_time->length] = '\0'; | |
2227 | vp = fr_pair_make(talloc_ctx, certs, cert_attr_names[FR_TLS_VALID_SINCE][lookup], buf, T_OP_SET); | |
2213 | 2228 | rdebug_pair(L_DBG_LVL_2, request, vp, NULL); |
2214 | 2229 | } |
2215 | 2230 | |
2359 | 2374 | if (*p == ' ') *p = '-'; |
2360 | 2375 | } |
2361 | 2376 | |
2362 | X509V3_EXT_print(out, ext, 0, 0); | |
2363 | len = BIO_read(out, value , sizeof(value) - 1); | |
2364 | if (len <= 0) continue; | |
2365 | ||
2366 | value[len] = '\0'; | |
2377 | if (X509V3_EXT_get(ext)) { /* Known extension, converting value into plain string */ | |
2378 | X509V3_EXT_print(out, ext, 0, 0); | |
2379 | len = BIO_read(out, value, sizeof(value) - 1); | |
2380 | if (len <= 0) continue; | |
2381 | value[len] = '\0'; | |
2382 | } else { | |
2383 | /* | |
2384 | * An extension not known to OpenSSL, dump it's value as a value of an unknown attribute. | |
2385 | */ | |
2386 | value[0] = '0'; | |
2387 | value[1] = 'x'; | |
2388 | const unsigned char *srcp; | |
2389 | #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) | |
2390 | const ASN1_STRING *srcasn1p; | |
2391 | srcasn1p = X509_EXTENSION_get_data(ext); | |
2392 | srcp = ASN1_STRING_get0_data(srcasn1p); | |
2393 | #else | |
2394 | ASN1_STRING *srcasn1p; | |
2395 | srcasn1p = X509_EXTENSION_get_data(ext); | |
2396 | srcp = ASN1_STRING_data(srcasn1p); | |
2397 | #endif | |
2398 | int asn1len = ASN1_STRING_length(srcasn1p); | |
2399 | /* 3 comes from '0x' + \0 */ | |
2400 | if ((size_t)(asn1len << 1) >= sizeof(value) - 3) { | |
2401 | RDEBUG("Value of '%s' attribute is too long to be stored, it will be truncated", attribute); | |
2402 | asn1len = (sizeof(value) - 3) >> 1; | |
2403 | } | |
2404 | fr_bin2hex(value + 2, srcp, asn1len); | |
2405 | } | |
2406 | ||
2367 | 2407 | |
2368 | 2408 | vp = fr_pair_make(talloc_ctx, certs, attribute, value, T_OP_ADD); |
2369 | 2409 | if (!vp) { |
3170 | 3210 | |
3171 | 3211 | if (rad_debug_lvl && insecure_tls_version) { |
3172 | 3212 | WARN("The configuration allows TLS 1.0 and/or TLS 1.1. We STRONGLY recommned using only TLS 1.2 for security"); |
3173 | WARN("Please set: min_tls_version = \"1.2\""); | |
3213 | WARN("Please set: tls_min_version = \"1.2\""); | |
3174 | 3214 | } |
3175 | 3215 | } |
3176 | 3216 | |
3393 | 3433 | */ |
3394 | 3434 | SSL_CTX_sess_set_cache_size(ctx, conf->session_cache_size); |
3395 | 3435 | |
3396 | #if OPENSSL_VERSION_NUMBER >= 0x10101000L | |
3436 | #if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER) | |
3397 | 3437 | SSL_CTX_set_num_tickets(ctx, 1); |
3398 | 3438 | #endif |
3399 | 3439 | |
3400 | 3440 | } else { |
3401 | 3441 | SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); |
3402 | 3442 | |
3403 | #if OPENSSL_VERSION_NUMBER >= 0x10101000L | |
3443 | #if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER) | |
3404 | 3444 | /* |
3405 | 3445 | * This controls the number of stateful or stateless tickets |
3406 | 3446 | * generated with TLS 1.3. In OpenSSL 1.1.1 it's also |
1705 | 1705 | } |
1706 | 1706 | return 0; |
1707 | 1707 | } |
1708 | ||
1709 | /** Determine the elapsed time between two timevals | |
1710 | * | |
1711 | * @param end timeval nearest to the present | |
1712 | * @param start timeval furthest from the present | |
1713 | * @param elapsed Where to write the elapsed time | |
1714 | */ | |
1715 | void rad_tv_sub(struct timeval const *end, struct timeval const *start, struct timeval *elapsed) | |
1716 | { | |
1717 | elapsed->tv_sec = end->tv_sec - start->tv_sec; | |
1718 | if (elapsed->tv_sec > 0) { | |
1719 | elapsed->tv_sec--; | |
1720 | elapsed->tv_usec = USEC; | |
1721 | } else { | |
1722 | elapsed->tv_usec = 0; | |
1723 | } | |
1724 | elapsed->tv_usec += end->tv_usec; | |
1725 | elapsed->tv_usec -= start->tv_usec; | |
1726 | ||
1727 | if (elapsed->tv_usec >= USEC) { | |
1728 | elapsed->tv_usec -= USEC; | |
1729 | elapsed->tv_sec++; | |
1730 | } | |
1731 | } |
485 | 485 | type++; |
486 | 486 | } |
487 | 487 | } |
488 | REXDENT(); | |
488 | 489 | |
489 | 490 | *out = '\0'; |
490 | 491 | return 0; |
1467 | 1468 | ssize_t slen; |
1468 | 1469 | xlat_exp_t *next; |
1469 | 1470 | |
1470 | if (!p[1] || !strchr("%}delmntDGHIMSTYv", p[1])) { | |
1471 | if (!p[1] || !strchr("%}cdelmntCDGHIMSTYv", p[1])) { | |
1471 | 1472 | talloc_free(node); |
1472 | 1473 | *error = "Invalid variable expansion"; |
1473 | 1474 | p++; |
2131 | 2132 | str[1] = '\0'; |
2132 | 2133 | break; |
2133 | 2134 | |
2135 | case 'c': /* current epoch time seconds */ | |
2136 | snprintf(str, freespace, "%" PRIu64, (uint64_t) time(NULL)); | |
2137 | break; | |
2138 | ||
2134 | 2139 | case 'd': /* request day */ |
2135 | 2140 | if (!localtime_r(&when, &ts)) goto error; |
2136 | 2141 | strftime(str, freespace, "%d", &ts); |
2160 | 2165 | CTIME_R(&when, str, freespace); |
2161 | 2166 | nl = strchr(str, '\n'); |
2162 | 2167 | if (nl) *nl = '\0'; |
2168 | break; | |
2169 | ||
2170 | case 'C': /* current epoch time microseconds */ | |
2171 | { | |
2172 | struct timeval tv; | |
2173 | ||
2174 | gettimeofday(&tv, NULL); | |
2175 | ||
2176 | snprintf(str, freespace, "%" PRIu64, (uint64_t) tv.tv_usec); | |
2177 | } | |
2163 | 2178 | break; |
2164 | 2179 | |
2165 | 2180 | case 'D': /* request date */ |
43 | 43 | { |
44 | 44 | const EVP_CIPHER *c; |
45 | 45 | const EVP_MD *h; |
46 | #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) | |
46 | #if OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) | |
47 | 47 | int md_size; |
48 | 48 | |
49 | 49 | if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL || |
313 | 313 | RINDENT(); |
314 | 314 | RDEBUG2("Stepbuf server challenge : "); |
315 | 315 | for (t = 0; t < challenge->vp_length; t++) { |
316 | fprintf(stderr, "%02x", challenge->vp_strvalue[t]); | |
316 | fprintf(stderr, "%02x", (unsigned int) challenge->vp_strvalue[t]); | |
317 | 317 | } |
318 | 318 | fprintf(stderr, "\n"); |
319 | 319 | #endif |
329 | 329 | #ifndef NDEBUG |
330 | 330 | RDEBUG2("Stepbuf peer challenge : "); |
331 | 331 | for (t = 2; t < 18; t++) { |
332 | fprintf(stderr, "%02x", response->vp_strvalue[t]); | |
332 | fprintf(stderr, "%02x", (unsigned int) response->vp_strvalue[t]); | |
333 | 333 | } |
334 | 334 | fprintf(stderr, "\n"); |
335 | 335 | #endif |
346 | 346 | RDEBUG2("Stepbuf p24 : "); |
347 | 347 | REXDENT(); |
348 | 348 | for (t = 26; t < 50; t++) { |
349 | fprintf(stderr, "%02x", response->vp_strvalue[t]); | |
349 | fprintf(stderr, "%02x", (unsigned int) response->vp_strvalue[t]); | |
350 | 350 | } |
351 | 351 | fprintf(stderr, "\n"); |
352 | 352 | #endif |
1118 | 1118 | * No password: can't do authentication. |
1119 | 1119 | */ |
1120 | 1120 | if (!password) { |
1121 | REDEBUG("FAILED: No NT/LM-Password. Cannot perform authentication"); | |
1121 | REDEBUG("FAILED: No NT-Password. Cannot perform authentication"); | |
1122 | 1122 | return -1; |
1123 | 1123 | } |
1124 | 1124 |
34 | 34 | #include <freeradius-devel/rad_assert.h> |
35 | 35 | |
36 | 36 | #include <Python.h> |
37 | #include <frameobject.h> /* Python header not pulled in by default. */ | |
37 | 38 | #include <dlfcn.h> |
38 | 39 | #ifdef HAVE_DL_ITERATE_PHDR |
39 | 40 | #include <link.h> |
40 | 41 | #endif |
41 | 42 | |
42 | 43 | #define LIBPYTHON_LINKER_NAME \ |
43 | "libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) ".so" | |
44 | "libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) LT_SHREXT | |
44 | 45 | |
45 | 46 | static uint32_t python_instances = 0; |
46 | 47 | static void *python_dlhandle; |
69 | 70 | |
70 | 71 | #if PY_VERSION_HEX > 0x03050000 |
71 | 72 | wchar_t *wide_name; //!< Special wide char encoding of radiusd name. |
72 | wchar_t *wide_path; //!< Special wide char encoding of radiusd path. | |
73 | 73 | #endif |
74 | 74 | PyObject *module; //!< Local, interpreter specific module, containing |
75 | 75 | //!< FreeRADIUS functions. |
217 | 217 | */ |
218 | 218 | static void python_error_log(void) |
219 | 219 | { |
220 | PyObject *pType = NULL, *pValue = NULL, *pTraceback = NULL, *pStr1 = NULL, *pStr2 = NULL; | |
221 | ||
222 | PyErr_Fetch(&pType, &pValue, &pTraceback); | |
223 | if (!pType || !pValue) | |
224 | goto failed; | |
225 | if (((pStr1 = PyObject_Str(pType)) == NULL) || | |
226 | ((pStr2 = PyObject_Str(pValue)) == NULL)) | |
227 | goto failed; | |
228 | ||
229 | ERROR("%s (%s)", PyString_AsString(pStr1), PyString_AsString(pStr2)); | |
220 | PyObject *p_type = NULL, *p_value = NULL, *p_traceback = NULL, *p_str_1 = NULL, *p_str_2 = NULL; | |
221 | ||
222 | PyErr_Fetch(&p_type, &p_value, &p_traceback); | |
223 | PyErr_NormalizeException(&p_type, &p_value, &p_traceback); | |
224 | if (!p_type || !p_value) goto failed; | |
225 | ||
226 | if (((p_str_1 = PyObject_Str(p_type)) == NULL) || ((p_str_2 = PyObject_Str(p_value)) == NULL)) goto failed; | |
227 | ||
228 | ERROR("%s (%s)", PyString_AsString(p_str_1), PyString_AsString(p_str_2)); | |
229 | ||
230 | if (p_traceback != Py_None) { | |
231 | PyTracebackObject *ptb = (PyTracebackObject*)p_traceback; | |
232 | size_t fnum = 0; | |
233 | ||
234 | for (; ptb != NULL; ptb = ptb->tb_next, fnum++) { | |
235 | PyFrameObject *cur_frame = ptb->tb_frame; | |
236 | ||
237 | ERROR("[%ld] %s:%d at %s()", | |
238 | fnum, | |
239 | PyString_AsString(cur_frame->f_code->co_filename), | |
240 | PyFrame_GetLineNumber(cur_frame), | |
241 | PyString_AsString(cur_frame->f_code->co_name) | |
242 | ); | |
243 | } | |
244 | } | |
230 | 245 | |
231 | 246 | failed: |
232 | Py_XDECREF(pStr1); | |
233 | Py_XDECREF(pStr2); | |
234 | Py_XDECREF(pType); | |
235 | Py_XDECREF(pValue); | |
236 | Py_XDECREF(pTraceback); | |
247 | Py_XDECREF(p_str_1); | |
248 | Py_XDECREF(p_str_2); | |
249 | Py_XDECREF(p_type); | |
250 | Py_XDECREF(p_value); | |
251 | Py_XDECREF(p_traceback); | |
237 | 252 | } |
238 | 253 | |
239 | 254 | static void mod_vptuple(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, PyObject *pValue, |
754 | 769 | |
755 | 770 | PyEval_RestoreThread(this_thread->state); /* Swap in our local thread state */ |
756 | 771 | ret = do_python_single(request, pFunc, funcname, inst->pass_all_vps, inst->pass_all_vps_dict); |
772 | if (ret == RLM_MODULE_FAIL) python_error_log(); | |
757 | 773 | PyEval_SaveThread(); |
758 | 774 | |
759 | 775 | return ret; |
1031 | 1047 | * the lifetime of the module. |
1032 | 1048 | */ |
1033 | 1049 | if (inst->python_path) { |
1034 | #if PY_VERSION_HEX > 0x03050000 | |
1035 | { | |
1036 | inst->wide_path = Py_DecodeLocale(inst->python_path, strlen(inst->python_path)); | |
1037 | PySys_SetPath(inst->wide_path); | |
1050 | char *p, *path; | |
1051 | PyObject *sys = PyImport_ImportModule("sys"); | |
1052 | PyObject *sys_path = PyObject_GetAttrString(sys, "path"); | |
1053 | ||
1054 | memcpy(&p, &inst->python_path, sizeof(path)); | |
1055 | ||
1056 | for (path = strtok(p, ":"); path != NULL; path = strtok(NULL, ":")) { | |
1057 | PyList_Append(sys_path, PyString_FromString(path)); | |
1038 | 1058 | } |
1039 | #else | |
1040 | { | |
1041 | char *path; | |
1042 | ||
1043 | memcpy(&path, &inst->python_path, sizeof(path)); | |
1044 | PySys_SetPath(path); | |
1045 | } | |
1046 | #endif | |
1059 | ||
1060 | PyObject_SetAttrString(sys, "path", sys_path); | |
1061 | Py_DecRef(sys); | |
1062 | Py_DecRef(sys_path); | |
1047 | 1063 | } |
1048 | 1064 | |
1049 | 1065 | /* |
1154 | 1170 | * Call the instantiate function. |
1155 | 1171 | */ |
1156 | 1172 | code = do_python_single(NULL, inst->instantiate.function, "instantiate", inst->pass_all_vps, inst->pass_all_vps_dict); |
1157 | if (code < 0) { | |
1173 | if (code == RLM_MODULE_FAIL) { | |
1158 | 1174 | error: |
1159 | 1175 | python_error_log(); /* Needs valid thread with GIL */ |
1160 | 1176 | PyEval_SaveThread(); |
1176 | 1192 | PyEval_RestoreThread(inst->sub_interpreter); |
1177 | 1193 | |
1178 | 1194 | ret = do_python_single(NULL, inst->detach.function, "detach", inst->pass_all_vps, inst->pass_all_vps_dict); |
1195 | if (ret == RLM_MODULE_FAIL) python_error_log(); | |
1179 | 1196 | |
1180 | 1197 | #define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x) |
1181 | 1198 | PYTHON_FUNC_DESTROY(instantiate); |
1212 | 1229 | |
1213 | 1230 | #if PY_VERSION_HEX > 0x03050000 |
1214 | 1231 | if (inst->wide_name) PyMem_RawFree(inst->wide_name); |
1215 | if (inst->wide_path) PyMem_RawFree(inst->wide_path); | |
1216 | 1232 | #endif |
1217 | 1233 | } |
1218 | 1234 |
587 | 587 | targetname |
588 | 588 | mod_cflags |
589 | 589 | mod_ldflags |
590 | PYTHON3_BIN | |
590 | PYTHON3_CONFIG_BIN | |
591 | 591 | CPP |
592 | 592 | OBJEXT |
593 | 593 | EXEEXT |
637 | 637 | ac_subst_files='' |
638 | 638 | ac_user_opts=' |
639 | 639 | enable_option_checking |
640 | with_rlm_python3_bin | |
641 | with_rlm_python3_lib_dir | |
642 | with_rlm_python3_include_dir | |
640 | with_rlm_python3_config_bin | |
643 | 641 | ' |
644 | 642 | ac_precious_vars='build_alias |
645 | 643 | host_alias |
1256 | 1254 | Optional Packages: |
1257 | 1255 | --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] |
1258 | 1256 | --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) |
1259 | --with-rlm-python3-bin=PATH Path to python3 binary | |
1260 | --with-rlm-python3-lib-dir=DIR Directory for Python library files | |
1261 | --with-rlm-python3-include-dir=DIR Directory for Python include files | |
1257 | --with-rlm-python3-config-bin=PATH Path to python-config3 binary | |
1262 | 1258 | |
1263 | 1259 | Some influential environment variables: |
1264 | 1260 | CC C compiler command |
1424 | 1420 | as_fn_set_status $ac_retval |
1425 | 1421 | |
1426 | 1422 | } # ac_fn_c_try_cpp |
1427 | ||
1428 | # ac_fn_c_try_link LINENO | |
1429 | # ----------------------- | |
1430 | # Try to link conftest.$ac_ext, and return whether this succeeded. | |
1431 | ac_fn_c_try_link () | |
1432 | { | |
1433 | as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack | |
1434 | rm -f conftest.$ac_objext conftest$ac_exeext | |
1435 | if { { ac_try="$ac_link" | |
1436 | case "(($ac_try" in | |
1437 | *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; | |
1438 | *) ac_try_echo=$ac_try;; | |
1439 | esac | |
1440 | eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" | |
1441 | $as_echo "$ac_try_echo"; } >&5 | |
1442 | (eval "$ac_link") 2>conftest.err | |
1443 | ac_status=$? | |
1444 | if test -s conftest.err; then | |
1445 | grep -v '^ *+' conftest.err >conftest.er1 | |
1446 | cat conftest.er1 >&5 | |
1447 | mv -f conftest.er1 conftest.err | |
1448 | fi | |
1449 | $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 | |
1450 | test $ac_status = 0; } && { | |
1451 | test -z "$ac_c_werror_flag" || | |
1452 | test ! -s conftest.err | |
1453 | } && test -s conftest$ac_exeext && { | |
1454 | test "$cross_compiling" = yes || | |
1455 | test -x conftest$ac_exeext | |
1456 | }; then : | |
1457 | ac_retval=0 | |
1458 | else | |
1459 | $as_echo "$as_me: failed program was:" >&5 | |
1460 | sed 's/^/| /' conftest.$ac_ext >&5 | |
1461 | ||
1462 | ac_retval=1 | |
1463 | fi | |
1464 | # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information | |
1465 | # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would | |
1466 | # interfere with the next link command; also delete a directory that is | |
1467 | # left behind by Apple's compiler. We do this before executing the actions. | |
1468 | rm -rf conftest.dSYM conftest_ipa8_conftest.oo | |
1469 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno | |
1470 | as_fn_set_status $ac_retval | |
1471 | ||
1472 | } # ac_fn_c_try_link | |
1473 | ||
1474 | # ac_fn_c_check_func LINENO FUNC VAR | |
1475 | # ---------------------------------- | |
1476 | # Tests whether FUNC exists, setting the cache variable VAR accordingly | |
1477 | ac_fn_c_check_func () | |
1478 | { | |
1479 | as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack | |
1480 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 | |
1481 | $as_echo_n "checking for $2... " >&6; } | |
1482 | if eval \${$3+:} false; then : | |
1483 | $as_echo_n "(cached) " >&6 | |
1484 | else | |
1485 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
1486 | /* end confdefs.h. */ | |
1487 | /* Define $2 to an innocuous variant, in case <limits.h> declares $2. | |
1488 | For example, HP-UX 11i <limits.h> declares gettimeofday. */ | |
1489 | #define $2 innocuous_$2 | |
1490 | ||
1491 | /* System header to define __stub macros and hopefully few prototypes, | |
1492 | which can conflict with char $2 (); below. | |
1493 | Prefer <limits.h> to <assert.h> if __STDC__ is defined, since | |
1494 | <limits.h> exists even on freestanding compilers. */ | |
1495 | ||
1496 | #ifdef __STDC__ | |
1497 | # include <limits.h> | |
1498 | #else | |
1499 | # include <assert.h> | |
1500 | #endif | |
1501 | ||
1502 | #undef $2 | |
1503 | ||
1504 | /* Override any GCC internal prototype to avoid an error. | |
1505 | Use char because int might match the return type of a GCC | |
1506 | builtin and then its argument prototype would still apply. */ | |
1507 | #ifdef __cplusplus | |
1508 | extern "C" | |
1509 | #endif | |
1510 | char $2 (); | |
1511 | /* The GNU C library defines this for functions which it implements | |
1512 | to always fail with ENOSYS. Some functions are actually named | |
1513 | something starting with __ and the normal name is an alias. */ | |
1514 | #if defined __stub_$2 || defined __stub___$2 | |
1515 | choke me | |
1516 | #endif | |
1517 | ||
1518 | int | |
1519 | main () | |
1520 | { | |
1521 | return $2 (); | |
1522 | ; | |
1523 | return 0; | |
1524 | } | |
1525 | _ACEOF | |
1526 | if ac_fn_c_try_link "$LINENO"; then : | |
1527 | eval "$3=yes" | |
1528 | else | |
1529 | eval "$3=no" | |
1530 | fi | |
1531 | rm -f core conftest.err conftest.$ac_objext \ | |
1532 | conftest$ac_exeext conftest.$ac_ext | |
1533 | fi | |
1534 | eval ac_res=\$$3 | |
1535 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 | |
1536 | $as_echo "$ac_res" >&6; } | |
1537 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno | |
1538 | ||
1539 | } # ac_fn_c_check_func | |
1540 | 1423 | cat >config.log <<_ACEOF |
1541 | 1424 | This file contains any messages produced by compilers while |
1542 | 1425 | running configure, to aid debugging if configure makes a mistake. |
2821 | 2704 | ac_compiler_gnu=$ac_cv_c_compiler_gnu |
2822 | 2705 | |
2823 | 2706 | |
2824 | PYTHON3_BIN= | |
2825 | ||
2826 | # Check whether --with-rlm-python3-bin was given. | |
2827 | if test "${with_rlm_python3_bin+set}" = set; then : | |
2828 | withval=$with_rlm_python3_bin; case "$withval" in | |
2707 | PYTHON3_CONFIG_BIN= | |
2708 | ||
2709 | # Check whether --with-rlm-python3-config-bin was given. | |
2710 | if test "${with_rlm_python3_config_bin+set}" = set; then : | |
2711 | withval=$with_rlm_python3_config_bin; case "$withval" in | |
2829 | 2712 | no) |
2830 | as_fn_error $? "Need rlm-python3-bin" "$LINENO" 5 | |
2713 | as_fn_error $? "Need rlm-python3-config-bin" "$LINENO" 5 | |
2831 | 2714 | ;; |
2832 | 2715 | yes) |
2833 | 2716 | ;; |
2834 | 2717 | *) |
2835 | PYTHON3_BIN="$withval" | |
2718 | PYTHON3_CONFIG_BIN="$withval" | |
2836 | 2719 | ;; |
2837 | 2720 | esac |
2838 | 2721 | |
2839 | 2722 | fi |
2840 | 2723 | |
2841 | 2724 | |
2842 | if test "x$PYTHON3_BIN" = x; then | |
2843 | for ac_prog in python3 | |
2725 | if test "x$PYTHON3_CONFIG_BIN" = x; then | |
2726 | for ac_prog in python3-config | |
2844 | 2727 | do |
2845 | 2728 | # Extract the first word of "$ac_prog", so it can be a program name with args. |
2846 | 2729 | set dummy $ac_prog; ac_word=$2 |
2847 | 2730 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 |
2848 | 2731 | $as_echo_n "checking for $ac_word... " >&6; } |
2849 | if ${ac_cv_prog_PYTHON3_BIN+:} false; then : | |
2732 | if ${ac_cv_prog_PYTHON3_CONFIG_BIN+:} false; then : | |
2850 | 2733 | $as_echo_n "(cached) " >&6 |
2851 | 2734 | else |
2852 | if test -n "$PYTHON3_BIN"; then | |
2853 | ac_cv_prog_PYTHON3_BIN="$PYTHON3_BIN" # Let the user override the test. | |
2735 | if test -n "$PYTHON3_CONFIG_BIN"; then | |
2736 | ac_cv_prog_PYTHON3_CONFIG_BIN="$PYTHON3_CONFIG_BIN" # Let the user override the test. | |
2854 | 2737 | else |
2855 | 2738 | as_save_IFS=$IFS; IFS=$PATH_SEPARATOR |
2856 | 2739 | as_dummy="${PATH}:/usr/bin:/usr/local/bin" |
2860 | 2743 | test -z "$as_dir" && as_dir=. |
2861 | 2744 | for ac_exec_ext in '' $ac_executable_extensions; do |
2862 | 2745 | if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then |
2863 | ac_cv_prog_PYTHON3_BIN="$ac_prog" | |
2746 | ac_cv_prog_PYTHON3_CONFIG_BIN="$ac_prog" | |
2864 | 2747 | $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 |
2865 | 2748 | break 2 |
2866 | 2749 | fi |
2870 | 2753 | |
2871 | 2754 | fi |
2872 | 2755 | fi |
2873 | PYTHON3_BIN=$ac_cv_prog_PYTHON3_BIN | |
2874 | if test -n "$PYTHON3_BIN"; then | |
2875 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON3_BIN" >&5 | |
2876 | $as_echo "$PYTHON3_BIN" >&6; } | |
2756 | PYTHON3_CONFIG_BIN=$ac_cv_prog_PYTHON3_CONFIG_BIN | |
2757 | if test -n "$PYTHON3_CONFIG_BIN"; then | |
2758 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON3_CONFIG_BIN" >&5 | |
2759 | $as_echo "$PYTHON3_CONFIG_BIN" >&6; } | |
2877 | 2760 | else |
2878 | 2761 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 |
2879 | 2762 | $as_echo "no" >&6; } |
2880 | 2763 | fi |
2881 | 2764 | |
2882 | 2765 | |
2883 | test -n "$PYTHON3_BIN" && break | |
2766 | test -n "$PYTHON3_CONFIG_BIN" && break | |
2884 | 2767 | done |
2885 | test -n "$PYTHON3_BIN" || PYTHON3_BIN="not-found" | |
2768 | test -n "$PYTHON3_CONFIG_BIN" || PYTHON3_CONFIG_BIN="not-found" | |
2886 | 2769 | |
2887 | 2770 | fi |
2888 | 2771 | |
2889 | if test "x$PYTHON3_BIN" = "xnot-found"; then | |
2890 | fail="python-binary" | |
2772 | if test "x$PYTHON3_CONFIG_BIN" = xnot-found; then | |
2773 | { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python3-config not found" >&5 | |
2774 | $as_echo "$as_me: WARNING: python3-config not found" >&2;} | |
2775 | fail="$fail python3-config" | |
2776 | else | |
2777 | old_CFLAGS="$CFLAGS" | |
2778 | unset CFLAGS | |
2779 | ||
2780 | python3_cflags=`${PYTHON3_CONFIG_BIN} --cflags` | |
2781 | { $as_echo "$as_me:${as_lineno-$LINENO}: ${PYTHON3_CONFIG_BIN}'s cflags were \"${python3_cflags}\"" >&5 | |
2782 | $as_echo "$as_me: ${PYTHON3_CONFIG_BIN}'s cflags were \"${python3_cflags}\"" >&6;} | |
2783 | ||
2784 | mod_cflags=`echo $python3_cflags | sed -e '\ | |
2785 | s/-I/-isystem/g;\ | |
2786 | s/-isysroot[ =]\{0,1\}[^-]*//g;\ | |
2787 | s/-O[^[[:blank:]]]*//g;\ | |
2788 | s/-Wp,-D_FORTIFY_SOURCE=[[:digit:]]//g;\ | |
2789 | s/-g[^ ]*//g;\ | |
2790 | s/-W[^ ]*//g;\ | |
2791 | s/-DNDEBUG[[:blank:]]*//g; | |
2792 | '` | |
2793 | { $as_echo "$as_me:${as_lineno-$LINENO}: Sanitized cflags were \"${mod_cflags}\"" >&5 | |
2794 | $as_echo "$as_me: Sanitized cflags were \"${mod_cflags}\"" >&6;} | |
2795 | ||
2796 | python3_ldflags=`${PYTHON3_CONFIG_BIN} --ldflags` | |
2797 | { $as_echo "$as_me:${as_lineno-$LINENO}: ${PYTHON3_CONFIG_BIN}'s ldflags were \"$python3_ldflags}\"" >&5 | |
2798 | $as_echo "$as_me: ${PYTHON3_CONFIG_BIN}'s ldflags were \"$python3_ldflags}\"" >&6;} | |
2799 | ||
2800 | mod_ldflags=`echo $python3_ldflags | sed -e '\ | |
2801 | s/-Wl,-O[[:digit:]][[:blank:]]*//g;\ | |
2802 | s/-Wl,-Bsymbolic-functions[[:blank:]]*//g;\ | |
2803 | s/-Xlinker -export-dynamic//g;\ | |
2804 | s/-Wl,-stack_size,[[:digit:]]*[[:blank:]]//g; | |
2805 | '` | |
2806 | { $as_echo "$as_me:${as_lineno-$LINENO}: Sanitized ldflags were \"${mod_ldflags}\"" >&5 | |
2807 | $as_echo "$as_me: Sanitized ldflags were \"${mod_ldflags}\"" >&6;} | |
2808 | ||
2809 | CFLAGS=$old_CFLAGS | |
2810 | ||
2811 | targetname="rlm_python3" | |
2891 | 2812 | fi |
2892 | ||
2893 | PY_LIB_DIR= | |
2894 | ||
2895 | # Check whether --with-rlm-python3-lib-dir was given. | |
2896 | if test "${with_rlm_python3_lib_dir+set}" = set; then : | |
2897 | withval=$with_rlm_python3_lib_dir; case "$withval" in | |
2898 | no) | |
2899 | as_fn_error $? "Need rlm-python3-lib-dir" "$LINENO" 5 | |
2900 | ;; | |
2901 | yes) | |
2902 | ;; | |
2903 | *) | |
2904 | PY_LIB_DIR="$withval" | |
2905 | ;; | |
2906 | esac | |
2907 | ||
2908 | fi | |
2909 | ||
2910 | ||
2911 | PY_INC_DIR= | |
2912 | ||
2913 | # Check whether --with-rlm-python3-include-dir was given. | |
2914 | if test "${with_rlm_python3_include_dir+set}" = set; then : | |
2915 | withval=$with_rlm_python3_include_dir; case "$withval" in | |
2916 | no) | |
2917 | as_fn_error $? "Need rlm-python3-include-dir" "$LINENO" 5 | |
2918 | ;; | |
2919 | yes) | |
2920 | ;; | |
2921 | *) | |
2922 | PY_INC_DIR="$withval" | |
2923 | ;; | |
2924 | esac | |
2925 | ||
2926 | fi | |
2927 | ||
2928 | ||
2929 | if test x$fail = x; then | |
2930 | PY_PREFIX=`${PYTHON3_BIN} -c 'import sys ; print(sys.prefix)'` | |
2931 | { $as_echo "$as_me:${as_lineno-$LINENO}: Python sys.prefix \"${PY_PREFIX}\"" >&5 | |
2932 | $as_echo "$as_me: Python sys.prefix \"${PY_PREFIX}\"" >&6;} | |
2933 | ||
2934 | PY_EXEC_PREFIX=`${PYTHON3_BIN} -c 'import sys ; print(sys.exec_prefix)'` | |
2935 | { $as_echo "$as_me:${as_lineno-$LINENO}: Python sys.exec_prefix \"${PY_EXEC_PREFIX}\"" >&5 | |
2936 | $as_echo "$as_me: Python sys.exec_prefix \"${PY_EXEC_PREFIX}\"" >&6;} | |
2937 | ||
2938 | PY_SYS_VERSION=`${PYTHON3_BIN} -c 'import sys ; print(sys.version[0:3])'` | |
2939 | { $as_echo "$as_me:${as_lineno-$LINENO}: Python sys.version \"${PY_SYS_VERSION}\"" >&5 | |
2940 | $as_echo "$as_me: Python sys.version \"${PY_SYS_VERSION}\"" >&6;} | |
2941 | ||
2942 | if test "x$PY_LIB_DIR" = "x"; then | |
2943 | PY_LIB_DIR="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config" | |
2944 | PY_LIB_LOC="-L$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config" | |
2945 | fi | |
2946 | ||
2947 | PY_MAKEFILE="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config/Makefile" | |
2948 | if test -f ${PY_MAKEFILE}; then | |
2949 | PY_LOCAL_MOD_LIBS=`sed -n -e 's/^LOCALMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/^ *//;s/ *$//'` | |
2950 | { $as_echo "$as_me:${as_lineno-$LINENO}: Python local_mod_libs \"${PY_LOCAL_MOD_LIBS}\"" >&5 | |
2951 | $as_echo "$as_me: Python local_mod_libs \"${PY_LOCAL_MOD_LIBS}\"" >&6;} | |
2952 | ||
2953 | PY_BASE_MOD_LIBS=`sed -n -e 's/^BASEMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/^ *//;s/ *$//'` | |
2954 | { $as_echo "$as_me:${as_lineno-$LINENO}: Python base_mod_libs \"${PY_BASE_MOD_LIBS}\"" >&5 | |
2955 | $as_echo "$as_me: Python base_mod_libs \"${PY_BASE_MOD_LIBS}\"" >&6;} | |
2956 | ||
2957 | PY_OTHER_LIBS=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/ / /g;s/^ *//;s/ *$//'` | |
2958 | PY_OTHER_LDFLAGS=`sed -n -e 's/^LINKFORSHARED=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[:blank:]]/ /g;s/ / /g;s/^ *//;s/ *$//'` | |
2959 | { $as_echo "$as_me:${as_lineno-$LINENO}: Python other_libs \"${PY_OTHER_LDFLAGS} ${PY_OTHER_LIBS}\"" >&5 | |
2960 | $as_echo "$as_me: Python other_libs \"${PY_OTHER_LDFLAGS} ${PY_OTHER_LIBS}\"" >&6;} | |
2961 | fi | |
2962 | PY_EXTRA_LIBS="$PY_LOCALMODLIBS $PY_BASE_MOD_LIBS $PY_OTHER_LIBS" | |
2963 | ||
2964 | old_CFLAGS=$CFLAGS | |
2965 | CFLAGS="$CFLAGS $PY_CFLAGS" | |
2966 | smart_try_dir="$PY_PREFIX/include/python$PY_SYS_VERSION" | |
2967 | ||
2968 | ||
2969 | ||
2970 | ac_safe=`echo "Python.h" | sed 'y%./+-%__pm%'` | |
2971 | old_CPPFLAGS="$CPPFLAGS" | |
2972 | smart_include= | |
2973 | smart_include_dir="/usr/local/include /opt/include" | |
2974 | ||
2975 | _smart_try_dir= | |
2976 | _smart_include_dir= | |
2977 | ||
2978 | for _prefix in $smart_prefix ""; do | |
2979 | for _dir in $smart_try_dir; do | |
2980 | _smart_try_dir="${_smart_try_dir} ${_dir}/${_prefix}" | |
2981 | done | |
2982 | ||
2983 | for _dir in $smart_include_dir; do | |
2984 | _smart_include_dir="${_smart_include_dir} ${_dir}/${_prefix}" | |
2985 | done | |
2986 | done | |
2987 | ||
2988 | if test "x$_smart_try_dir" != "x"; then | |
2989 | for try in $_smart_try_dir; do | |
2990 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python.h in $try" >&5 | |
2991 | $as_echo_n "checking for Python.h in $try... " >&6; } | |
2992 | CPPFLAGS="-isystem $try $old_CPPFLAGS" | |
2993 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
2994 | /* end confdefs.h. */ | |
2995 | ||
2996 | #include <Python.h> | |
2997 | int | |
2998 | main () | |
2999 | { | |
3000 | int a = 1; | |
3001 | ; | |
3002 | return 0; | |
3003 | } | |
3004 | _ACEOF | |
3005 | if ac_fn_c_try_compile "$LINENO"; then : | |
3006 | ||
3007 | smart_include="-isystem $try" | |
3008 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3009 | $as_echo "yes" >&6; } | |
3010 | break | |
3011 | ||
3012 | else | |
3013 | ||
3014 | smart_include= | |
3015 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3016 | $as_echo "no" >&6; } | |
3017 | ||
3018 | fi | |
3019 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
3020 | done | |
3021 | CPPFLAGS="$old_CPPFLAGS" | |
3022 | fi | |
3023 | ||
3024 | if test "x$smart_include" = "x"; then | |
3025 | for _prefix in $smart_prefix; do | |
3026 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${_prefix}/Python.h" >&5 | |
3027 | $as_echo_n "checking for ${_prefix}/Python.h... " >&6; } | |
3028 | ||
3029 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3030 | /* end confdefs.h. */ | |
3031 | ||
3032 | #include <Python.h> | |
3033 | int | |
3034 | main () | |
3035 | { | |
3036 | int a = 1; | |
3037 | ; | |
3038 | return 0; | |
3039 | } | |
3040 | _ACEOF | |
3041 | if ac_fn_c_try_compile "$LINENO"; then : | |
3042 | ||
3043 | smart_include="-isystem ${_prefix}/" | |
3044 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3045 | $as_echo "yes" >&6; } | |
3046 | break | |
3047 | ||
3048 | else | |
3049 | ||
3050 | smart_include= | |
3051 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3052 | $as_echo "no" >&6; } | |
3053 | ||
3054 | fi | |
3055 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
3056 | done | |
3057 | fi | |
3058 | ||
3059 | if test "x$smart_include" = "x"; then | |
3060 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python.h" >&5 | |
3061 | $as_echo_n "checking for Python.h... " >&6; } | |
3062 | ||
3063 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3064 | /* end confdefs.h. */ | |
3065 | ||
3066 | #include <Python.h> | |
3067 | int | |
3068 | main () | |
3069 | { | |
3070 | int a = 1; | |
3071 | ; | |
3072 | return 0; | |
3073 | } | |
3074 | _ACEOF | |
3075 | if ac_fn_c_try_compile "$LINENO"; then : | |
3076 | ||
3077 | smart_include=" " | |
3078 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3079 | $as_echo "yes" >&6; } | |
3080 | break | |
3081 | ||
3082 | else | |
3083 | ||
3084 | smart_include= | |
3085 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3086 | $as_echo "no" >&6; } | |
3087 | ||
3088 | fi | |
3089 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
3090 | fi | |
3091 | ||
3092 | if test "x$smart_include" = "x"; then | |
3093 | ||
3094 | for prefix in $smart_prefix; do | |
3095 | ||
3096 | ||
3097 | if test "x$LOCATE" != "x"; then | |
3098 | DIRS= | |
3099 | file="${_prefix}/${1}" | |
3100 | ||
3101 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3102 | base=`echo $x | sed "s%/${file}%%"` | |
3103 | if test "x$x" = "x$base"; then | |
3104 | continue; | |
3105 | fi | |
3106 | ||
3107 | dir=`${DIRNAME} $x 2>/dev/null` | |
3108 | exclude=`echo ${dir} | ${GREP} /home` | |
3109 | if test "x$exclude" != "x"; then | |
3110 | continue | |
3111 | fi | |
3112 | ||
3113 | already=`echo \$_smart_include_dir ${DIRS} | ${GREP} ${dir}` | |
3114 | if test "x$already" = "x"; then | |
3115 | DIRS="$DIRS $dir" | |
3116 | fi | |
3117 | done | |
3118 | fi | |
3119 | ||
3120 | eval "_smart_include_dir=\"\$_smart_include_dir $DIRS\"" | |
3121 | ||
3122 | done | |
3123 | ||
3124 | ||
3125 | if test "x$LOCATE" != "x"; then | |
3126 | DIRS= | |
3127 | file=Python.h | |
3128 | ||
3129 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3130 | base=`echo $x | sed "s%/${file}%%"` | |
3131 | if test "x$x" = "x$base"; then | |
3132 | continue; | |
3133 | fi | |
3134 | ||
3135 | dir=`${DIRNAME} $x 2>/dev/null` | |
3136 | exclude=`echo ${dir} | ${GREP} /home` | |
3137 | if test "x$exclude" != "x"; then | |
3138 | continue | |
3139 | fi | |
3140 | ||
3141 | already=`echo \$_smart_include_dir ${DIRS} | ${GREP} ${dir}` | |
3142 | if test "x$already" = "x"; then | |
3143 | DIRS="$DIRS $dir" | |
3144 | fi | |
3145 | done | |
3146 | fi | |
3147 | ||
3148 | eval "_smart_include_dir=\"\$_smart_include_dir $DIRS\"" | |
3149 | ||
3150 | ||
3151 | for try in $_smart_include_dir; do | |
3152 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python.h in $try" >&5 | |
3153 | $as_echo_n "checking for Python.h in $try... " >&6; } | |
3154 | CPPFLAGS="-isystem $try $old_CPPFLAGS" | |
3155 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3156 | /* end confdefs.h. */ | |
3157 | ||
3158 | #include <Python.h> | |
3159 | int | |
3160 | main () | |
3161 | { | |
3162 | int a = 1; | |
3163 | ; | |
3164 | return 0; | |
3165 | } | |
3166 | _ACEOF | |
3167 | if ac_fn_c_try_compile "$LINENO"; then : | |
3168 | ||
3169 | smart_include="-isystem $try" | |
3170 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3171 | $as_echo "yes" >&6; } | |
3172 | break | |
3173 | ||
3174 | else | |
3175 | ||
3176 | smart_include= | |
3177 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3178 | $as_echo "no" >&6; } | |
3179 | ||
3180 | fi | |
3181 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
3182 | done | |
3183 | CPPFLAGS="$old_CPPFLAGS" | |
3184 | fi | |
3185 | ||
3186 | if test "x$smart_include" != "x"; then | |
3187 | eval "ac_cv_header_$ac_safe=yes" | |
3188 | CPPFLAGS="$smart_include $old_CPPFLAGS" | |
3189 | SMART_CPPFLAGS="$smart_include $SMART_CPPFLAGS" | |
3190 | fi | |
3191 | ||
3192 | smart_prefix= | |
3193 | ||
3194 | CFLAGS=$old_CFLAGS | |
3195 | ||
3196 | if test "x$ac_cv_header_Python_h" = "xyes"; then | |
3197 | mod_cflags="$SMART_CPPFLAGS" | |
3198 | else | |
3199 | fail="$fail Python.h" | |
3200 | targetname= | |
3201 | fi | |
3202 | ||
3203 | old_LIBS=$LIBS | |
3204 | LIBS="$LIBS $PY_LIB_LOC $PY_EXTRA_LIBS -lm" | |
3205 | smart_try_dir=$PY_LIB_DIR | |
3206 | ||
3207 | ||
3208 | sm_lib_safe=`echo "python${PY_SYS_VERSION}" | sed 'y%./+-%__p_%'` | |
3209 | sm_func_safe=`echo "Py_Initialize" | sed 'y%./+-%__p_%'` | |
3210 | ||
3211 | old_LIBS="$LIBS" | |
3212 | old_CPPFLAGS="$CPPFLAGS" | |
3213 | smart_lib= | |
3214 | smart_ldflags= | |
3215 | smart_lib_dir= | |
3216 | ||
3217 | if test "x$smart_try_dir" != "x"; then | |
3218 | for try in $smart_try_dir; do | |
3219 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try" >&5 | |
3220 | $as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try... " >&6; } | |
3221 | LIBS="-lpython${PY_SYS_VERSION} $old_LIBS" | |
3222 | CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS" | |
3223 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3224 | /* end confdefs.h. */ | |
3225 | extern char Py_Initialize(); | |
3226 | int | |
3227 | main () | |
3228 | { | |
3229 | Py_Initialize() | |
3230 | ; | |
3231 | return 0; | |
3232 | } | |
3233 | _ACEOF | |
3234 | if ac_fn_c_try_link "$LINENO"; then : | |
3235 | ||
3236 | smart_lib="-lpython${PY_SYS_VERSION}" | |
3237 | smart_ldflags="-L$try -Wl,-rpath,$try" | |
3238 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3239 | $as_echo "yes" >&6; } | |
3240 | break | |
3241 | ||
3242 | else | |
3243 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3244 | $as_echo "no" >&6; } | |
3245 | fi | |
3246 | rm -f core conftest.err conftest.$ac_objext \ | |
3247 | conftest$ac_exeext conftest.$ac_ext | |
3248 | done | |
3249 | LIBS="$old_LIBS" | |
3250 | CPPFLAGS="$old_CPPFLAGS" | |
3251 | fi | |
3252 | ||
3253 | if test "x$smart_lib" = "x"; then | |
3254 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}" >&5 | |
3255 | $as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}... " >&6; } | |
3256 | LIBS="-lpython${PY_SYS_VERSION} $old_LIBS" | |
3257 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3258 | /* end confdefs.h. */ | |
3259 | extern char Py_Initialize(); | |
3260 | int | |
3261 | main () | |
3262 | { | |
3263 | Py_Initialize() | |
3264 | ; | |
3265 | return 0; | |
3266 | } | |
3267 | _ACEOF | |
3268 | if ac_fn_c_try_link "$LINENO"; then : | |
3269 | ||
3270 | smart_lib="-lpython${PY_SYS_VERSION}" | |
3271 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3272 | $as_echo "yes" >&6; } | |
3273 | ||
3274 | else | |
3275 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3276 | $as_echo "no" >&6; } | |
3277 | fi | |
3278 | rm -f core conftest.err conftest.$ac_objext \ | |
3279 | conftest$ac_exeext conftest.$ac_ext | |
3280 | LIBS="$old_LIBS" | |
3281 | fi | |
3282 | ||
3283 | if test "x$smart_lib" = "x"; then | |
3284 | ||
3285 | ||
3286 | if test "x$LOCATE" != "x"; then | |
3287 | DIRS= | |
3288 | file=libpython${PY_SYS_VERSION}${libltdl_cv_shlibext} | |
3289 | ||
3290 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3291 | base=`echo $x | sed "s%/${file}%%"` | |
3292 | if test "x$x" = "x$base"; then | |
3293 | continue; | |
3294 | fi | |
3295 | ||
3296 | dir=`${DIRNAME} $x 2>/dev/null` | |
3297 | exclude=`echo ${dir} | ${GREP} /home` | |
3298 | if test "x$exclude" != "x"; then | |
3299 | continue | |
3300 | fi | |
3301 | ||
3302 | already=`echo \$smart_lib_dir ${DIRS} | ${GREP} ${dir}` | |
3303 | if test "x$already" = "x"; then | |
3304 | DIRS="$DIRS $dir" | |
3305 | fi | |
3306 | done | |
3307 | fi | |
3308 | ||
3309 | eval "smart_lib_dir=\"\$smart_lib_dir $DIRS\"" | |
3310 | ||
3311 | ||
3312 | ||
3313 | if test "x$LOCATE" != "x"; then | |
3314 | DIRS= | |
3315 | file=libpython${PY_SYS_VERSION}.a | |
3316 | ||
3317 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3318 | base=`echo $x | sed "s%/${file}%%"` | |
3319 | if test "x$x" = "x$base"; then | |
3320 | continue; | |
3321 | fi | |
3322 | ||
3323 | dir=`${DIRNAME} $x 2>/dev/null` | |
3324 | exclude=`echo ${dir} | ${GREP} /home` | |
3325 | if test "x$exclude" != "x"; then | |
3326 | continue | |
3327 | fi | |
3328 | ||
3329 | already=`echo \$smart_lib_dir ${DIRS} | ${GREP} ${dir}` | |
3330 | if test "x$already" = "x"; then | |
3331 | DIRS="$DIRS $dir" | |
3332 | fi | |
3333 | done | |
3334 | fi | |
3335 | ||
3336 | eval "smart_lib_dir=\"\$smart_lib_dir $DIRS\"" | |
3337 | ||
3338 | ||
3339 | for try in $smart_lib_dir /usr/local/lib /opt/lib; do | |
3340 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try" >&5 | |
3341 | $as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION} in $try... " >&6; } | |
3342 | LIBS="-lpython${PY_SYS_VERSION} $old_LIBS" | |
3343 | CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS" | |
3344 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3345 | /* end confdefs.h. */ | |
3346 | extern char Py_Initialize(); | |
3347 | int | |
3348 | main () | |
3349 | { | |
3350 | Py_Initialize() | |
3351 | ; | |
3352 | return 0; | |
3353 | } | |
3354 | _ACEOF | |
3355 | if ac_fn_c_try_link "$LINENO"; then : | |
3356 | ||
3357 | smart_lib="-lpython${PY_SYS_VERSION}" | |
3358 | smart_ldflags="-L$try -Wl,-rpath,$try" | |
3359 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3360 | $as_echo "yes" >&6; } | |
3361 | break | |
3362 | ||
3363 | else | |
3364 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3365 | $as_echo "no" >&6; } | |
3366 | fi | |
3367 | rm -f core conftest.err conftest.$ac_objext \ | |
3368 | conftest$ac_exeext conftest.$ac_ext | |
3369 | done | |
3370 | LIBS="$old_LIBS" | |
3371 | CPPFLAGS="$old_CPPFLAGS" | |
3372 | fi | |
3373 | ||
3374 | if test "x$smart_lib" != "x"; then | |
3375 | eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes" | |
3376 | LIBS="$smart_ldflags $smart_lib $old_LIBS" | |
3377 | SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS" | |
3378 | fi | |
3379 | ||
3380 | LIBS=$old_LIBS | |
3381 | ||
3382 | eval t=\${ac_cv_lib_${sm_lib_safe}_${sm_func_safe}} | |
3383 | if test "x$t" = "xyes"; then | |
3384 | mod_ldflags="$PY_LIB_LOC $PY_EXTRA_LIBS $SMART_LIBS -lm" | |
3385 | targetname=rlm_python3 | |
3386 | else | |
3387 | ||
3388 | ||
3389 | sm_lib_safe=`echo "python${PY_SYS_VERSION}m" | sed 'y%./+-%__p_%'` | |
3390 | sm_func_safe=`echo "Py_Initialize" | sed 'y%./+-%__p_%'` | |
3391 | ||
3392 | old_LIBS="$LIBS" | |
3393 | old_CPPFLAGS="$CPPFLAGS" | |
3394 | smart_lib= | |
3395 | smart_ldflags= | |
3396 | smart_lib_dir= | |
3397 | ||
3398 | if test "x$smart_try_dir" != "x"; then | |
3399 | for try in $smart_try_dir; do | |
3400 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try" >&5 | |
3401 | $as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try... " >&6; } | |
3402 | LIBS="-lpython${PY_SYS_VERSION}m $old_LIBS" | |
3403 | CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS" | |
3404 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3405 | /* end confdefs.h. */ | |
3406 | extern char Py_Initialize(); | |
3407 | int | |
3408 | main () | |
3409 | { | |
3410 | Py_Initialize() | |
3411 | ; | |
3412 | return 0; | |
3413 | } | |
3414 | _ACEOF | |
3415 | if ac_fn_c_try_link "$LINENO"; then : | |
3416 | ||
3417 | smart_lib="-lpython${PY_SYS_VERSION}m" | |
3418 | smart_ldflags="-L$try -Wl,-rpath,$try" | |
3419 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3420 | $as_echo "yes" >&6; } | |
3421 | break | |
3422 | ||
3423 | else | |
3424 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3425 | $as_echo "no" >&6; } | |
3426 | fi | |
3427 | rm -f core conftest.err conftest.$ac_objext \ | |
3428 | conftest$ac_exeext conftest.$ac_ext | |
3429 | done | |
3430 | LIBS="$old_LIBS" | |
3431 | CPPFLAGS="$old_CPPFLAGS" | |
3432 | fi | |
3433 | ||
3434 | if test "x$smart_lib" = "x"; then | |
3435 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}m" >&5 | |
3436 | $as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}m... " >&6; } | |
3437 | LIBS="-lpython${PY_SYS_VERSION}m $old_LIBS" | |
3438 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3439 | /* end confdefs.h. */ | |
3440 | extern char Py_Initialize(); | |
3441 | int | |
3442 | main () | |
3443 | { | |
3444 | Py_Initialize() | |
3445 | ; | |
3446 | return 0; | |
3447 | } | |
3448 | _ACEOF | |
3449 | if ac_fn_c_try_link "$LINENO"; then : | |
3450 | ||
3451 | smart_lib="-lpython${PY_SYS_VERSION}m" | |
3452 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3453 | $as_echo "yes" >&6; } | |
3454 | ||
3455 | else | |
3456 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3457 | $as_echo "no" >&6; } | |
3458 | fi | |
3459 | rm -f core conftest.err conftest.$ac_objext \ | |
3460 | conftest$ac_exeext conftest.$ac_ext | |
3461 | LIBS="$old_LIBS" | |
3462 | fi | |
3463 | ||
3464 | if test "x$smart_lib" = "x"; then | |
3465 | ||
3466 | ||
3467 | if test "x$LOCATE" != "x"; then | |
3468 | DIRS= | |
3469 | file=libpython${PY_SYS_VERSION}m${libltdl_cv_shlibext} | |
3470 | ||
3471 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3472 | base=`echo $x | sed "s%/${file}%%"` | |
3473 | if test "x$x" = "x$base"; then | |
3474 | continue; | |
3475 | fi | |
3476 | ||
3477 | dir=`${DIRNAME} $x 2>/dev/null` | |
3478 | exclude=`echo ${dir} | ${GREP} /home` | |
3479 | if test "x$exclude" != "x"; then | |
3480 | continue | |
3481 | fi | |
3482 | ||
3483 | already=`echo \$smart_lib_dir ${DIRS} | ${GREP} ${dir}` | |
3484 | if test "x$already" = "x"; then | |
3485 | DIRS="$DIRS $dir" | |
3486 | fi | |
3487 | done | |
3488 | fi | |
3489 | ||
3490 | eval "smart_lib_dir=\"\$smart_lib_dir $DIRS\"" | |
3491 | ||
3492 | ||
3493 | ||
3494 | if test "x$LOCATE" != "x"; then | |
3495 | DIRS= | |
3496 | file=libpython${PY_SYS_VERSION}m.a | |
3497 | ||
3498 | for x in `${LOCATE} $file 2>/dev/null`; do | |
3499 | base=`echo $x | sed "s%/${file}%%"` | |
3500 | if test "x$x" = "x$base"; then | |
3501 | continue; | |
3502 | fi | |
3503 | ||
3504 | dir=`${DIRNAME} $x 2>/dev/null` | |
3505 | exclude=`echo ${dir} | ${GREP} /home` | |
3506 | if test "x$exclude" != "x"; then | |
3507 | continue | |
3508 | fi | |
3509 | ||
3510 | already=`echo \$smart_lib_dir ${DIRS} | ${GREP} ${dir}` | |
3511 | if test "x$already" = "x"; then | |
3512 | DIRS="$DIRS $dir" | |
3513 | fi | |
3514 | done | |
3515 | fi | |
3516 | ||
3517 | eval "smart_lib_dir=\"\$smart_lib_dir $DIRS\"" | |
3518 | ||
3519 | ||
3520 | for try in $smart_lib_dir /usr/local/lib /opt/lib; do | |
3521 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try" >&5 | |
3522 | $as_echo_n "checking for Py_Initialize in -lpython${PY_SYS_VERSION}m in $try... " >&6; } | |
3523 | LIBS="-lpython${PY_SYS_VERSION}m $old_LIBS" | |
3524 | CPPFLAGS="-L$try -Wl,-rpath,$try $old_CPPFLAGS" | |
3525 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
3526 | /* end confdefs.h. */ | |
3527 | extern char Py_Initialize(); | |
3528 | int | |
3529 | main () | |
3530 | { | |
3531 | Py_Initialize() | |
3532 | ; | |
3533 | return 0; | |
3534 | } | |
3535 | _ACEOF | |
3536 | if ac_fn_c_try_link "$LINENO"; then : | |
3537 | ||
3538 | smart_lib="-lpython${PY_SYS_VERSION}m" | |
3539 | smart_ldflags="-L$try -Wl,-rpath,$try" | |
3540 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
3541 | $as_echo "yes" >&6; } | |
3542 | break | |
3543 | ||
3544 | else | |
3545 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
3546 | $as_echo "no" >&6; } | |
3547 | fi | |
3548 | rm -f core conftest.err conftest.$ac_objext \ | |
3549 | conftest$ac_exeext conftest.$ac_ext | |
3550 | done | |
3551 | LIBS="$old_LIBS" | |
3552 | CPPFLAGS="$old_CPPFLAGS" | |
3553 | fi | |
3554 | ||
3555 | if test "x$smart_lib" != "x"; then | |
3556 | eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes" | |
3557 | LIBS="$smart_ldflags $smart_lib $old_LIBS" | |
3558 | SMART_LIBS="$smart_ldflags $smart_lib $SMART_LIBS" | |
3559 | fi | |
3560 | ||
3561 | eval t=\${ac_cv_lib_${sm_lib_safe}_${sm_func_safe}} | |
3562 | if test "x$t" = "xyes"; then | |
3563 | mod_ldflags="$PY_LIB_LOC $PY_EXTRA_LIBS $SMART_LIBS -lm" | |
3564 | targetname=rlm_python3 | |
3565 | else | |
3566 | targetname= | |
3567 | fail="$fail libpython$PY_SYS_VERSION" | |
3568 | fi | |
3569 | fi | |
3570 | fi | |
3571 | ||
3572 | for ac_func in dl_iterate_phdr | |
3573 | do : | |
3574 | ac_fn_c_check_func "$LINENO" "dl_iterate_phdr" "ac_cv_func_dl_iterate_phdr" | |
3575 | if test "x$ac_cv_func_dl_iterate_phdr" = xyes; then : | |
3576 | cat >>confdefs.h <<_ACEOF | |
3577 | #define HAVE_DL_ITERATE_PHDR 1 | |
3578 | _ACEOF | |
3579 | ||
3580 | fi | |
3581 | done | |
3582 | ||
3583 | 2813 | else |
3584 | 2814 | targetname= |
3585 | 2815 | echo \*\*\* module rlm_python3 is disabled. |
7 | 7 | AC_PROG_CC |
8 | 8 | AC_PROG_CPP |
9 | 9 | |
10 | dnl extra argument: --with-rlm-python3-bin | |
11 | PYTHON3_BIN= | |
12 | AC_ARG_WITH(rlm-python3-bin, | |
13 | [ --with-rlm-python3-bin=PATH Path to python3 binary []], | |
10 | dnl extra argument: --with-rlm-python3-config-bin | |
11 | PYTHON3_CONFIG_BIN= | |
12 | AC_ARG_WITH(rlm-python3-config-bin, | |
13 | [ --with-rlm-python3-config-bin=PATH Path to python-config3 binary []], | |
14 | 14 | [ case "$withval" in |
15 | 15 | no) |
16 | AC_MSG_ERROR(Need rlm-python3-bin) | |
16 | AC_MSG_ERROR(Need rlm-python3-config-bin) | |
17 | 17 | ;; |
18 | 18 | yes) |
19 | 19 | ;; |
20 | 20 | *) |
21 | PYTHON3_BIN="$withval" | |
21 | PYTHON3_CONFIG_BIN="$withval" | |
22 | 22 | ;; |
23 | 23 | esac ] |
24 | 24 | ) |
25 | 25 | |
26 | if test "x$PYTHON3_BIN" = x; then | |
27 | AC_CHECK_PROGS(PYTHON3_BIN, [ python3 ], not-found, [${PATH}:/usr/bin:/usr/local/bin]) | |
26 | if test "x$PYTHON3_CONFIG_BIN" = x; then | |
27 | AC_CHECK_PROGS(PYTHON3_CONFIG_BIN, [ python3-config ], not-found, [${PATH}:/usr/bin:/usr/local/bin]) | |
28 | 28 | fi |
29 | 29 | |
30 | if test "x$PYTHON3_BIN" = "xnot-found"; then | |
31 | fail="python-binary" | |
32 | fi | |
30 | if test "x$PYTHON3_CONFIG_BIN" = xnot-found; then | |
31 | fail="$fail python3-config" | |
32 | else | |
33 | dnl # | |
34 | dnl # It is necessary due to a weird behavior with 'python3-config' | |
35 | dnl # | |
36 | old_CFLAGS="$CFLAGS" | |
37 | unset CFLAGS | |
33 | 38 | |
34 | dnl extra argument: --with-rlm-python3-lib-dir | |
35 | PY_LIB_DIR= | |
36 | AC_ARG_WITH(rlm-python3-lib-dir, | |
37 | [ --with-rlm-python3-lib-dir=DIR Directory for Python library files []], | |
38 | [ case "$withval" in | |
39 | no) | |
40 | AC_MSG_ERROR(Need rlm-python3-lib-dir) | |
41 | ;; | |
42 | yes) | |
43 | ;; | |
44 | *) | |
45 | PY_LIB_DIR="$withval" | |
46 | ;; | |
47 | esac ] | |
48 | ) | |
39 | python3_cflags=`${PYTHON3_CONFIG_BIN} --cflags` | |
40 | AC_MSG_NOTICE([${PYTHON3_CONFIG_BIN}'s cflags were \"${python3_cflags}\"]) | |
49 | 41 | |
50 | dnl extra argument: --with-rlm-python3-include-dir | |
51 | PY_INC_DIR= | |
52 | AC_ARG_WITH(rlm-python3-include-dir, | |
53 | [ --with-rlm-python3-include-dir=DIR Directory for Python include files []], | |
54 | [ case "$withval" in | |
55 | no) | |
56 | AC_MSG_ERROR(Need rlm-python3-include-dir) | |
57 | ;; | |
58 | yes) | |
59 | ;; | |
60 | *) | |
61 | PY_INC_DIR="$withval" | |
62 | ;; | |
63 | esac ] | |
64 | ) | |
42 | dnl # Convert -I to -isystem to get rid of warnings about issues in Python headers | |
43 | dnl # Strip -systemroot | |
44 | dnl # Strip optimisation flags (-O[0-9]?). We decide our optimisation level, not python. | |
45 | dnl # -D_FORTIFY_SOURCE needs -O. | |
46 | dnl # Strip debug symbol flags (-g[0-9]?). We decide on debugging symbols, not python | |
47 | dnl # Strip -W*, we decide what warnings are important | |
48 | dnl # Strip -DNDEBUG | |
49 | mod_cflags=`echo $python3_cflags | sed -e '\ | |
50 | s/-I/-isystem/g;\ | |
51 | s/-isysroot[[ =]]\{0,1\}[[^-]]*//g;\ | |
52 | s/-O[[^[[:blank:]]]]*//g;\ | |
53 | s/-Wp,-D_FORTIFY_SOURCE=[[[:digit:]]]//g;\ | |
54 | s/-g[[^ ]]*//g;\ | |
55 | s/-W[[^ ]]*//g;\ | |
56 | s/-DNDEBUG[[[:blank:]]]*//g; | |
57 | '` | |
58 | AC_MSG_NOTICE([Sanitized cflags were \"${mod_cflags}\"]) | |
65 | 59 | |
66 | if test x$fail = x; then | |
67 | PY_PREFIX=`${PYTHON3_BIN} -c 'import sys ; print(sys.prefix)'` | |
68 | AC_MSG_NOTICE([Python sys.prefix \"${PY_PREFIX}\"]) | |
60 | python3_ldflags=`${PYTHON3_CONFIG_BIN} --ldflags` | |
61 | AC_MSG_NOTICE([${PYTHON3_CONFIG_BIN}'s ldflags were \"$python3_ldflags}\"]) | |
69 | 62 | |
70 | PY_EXEC_PREFIX=`${PYTHON3_BIN} -c 'import sys ; print(sys.exec_prefix)'` | |
71 | AC_MSG_NOTICE([Python sys.exec_prefix \"${PY_EXEC_PREFIX}\"]) | |
63 | dnl # Strip -Wl,-O1... Is -O even a valid linker flag?? | |
64 | dnl # Strip -Wl,-Bsymbolic-functions as thats not always supported or required | |
65 | dnl # Strip -Xlinker -export-dynamic as it causes weird linking issues on Linux | |
66 | dnl # See: https://bugs.python.org/issue36508 | |
67 | mod_ldflags=`echo $python3_ldflags | sed -e '\ | |
68 | s/-Wl,-O[[[:digit:]]][[[:blank:]]]*//g;\ | |
69 | s/-Wl,-Bsymbolic-functions[[[:blank:]]]*//g;\ | |
70 | s/-Xlinker -export-dynamic//g;\ | |
71 | s/-Wl,-stack_size,[[[:digit:]]]*[[[:blank:]]]//g; | |
72 | '` | |
73 | AC_MSG_NOTICE([Sanitized ldflags were \"${mod_ldflags}\"]) | |
72 | 74 | |
73 | PY_SYS_VERSION=`${PYTHON3_BIN} -c 'import sys ; print(sys.version[[0:3]])'` | |
74 | AC_MSG_NOTICE([Python sys.version \"${PY_SYS_VERSION}\"]) | |
75 | ||
76 | if test "x$PY_LIB_DIR" = "x"; then | |
77 | PY_LIB_DIR="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config" | |
78 | PY_LIB_LOC="-L$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config" | |
79 | fi | |
80 | ||
81 | PY_MAKEFILE="$PY_EXEC_PREFIX/lib/python${PY_SYS_VERSION}/config/Makefile" | |
82 | if test -f ${PY_MAKEFILE}; then | |
83 | PY_LOCAL_MOD_LIBS=`sed -n -e 's/^LOCALMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/^ *//;s/ *$//'` | |
84 | AC_MSG_NOTICE([Python local_mod_libs \"${PY_LOCAL_MOD_LIBS}\"]) | |
85 | ||
86 | PY_BASE_MOD_LIBS=`sed -n -e 's/^BASEMODLIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/^ *//;s/ *$//'` | |
87 | AC_MSG_NOTICE([Python base_mod_libs \"${PY_BASE_MOD_LIBS}\"]) | |
88 | ||
89 | PY_OTHER_LIBS=`sed -n -e 's/^LIBS=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/ / /g;s/^ *//;s/ *$//'` | |
90 | PY_OTHER_LDFLAGS=`sed -n -e 's/^LINKFORSHARED=\(.*\)/\1/p' $PY_MAKEFILE | sed -e 's/[[[:blank:]]]/ /g;s/ / /g;s/^ *//;s/ *$//'` | |
91 | AC_MSG_NOTICE([Python other_libs \"${PY_OTHER_LDFLAGS} ${PY_OTHER_LIBS}\"]) | |
92 | fi | |
93 | PY_EXTRA_LIBS="$PY_LOCALMODLIBS $PY_BASE_MOD_LIBS $PY_OTHER_LIBS" | |
94 | ||
95 | old_CFLAGS=$CFLAGS | |
96 | CFLAGS="$CFLAGS $PY_CFLAGS" | |
97 | smart_try_dir="$PY_PREFIX/include/python$PY_SYS_VERSION" | |
98 | FR_SMART_CHECK_INCLUDE(Python.h) | |
99 | 75 | CFLAGS=$old_CFLAGS |
100 | 76 | |
101 | if test "x$ac_cv_header_Python_h" = "xyes"; then | |
102 | mod_cflags="$SMART_CPPFLAGS" | |
103 | else | |
104 | fail="$fail Python.h" | |
105 | targetname= | |
106 | fi | |
107 | ||
108 | old_LIBS=$LIBS | |
109 | LIBS="$LIBS $PY_LIB_LOC $PY_EXTRA_LIBS -lm" | |
110 | smart_try_dir=$PY_LIB_DIR | |
111 | FR_SMART_CHECK_LIB(python${PY_SYS_VERSION}, Py_Initialize) | |
112 | LIBS=$old_LIBS | |
113 | ||
114 | eval t=\${ac_cv_lib_${sm_lib_safe}_${sm_func_safe}} | |
115 | if test "x$t" = "xyes"; then | |
116 | mod_ldflags="$PY_LIB_LOC $PY_EXTRA_LIBS $SMART_LIBS -lm" | |
117 | targetname=modname | |
118 | else | |
119 | FR_SMART_CHECK_LIB(python${PY_SYS_VERSION}m, Py_Initialize) | |
120 | eval t=\${ac_cv_lib_${sm_lib_safe}_${sm_func_safe}} | |
121 | if test "x$t" = "xyes"; then | |
122 | mod_ldflags="$PY_LIB_LOC $PY_EXTRA_LIBS $SMART_LIBS -lm" | |
123 | targetname=modname | |
124 | else | |
125 | targetname= | |
126 | fail="$fail libpython$PY_SYS_VERSION" | |
127 | fi | |
128 | fi | |
77 | targetname="rlm_python3" | |
129 | 78 | fi |
130 | ||
131 | AC_CHECK_FUNCS([dl_iterate_phdr]) | |
132 | 79 | else |
133 | 80 | targetname= |
134 | 81 | echo \*\*\* module modname is disabled. |
0 | #! /usr/bin/env python3 | |
1 | # | |
2 | # Python module test | |
3 | # Miguel A.L. Paraz <mparaz@mparaz.com> | |
4 | # | |
5 | # $Id$ | |
6 | ||
7 | import radiusd | |
8 | ||
9 | def instantiate(p): | |
10 | print "*** instantiate ***" | |
11 | print p | |
12 | ||
13 | def authorize(p): | |
14 | print "*** authorize ***" | |
15 | ||
16 | radiusd.radlog(radiusd.L_INFO, '*** radlog call in authorize ***') | |
17 | ||
18 | print p | |
19 | return radiusd.RLM_MODULE_OK | |
20 | ||
21 | def preacct(p): | |
22 | print "*** preacct ***" | |
23 | print p | |
24 | return radiusd.RLM_MODULE_OK | |
25 | ||
26 | def accounting(p): | |
27 | print "*** accounting ***" | |
28 | radiusd.radlog(radiusd.L_INFO, '*** radlog call in accounting (0) ***') | |
29 | ||
30 | print p | |
31 | return radiusd.RLM_MODULE_OK | |
32 | ||
33 | def pre_proxy(p): | |
34 | print "*** pre_proxy ***" | |
35 | print p | |
36 | return radiusd.RLM_MODULE_OK | |
37 | ||
38 | def post_proxy(p): | |
39 | print "*** post_proxy ***" | |
40 | print p | |
41 | return radiusd.RLM_MODULE_OK | |
42 | ||
43 | def post_auth(p): | |
44 | print "*** post_auth ***" | |
45 | print p | |
46 | return radiusd.RLM_MODULE_OK | |
47 | ||
48 | def recv_coa(p): | |
49 | print "*** recv_coa ***" | |
50 | print p | |
51 | return radiusd.RLM_MODULE_OK | |
52 | ||
53 | def send_coa(p): | |
54 | print "*** send_coa ***" | |
55 | print p | |
56 | return radiusd.RLM_MODULE_OK | |
57 | ||
58 | ||
59 | def detach(): | |
60 | print "*** goodbye from radiusd_test.py ***" | |
61 | return radiusd.RLM_MODULE_OK | |
62 |
41 | 41 | #endif |
42 | 42 | |
43 | 43 | #define LIBPYTHON_LINKER_NAME \ |
44 | "libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) "m.so" | |
44 | "libpython" STRINGIFY(PY_MAJOR_VERSION) "." STRINGIFY(PY_MINOR_VERSION) "m" LT_SHREXT | |
45 | 45 | |
46 | 46 | static uint32_t python_instances = 0; |
47 | 47 | static void *python_dlhandle; |
66 | 66 | A(preacct) |
67 | 67 | A(accounting) |
68 | 68 | A(checksimul) |
69 | #ifdef WITH_PROXY | |
69 | 70 | A(pre_proxy) |
70 | 71 | A(post_proxy) |
72 | #endif | |
71 | 73 | A(post_auth) |
72 | 74 | #ifdef WITH_COA |
73 | 75 | A(recv_coa) |
97 | 99 | A(L_AUTH) |
98 | 100 | A(L_INFO) |
99 | 101 | A(L_ERR) |
102 | #ifdef WITH_PROXY | |
100 | 103 | A(L_PROXY) |
104 | #endif | |
101 | 105 | A(L_ACCT) |
102 | 106 | A(L_DBG_WARN) |
103 | 107 | A(L_DBG_ERR) |
185 | 189 | |
186 | 190 | if (!pExcType || !pExcValue) { |
187 | 191 | ERROR("%s:%d, Unknown error", __func__, __LINE__); |
188 | if (pExcType) { | |
189 | Py_DecRef(pExcType); | |
190 | } | |
191 | if (pExcValue) { | |
192 | Py_DecRef(pExcValue); | |
193 | } | |
192 | Py_XDECREF(pExcType); | |
193 | Py_XDECREF(pExcValue); | |
194 | 194 | return; |
195 | 195 | } |
196 | 196 | |
197 | 197 | if (((pStr1 = PyObject_Str(pExcType)) != NULL) && |
198 | 198 | ((pStr2 = PyObject_Str(pExcValue)) != NULL)) { |
199 | 199 | ERROR("%s:%d, Exception type: %s, Exception value: %s", __func__, __LINE__, PyUnicode_AsUTF8(pStr1), PyUnicode_AsUTF8(pStr2)); |
200 | Py_DECREF(pStr1); | |
201 | Py_DECREF(pStr2); | |
200 | 202 | } |
201 | 203 | |
202 | 204 | if (pExcTraceback) { |
216 | 218 | char *str = PyBytes_AsString(pTraceString); |
217 | 219 | ERROR("%s:%d, full_backtrace: %s", __func__, __LINE__, str); |
218 | 220 | |
219 | if (pyth_val) { | |
220 | Py_DecRef(pyth_val); | |
221 | } | |
222 | if (pystr) { | |
223 | Py_DecRef(pystr); | |
224 | } | |
225 | if (pTraceString) { | |
226 | Py_DecRef(pTraceString); | |
227 | } | |
221 | Py_DECREF(pyth_val); | |
222 | Py_DECREF(pystr); | |
223 | Py_DECREF(pTraceString); | |
224 | Py_DECREF(pyth_func); | |
228 | 225 | } |
229 | if (pyth_func) { | |
230 | Py_DecRef(pyth_func); | |
231 | } | |
232 | Py_DecRef(pyth_module); | |
226 | Py_DECREF(pyth_module); | |
233 | 227 | } else { |
234 | 228 | ERROR("%s:%d, py_module is null, name: %p", __func__, __LINE__, module_name); |
235 | 229 | } |
236 | 230 | |
237 | if (module_name) { | |
238 | Py_DecRef(module_name); | |
239 | } | |
240 | ||
241 | Py_DecRef(pRepr); | |
242 | } | |
243 | ||
244 | if (pExcType) { | |
245 | Py_DecRef(pExcType); | |
246 | } | |
247 | if (pExcValue) { | |
248 | Py_DecRef(pExcValue); | |
249 | } | |
250 | if (pExcTraceback) { | |
251 | Py_DecRef(pExcTraceback); | |
252 | } | |
253 | if (pStr1) { | |
254 | Py_DecRef(pStr1); | |
255 | } | |
256 | if (pStr2) { | |
257 | Py_DecRef(pStr2); | |
258 | } | |
231 | Py_DECREF(module_name); | |
232 | Py_DECREF(pRepr); | |
233 | Py_DECREF(pExcTraceback); | |
234 | } | |
235 | ||
236 | Py_DECREF(pExcType); | |
237 | Py_DECREF(pExcValue); | |
259 | 238 | } |
260 | 239 | |
261 | 240 | static void mod_vptuple(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, PyObject *pValue, |
509 | 488 | goto finish; |
510 | 489 | } |
511 | 490 | |
491 | #ifdef WITH_PROXY | |
512 | 492 | /* fill proxy vps */ |
513 | 493 | if (request->proxy) { |
514 | 494 | if (!mod_populate_vps(pArgs, 4, request->proxy->vps)) { |
516 | 496 | ret = RLM_MODULE_FAIL; |
517 | 497 | goto finish; |
518 | 498 | } |
519 | } else { | |
499 | } else | |
500 | #endif | |
501 | { | |
520 | 502 | mod_populate_vps(pArgs, 4, NULL); |
521 | 503 | } |
522 | 504 | |
505 | #ifdef WITH_PROXY | |
523 | 506 | /* fill proxy_reply vps */ |
524 | 507 | if (request->proxy_reply) { |
525 | 508 | if (!mod_populate_vps(pArgs, 5, request->proxy_reply->vps)) { |
527 | 510 | ret = RLM_MODULE_FAIL; |
528 | 511 | goto finish; |
529 | 512 | } |
530 | } else { | |
513 | } else | |
514 | #endif | |
515 | { | |
531 | 516 | mod_populate_vps(pArgs, 5, NULL); |
532 | 517 | } |
533 | 518 | |
549 | 534 | PyDict_SetItemString(pDictInput, "request", PyTuple_GET_ITEM(pArgs, 0)) || |
550 | 535 | PyDict_SetItemString(pDictInput, "reply", PyTuple_GET_ITEM(pArgs, 1)) || |
551 | 536 | PyDict_SetItemString(pDictInput, "config", PyTuple_GET_ITEM(pArgs, 2)) || |
552 | PyDict_SetItemString(pDictInput, "session-state", PyTuple_GET_ITEM(pArgs, 3)) || | |
537 | PyDict_SetItemString(pDictInput, "session-state", PyTuple_GET_ITEM(pArgs, 3)) | |
538 | #ifdef WITH_PROXY | |
539 | || | |
553 | 540 | PyDict_SetItemString(pDictInput, "proxy-request", PyTuple_GET_ITEM(pArgs, 4)) || |
554 | PyDict_SetItemString(pDictInput, "proxy-reply", PyTuple_GET_ITEM(pArgs, 5))) { | |
541 | PyDict_SetItemString(pDictInput, "proxy-reply", PyTuple_GET_ITEM(pArgs, 5)) | |
542 | #endif | |
543 | ) { | |
544 | ||
555 | 545 | ERROR("%s:%d, %s - PyDict_SetItemString failed", __func__, __LINE__, funcname); |
556 | 546 | ret = RLM_MODULE_FAIL; |
557 | 547 | goto finish; |
818 | 808 | MOD_FUNC(preacct) |
819 | 809 | MOD_FUNC(accounting) |
820 | 810 | MOD_FUNC(checksimul) |
811 | #ifdef WITH_PROXY | |
821 | 812 | MOD_FUNC(pre_proxy) |
822 | 813 | MOD_FUNC(post_proxy) |
814 | #endif | |
823 | 815 | MOD_FUNC(post_auth) |
824 | 816 | #ifdef WITH_COA |
825 | 817 | MOD_FUNC(recv_coa) |
1101 | 1093 | python_dlhandle = dlopen_libpython(RTLD_NOW | RTLD_GLOBAL); |
1102 | 1094 | if (!python_dlhandle) WARN("Failed loading libpython symbols into global symbol table"); |
1103 | 1095 | |
1104 | #if PY_VERSION_HEX > 0x03050000 | |
1096 | #if PY_VERSION_HEX >= 0x03050000 | |
1105 | 1097 | { |
1106 | 1098 | wchar_t *name; |
1107 | 1099 | |
1108 | 1100 | MEM(name = Py_DecodeLocale(main_config.name, NULL)); |
1109 | 1101 | Py_SetProgramName(name); /* The value of argv[0] as a wide char string */ |
1110 | 1102 | PyMem_RawFree(name); |
1111 | } | |
1112 | #elif PY_VERSION_HEX > 0x0300000 | |
1113 | { | |
1114 | wchar_t *name; | |
1115 | ||
1116 | MEM(name = _Py_char2wchar(main_config.name, NULL)); | |
1117 | Py_SetProgramName(inst->wide_name); /* The value of argv[0] as a wide char string */ | |
1118 | 1103 | } |
1119 | 1104 | #else |
1120 | 1105 | { |
1162 | 1147 | * the lifetime of the module. |
1163 | 1148 | */ |
1164 | 1149 | if (inst->python_path) { |
1150 | char *p, *path; | |
1151 | PyObject *sys = PyImport_ImportModule("sys"); | |
1152 | PyObject *sys_path = PyObject_GetAttrString(sys, "path"); | |
1153 | ||
1154 | memcpy(&p, &inst->python_path, sizeof(path)); | |
1155 | ||
1156 | for (path = strtok(p, ":"); path != NULL; path = strtok(NULL, ":")) { | |
1165 | 1157 | #if PY_VERSION_HEX > 0x03050000 |
1166 | { | |
1167 | wchar_t *path; | |
1168 | PyObject* sys = PyImport_ImportModule("sys"); | |
1169 | PyObject* sys_path = PyObject_GetAttrString(sys,"path"); | |
1170 | ||
1171 | MEM(path = Py_DecodeLocale(inst->python_path, NULL)); | |
1172 | PyList_Append(sys_path, PyUnicode_FromWideChar(path,-1)); | |
1173 | PyObject_SetAttrString(sys,"path",sys_path); | |
1174 | PyMem_RawFree(path); | |
1158 | wchar_t *py_path; | |
1159 | ||
1160 | MEM(py_path = Py_DecodeLocale(path, NULL)); | |
1161 | PyList_Append(sys_path, PyUnicode_FromWideChar(py_path, -1)); | |
1162 | PyMem_RawFree(py_path); | |
1163 | #elif PY_VERSION_HEX > 0x03000000 | |
1164 | wchar_t *py_path; | |
1165 | ||
1166 | MEM(py_path = _Py_char2wchar(path, NULL)); | |
1167 | PyList_Append(sys_path, PyUnicode_FromWideChar(py_path, -1)); | |
1168 | PyMem_RawFree(py_path); | |
1169 | #else | |
1170 | PyList_Append(sys_path, PyLong_FromString(path)); | |
1171 | #endif | |
1175 | 1172 | } |
1176 | #elif PY_VERSION_HEX > 0x03000000 | |
1177 | { | |
1178 | wchar_t *path; | |
1179 | PyObject* sys = PyImport_ImportModule("sys"); | |
1180 | PyObject* sys_path = PyObject_GetAttrString(sys,"path"); | |
1181 | ||
1182 | MEM(path = _Py_char2wchar(inst->python_path, NULL)); | |
1183 | PyList_Append(sys_path, PyUnicode_FromWideChar(path,-1)); | |
1184 | PyObject_SetAttrString(sys,"path",sys_path); | |
1185 | } | |
1186 | #else | |
1187 | { | |
1188 | char *path; | |
1189 | ||
1190 | memcpy(&path, &inst->python_path, sizeof(path)); | |
1191 | Py_SetPath(path); | |
1192 | } | |
1193 | #endif | |
1194 | } | |
1195 | ||
1173 | ||
1174 | PyObject_SetAttrString(sys, "path", sys_path); | |
1175 | Py_DecRef(sys); | |
1176 | Py_DecRef(sys_path); | |
1177 | } | |
1196 | 1178 | } else { |
1197 | 1179 | inst->module = main_module; |
1198 | 1180 | Py_IncRef(inst->module); |
1219 | 1201 | static int mod_instantiate(CONF_SECTION *conf, void *instance) |
1220 | 1202 | { |
1221 | 1203 | rlm_python_t *inst = instance; |
1222 | int code = 0; | |
1204 | int code = RLM_MODULE_OK; | |
1223 | 1205 | |
1224 | 1206 | inst->name = cf_section_name2(conf); |
1225 | 1207 | if (!inst->name) inst->name = cf_section_name1(conf); |
1244 | 1226 | PYTHON_FUNC_LOAD(preacct); |
1245 | 1227 | PYTHON_FUNC_LOAD(accounting); |
1246 | 1228 | PYTHON_FUNC_LOAD(checksimul); |
1229 | #ifdef WITH_PROXY | |
1247 | 1230 | PYTHON_FUNC_LOAD(pre_proxy); |
1248 | 1231 | PYTHON_FUNC_LOAD(post_proxy); |
1232 | #endif | |
1249 | 1233 | PYTHON_FUNC_LOAD(post_auth); |
1250 | 1234 | #ifdef WITH_COA |
1251 | 1235 | PYTHON_FUNC_LOAD(recv_coa); |
1256 | 1240 | /* |
1257 | 1241 | * Call the instantiate function. |
1258 | 1242 | */ |
1259 | code = do_python_single(NULL, inst->instantiate.function, "instantiate", inst->pass_all_vps, inst->pass_all_vps_dict); | |
1260 | if (code < 0) { | |
1261 | error: | |
1262 | python_error_log(); /* Needs valid thread with GIL */ | |
1263 | PyEval_SaveThread(); | |
1264 | return -1; | |
1243 | if (inst->instantiate.function) { | |
1244 | code = do_python_single(NULL, inst->instantiate.function, "instantiate", inst->pass_all_vps, inst->pass_all_vps_dict); | |
1245 | if (code < 0) { | |
1246 | error: | |
1247 | python_error_log(); /* Needs valid thread with GIL */ | |
1248 | PyEval_SaveThread(); | |
1249 | return -1; | |
1250 | } | |
1265 | 1251 | } |
1266 | 1252 | PyEval_SaveThread(); |
1267 | 1253 | |
1271 | 1257 | static int mod_detach(void *instance) |
1272 | 1258 | { |
1273 | 1259 | rlm_python_t *inst = instance; |
1274 | int ret; | |
1260 | int ret = RLM_MODULE_OK; | |
1275 | 1261 | |
1276 | 1262 | /* |
1277 | 1263 | * Call module destructor |
1278 | 1264 | */ |
1279 | 1265 | PyEval_RestoreThread(inst->sub_interpreter); |
1280 | 1266 | |
1281 | ret = do_python_single(NULL, inst->detach.function, "detach", inst->pass_all_vps, inst->pass_all_vps_dict); | |
1267 | if (inst->detach.function) ret = do_python_single(NULL, inst->detach.function, "detach", inst->pass_all_vps, inst->pass_all_vps_dict); | |
1282 | 1268 | |
1283 | 1269 | #define PYTHON_FUNC_DESTROY(_x) python_function_destroy(&inst->_x) |
1284 | 1270 | PYTHON_FUNC_DESTROY(instantiate); |
1271 | PYTHON_FUNC_DESTROY(authenticate); | |
1285 | 1272 | PYTHON_FUNC_DESTROY(authorize); |
1286 | PYTHON_FUNC_DESTROY(authenticate); | |
1287 | 1273 | PYTHON_FUNC_DESTROY(preacct); |
1288 | 1274 | PYTHON_FUNC_DESTROY(accounting); |
1289 | 1275 | PYTHON_FUNC_DESTROY(checksimul); |
1276 | #ifdef WITH_PROXY | |
1277 | PYTHON_FUNC_DESTROY(pre_proxy); | |
1278 | PYTHON_FUNC_DESTROY(post_proxy); | |
1279 | #endif | |
1280 | PYTHON_FUNC_DESTROY(post_auth); | |
1281 | #ifdef WITH_COA | |
1282 | PYTHON_FUNC_DESTROY(recv_coa); | |
1283 | PYTHON_FUNC_DESTROY(send_coa); | |
1284 | #endif | |
1290 | 1285 | PYTHON_FUNC_DESTROY(detach); |
1291 | 1286 | |
1292 | 1287 | Py_DecRef(inst->pythonconf_dict); |
1312 | 1307 | PyThreadState_Swap(main_interpreter); /* Swap to the main thread */ |
1313 | 1308 | Py_Finalize(); |
1314 | 1309 | dlclose(python_dlhandle); |
1315 | ||
1316 | #if PY_VERSION_HEX > 0x03050000 | |
1317 | //if (inst->wide_name) PyMem_RawFree(inst->wide_name); | |
1318 | //if (inst->wide_path) PyMem_RawFree(inst->wide_path); | |
1319 | #endif | |
1320 | } | |
1321 | ||
1310 | } | |
1322 | 1311 | |
1323 | 1312 | return ret; |
1324 | 1313 | } |
1347 | 1336 | [MOD_PREACCT] = mod_preacct, |
1348 | 1337 | [MOD_ACCOUNTING] = mod_accounting, |
1349 | 1338 | [MOD_SESSION] = mod_checksimul, |
1339 | #ifdef WITH_PROXY | |
1350 | 1340 | [MOD_PRE_PROXY] = mod_pre_proxy, |
1351 | 1341 | [MOD_POST_PROXY] = mod_post_proxy, |
1342 | #endif | |
1352 | 1343 | [MOD_POST_AUTH] = mod_post_auth, |
1353 | 1344 | #ifdef WITH_COA |
1354 | 1345 | [MOD_RECV_COA] = mod_recv_coa, |
499 | 499 | static int sql_num_rows(rlm_sql_handle_t *handle, UNUSED rlm_sql_config_t *config) |
500 | 500 | { |
501 | 501 | rlm_sql_freetds_conn_t *conn = handle->conn; |
502 | int num; | |
503 | ||
504 | if (ct_res_info(conn->command, CS_ROW_COUNT, (CS_INT *)&num, CS_UNUSED, NULL) != CS_SUCCEED) { | |
502 | CS_INT num; | |
503 | ||
504 | if (ct_res_info(conn->command, CS_ROW_COUNT, &num, CS_UNUSED, NULL) != CS_SUCCEED) { | |
505 | 505 | ERROR("rlm_sql_freetds: error retrieving row count"); |
506 | 506 | |
507 | 507 | return RLM_SQL_ERROR; |
303 | 303 | char const *query) |
304 | 304 | { |
305 | 305 | rlm_sql_postgres_conn_t *conn = handle->conn; |
306 | struct timeval timeout = {config->query_timeout, 0}; | |
307 | int sockfd, r; | |
308 | fd_set read_fd; | |
306 | struct timeval start; | |
307 | int sockfd; | |
309 | 308 | ExecStatusType status; |
310 | 309 | int numfields = 0; |
311 | 310 | PGresult *tmp_result; |
330 | 329 | * We try to avoid blocking by waiting until the driver indicates that |
331 | 330 | * the result is ready or our timeout expires |
332 | 331 | */ |
332 | gettimeofday(&start, NULL); | |
333 | 333 | while (PQisBusy(conn->db)) { |
334 | int r; | |
335 | fd_set read_fd; | |
336 | struct timeval when, elapsed, wake; | |
337 | ||
334 | 338 | FD_ZERO(&read_fd); |
335 | 339 | FD_SET(sockfd, &read_fd); |
336 | r = select(sockfd + 1, &read_fd, NULL, NULL, config->query_timeout ? &timeout : NULL); | |
340 | ||
341 | if (config->query_timeout) { | |
342 | gettimeofday(&when, NULL); | |
343 | rad_tv_sub(&when, &start, &elapsed); | |
344 | if (elapsed.tv_sec >= config->query_timeout) goto too_long; | |
345 | ||
346 | when.tv_sec = config->query_timeout; | |
347 | when.tv_usec = 0; | |
348 | rad_tv_sub(&when, &elapsed, &wake); | |
349 | } | |
350 | ||
351 | r = select(sockfd + 1, &read_fd, NULL, NULL, config->query_timeout ? &wake : NULL); | |
337 | 352 | if (r == 0) { |
353 | too_long: | |
338 | 354 | ERROR("rlm_sql_postgresql: Socket read timeout after %d seconds", config->query_timeout); |
339 | 355 | return RLM_SQL_RECONNECT; |
340 | 356 | } |
160 | 160 | conn->row = talloc_zero_array(conn, char *, colcount + 1); /* Space for pointers */ |
161 | 161 | |
162 | 162 | for (i = 1; i <= colcount; i++) { |
163 | SQLColAttributes(conn->stmt, ((SQLUSMALLINT) i), SQL_COLUMN_LENGTH, NULL, 0, NULL, &len); | |
163 | len = 0; | |
164 | SQLColAttributes(conn->stmt, ((SQLUSMALLINT) i), SQL_DESC_LENGTH, NULL, 0, NULL, &len); | |
164 | 165 | conn->row[i - 1] = talloc_array(conn->row, char, ++len); |
165 | 166 | SQLBindCol(conn->stmt, i, SQL_C_CHAR, (SQLCHAR *)conn->row[i - 1], len, NULL); |
166 | 167 | } |
2 | 2 | if ('${feature.regex-pcre}' == 'yes') { |
3 | 3 | update request { |
4 | 4 | Tmp-Integer-0 := '123456789' |
5 | Tmp-Integer-1 := 1 | |
6 | } | |
7 | ||
8 | # Check failures when no previous capture | |
9 | if ("%{regex:}" != "") { | |
10 | update reply { | |
11 | Filter-Id += 'Fail 0.1' | |
12 | } | |
13 | } | |
14 | ||
15 | if ("%{regex:foo}" != "") { | |
16 | update reply { | |
17 | Filter-Id += 'Fail 0.2' | |
18 | } | |
19 | } | |
20 | ||
21 | if ("%{regex:%{Tmp-Integer-1}}" != "") { | |
22 | update reply { | |
23 | Filter-Id += 'Fail 0.3' | |
24 | } | |
25 | } | |
26 | ||
27 | if ("%{regex:1}" != "") { | |
28 | update reply { | |
29 | Filter-Id += 'Fail 0.4' | |
30 | } | |
5 | 31 | } |
6 | 32 | |
7 | 33 | # uncompiled - ref - named capture groups |