aboutsummaryrefslogtreecommitdiffstats
path: root/notes
diff options
context:
space:
mode:
authorDavid M. Syzdek <syzdek@bindlebinaries.com>2019-05-13 16:17:03 -0800
committerDavid M. Syzdek <syzdek@bindlebinaries.com>2019-05-13 16:17:03 -0800
commitb8d308885a9d52bfc068bce3fed63e89d8d18222 (patch)
tree38c927acced214c1d4494d799481d90c951e8ad9 /notes
parentf59af0fc6b761dcdf71d41d62e878191ed44d688 (diff)
downloadscratchpad-b8d308885a9d52bfc068bce3fed63e89d8d18222.tar.gz
scratchpad-b8d308885a9d52bfc068bce3fed63e89d8d18222.tar.bz2
scratchpad-b8d308885a9d52bfc068bce3fed63e89d8d18222.tar.xz
scratchpad-b8d308885a9d52bfc068bce3fed63e89d8d18222.zip
Simplifiing schema
Diffstat (limited to 'notes')
-rw-r--r--notes/projects/radius/sql/ippool-demo.sql18
-rw-r--r--notes/projects/radius/sql/ippool-schema.sql365
2 files changed, 174 insertions, 209 deletions
diff --git a/notes/projects/radius/sql/ippool-demo.sql b/notes/projects/radius/sql/ippool-demo.sql
index 3875eed..e6eb48a 100644
--- a/notes/projects/radius/sql/ippool-demo.sql
+++ b/notes/projects/radius/sql/ippool-demo.sql
@@ -12,16 +12,16 @@ SET ROLE radius;
12 12
13 13
14-- create example pools 14-- create example pools
15SELECT pool_add( poolName := 'DHCP' ); 15INSERT INTO pool ( name ) VALUES ( 'DHCP' );
16SELECT pool_add( poolName := 'PPPoE' ); 16INSERT INTO pool ( name ) VALUES ( 'PPPoE' );
17SELECT pool_add( poolName := 'reserved' ); 17INSERT INTO pool ( name ) VALUES ( 'reserved' );
18 18
19 19
20-- create example regions 20-- create example regions
21SELECT region_add( regionName := 'Anchorage' ); 21INSERT INTO region ( name ) VALUES ( 'Anchorage' );
22SELECT region_add( regionName := 'Soldotna' ); 22INSERT INTO region ( name ) VALUES ( 'Soldotna' );
23SELECT region_add( regionName := 'Fairbanks' ); 23INSERT INTO region ( name ) VALUES ( 'Fairbanks' );
24SELECT region_add( regionName := 'No where' ); 24INSERT INTO region ( name ) VALUES ( 'No where' );
25 25
26 26
27-- create example NAS clients 27-- create example NAS clients
@@ -118,8 +118,8 @@ SELECT ip_assign
118 118
119 119
120-- add missing IP addresses to netblock 120-- add missing IP addresses to netblock
121SELECT ip_add_network( ipNetwork := '209.112.192.0/19' ); 121-- SELECT ip_add_network( ipNetwork := '209.112.192.0/19' );
122SELECT ip_add_network( ipNetwork := '209.112.128.0/18' ); 122-- SELECT ip_add_network( ipNetwork := '209.112.128.0/18' );
123 123
124 124
125/* end of sql */ 125/* end of sql */
diff --git a/notes/projects/radius/sql/ippool-schema.sql b/notes/projects/radius/sql/ippool-schema.sql
index b048b72..ea50e5d 100644
--- a/notes/projects/radius/sql/ippool-schema.sql
+++ b/notes/projects/radius/sql/ippool-schema.sql
@@ -19,14 +19,14 @@ SET client_min_messages TO WARNING;
19-- ////////////////// 19-- //////////////////
20 20
21 21
22-- GRANT CONNECT 22GRANT CONNECT
23-- ON DATABASE radius_ippool 23 ON DATABASE radius_ippool
24-- TO radius_user; 24 TO radius_user;
25 25
26 26
27GRANT USAGE 27--GRANT USAGE
28 ON SCHEMA public 28-- ON SCHEMA public
29 TO radius_user; 29-- TO radius_user;
30 30
31 31
32ALTER DEFAULT PRIVILEGES 32ALTER DEFAULT PRIVILEGES
@@ -183,6 +183,9 @@ CREATE INDEX
183 * address 183 * address
184 * : user assignable IP address 184 * : user assignable IP address
185 * 185 *
186 * netblockId
187 * : reference to owning netblock
188 *
186 * modified 189 * modified
187 * : timestamp generated when entry is modified 190 * : timestamp generated when entry is modified
188 * 191 *
@@ -198,6 +201,7 @@ CREATE INDEX
198CREATE TABLE IF NOT EXISTS ip 201CREATE TABLE IF NOT EXISTS ip
199( 202(
200 address INET, 203 address INET,
204 netblockId INTEGER NOT NULL,
201 modified timestamp WITH TIME ZONE NOT NULL 205 modified timestamp WITH TIME ZONE NOT NULL
202 DEFAULT TIMESTAMP 'epoch', 206 DEFAULT TIMESTAMP 'epoch',
203 username VARCHAR(64), 207 username VARCHAR(64),
@@ -206,12 +210,16 @@ CREATE TABLE IF NOT EXISTS ip
206 PRIMARY KEY ( address ), 210 PRIMARY KEY ( address ),
207 FOREIGN KEY ( nasId ) 211 FOREIGN KEY ( nasId )
208 REFERENCES nas 212 REFERENCES nas
213 ( id ),
214 FOREIGN KEY ( netblockId )
215 REFERENCES netblock
209 ( id ) 216 ( id )
210); 217);
211CREATE INDEX 218CREATE INDEX
212 IF NOT EXISTS ip_index 219 IF NOT EXISTS ip_index
213 ON ip 220 ON ip
214 ( address, 221 ( address,
222 netblockId,
215 modified, 223 modified,
216 username, 224 username,
217 acctSession, 225 acctSession,
@@ -231,15 +239,26 @@ CREATE INDEX
231 * % SELECT ip_add_network( 239 * % SELECT ip_add_network(
232 * ipNetwork := '198.51.100.0/24' 240 * ipNetwork := '198.51.100.0/24'
233 * ); 241 * );
242 * % SELECT ip_add_network(
243 * ipNetblockId := (
244 * SELECT id
245 * FROM netblock
246 * WHERE network = '198.51.100.0/24'
247 * )
248 * );
234 * 249 *
235 * ipNetwork 250 * ipNetwork
236 * : network address and network size being added to database 251 * : network address and network size being added to database
237 * 252 *
253 * ipNetblockId
254 * : reference to netblock to add to database
255 *
238 * Returns the number of new IP addresses registered 256 * Returns the number of new IP addresses registered
239 */ 257 */
240CREATE OR REPLACE FUNCTION ip_add_network 258CREATE OR REPLACE FUNCTION ip_add_network
241( 259(
242 ipNetwork CIDR 260 ipNetwork CIDR DEFAULT NULL,
261 ipNetblockId INTEGER DEFAULT NULL
243) 262)
244 RETURNS INTEGER 263 RETURNS INTEGER
245 LANGUAGE plpgsql 264 LANGUAGE plpgsql
@@ -247,17 +266,28 @@ CREATE OR REPLACE FUNCTION ip_add_network
247 AS $$ 266 AS $$
248DECLARE 267DECLARE
249 ipAddress INET; 268 ipAddress INET;
250 resultCount INTEGER; 269 resultAddress INET;
251 ipAdded INTEGER; 270 ipAdded INTEGER;
252 ipMask INTEGER; 271 ipMask INTEGER;
253BEGIN 272BEGIN
254 273
255 -- searches for a matching netblock 274 -- verifies input
256 SELECT count(network) INTO resultCount 275 IF ( ( ipNetwork IS NULL ) AND ( ipNetblockId IS NULL ) ) THEN
257 FROM netblock 276 RAISE EXCEPTION 'must specify either ipNetwork or ipNetblockId';
258 WHERE network >>= ipNetwork; 277 END IF;
259 IF ( resultCount = 0 ) THEN 278
260 RAISE EXCEPTION 'matching netblock not found'; 279 -- determines netblock
280 if ( ipNetblockId IS NULL ) THEN
281 SELECT id INTO ipNetblockId
282 FROM netblock
283 WHERE network >>= ipNetwork;
284 ELSE
285 SELECT network INTO ipNetwork
286 FROM netblock
287 WHERE id = ipNetblockId;
288 END IF;
289 if ( ( ipNetblockId IS NULL ) OR ( ipNetwork IS NULL ) ) THEN
290 RAISE EXCEPTION 'specified netblock does not exist';
261 END IF; 291 END IF;
262 292
263 -- restricts access to IPv4 addresses 293 -- restricts access to IPv4 addresses
@@ -273,16 +303,16 @@ BEGIN
273 LOOP 303 LOOP
274 EXIT WHEN ipAddress > set_masklen( broadcast(ipNetwork), 32 ); 304 EXIT WHEN ipAddress > set_masklen( broadcast(ipNetwork), 32 );
275 305
276 -- searches for existing IP address 306 INSERT INTO ip
277 SELECT count( address ) INTO resultCount 307 ( address,
278 FROM ip 308 netblockId
279 WHERE address = ipAddress; 309 )
280 310 SELECT ipAddress,
281 -- defines IP address if not defined and counts results 311 ipNetblockId
282 IF ( resultCount = 0 ) THEN 312 WHERE NOT EXISTS
283 INSERT INTO ip 313 ( SELECT address FROM ip WHERE address = ipAddress )
284 ( address ) 314 RETURNING address INTO resultAddress;
285 VALUES ( ipAddress ); 315 IF ( resultAddress IS NOT NULL ) THEN
286 ipAdded := ipAdded + 1; 316 ipAdded := ipAdded + 1;
287 END IF; 317 END IF;
288 ipAddress := ipAddress + 1; 318 ipAddress := ipAddress + 1;
@@ -335,7 +365,7 @@ $$;
335 * 365 *
336 * returns trigger 366 * returns trigger
337 */ 367 */
338CREATE OR REPLACE FUNCTION ip_trigger 368CREATE OR REPLACE FUNCTION ip_trigger_delete
339( ) 369( )
340 RETURNS trigger 370 RETURNS trigger
341 LANGUAGE plpgsql 371 LANGUAGE plpgsql
@@ -343,57 +373,58 @@ CREATE OR REPLACE FUNCTION ip_trigger
343DECLARE 373DECLARE
344BEGIN 374BEGIN
345 375
346 -- prevents IP address from being modified 376 -- verifies ip is not assigned to a RADIUS accounting session
347 IF ( ( TG_OP = 'UPDATE' ) AND ( NEW.address != OLD.address ) ) THEN 377 IF ( OLD.nasId IS NOT NULL ) THEN
348 RAISE EXCEPTION 'address cannot be modified'; 378 RAISE EXCEPTION 'IP address is still assigned to NAS session';
349 END IF; 379 END IF;
350 380
381 RETURN NEW;
382END;
383$$;
384
385
386/*
387 * forces initial values on insert
388 *
389 * returns trigger
390 */
391CREATE OR REPLACE FUNCTION ip_trigger_insert
392( )
393 RETURNS trigger
394 LANGUAGE plpgsql
395 AS $$
396DECLARE
397BEGIN
398
351 -- forces initial values 399 -- forces initial values
352 IF ( TG_OP = 'INSERT' ) THEN 400 NEW.username := NULL;
353 NEW.username := NULL; 401 NEW.acctSession := NULL;
354 NEW.acctSession := NULL; 402 NEW.nasId := NULL;
355 NEW.nasId := NULL; 403 NEW.modified := TIMESTAMP 'epoch';
356 END IF;
357 404
358 -- determines mask for single IP address 405 -- determines mask for single IP address
359 IF ( family(NEW.address) != 4 ) THEN 406 IF ( family(NEW.address) != 4 ) THEN
360 RAISE EXCEPTION 'only IPv4 addresses are supported'; 407 RAISE EXCEPTION 'only IPv4 addresses are supported';
361 END IF; 408 END IF;
362 409
363 -- update timestamp
364 IF ( TG_OP = 'UPDATE' ) THEN
365 NEW.modified := current_timestamp;
366 ELSIF ( TG_OP = 'INSERT' ) THEN
367 NEW.modified := TIMESTAMP 'epoch';
368 END IF;
369
370 RETURN NEW; 410 RETURN NEW;
371END; 411END;
372$$; 412$$;
373 413
374 414
375/* 415/*
376 * updates timestamp of addresses 416 * verifies no assigned IP addresses before truncating
377 * 417 *
378 * returns trigger 418 * returns trigger
379 */ 419 */
380CREATE OR REPLACE FUNCTION ip_trigger_delete 420CREATE OR REPLACE FUNCTION ip_trigger_truncate
381( ) 421( )
382 RETURNS trigger 422 RETURNS trigger
383 LANGUAGE plpgsql 423 LANGUAGE plpgsql
384 AS $$ 424 AS $$
385DECLARE 425DECLARE
386BEGIN 426BEGIN
387 -- verifies ip is not assigned to a RADIUS accounting session 427 RAISE EXCEPTION 'DO NOT TRUNCATE IP TABLE';
388 IF ( OLD.acctSession IS NOT NULL ) THEN
389 RAISE EXCEPTION 'IP address is still assigned to accounting session';
390 END IF;
391
392 -- verifies ip is not assigned to a RADIUS accounting session
393 IF ( OLD.nasId IS NOT NULL ) THEN
394 RAISE EXCEPTION 'IP address is still assigned to NAS session';
395 END IF;
396
397 RETURN NEW; 428 RETURN NEW;
398END; 429END;
399$$; 430$$;
@@ -404,23 +435,22 @@ $$;
404 * 435 *
405 * returns trigger 436 * returns trigger
406 */ 437 */
407CREATE OR REPLACE FUNCTION ip_trigger_truncate 438CREATE OR REPLACE FUNCTION ip_trigger_update
408( ) 439( )
409 RETURNS trigger 440 RETURNS trigger
410 LANGUAGE plpgsql 441 LANGUAGE plpgsql
411 AS $$ 442 AS $$
412DECLARE 443DECLARE
413 resultCount INTEGER;
414BEGIN 444BEGIN
415 -- searches for assigned IP addresses 445
416 SELECT count( address ) INTO resultCount 446 -- prevents IP address from being modified
417 FROM ip 447 IF ( NEW.address != OLD.address ) THEN
418 WHERE acctSession IS NOT NULL 448 RAISE EXCEPTION 'address cannot be modified';
419 OR nasId IS NOT NULL;
420 IF ( resultCount != 0 ) THEN
421 RAISE EXCEPTION 'IP addresses are still assigned to sessions';
422 END IF; 449 END IF;
423 450
451 -- update timestamp
452 NEW.modified := current_timestamp;
453
424 RETURN NEW; 454 RETURN NEW;
425END; 455END;
426$$; 456$$;
@@ -479,6 +509,27 @@ $$;
479 509
480 510
481/* 511/*
512 * updates timestamp of addresses
513 *
514 * returns trigger
515 */
516CREATE OR REPLACE FUNCTION nas_trigger_insert_or_update
517( )
518 RETURNS trigger
519 LANGUAGE plpgsql
520 AS $$
521DECLARE
522BEGIN
523
524 -- normalizes name
525 NEW.name = lower( NEW.name );
526
527 RETURN NEW;
528END;
529$$;
530
531
532/*
482 * Creates entry for network block 533 * Creates entry for network block
483 * 534 *
484 * % SELECT netblock_add( 535 * % SELECT netblock_add(
@@ -534,6 +585,11 @@ DECLARE
534 returnId INTEGER DEFAULT 1; 585 returnId INTEGER DEFAULT 1;
535BEGIN 586BEGIN
536 587
588 -- restricts access to IPv4 addresses
589 IF ( family(netAddress) != 4 ) THEN
590 RAISE EXCEPTION 'only IPv4 addresses are supported';
591 END IF;
592
537 -- searches for region id 593 -- searches for region id
538 if ( regionName IS NOT NULL ) THEN 594 if ( regionName IS NOT NULL ) THEN
539 SELECT id INTO netRegionId 595 SELECT id INTO netRegionId
@@ -567,7 +623,7 @@ BEGIN
567 623
568 -- adds IP entries 624 -- adds IP entries
569 if ( addIpEntries IS NOT FALSE ) THEN 625 if ( addIpEntries IS NOT FALSE ) THEN
570 PERFORM ip_add_network( ipNetwork := netAddress ); 626 PERFORM ip_add_network( ipNetblockId := returnId);
571 END IF; 627 END IF;
572 628
573 RETURN returnId; 629 RETURN returnId;
@@ -580,7 +636,7 @@ $$;
580 * 636 *
581 * returns trigger 637 * returns trigger
582 */ 638 */
583CREATE OR REPLACE FUNCTION netblock_trigger 639CREATE OR REPLACE FUNCTION netblock_trigger_insert_or_update
584( ) 640( )
585 RETURNS trigger 641 RETURNS trigger
586 LANGUAGE plpgsql 642 LANGUAGE plpgsql
@@ -625,34 +681,20 @@ $$;
625 681
626 682
627/* 683/*
628 * adds contraints to netblocks 684 * updates timestamp of addresses
629 * 685 *
630 * returns trigger 686 * returns trigger
631 */ 687 */
632CREATE OR REPLACE FUNCTION netblock_trigger_delete 688CREATE OR REPLACE FUNCTION pool_trigger_insert_or_update
633( ) 689( )
634 RETURNS trigger 690 RETURNS trigger
635 LANGUAGE plpgsql 691 LANGUAGE plpgsql
636 AS $$ 692 AS $$
637DECLARE 693DECLARE
638 resultCount INTEGER;
639BEGIN 694BEGIN
640 -- checks for IP addresses which would be orphaned 695
641 SELECT count( address ) INTO resultCount 696 -- normalizes name
642 FROM ip 697 NEW.name = lower( NEW.name );
643 WHERE address NOT IN
644 (
645 SELECT address
646 FROM ip
647 INNER JOIN netblock
648 ON ip.address <<= netblock.network
649 WHERE ip.address <<= OLD.network
650 AND netblock.network <> OLD.network
651 )
652 AND address <<= OLD.network;
653 IF ( resultCount != 0 ) THEN
654 RAISE EXCEPTION 'IP addresses still defined within netblock';
655 END IF;
656 698
657 RETURN NEW; 699 RETURN NEW;
658END; 700END;
@@ -660,119 +702,22 @@ $$;
660 702
661 703
662/* 704/*
663 * adds contraints to netblocks 705 * updates timestamp of addresses
664 * 706 *
665 * returns trigger 707 * returns trigger
666 */ 708 */
667CREATE OR REPLACE FUNCTION netblock_trigger_truncate 709CREATE OR REPLACE FUNCTION region_trigger_insert_or_update
668( ) 710( )
669 RETURNS trigger 711 RETURNS trigger
670 LANGUAGE plpgsql 712 LANGUAGE plpgsql
671 AS $$ 713 AS $$
672DECLARE 714DECLARE
673 resultCount INTEGER;
674BEGIN 715BEGIN
675 -- checks for IP addresses which would be orphaned
676 SELECT count( address ) INTO resultCount
677 FROM ip;
678 IF ( resultCount != 0 ) THEN
679 RAISE EXCEPTION 'IP addresses still defined';
680 END IF;
681
682 RETURN NEW;
683END;
684$$;
685
686
687
688/*
689 * Creates entry for IP Pool
690 *
691 * % SELECT pool_add(
692 * poolName := 'dhcp'
693 * );
694 * % SELECT pool_add(
695 * poolName := 'dhcp',
696 * poolDesc := 'Pool of IP addresses for PPPoE connections'
697 * );
698 *
699 * poolName
700 * : name of pool being created in the database
701 *
702 * poolDesc
703 * : human readable description of the pool
704 *
705 * Returns the `id` of the created pool
706 */
707CREATE OR REPLACE FUNCTION pool_add
708(
709 poolName VARCHAR(32),
710 poolDesc VARCHAR(128) DEFAULT NULL
711)
712 RETURNS INTEGER
713 LANGUAGE plpgsql
714 SECURITY DEFINER
715 AS $$
716DECLARE
717 returnId INTEGER;
718BEGIN
719 -- adds new pool
720 INSERT INTO pool
721 ( name,
722 description
723 )
724 VALUES ( lower(poolName),
725 poolDesc
726 )
727 RETURNING id INTO returnId;
728
729 RETURN returnId;
730END;
731$$;
732 716
717 -- normalizes name
718 NEW.name = lower( NEW.name );
733 719
734/* 720 RETURN NEW;
735 * Creates entry for geographic region
736 *
737 * % SELECT region_add(
738 * regionName := 'Anchorage'
739 * );
740 * % SELECT region_add(
741 * regionName := 'Anchorage',
742 * regionDesc := 'Anchorage Area'
743 * );
744 *
745 * regionName
746 * : name of region being created in the database
747 *
748 * regionDesc
749 * : human readable description of the region
750 *
751 * Returns the `id` of the created pool
752 */
753CREATE OR REPLACE FUNCTION region_add
754(
755 regionName VARCHAR(32),
756 regionDesc VARCHAR(128) DEFAULT NULL
757)
758 RETURNS INTEGER
759 LANGUAGE plpgsql
760 SECURITY DEFINER
761 AS $$
762DECLARE
763 returnId INTEGER;
764BEGIN
765 -- adds new pool
766 INSERT INTO region
767 ( name,
768 description
769 )
770 VALUES ( lower(regionName),
771 regionDesc
772 )
773 RETURNING id INTO returnId;
774
775 RETURN returnId;
776END; 721END;
777$$; 722$$;
778 723
@@ -784,37 +729,57 @@ $$;
784-- //////////////// 729-- ////////////////
785 730
786-- address table triggers 731-- address table triggers
787CREATE TRIGGER ip_trigger
788 BEFORE INSERT OR UPDATE
789 ON ip
790 FOR EACH ROW
791 EXECUTE PROCEDURE ip_trigger();
792CREATE TRIGGER ip_trigger_delete 732CREATE TRIGGER ip_trigger_delete
793 BEFORE DELETE 733 BEFORE DELETE
794 ON ip 734 ON ip
795 FOR EACH ROW 735 FOR EACH ROW
796 EXECUTE PROCEDURE ip_trigger_delete(); 736 EXECUTE PROCEDURE ip_trigger_delete();
737CREATE TRIGGER ip_trigger_insert
738 BEFORE INSERT
739 ON ip
740 FOR EACH ROW
741 EXECUTE PROCEDURE ip_trigger_insert();
797CREATE TRIGGER ip_trigger_truncate 742CREATE TRIGGER ip_trigger_truncate
798 BEFORE TRUNCATE 743 BEFORE TRUNCATE
799 ON ip 744 ON ip
800 FOR EACH STATEMENT 745 FOR EACH STATEMENT
801 EXECUTE PROCEDURE ip_trigger_truncate(); 746 EXECUTE PROCEDURE ip_trigger_truncate();
747CREATE TRIGGER ip_trigger_update
748 BEFORE UPDATE
749 ON ip
750 FOR EACH ROW
751 EXECUTE PROCEDURE ip_trigger_update();
752
802 753
803-- netblock table triggers 754-- netblock table triggers
804CREATE TRIGGER netblock_trigger 755CREATE TRIGGER netblock_trigger_insert_or_update
805 BEFORE INSERT OR UPDATE 756 BEFORE INSERT OR UPDATE
806 ON netblock 757 ON netblock
807 FOR EACH ROW 758 FOR EACH ROW
808 EXECUTE PROCEDURE netblock_trigger(); 759 EXECUTE PROCEDURE netblock_trigger_insert_or_update();
809CREATE TRIGGER netblock_trigger_delete 760
810 BEFORE DELETE 761
811 ON netblock 762-- nas table triggers
763CREATE TRIGGER nas_trigger_insert_or_update
764 BEFORE INSERT OR UPDATE
765 ON nas
812 FOR EACH ROW 766 FOR EACH ROW
813 EXECUTE PROCEDURE netblock_trigger_delete(); 767 EXECUTE PROCEDURE nas_trigger_insert_or_update();
814CREATE TRIGGER netblock_trigger_truncate 768
815 BEFORE TRUNCATE 769
816 ON netblock 770-- pool table triggers
817 FOR EACH STATEMENT 771CREATE TRIGGER pool_trigger_insert_or_update
818 EXECUTE PROCEDURE netblock_trigger_truncate(); 772 BEFORE INSERT OR UPDATE
773 ON pool
774 FOR EACH ROW
775 EXECUTE PROCEDURE pool_trigger_insert_or_update();
776
777
778-- region table triggers
779CREATE TRIGGER region_trigger_insert_or_update
780 BEFORE INSERT OR UPDATE
781 ON region
782 FOR EACH ROW
783 EXECUTE PROCEDURE region_trigger_insert_or_update();
819 784
820/* end of sql */ 785/* end of sql */