mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr.git
				synced 2025-11-04 06:03:28 +00:00 
			
		
		
		
	Compare commits
	
		
			447 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					65f51535d0 | ||
| 
						 | 
					386381662c | ||
| 
						 | 
					777860ddb5 | ||
| 
						 | 
					1d0a030aa4 | ||
| 
						 | 
					3ca9a1fd4f | ||
| 
						 | 
					b74769f1b4 | ||
| 
						 | 
					140dffd8f7 | ||
| 
						 | 
					d63ec88dba | ||
| 
						 | 
					e427bb299f | ||
| 
						 | 
					d456fced21 | ||
| 
						 | 
					c772e525ef | ||
| 
						 | 
					83a41471da | ||
| 
						 | 
					b4f25a0d1a | ||
| 
						 | 
					b246580900 | ||
| 
						 | 
					0c13953ed0 | ||
| 
						 | 
					77a1bf66e6 | ||
| 
						 | 
					37a5b70195 | ||
| 
						 | 
					4d7cbfcc9a | ||
| 
						 | 
					bfeea69cab | ||
| 
						 | 
					3f9d1977df | ||
| 
						 | 
					608e2e483f | ||
| 
						 | 
					60673e7f77 | ||
| 
						 | 
					ca8e6efca6 | ||
| 
						 | 
					ed2e36316b | ||
| 
						 | 
					649c335602 | ||
| 
						 | 
					6240465503 | ||
| 
						 | 
					8c9087dd16 | ||
| 
						 | 
					2bd1a45553 | ||
| 
						 | 
					d6993ea4b5 | ||
| 
						 | 
					f551ccf9fb | ||
| 
						 | 
					b5a5676cff | ||
| 
						 | 
					89fda3024a | ||
| 
						 | 
					dd746949d0 | ||
| 
						 | 
					cc90bfd0f4 | ||
| 
						 | 
					f4d64cb98b | ||
| 
						 | 
					bd94b41fa8 | ||
| 
						 | 
					6e237d3a90 | ||
| 
						 | 
					dac855e5c8 | ||
| 
						 | 
					6a6c7f87ca | ||
| 
						 | 
					6cfef3ac26 | ||
| 
						 | 
					66f0b5fbea | ||
| 
						 | 
					c47d5c0d77 | ||
| 
						 | 
					dfbc2cbbc2 | ||
| 
						 | 
					89649ea997 | ||
| 
						 | 
					23ac586522 | ||
| 
						 | 
					de50b20116 | ||
| 
						 | 
					ed18fa908c | ||
| 
						 | 
					f464fff173 | ||
| 
						 | 
					e893eeb1b3 | ||
| 
						 | 
					b77d568196 | ||
| 
						 | 
					80cb6c93b9 | ||
| 
						 | 
					565cf83a42 | ||
| 
						 | 
					fa20702e67 | ||
| 
						 | 
					949a53cdf0 | ||
| 
						 | 
					102e362943 | ||
| 
						 | 
					2f7fb2e36b | ||
| 
						 | 
					377fe5a645 | ||
| 
						 | 
					c7ea21357a | ||
| 
						 | 
					9b8e7b4e39 | ||
| 
						 | 
					010ceb8206 | ||
| 
						 | 
					1bd3ec49b1 | ||
| 
						 | 
					dfe6f41c81 | ||
| 
						 | 
					3e79a38440 | ||
| 
						 | 
					a450a85956 | ||
| 
						 | 
					26b4905e7f | ||
| 
						 | 
					d9b3606234 | ||
| 
						 | 
					0d82a87c0d | ||
| 
						 | 
					9489a9ce4b | ||
| 
						 | 
					edc27ef390 | ||
| 
						 | 
					af748923bd | ||
| 
						 | 
					76328bdc91 | ||
| 
						 | 
					407925dcab | ||
| 
						 | 
					ab7dc40f16 | ||
| 
						 | 
					86b507b6ea | ||
| 
						 | 
					d017d7b215 | ||
| 
						 | 
					04c2375b38 | ||
| 
						 | 
					939f508f00 | ||
| 
						 | 
					c79bcdedc9 | ||
| 
						 | 
					ad868e29ba | ||
| 
						 | 
					0c27a4c2d1 | ||
| 
						 | 
					08358b2752 | ||
| 
						 | 
					5424dcb879 | ||
| 
						 | 
					f0e90e6bd5 | ||
| 
						 | 
					15ad7bef5f | ||
| 
						 | 
					74e7072f63 | ||
| 
						 | 
					4fa9653733 | ||
| 
						 | 
					5e5ce4aef2 | ||
| 
						 | 
					9e533f666d | ||
| 
						 | 
					544b15d3fa | ||
| 
						 | 
					89afb7f78b | ||
| 
						 | 
					b1775162ea | ||
| 
						 | 
					f55f605931 | ||
| 
						 | 
					fbe4929543 | ||
| 
						 | 
					e53a34a7e1 | ||
| 
						 | 
					52ef60fe96 | ||
| 
						 | 
					3a9f267983 | ||
| 
						 | 
					5436c77a96 | ||
| 
						 | 
					110a49f69f | ||
| 
						 | 
					41fe362591 | ||
| 
						 | 
					0bb8fce2f1 | ||
| 
						 | 
					637bbfcd92 | ||
| 
						 | 
					f10463c5fc | ||
| 
						 | 
					bf7deda0fc | ||
| 
						 | 
					81b92bbe69 | ||
| 
						 | 
					3a66698d87 | ||
| 
						 | 
					276c5a7719 | ||
| 
						 | 
					80dc9ae4be | ||
| 
						 | 
					a377c41bd4 | ||
| 
						 | 
					06f5af22c8 | ||
| 
						 | 
					07e1602d2d | ||
| 
						 | 
					abdfdb8a4a | ||
| 
						 | 
					7355d0ddfe | ||
| 
						 | 
					6b305b4c30 | ||
| 
						 | 
					a7d0f87eb7 | ||
| 
						 | 
					981e126686 | ||
| 
						 | 
					7143f3a0cb | ||
| 
						 | 
					f0968798a2 | ||
| 
						 | 
					2f75803e5d | ||
| 
						 | 
					7f4dd11682 | ||
| 
						 | 
					a8045daeef | ||
| 
						 | 
					4359b885d4 | ||
| 
						 | 
					5b65461d68 | ||
| 
						 | 
					f8ad67e7fc | ||
| 
						 | 
					c3d40326ec | ||
| 
						 | 
					a9f8a4bdce | ||
| 
						 | 
					f5459de2e2 | ||
| 
						 | 
					7d2843df4c | ||
| 
						 | 
					2b0bf31183 | ||
| 
						 | 
					28f0774e34 | ||
| 
						 | 
					b07f33df41 | ||
| 
						 | 
					8b860e54be | ||
| 
						 | 
					9cf0030b6a | ||
| 
						 | 
					b9b224c7bd | ||
| 
						 | 
					e49391bfc4 | ||
| 
						 | 
					fbd736ef37 | ||
| 
						 | 
					dc30154fdf | ||
| 
						 | 
					37642177f9 | ||
| 
						 | 
					6401b90574 | ||
| 
						 | 
					5b5cac7e94 | ||
| 
						 | 
					937f583a7e | ||
| 
						 | 
					4ca7f6a17e | ||
| 
						 | 
					b64cb27003 | ||
| 
						 | 
					3b33b01fb0 | ||
| 
						 | 
					78abea6a0e | ||
| 
						 | 
					9ac494f486 | ||
| 
						 | 
					d62d401d07 | ||
| 
						 | 
					103c11bd24 | ||
| 
						 | 
					63de00cfc1 | ||
| 
						 | 
					1a1398ed54 | ||
| 
						 | 
					a8253a54ba | ||
| 
						 | 
					29f371fddf | ||
| 
						 | 
					2e403d6c3f | ||
| 
						 | 
					c41572330d | ||
| 
						 | 
					c7f1787c18 | ||
| 
						 | 
					c13599dc69 | ||
| 
						 | 
					6b73fd9678 | ||
| 
						 | 
					cd2af5ead7 | ||
| 
						 | 
					e21b45aecd | ||
| 
						 | 
					5857c595b3 | ||
| 
						 | 
					d9724f4298 | ||
| 
						 | 
					c69a18bb3d | ||
| 
						 | 
					8625cdaf2a | ||
| 
						 | 
					609978d0ab | ||
| 
						 | 
					28f0af872e | ||
| 
						 | 
					9f6e558215 | ||
| 
						 | 
					633fe291f5 | ||
| 
						 | 
					7d53ae1db8 | ||
| 
						 | 
					95abc2be17 | ||
| 
						 | 
					f1fe94c8ca | ||
| 
						 | 
					f7d3251d9a | ||
| 
						 | 
					3cf87fe22c | ||
| 
						 | 
					ee7c0cb8d9 | ||
| 
						 | 
					c5044cfd80 | ||
| 
						 | 
					20ddfdbc53 | ||
| 
						 | 
					227834b6bc | ||
| 
						 | 
					44a2180009 | ||
| 
						 | 
					f9cf180ebe | ||
| 
						 | 
					02078b7d91 | ||
| 
						 | 
					ef64b231dc | ||
| 
						 | 
					851814aa7c | ||
| 
						 | 
					81db389fd4 | ||
| 
						 | 
					7943e26938 | ||
| 
						 | 
					e0c6fe5921 | ||
| 
						 | 
					f58f44543f | ||
| 
						 | 
					15f624ec53 | ||
| 
						 | 
					d4e0e4d503 | ||
| 
						 | 
					2dc7d960a1 | ||
| 
						 | 
					52c4aa09b2 | ||
| 
						 | 
					66106c0992 | ||
| 
						 | 
					783ac81b9c | ||
| 
						 | 
					df8d454919 | ||
| 
						 | 
					9ea9bbbc7f | ||
| 
						 | 
					5c14c9ccca | ||
| 
						 | 
					705b61bcb7 | ||
| 
						 | 
					638ba8cc04 | ||
| 
						 | 
					55f5efa568 | ||
| 
						 | 
					e6ce52bbde | ||
| 
						 | 
					d157a56361 | ||
| 
						 | 
					9c8806acf5 | ||
| 
						 | 
					4b8be4d12d | ||
| 
						 | 
					bc9bead62a | ||
| 
						 | 
					4655e6f1fe | ||
| 
						 | 
					8f3a7cce80 | ||
| 
						 | 
					a820ea1f67 | ||
| 
						 | 
					8aa780bf80 | ||
| 
						 | 
					f08da2459b | ||
| 
						 | 
					62ce834fbf | ||
| 
						 | 
					bf6b4eb0b9 | ||
| 
						 | 
					79efdf3474 | ||
| 
						 | 
					b41394a700 | ||
| 
						 | 
					0c331abdbc | ||
| 
						 | 
					25e716c849 | ||
| 
						 | 
					92e49ef363 | ||
| 
						 | 
					95380ab037 | ||
| 
						 | 
					849bfd0bef | ||
| 
						 | 
					7e2d3c7f4c | ||
| 
						 | 
					8f725ae655 | ||
| 
						 | 
					1ed4bb4ff1 | ||
| 
						 | 
					25dd785157 | ||
| 
						 | 
					4f5f6f83f3 | ||
| 
						 | 
					e66e525e09 | ||
| 
						 | 
					4a4bdcdf97 | ||
| 
						 | 
					cb364bb429 | ||
| 
						 | 
					d646207553 | ||
| 
						 | 
					6cee799d5e | ||
| 
						 | 
					c88bdab96d | ||
| 
						 | 
					607ce5ca93 | ||
| 
						 | 
					ccdb970c57 | ||
| 
						 | 
					a5b36a0904 | ||
| 
						 | 
					13000d8d14 | ||
| 
						 | 
					7ebfd065da | ||
| 
						 | 
					966fcb2ca8 | ||
| 
						 | 
					6fe1c2220a | ||
| 
						 | 
					0da9f2f19c | ||
| 
						 | 
					1eb9869d81 | ||
| 
						 | 
					3adb33de93 | ||
| 
						 | 
					791ea72ee4 | ||
| 
						 | 
					9f7b69a618 | ||
| 
						 | 
					e6c839ed2d | ||
| 
						 | 
					b93c44f32e | ||
| 
						 | 
					a05efe8803 | ||
| 
						 | 
					764514198b | ||
| 
						 | 
					5198609a5e | ||
| 
						 | 
					7c2f430fc5 | ||
| 
						 | 
					633fddebcd | ||
| 
						 | 
					7c5e930aa8 | ||
| 
						 | 
					83df349045 | ||
| 
						 | 
					05fe0233d2 | ||
| 
						 | 
					2781bb767e | ||
| 
						 | 
					f473c7b23c | ||
| 
						 | 
					dab544e14b | ||
| 
						 | 
					7d29d59292 | ||
| 
						 | 
					55d32a1e3c | ||
| 
						 | 
					95b96d4245 | ||
| 
						 | 
					9b6bc9e479 | ||
| 
						 | 
					7f32f5f3e6 | ||
| 
						 | 
					7266731eca | ||
| 
						 | 
					97bfb65eeb | ||
| 
						 | 
					bb77939a86 | ||
| 
						 | 
					4956ae1f70 | ||
| 
						 | 
					d5807b8c87 | ||
| 
						 | 
					21c14fc7f4 | ||
| 
						 | 
					050eb1d803 | ||
| 
						 | 
					dc17e05e28 | ||
| 
						 | 
					953d27ce8f | ||
| 
						 | 
					ec6915a771 | ||
| 
						 | 
					9fdb854174 | ||
| 
						 | 
					4793a7efc3 | ||
| 
						 | 
					527d934807 | ||
| 
						 | 
					6b274b95fc | ||
| 
						 | 
					edca4f88a6 | ||
| 
						 | 
					b9c1028cb0 | ||
| 
						 | 
					1442e3a3d3 | ||
| 
						 | 
					0b8f054b5f | ||
| 
						 | 
					fa7ee333f7 | ||
| 
						 | 
					8fbf82b83f | ||
| 
						 | 
					bd72f1331d | ||
| 
						 | 
					32acace879 | ||
| 
						 | 
					b85f60477f | ||
| 
						 | 
					a1d3b048fb | ||
| 
						 | 
					f83432c25c | ||
| 
						 | 
					78f4301025 | ||
| 
						 | 
					1b8a1dc00a | ||
| 
						 | 
					9d307ec7ae | ||
| 
						 | 
					5aeb438194 | ||
| 
						 | 
					cb360f06c8 | ||
| 
						 | 
					1cb489231a | ||
| 
						 | 
					93c5b10310 | ||
| 
						 | 
					ec9440f1bc | ||
| 
						 | 
					51530311a8 | ||
| 
						 | 
					f162252a08 | ||
| 
						 | 
					8f8401453c | ||
| 
						 | 
					70e7f21cb1 | ||
| 
						 | 
					2e78858756 | ||
| 
						 | 
					3f2a9a2ab1 | ||
| 
						 | 
					880a34d2ef | ||
| 
						 | 
					7ee6e554af | ||
| 
						 | 
					9214c6c7ef | ||
| 
						 | 
					79fc6984ac | ||
| 
						 | 
					ba1605afdc | ||
| 
						 | 
					b6265d1a55 | ||
| 
						 | 
					6c84da5942 | ||
| 
						 | 
					84c2f43d00 | ||
| 
						 | 
					63f68ccc4c | ||
| 
						 | 
					b5d77012d1 | ||
| 
						 | 
					fc96f688d4 | ||
| 
						 | 
					43bd6069e8 | ||
| 
						 | 
					2dee60ef44 | ||
| 
						 | 
					ab4d509a83 | ||
| 
						 | 
					bd1dca0859 | ||
| 
						 | 
					33eeeef9dc | ||
| 
						 | 
					33cbde9ced | ||
| 
						 | 
					671db90ac3 | ||
| 
						 | 
					d3814b936b | ||
| 
						 | 
					6f3e8d6297 | ||
| 
						 | 
					db5dae6c99 | ||
| 
						 | 
					38f08770a3 | ||
| 
						 | 
					aee7be901b | ||
| 
						 | 
					8db490695d | ||
| 
						 | 
					c82e6ad190 | ||
| 
						 | 
					0959e8b354 | ||
| 
						 | 
					4f3841c153 | ||
| 
						 | 
					bd0d5bf5d8 | ||
| 
						 | 
					87a04b6b95 | ||
| 
						 | 
					85e8a64bb4 | ||
| 
						 | 
					0dcbd47a1e | ||
| 
						 | 
					71b5f5b923 | ||
| 
						 | 
					73d14af278 | ||
| 
						 | 
					6eb231eccc | ||
| 
						 | 
					dbced93b5f | ||
| 
						 | 
					88c91f6fb2 | ||
| 
						 | 
					7750d2cedc | ||
| 
						 | 
					cd7fa4502c | ||
| 
						 | 
					99a14c8ca1 | ||
| 
						 | 
					c6a6d26f50 | ||
| 
						 | 
					3f697cdc71 | ||
| 
						 | 
					446eb0f1bc | ||
| 
						 | 
					234f9cb701 | ||
| 
						 | 
					16140f70c5 | ||
| 
						 | 
					36bec87104 | ||
| 
						 | 
					00b1d43435 | ||
| 
						 | 
					7ae8d878cf | ||
| 
						 | 
					68f87915e4 | ||
| 
						 | 
					e86437cae4 | ||
| 
						 | 
					200f56e995 | ||
| 
						 | 
					50e4de7e49 | ||
| 
						 | 
					86d09ec266 | ||
| 
						 | 
					183e7009af | ||
| 
						 | 
					b6837e36a3 | ||
| 
						 | 
					2e86ab3a87 | ||
| 
						 | 
					c5122f2829 | ||
| 
						 | 
					1cbdb70b27 | ||
| 
						 | 
					76328e57d1 | ||
| 
						 | 
					57a8792f23 | ||
| 
						 | 
					1332a17a3d | ||
| 
						 | 
					e50121ec96 | ||
| 
						 | 
					dd783056f7 | ||
| 
						 | 
					e8ccd5013a | ||
| 
						 | 
					9c2bbc840f | ||
| 
						 | 
					32633e2b89 | ||
| 
						 | 
					d7d9697d85 | ||
| 
						 | 
					9850946013 | ||
| 
						 | 
					f7c3e6e3a2 | ||
| 
						 | 
					28da26ec19 | ||
| 
						 | 
					cd83b8a44c | ||
| 
						 | 
					d3cd102505 | ||
| 
						 | 
					d4bb51ba1f | ||
| 
						 | 
					1e31d18822 | ||
| 
						 | 
					e9c0c5b272 | ||
| 
						 | 
					3522819d8b | ||
| 
						 | 
					40aa61ccf0 | ||
| 
						 | 
					0cac0a067e | ||
| 
						 | 
					f31445915e | ||
| 
						 | 
					518335e688 | ||
| 
						 | 
					4bde949b34 | ||
| 
						 | 
					32c38f09e5 | ||
| 
						 | 
					f88c914efd | ||
| 
						 | 
					f95ce04cbd | ||
| 
						 | 
					05c8b465ab | ||
| 
						 | 
					43bf7bc5c5 | ||
| 
						 | 
					0b1b6b1f1e | ||
| 
						 | 
					84201d3a4b | ||
| 
						 | 
					62491379f1 | ||
| 
						 | 
					02098d9d22 | ||
| 
						 | 
					886ecef1c0 | ||
| 
						 | 
					1f3a1ce1a3 | ||
| 
						 | 
					69f3860d28 | ||
| 
						 | 
					ce9bc40846 | ||
| 
						 | 
					1790c8246a | ||
| 
						 | 
					63b7e86dcf | ||
| 
						 | 
					0ad929b418 | ||
| 
						 | 
					6fb234c251 | ||
| 
						 | 
					743cf42ac5 | ||
| 
						 | 
					9d27398e5b | ||
| 
						 | 
					edebc22989 | ||
| 
						 | 
					cab2fcd5b5 | ||
| 
						 | 
					ee392bb3b1 | ||
| 
						 | 
					ea1052d300 | ||
| 
						 | 
					d846ae8978 | ||
| 
						 | 
					7f39468c75 | ||
| 
						 | 
					e9d37db7f2 | ||
| 
						 | 
					5ecdc56ad4 | ||
| 
						 | 
					9cacb6f74b | ||
| 
						 | 
					372868baa3 | ||
| 
						 | 
					adc6648841 | ||
| 
						 | 
					d4bebbd855 | ||
| 
						 | 
					4436dececd | ||
| 
						 | 
					21380ae55e | ||
| 
						 | 
					b5b11e31fb | ||
| 
						 | 
					8d97d34f58 | ||
| 
						 | 
					428c9478cd | ||
| 
						 | 
					3aa3c103c2 | ||
| 
						 | 
					569d322597 | ||
| 
						 | 
					ec9036bdd2 | ||
| 
						 | 
					3ce3686768 | ||
| 
						 | 
					58d4a84a31 | ||
| 
						 | 
					00b3715723 | ||
| 
						 | 
					ea8b0d46eb | ||
| 
						 | 
					aa0fefd5d6 | ||
| 
						 | 
					27c6b9016a | ||
| 
						 | 
					f8c7b6f3c9 | ||
| 
						 | 
					912a303fec | ||
| 
						 | 
					cc785f0c43 | ||
| 
						 | 
					6b883f7848 | ||
| 
						 | 
					8cde66242a | ||
| 
						 | 
					00c069726e | ||
| 
						 | 
					8089d51f74 | ||
| 
						 | 
					d71dbec7b6 | ||
| 
						 | 
					862f1dc4fd | ||
| 
						 | 
					24537b95bd | ||
| 
						 | 
					7685a78757 | ||
| 
						 | 
					7f9491fe5f | ||
| 
						 | 
					ca43e30be3 | ||
| 
						 | 
					5b581ac6eb | ||
| 
						 | 
					2116ce2471 | ||
| 
						 | 
					0acd31e9a6 | ||
| 
						 | 
					4307ad94b6 | ||
| 
						 | 
					627de84abe | ||
| 
						 | 
					2fc63a6e84 | ||
| 
						 | 
					21229a06be | ||
| 
						 | 
					54db5e712d | ||
| 
						 | 
					c317cc20c8 | ||
| 
						 | 
					cb2a63406e | ||
| 
						 | 
					3e6a69d2ab | ||
| 
						 | 
					ec1b959496 | ||
| 
						 | 
					6eed322063 | ||
| 
						 | 
					40d8b01dea | 
							
								
								
									
										70
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,72 @@
 | 
				
			|||||||
*.o
 | 
					*.o
 | 
				
			||||||
 | 
					*.lo
 | 
				
			||||||
 | 
					*.la
 | 
				
			||||||
*.db
 | 
					*.db
 | 
				
			||||||
src/hlr
 | 
					*.db-shm
 | 
				
			||||||
 | 
					*.db-wal
 | 
				
			||||||
 | 
					*.pyc
 | 
				
			||||||
 | 
					.*.sw?
 | 
				
			||||||
 | 
					.version
 | 
				
			||||||
 | 
					.tarball-version
 | 
				
			||||||
 | 
					Makefile
 | 
				
			||||||
 | 
					Makefile.in
 | 
				
			||||||
 | 
					aclocal.m4
 | 
				
			||||||
 | 
					autom4te.cache
 | 
				
			||||||
 | 
					compile
 | 
				
			||||||
 | 
					config.guess
 | 
				
			||||||
 | 
					config.log
 | 
				
			||||||
 | 
					config.status
 | 
				
			||||||
 | 
					config.sub
 | 
				
			||||||
 | 
					configure
 | 
				
			||||||
 | 
					depcomp
 | 
				
			||||||
 | 
					install-sh
 | 
				
			||||||
 | 
					libtool
 | 
				
			||||||
 | 
					ltmain.sh
 | 
				
			||||||
 | 
					m4
 | 
				
			||||||
 | 
					*.m4
 | 
				
			||||||
 | 
					missing
 | 
				
			||||||
 | 
					.deps
 | 
				
			||||||
 | 
					*~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*.pc
 | 
				
			||||||
 | 
					.libs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
src/db_test
 | 
					src/db_test
 | 
				
			||||||
 | 
					src/db_bootstrap.h
 | 
				
			||||||
 | 
					src/osmo-hlr
 | 
				
			||||||
 | 
					src/osmo-hlr-db-tool
 | 
				
			||||||
 | 
					src/osmo-euse-demo
 | 
				
			||||||
 | 
					src/gsupclient/gsup-test-client
 | 
				
			||||||
 | 
					src/mslookup/osmo-mslookup-client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tests/atconfig
 | 
				
			||||||
 | 
					tests/testsuite
 | 
				
			||||||
 | 
					tests/testsuite.log
 | 
				
			||||||
 | 
					tests/testsuite.dir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tests/auc/auc_3g_test
 | 
				
			||||||
 | 
					tests/auc/auc_ts_55_205_test_sets.c
 | 
				
			||||||
 | 
					tests/auc/auc_ts_55_205_test_sets
 | 
				
			||||||
 | 
					tests/auc/auc_test
 | 
				
			||||||
 | 
					tests/gsup_server/gsup_server_test
 | 
				
			||||||
 | 
					tests/gsup/gsup_test
 | 
				
			||||||
 | 
					tests/db/db_test
 | 
				
			||||||
 | 
					tests/hlr_vty_test.db*
 | 
				
			||||||
 | 
					tests/db_upgrade/*.dump
 | 
				
			||||||
 | 
					tests/mslookup/mdns_test
 | 
				
			||||||
 | 
					tests/mslookup/mslookup_client_mdns_test
 | 
				
			||||||
 | 
					tests/mslookup/mslookup_client_test
 | 
				
			||||||
 | 
					tests/mslookup/mslookup_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# manuals
 | 
				
			||||||
 | 
					doc/manuals/*.html
 | 
				
			||||||
 | 
					doc/manuals/*.svg
 | 
				
			||||||
 | 
					doc/manuals/*.pdf
 | 
				
			||||||
 | 
					doc/manuals/*__*.png
 | 
				
			||||||
 | 
					doc/manuals/*.check
 | 
				
			||||||
 | 
					doc/manuals/generated/
 | 
				
			||||||
 | 
					doc/manuals/osmomsc-usermanual.xml
 | 
				
			||||||
 | 
					doc/manuals/common
 | 
				
			||||||
 | 
					doc/manuals/build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					contrib/osmo-hlr.spec
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								.gitreview
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitreview
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					[gerrit]
 | 
				
			||||||
 | 
					host=gerrit.osmocom.org
 | 
				
			||||||
 | 
					project=osmo-hlr
 | 
				
			||||||
							
								
								
									
										31
									
								
								Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					AUTOMAKE_OPTIONS = foreign dist-bzip2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SUBDIRS = \
 | 
				
			||||||
 | 
						src \
 | 
				
			||||||
 | 
						include \
 | 
				
			||||||
 | 
						doc \
 | 
				
			||||||
 | 
						sql \
 | 
				
			||||||
 | 
						contrib \
 | 
				
			||||||
 | 
						tests \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_DIST = \
 | 
				
			||||||
 | 
						.version \
 | 
				
			||||||
 | 
						contrib/osmo-hlr.spec.in \
 | 
				
			||||||
 | 
						debian \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AM_DISTCHECK_CONFIGURE_FLAGS = \
 | 
				
			||||||
 | 
						--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pkgconfigdir = $(libdir)/pkgconfig
 | 
				
			||||||
 | 
					pkgconfig_DATA = libosmo-gsup-client.pc \
 | 
				
			||||||
 | 
							 libosmo-mslookup.pc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@RELMAKE@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BUILT_SOURCES = $(top_srcdir)/.version
 | 
				
			||||||
 | 
					$(top_srcdir)/.version:
 | 
				
			||||||
 | 
						echo $(VERSION) > $@-t && mv $@-t $@
 | 
				
			||||||
 | 
					dist-hook:
 | 
				
			||||||
 | 
						echo $(VERSION) > $(distdir)/.tarball-version
 | 
				
			||||||
							
								
								
									
										65
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					osmo-hlr - Osmocom HLR Implementation
 | 
				
			||||||
 | 
					=====================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This repository contains a C-language implementation of a GSM Home
 | 
				
			||||||
 | 
					Location Register (HLR). It is part of the
 | 
				
			||||||
 | 
					[Osmocom](https://osmocom.org/) Open Source Mobile Communications
 | 
				
			||||||
 | 
					project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Warning: While the HLR logical functionality is implemented, OsmoHLR
 | 
				
			||||||
 | 
					does not use the ETSI/3GPP TCAP/MAP protocol stack. Instead, a much
 | 
				
			||||||
 | 
					simpler custom protocol (GSUP) is used.  This means, OsmoHLR is of
 | 
				
			||||||
 | 
					no use outside the context of an Osmocom core network.  You can use
 | 
				
			||||||
 | 
					it with OsmoMSC, OsmoSGSN etc. - but not with third party components.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Homepage
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The official homepage of the project is
 | 
				
			||||||
 | 
					https://osmocom.org/projects/osmo-hlr/wiki
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GIT Repository
 | 
				
			||||||
 | 
					--------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can clone from the official osmo-hlr.git repository using
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git clone https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There is a web interface at <https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Documentation
 | 
				
			||||||
 | 
					-------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					User Manuals and VTY reference manuals are [optionally] built in PDF form
 | 
				
			||||||
 | 
					as part of the build process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Pre-rendered PDF version of the current "master" can be found at
 | 
				
			||||||
 | 
					[User Manual](https://ftp.osmocom.org/docs/latest/osmohlr-usermanual.pdf)
 | 
				
			||||||
 | 
					as well as the VTY reference manuals
 | 
				
			||||||
 | 
					* [VTY Reference Manual for osmo-hlr](https://ftp.osmocom.org/docs/latest/osmohlr-vty-reference.pdf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Mailing List
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Discussions related to osmo-hlr are happening on the
 | 
				
			||||||
 | 
					openbsc@lists.osmocom.org mailing list, please see
 | 
				
			||||||
 | 
					https://lists.osmocom.org/mailman/listinfo/openbsc for subscription
 | 
				
			||||||
 | 
					options and the list archive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please observe the [Osmocom Mailing List
 | 
				
			||||||
 | 
					Rules](https://osmocom.org/projects/cellular-infrastructure/wiki/Mailing_List_Rules)
 | 
				
			||||||
 | 
					when posting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Contributing
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Our coding standards are described at
 | 
				
			||||||
 | 
					https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We us a gerrit based patch submission/review process for managing
 | 
				
			||||||
 | 
					contributions.  Please see
 | 
				
			||||||
 | 
					https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit for
 | 
				
			||||||
 | 
					more details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The current patch queue for osmo-hlr can be seen at
 | 
				
			||||||
 | 
					https://gerrit.osmocom.org/#/q/project:osmo-hlr+status:open
 | 
				
			||||||
							
								
								
									
										9
									
								
								TODO-RELEASE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								TODO-RELEASE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install
 | 
				
			||||||
 | 
					# according to https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
 | 
				
			||||||
 | 
					# In short:
 | 
				
			||||||
 | 
					# LIBVERSION=c:r:a
 | 
				
			||||||
 | 
					# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a.
 | 
				
			||||||
 | 
					# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0.
 | 
				
			||||||
 | 
					# If any interfaces have been added since the last public release: c:r:a + 1.
 | 
				
			||||||
 | 
					# If any interfaces have been removed or changed since the last public release: c:r:0.
 | 
				
			||||||
 | 
					#library        what            description / commit summary line
 | 
				
			||||||
							
								
								
									
										213
									
								
								configure.ac
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								configure.ac
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
				
			|||||||
 | 
					AC_INIT([osmo-hlr],
 | 
				
			||||||
 | 
						m4_esyscmd([./git-version-gen .tarball-version]),
 | 
				
			||||||
 | 
						[openbsc@lists.osmocom.org])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl *This* is the root dir, even if an install-sh exists in ../ or ../../
 | 
				
			||||||
 | 
					AC_CONFIG_AUX_DIR([.])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl libtool init
 | 
				
			||||||
 | 
					LT_INIT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip 1.9])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_CONFIG_TESTDIR(tests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CFLAGS="$CFLAGS -std=gnu11"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl kernel style compile messages
 | 
				
			||||||
 | 
					m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl include release helper
 | 
				
			||||||
 | 
					RELMAKE='-include osmo-release.mk'
 | 
				
			||||||
 | 
					AC_SUBST([RELMAKE])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl checks for programs
 | 
				
			||||||
 | 
					AC_PROG_MAKE_SET
 | 
				
			||||||
 | 
					AC_PROG_MKDIR_P
 | 
				
			||||||
 | 
					AC_PROG_CC
 | 
				
			||||||
 | 
					AC_PROG_INSTALL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl patching ${archive_cmds} to affect generation of file "libtool" to fix linking with clang
 | 
				
			||||||
 | 
					AS_CASE(["$LD"],[*clang*],
 | 
				
			||||||
 | 
					  [AS_CASE(["${host_os}"],
 | 
				
			||||||
 | 
					     [*linux*],[archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'])])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl check for pkg-config (explained in detail in libosmocore/configure.ac)
 | 
				
			||||||
 | 
					AC_PATH_PROG(PKG_CONFIG_INSTALLED, pkg-config, no)
 | 
				
			||||||
 | 
					if test "x$PKG_CONFIG_INSTALLED" = "xno"; then
 | 
				
			||||||
 | 
					        AC_MSG_WARN([You need to install pkg-config])
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					PKG_PROG_PKG_CONFIG([0.20])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(TALLOC, [talloc >= 2.0.1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.7.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.7.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.7.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.7.0)
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 1.3.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PKG_CHECK_MODULES(SQLITE3, sqlite3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_CONFIG_MACRO_DIR([m4])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dnl checks for header files
 | 
				
			||||||
 | 
					AC_HEADER_STDC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(sanitize,
 | 
				
			||||||
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
 | 
							[--enable-sanitize],
 | 
				
			||||||
 | 
							[Compile with address sanitizer enabled],
 | 
				
			||||||
 | 
						)],
 | 
				
			||||||
 | 
						[sanitize=$enableval], [sanitize="no"])
 | 
				
			||||||
 | 
					if test x"$sanitize" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						CFLAGS="$CFLAGS -fsanitize=address -fsanitize=undefined"
 | 
				
			||||||
 | 
						CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_ARG_ENABLE([sqlite_talloc],
 | 
				
			||||||
 | 
							AC_HELP_STRING([--enable-sqlite-talloc],
 | 
				
			||||||
 | 
									[Configure SQLite3 to use talloc memory allocator [default=no]]),
 | 
				
			||||||
 | 
							[sqlite_talloc="$enableval"],[sqlite_talloc="no"])
 | 
				
			||||||
 | 
					if test "x$sqlite_talloc" = "xyes" ; then
 | 
				
			||||||
 | 
						# Older versions of SQLite3 (at least 3.8.2) become unstable with talloc.
 | 
				
			||||||
 | 
						# Feel free to relax to 3.24.0 > VER > 3.8.2 if it works for you.
 | 
				
			||||||
 | 
						# FIXME: PKG_CHECK_MODULES() may return cached result here!
 | 
				
			||||||
 | 
						PKG_CHECK_MODULES(SQLITE3, sqlite3 >= 3.24.0)
 | 
				
			||||||
 | 
						AC_DEFINE([SQLITE_USE_TALLOC], 1, [Use talloc for SQLite3])
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					AC_MSG_CHECKING([whether to use talloc for SQLite3])
 | 
				
			||||||
 | 
					AC_MSG_RESULT([$sqlite_talloc])
 | 
				
			||||||
 | 
					AM_CONDITIONAL([DB_SQLITE_DEBUG], [test "x$sqlite_talloc" = "xyes"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(werror,
 | 
				
			||||||
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
 | 
							[--enable-werror],
 | 
				
			||||||
 | 
							[Turn all compiler warnings into errors, with exceptions:
 | 
				
			||||||
 | 
							 a) deprecation (allow upstream to mark deprecation without breaking builds);
 | 
				
			||||||
 | 
							 b) "#warning" pragmas (allow to remind ourselves of errors without breaking builds)
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						)],
 | 
				
			||||||
 | 
						[werror=$enableval], [werror="no"])
 | 
				
			||||||
 | 
					if test x"$werror" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						WERROR_FLAGS="-Werror"
 | 
				
			||||||
 | 
						WERROR_FLAGS+=" -Wno-error=deprecated -Wno-error=deprecated-declarations"
 | 
				
			||||||
 | 
						WERROR_FLAGS+=" -Wno-error=cpp" # "#warning"
 | 
				
			||||||
 | 
						CFLAGS="$CFLAGS $WERROR_FLAGS"
 | 
				
			||||||
 | 
						CPPFLAGS="$CPPFLAGS $WERROR_FLAGS"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_ARG_ENABLE([external_tests],
 | 
				
			||||||
 | 
							AC_HELP_STRING([--enable-external-tests],
 | 
				
			||||||
 | 
									[Include the VTY/CTRL tests in make check [default=no]]),
 | 
				
			||||||
 | 
							[enable_ext_tests="$enableval"],[enable_ext_tests="no"])
 | 
				
			||||||
 | 
					if test "x$enable_ext_tests" = "xyes" ; then
 | 
				
			||||||
 | 
						AM_PATH_PYTHON
 | 
				
			||||||
 | 
						AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmotestvty.py,yes)
 | 
				
			||||||
 | 
						 if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then
 | 
				
			||||||
 | 
							AC_MSG_ERROR([Please install https://gitea.osmocom.org/cellular-infrastructure/osmo-python-tests to run the VTY/CTRL tests.])
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					AC_MSG_CHECKING([whether to enable VTY/CTRL tests])
 | 
				
			||||||
 | 
					AC_MSG_RESULT([$enable_ext_tests])
 | 
				
			||||||
 | 
					AM_CONDITIONAL(ENABLE_EXT_TESTS, test "x$enable_ext_tests" = "xyes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# mslookup_client_mdns_test (OS#4385: does not work everywhere)
 | 
				
			||||||
 | 
					AC_ARG_ENABLE([mslookup_client_mdns_test],
 | 
				
			||||||
 | 
							AC_HELP_STRING([--enable-mslookup-client-mdns-test],
 | 
				
			||||||
 | 
									[Include the mslookup_client_mdns_test in make check [default=no]]),
 | 
				
			||||||
 | 
							[enable_mslookup_client_mdns_test="$enableval"],[enable_mslookup_client_mdns_test="no"])
 | 
				
			||||||
 | 
					AC_MSG_CHECKING([whether to enable mslookup_client_mdns_test])
 | 
				
			||||||
 | 
					AC_MSG_RESULT([$enable_mslookup_client_mdns_test])
 | 
				
			||||||
 | 
					AM_CONDITIONAL(ENABLE_MSLOOKUP_CLIENT_MDNS_TEST, test "x$enable_mslookup_client_mdns_test" = "xyes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Generate manuals
 | 
				
			||||||
 | 
					AC_ARG_ENABLE(manuals,
 | 
				
			||||||
 | 
						[AS_HELP_STRING(
 | 
				
			||||||
 | 
							[--enable-manuals],
 | 
				
			||||||
 | 
							[Generate manual PDFs [default=no]],
 | 
				
			||||||
 | 
						)],
 | 
				
			||||||
 | 
						[osmo_ac_build_manuals=$enableval], [osmo_ac_build_manuals="no"])
 | 
				
			||||||
 | 
					AM_CONDITIONAL([BUILD_MANUALS], [test x"$osmo_ac_build_manuals" = x"yes"])
 | 
				
			||||||
 | 
					AC_ARG_VAR(OSMO_GSM_MANUALS_DIR, [path to common osmo-gsm-manuals files, overriding pkg-config and "../osmo-gsm-manuals"
 | 
				
			||||||
 | 
						fallback])
 | 
				
			||||||
 | 
					if test x"$osmo_ac_build_manuals" = x"yes"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						# Find OSMO_GSM_MANUALS_DIR (env, pkg-conf, fallback)
 | 
				
			||||||
 | 
						if test -n "$OSMO_GSM_MANUALS_DIR"; then
 | 
				
			||||||
 | 
							echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from env)"
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							OSMO_GSM_MANUALS_DIR="$($PKG_CONFIG osmo-gsm-manuals --variable=osmogsmmanualsdir 2>/dev/null)"
 | 
				
			||||||
 | 
							if test -n "$OSMO_GSM_MANUALS_DIR"; then
 | 
				
			||||||
 | 
								echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (from pkg-conf)"
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								OSMO_GSM_MANUALS_DIR="../osmo-gsm-manuals"
 | 
				
			||||||
 | 
								echo "checking for OSMO_GSM_MANUALS_DIR... $OSMO_GSM_MANUALS_DIR (fallback)"
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						if ! test -d "$OSMO_GSM_MANUALS_DIR"; then
 | 
				
			||||||
 | 
							AC_MSG_ERROR("OSMO_GSM_MANUALS_DIR does not exist! Install osmo-gsm-manuals or set OSMO_GSM_MANUALS_DIR.")
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Find and run check-depends
 | 
				
			||||||
 | 
						CHECK_DEPENDS="$OSMO_GSM_MANUALS_DIR/check-depends.sh"
 | 
				
			||||||
 | 
						if ! test -x "$CHECK_DEPENDS"; then
 | 
				
			||||||
 | 
							CHECK_DEPENDS="osmo-gsm-manuals-check-depends"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						if ! $CHECK_DEPENDS; then
 | 
				
			||||||
 | 
							AC_MSG_ERROR("missing dependencies for --enable-manuals")
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Put in Makefile with absolute path
 | 
				
			||||||
 | 
						OSMO_GSM_MANUALS_DIR="$(realpath "$OSMO_GSM_MANUALS_DIR")"
 | 
				
			||||||
 | 
						AC_SUBST([OSMO_GSM_MANUALS_DIR])
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# https://www.freedesktop.org/software/systemd/man/daemon.html
 | 
				
			||||||
 | 
					AC_ARG_WITH([systemdsystemunitdir],
 | 
				
			||||||
 | 
					     [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])],,
 | 
				
			||||||
 | 
					     [with_systemdsystemunitdir=auto])
 | 
				
			||||||
 | 
					AS_IF([test "x$with_systemdsystemunitdir" = "xyes" -o "x$with_systemdsystemunitdir" = "xauto"], [
 | 
				
			||||||
 | 
					     def_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     AS_IF([test "x$def_systemdsystemunitdir" = "x"],
 | 
				
			||||||
 | 
					   [AS_IF([test "x$with_systemdsystemunitdir" = "xyes"],
 | 
				
			||||||
 | 
					    [AC_MSG_ERROR([systemd support requested but pkg-config unable to query systemd package])])
 | 
				
			||||||
 | 
					    with_systemdsystemunitdir=no],
 | 
				
			||||||
 | 
					   [with_systemdsystemunitdir="$def_systemdsystemunitdir"])])
 | 
				
			||||||
 | 
					AS_IF([test "x$with_systemdsystemunitdir" != "xno"],
 | 
				
			||||||
 | 
					      [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])])
 | 
				
			||||||
 | 
					AM_CONDITIONAL([HAVE_SYSTEMD], [test "x$with_systemdsystemunitdir" != "xno"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_MSG_RESULT([CFLAGS="$CFLAGS"])
 | 
				
			||||||
 | 
					AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AC_OUTPUT(
 | 
				
			||||||
 | 
						Makefile
 | 
				
			||||||
 | 
						doc/Makefile
 | 
				
			||||||
 | 
						doc/examples/Makefile
 | 
				
			||||||
 | 
						src/Makefile
 | 
				
			||||||
 | 
						src/gsupclient/Makefile
 | 
				
			||||||
 | 
						src/mslookup/Makefile
 | 
				
			||||||
 | 
						include/Makefile
 | 
				
			||||||
 | 
						include/osmocom/Makefile
 | 
				
			||||||
 | 
						include/osmocom/hlr/Makefile
 | 
				
			||||||
 | 
						include/osmocom/mslookup/Makefile
 | 
				
			||||||
 | 
						libosmo-gsup-client.pc
 | 
				
			||||||
 | 
						libosmo-mslookup.pc
 | 
				
			||||||
 | 
						sql/Makefile
 | 
				
			||||||
 | 
						doc/manuals/Makefile
 | 
				
			||||||
 | 
						contrib/Makefile
 | 
				
			||||||
 | 
						contrib/systemd/Makefile
 | 
				
			||||||
 | 
						contrib/dgsm/Makefile
 | 
				
			||||||
 | 
						contrib/osmo-hlr.spec
 | 
				
			||||||
 | 
						tests/Makefile
 | 
				
			||||||
 | 
						tests/auc/Makefile
 | 
				
			||||||
 | 
						tests/auc/gen_ts_55_205_test_sets/Makefile
 | 
				
			||||||
 | 
						tests/gsup/Makefile
 | 
				
			||||||
 | 
						tests/db/Makefile
 | 
				
			||||||
 | 
						tests/db_upgrade/Makefile
 | 
				
			||||||
 | 
						tests/mslookup/Makefile
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
							
								
								
									
										14
									
								
								contrib/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								contrib/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					SUBDIRS = \
 | 
				
			||||||
 | 
						systemd \
 | 
				
			||||||
 | 
						dgsm \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_DIST = osmo-hlr-post-upgrade.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install-data-hook:
 | 
				
			||||||
 | 
						install -Dm755 $(srcdir)/osmo-hlr-post-upgrade.sh \
 | 
				
			||||||
 | 
							-t $(DESTDIR)$(datadir)/osmocom/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uninstall-hook:
 | 
				
			||||||
 | 
						@$(PRE_UNINSTALL)
 | 
				
			||||||
 | 
						$(RM) $(DESTDIR)$(datadir)/osmocom/osmo-hlr-post-upgrade.sh
 | 
				
			||||||
							
								
								
									
										6
									
								
								contrib/dgsm/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								contrib/dgsm/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					EXTRA_DIST = \
 | 
				
			||||||
 | 
						esme_dgsm.py \
 | 
				
			||||||
 | 
						freeswitch_dialplan_dgsm.py \
 | 
				
			||||||
 | 
						osmo-mslookup-pipe.py \
 | 
				
			||||||
 | 
						osmo-mslookup-socket.py \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
							
								
								
									
										184
									
								
								contrib/dgsm/esme_dgsm.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										184
									
								
								contrib/dgsm/esme_dgsm.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,184 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					Copyright 2019 sysmocom s.f.m.c GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WARNING: this is just a proof-of-concept implementation, it blocks for every
 | 
				
			||||||
 | 
					received SMPP request and is not suitable for servicing more than one request
 | 
				
			||||||
 | 
					at a time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Based on esme.py from RCCN (license changed with permission from author):
 | 
				
			||||||
 | 
					https://github.com/Rhizomatica/rccn/blob/master/rccn/esme.py
 | 
				
			||||||
 | 
					Copyright 2017 keith <keith@rhizomatica.org>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Forward SMS to the receiver's SMSC, as determined with mslookup.
 | 
				
			||||||
 | 
					Requires smpplip (pip3 install --user smpplib) and osmo-mslookup-client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example SMPP configuration for osmo-msc.cfg:
 | 
				
			||||||
 | 
					smpp
 | 
				
			||||||
 | 
					 local-tcp-ip 127.0.0.1 2775
 | 
				
			||||||
 | 
					 policy closed
 | 
				
			||||||
 | 
					 smpp-first
 | 
				
			||||||
 | 
					# outgoing to esme_dgsm.py
 | 
				
			||||||
 | 
					 esme OSMPP
 | 
				
			||||||
 | 
					  no alert-notifications
 | 
				
			||||||
 | 
					  password foo
 | 
				
			||||||
 | 
					  default-route
 | 
				
			||||||
 | 
					# incoming from esme_dgsm.py
 | 
				
			||||||
 | 
					 esme ISMPP
 | 
				
			||||||
 | 
					  no alert-notifications
 | 
				
			||||||
 | 
					  password foo
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					import smpplib
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def can_handle_pdu(pdu):
 | 
				
			||||||
 | 
					    if not isinstance(pdu, smpplib.command.DeliverSM):
 | 
				
			||||||
 | 
					        logging.info('PDU is not a DeliverSM, ignoring')
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if int(pdu.dest_addr_ton) == smpplib.consts.SMPP_TON_INTL:
 | 
				
			||||||
 | 
					        logging.info("Unable to handle SMS for %s: SMPP_TON_INTL" %
 | 
				
			||||||
 | 
					                     (pdu.destination_addr))
 | 
				
			||||||
 | 
					        return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def query_mslookup(service_type, id, id_type='msisdn'):
 | 
				
			||||||
 | 
					    query_str = '%s.%s.%s' % (service_type, id, id_type)
 | 
				
			||||||
 | 
					    logging.info('mslookup: ' + query_str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result_line = subprocess.check_output(['osmo-mslookup-client', query_str,
 | 
				
			||||||
 | 
					                                           '-f', 'json'])
 | 
				
			||||||
 | 
					    if isinstance(result_line, bytes):
 | 
				
			||||||
 | 
					        result_line = result_line.decode('ascii')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    logging.info('mslookup result: ' + result_line.rstrip())
 | 
				
			||||||
 | 
					    return json.loads(result_line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def tx_sms(dst_host, dst_port, source, destination, registered_delivery,
 | 
				
			||||||
 | 
					           unicode_text):
 | 
				
			||||||
 | 
					    smpp_client = smpplib.client.Client(dst_host, dst_port, 90)
 | 
				
			||||||
 | 
					    smpp_client.connect()
 | 
				
			||||||
 | 
					    smpp_client.bind_transceiver(system_id=args.dst_id, password=args.dst_pass)
 | 
				
			||||||
 | 
					    logging.info('Connected to destination SMSC (%s@%s:%s)' % (args.dst_id,
 | 
				
			||||||
 | 
					                 dst_host, dst_port))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pdu = smpp_client.send_message(
 | 
				
			||||||
 | 
					        source_addr_ton=smpplib.consts.SMPP_TON_ALNUM,
 | 
				
			||||||
 | 
					        source_addr_npi=smpplib.consts.SMPP_NPI_UNK,
 | 
				
			||||||
 | 
					        source_addr=source.decode(),
 | 
				
			||||||
 | 
					        dest_addr_ton=smpplib.consts.SMPP_TON_SBSCR,
 | 
				
			||||||
 | 
					        dest_addr_npi=smpplib.consts.SMPP_NPI_ISDN,
 | 
				
			||||||
 | 
					        destination_addr=destination.decode(),
 | 
				
			||||||
 | 
					        short_message=unicode_text,
 | 
				
			||||||
 | 
					        registered_delivery=registered_delivery,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    smpp_client.unbind()
 | 
				
			||||||
 | 
					    smpp_client.disconnect()
 | 
				
			||||||
 | 
					    del pdu
 | 
				
			||||||
 | 
					    del smpp_client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def rx_deliver_sm(pdu):
 | 
				
			||||||
 | 
					    if not can_handle_pdu(pdu):
 | 
				
			||||||
 | 
					        return smpplib.consts.SMPP_ESME_RSYSERR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    msisdn = pdu.destination_addr.decode()
 | 
				
			||||||
 | 
					    logging.info("Incoming SMS for: " + msisdn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.sleep:
 | 
				
			||||||
 | 
					        logging.info("Sleeping for %i seconds" % (args.sleep))
 | 
				
			||||||
 | 
					        time.sleep(args.sleep)
 | 
				
			||||||
 | 
					        logging.info("Sleep done")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.always_fail is not None:
 | 
				
			||||||
 | 
					        return args.always_fail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = query_mslookup("smpp.sms", msisdn)
 | 
				
			||||||
 | 
					    if 'v4' not in result or not result['v4']:
 | 
				
			||||||
 | 
					        logging.info('No IPv4 result from mslookup! This example only'
 | 
				
			||||||
 | 
					                     ' makes use of IPv4, dropping.')
 | 
				
			||||||
 | 
					        return smpplib.consts.SMPP_ESME_RSYSERR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dst_host, dst_port = result['v4']
 | 
				
			||||||
 | 
					    tx_sms(dst_host, dst_port, pdu.source_addr,
 | 
				
			||||||
 | 
					           pdu.destination_addr, int(pdu.registered_delivery),
 | 
				
			||||||
 | 
					           pdu.short_message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return smpplib.consts.SMPP_ESME_ROK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def smpp_bind():
 | 
				
			||||||
 | 
					    client = smpplib.client.Client(args.src_host, args.src_port, 90)
 | 
				
			||||||
 | 
					    client.set_message_received_handler(rx_deliver_sm)
 | 
				
			||||||
 | 
					    client.connect()
 | 
				
			||||||
 | 
					    client.bind_transceiver(system_id=args.src_id, password=args.src_pass)
 | 
				
			||||||
 | 
					    logging.info('Connected to source SMSC (%s@%s:%s)' % (args.src_id,
 | 
				
			||||||
 | 
					                 args.src_host, args.src_port))
 | 
				
			||||||
 | 
					    logging.info('Waiting for SMS...')
 | 
				
			||||||
 | 
					    client.listen()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    global args
 | 
				
			||||||
 | 
					    parser = argparse.ArgumentParser()
 | 
				
			||||||
 | 
					    parser.add_argument('--src-host', default='127.0.0.1',
 | 
				
			||||||
 | 
					                        help='source SMSC (OsmoMSC) host (default: 127.0.0.1)')
 | 
				
			||||||
 | 
					    parser.add_argument('--src-port', default=2775, type=int,
 | 
				
			||||||
 | 
					                        help='source SMSC (OsmoMSC) port (default: 2775)')
 | 
				
			||||||
 | 
					    parser.add_argument('--src-id', default='OSMPP',
 | 
				
			||||||
 | 
					                        help='source system id, as configured in osmo-msc.cfg'
 | 
				
			||||||
 | 
					                             ' (default: OSMPP)')
 | 
				
			||||||
 | 
					    parser.add_argument('--src-pass', default='foo',
 | 
				
			||||||
 | 
					                        help='source system password, as configured in'
 | 
				
			||||||
 | 
					                             ' osmo-msc.cfg (default: foo)')
 | 
				
			||||||
 | 
					    parser.add_argument('--dst-id', default='ISMPP',
 | 
				
			||||||
 | 
					                        help='destination system id, as configured in'
 | 
				
			||||||
 | 
					                             ' osmo-msc.cfg (default: ISMPP)')
 | 
				
			||||||
 | 
					    parser.add_argument('--dst-pass', default='foo',
 | 
				
			||||||
 | 
					                        help='destination system password, as configured in'
 | 
				
			||||||
 | 
					                             ' osmo-msc.cfg (default: foo)')
 | 
				
			||||||
 | 
					    parser.add_argument('--sleep', default=0, type=float,
 | 
				
			||||||
 | 
					                        help='sleep time in seconds before forwarding an SMS,'
 | 
				
			||||||
 | 
					                             ' to test multithreading (default: 0)')
 | 
				
			||||||
 | 
					    parser.add_argument('--always-fail', default=None, metavar='SMPP_ESME_ERRCODE',
 | 
				
			||||||
 | 
					                        help='test delivery failure: always return an error code on Deliver-SM,'
 | 
				
			||||||
 | 
					                        ' pass an smpplib error code name like RDELIVERYFAILURE (see smpplib/consts.py),'
 | 
				
			||||||
 | 
					                        ' or an SMPP error code in hex digits')
 | 
				
			||||||
 | 
					    args = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    logging.basicConfig(level=logging.INFO, format='[%(asctime)s]'
 | 
				
			||||||
 | 
					                        ' (%(threadName)s) %(message)s', datefmt="%H:%M:%S")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.always_fail:
 | 
				
			||||||
 | 
					        resolved = None
 | 
				
			||||||
 | 
					        name = 'SMPP_ESME_' + args.always_fail
 | 
				
			||||||
 | 
					        if hasattr(smpplib.consts, name):
 | 
				
			||||||
 | 
					            resolved = getattr(smpplib.consts, name)
 | 
				
			||||||
 | 
					        if resolved is None:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                resolved = int(args.always_fail, 16)
 | 
				
			||||||
 | 
					            except ValueError:
 | 
				
			||||||
 | 
					                resolved = None
 | 
				
			||||||
 | 
					        if resolved is None:
 | 
				
			||||||
 | 
					            print('Invalid argument for --always-fail: %r' % args.always_fail)
 | 
				
			||||||
 | 
					            exit(1)
 | 
				
			||||||
 | 
					        args.always_fail = resolved
 | 
				
			||||||
 | 
					        logging.info('--always-fail: returning error code %s to all Deliver-SM' % hex(args.always_fail))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    smpp_bind()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# vim: expandtab tabstop=4 shiftwidth=4
 | 
				
			||||||
							
								
								
									
										77
									
								
								contrib/dgsm/freeswitch_dialplan_dgsm.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										77
									
								
								contrib/dgsm/freeswitch_dialplan_dgsm.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					SPDX-License-Identifier: MIT
 | 
				
			||||||
 | 
					Copyright 2019 sysmocom s.f.m.c GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is a freeswitch dialplan implementation, see:
 | 
				
			||||||
 | 
					https://freeswitch.org/confluence/display/FREESWITCH/mod_python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Find the right SIP server with mslookup (depending on the destination number)
 | 
				
			||||||
 | 
					and bridge calls accordingly.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def query_mslookup(service_type, id, id_type='msisdn'):
 | 
				
			||||||
 | 
					    query_str = '%s.%s.%s' % (service_type, id, id_type)
 | 
				
			||||||
 | 
					    print('[dialplan-dgsm] mslookup: ' + query_str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result_line = subprocess.check_output([
 | 
				
			||||||
 | 
					        'osmo-mslookup-client', query_str, '-f', 'json'])
 | 
				
			||||||
 | 
					    if isinstance(result_line, bytes):
 | 
				
			||||||
 | 
					        result_line = result_line.decode('ascii')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print('[dialplan-dgsm] mslookup result: ' + result_line)
 | 
				
			||||||
 | 
					    return json.loads(result_line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def handler(session, args):
 | 
				
			||||||
 | 
					    """ Handle calls: bridge to the SIP server found with mslookup. """
 | 
				
			||||||
 | 
					    print('[dialplan-dgsm] call handler')
 | 
				
			||||||
 | 
					    msisdn = session.getVariable('destination_number')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Run osmo-mslookup-client binary. We have also tried to directly call the
 | 
				
			||||||
 | 
					    # C functions with ctypes but this has lead to hard-to-debug segfaults.
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        result = query_mslookup("sip.voice", msisdn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # This example only makes use of IPv4
 | 
				
			||||||
 | 
					        if not result['v4']:
 | 
				
			||||||
 | 
					            print('[dialplan-dgsm] no IPv4 result from mslookup')
 | 
				
			||||||
 | 
					            session.hangup('UNALLOCATED_NUMBER')
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sip_ip, sip_port = result['v4']
 | 
				
			||||||
 | 
					        dial_str = 'sofia/internal/sip:{}@{}:{}'.format(
 | 
				
			||||||
 | 
					            msisdn, sip_ip, sip_port)
 | 
				
			||||||
 | 
					        print('[dialplan-dgsm] dial_str: ' + str(dial_str))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        session.execute('bridge', dial_str)
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        print('[dialplan-dgsm]: exception during call handler')
 | 
				
			||||||
 | 
					        session.hangup('UNALLOCATED_NUMBER')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def fsapi(session, stream, env, args):
 | 
				
			||||||
 | 
					    """ Freeswitch refuses to load the module without this. """
 | 
				
			||||||
 | 
					    stream.write(env.serialize())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    import argparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser = argparse.ArgumentParser()
 | 
				
			||||||
 | 
					    parser.add_argument('id', type=int)
 | 
				
			||||||
 | 
					    parser.add_argument('-i', '--id-type', default='msisdn',
 | 
				
			||||||
 | 
					                        help='default: "msisdn"')
 | 
				
			||||||
 | 
					    parser.add_argument('-s', '--service', default='sip.voice',
 | 
				
			||||||
 | 
					                        help='default: "sip.voice"')
 | 
				
			||||||
 | 
					    args = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    result = query_mslookup(args.service, args.id, args.id_type)
 | 
				
			||||||
 | 
					    print(json.dumps(result))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										24
									
								
								contrib/dgsm/osmo-mslookup-pipe.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								contrib/dgsm/osmo-mslookup-pipe.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					# vim: shiftwidth=4 tabstop=4 expandtab
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def query_mslookup(query_str):
 | 
				
			||||||
 | 
					    result = {'result': 'not-found'}
 | 
				
			||||||
 | 
					    proc = subprocess.Popen(('osmo-mslookup-client', '-f', 'json', query_str),
 | 
				
			||||||
 | 
							            stdout=subprocess.PIPE)
 | 
				
			||||||
 | 
					    for line in iter(proc.stdout.readline,''):
 | 
				
			||||||
 | 
					        if not line:
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        response = json.loads(line)
 | 
				
			||||||
 | 
					        if response.get('result') == 'result':
 | 
				
			||||||
 | 
					                result = response
 | 
				
			||||||
 | 
					        print('Response: %r' % response)
 | 
				
			||||||
 | 
					    return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    import sys
 | 
				
			||||||
 | 
					    query_str = '1000-5000@sip.voice.12345.msisdn'
 | 
				
			||||||
 | 
					    if len(sys.argv) > 1:
 | 
				
			||||||
 | 
					        query_str = sys.argv[1]
 | 
				
			||||||
 | 
					    print('Final result: %r' % query_mslookup(query_str))
 | 
				
			||||||
							
								
								
									
										35
									
								
								contrib/dgsm/osmo-mslookup-socket.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										35
									
								
								contrib/dgsm/osmo-mslookup-socket.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					# vim: shiftwidth=4 tabstop=4 expandtab
 | 
				
			||||||
 | 
					import socket
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MSLOOKUP_SOCKET_PATH = '/tmp/mslookup'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def query_mslookup_socket(query_str, socket_path=MSLOOKUP_SOCKET_PATH):
 | 
				
			||||||
 | 
					    mslookup_socket = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
 | 
				
			||||||
 | 
					    mslookup_socket.setblocking(True)
 | 
				
			||||||
 | 
					    mslookup_socket.connect(socket_path)
 | 
				
			||||||
 | 
					    result = {'result': 'not-found'}
 | 
				
			||||||
 | 
					    column_names = mslookup_socket.recv(1024).decode('ascii')
 | 
				
			||||||
 | 
					    if not column_names:
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    column_names = column_names.split('\t')
 | 
				
			||||||
 | 
					    mslookup_socket.sendall(query_str.encode('ascii'))
 | 
				
			||||||
 | 
					    while True:
 | 
				
			||||||
 | 
					        csv = mslookup_socket.recv(1024).decode('ascii')
 | 
				
			||||||
 | 
					        if not csv:
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        response = dict(zip(column_names, csv.split('\t')))
 | 
				
			||||||
 | 
					        if response.get('result') == 'result':
 | 
				
			||||||
 | 
					            result = response
 | 
				
			||||||
 | 
					        print('Response: %r' % response)
 | 
				
			||||||
 | 
					    return result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    import sys
 | 
				
			||||||
 | 
					    print(
 | 
				
			||||||
 | 
					        '\nPlease run separately: osmo-mslookup-client --socket /tmp/mslookup -d\n')
 | 
				
			||||||
 | 
					    query_str = '1000-5000@sip.voice.12345.msisdn'
 | 
				
			||||||
 | 
					    if len(sys.argv) > 1:
 | 
				
			||||||
 | 
					        query_str = sys.argv[1]
 | 
				
			||||||
 | 
					    print('Final result: %r' % query_mslookup_socket(query_str))
 | 
				
			||||||
							
								
								
									
										66
									
								
								contrib/jenkins.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										66
									
								
								contrib/jenkins.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					# jenkins build helper script for osmo-hlr.  This is how we build on jenkins.osmocom.org
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# environment variables:
 | 
				
			||||||
 | 
					# * WITH_MANUALS: build manual PDFs if set to "1"
 | 
				
			||||||
 | 
					# * PUBLISH: upload manuals after building if set to "1" (ignored without WITH_MANUALS = "1")
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
 | 
				
			||||||
 | 
						echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
 | 
				
			||||||
 | 
						exit 2
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -ex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					base="$PWD"
 | 
				
			||||||
 | 
					deps="$base/deps"
 | 
				
			||||||
 | 
					inst="$deps/install"
 | 
				
			||||||
 | 
					export deps inst
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mkdir "$deps" || true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
 | 
				
			||||||
 | 
					export LD_LIBRARY_PATH="$inst/lib"
 | 
				
			||||||
 | 
					export PATH="$inst/bin:$PATH"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-build-dep.sh libosmocore "" ac_cv_path_DOXYGEN=false
 | 
				
			||||||
 | 
					osmo-build-dep.sh libosmo-abis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Additional configure options and depends
 | 
				
			||||||
 | 
					CONFIG=""
 | 
				
			||||||
 | 
					if [ "$WITH_MANUALS" = "1" ]; then
 | 
				
			||||||
 | 
						CONFIG="--enable-manuals"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set +x
 | 
				
			||||||
 | 
					echo
 | 
				
			||||||
 | 
					echo
 | 
				
			||||||
 | 
					echo
 | 
				
			||||||
 | 
					echo " =============================== osmo-hlr ==============================="
 | 
				
			||||||
 | 
					echo
 | 
				
			||||||
 | 
					set -x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd "$base"
 | 
				
			||||||
 | 
					autoreconf --install --force
 | 
				
			||||||
 | 
					./configure \
 | 
				
			||||||
 | 
						--enable-sanitize \
 | 
				
			||||||
 | 
						--enable-external-tests \
 | 
				
			||||||
 | 
						--enable-mslookup-client-mdns-test \
 | 
				
			||||||
 | 
						--enable-werror \
 | 
				
			||||||
 | 
						$CONFIG
 | 
				
			||||||
 | 
					$MAKE $PARALLEL_MAKE
 | 
				
			||||||
 | 
					$MAKE check || cat-testlogs.sh
 | 
				
			||||||
 | 
					DISTCHECK_CONFIGURE_FLAGS="$CONFIG" $MAKE $PARALLEL_MAKE distcheck || cat-testlogs.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$WITH_MANUALS" = "1" ] && [ "$PUBLISH" = "1" ]; then
 | 
				
			||||||
 | 
						make -C "$base/doc/manuals" publish
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$MAKE $PARALLEL_MAKE maintainer-clean
 | 
				
			||||||
 | 
					osmo-clean-workspace.sh
 | 
				
			||||||
							
								
								
									
										95
									
								
								contrib/osmo-hlr-post-upgrade.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								contrib/osmo-hlr-post-upgrade.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					#!/bin/sh -e
 | 
				
			||||||
 | 
					# SPDX-License-Identifier: AGPL-3.0-or-later
 | 
				
			||||||
 | 
					# Copyright 2021 sysmocom s.f.m.c GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Packagers are supposed to call this script in post-upgrade, so it can safely
 | 
				
			||||||
 | 
					# upgrade the database scheme if required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DB="/var/lib/osmocom/hlr.db"
 | 
				
			||||||
 | 
					IS_ACTIVE=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					msg() {
 | 
				
			||||||
 | 
						echo "osmo-hlr-post-upgrade: $@"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err() {
 | 
				
			||||||
 | 
						msg "ERROR: $@"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					open_db() {
 | 
				
			||||||
 | 
						# Attempt to open the database with osmo-hlr-db-tool, it will fail if
 | 
				
			||||||
 | 
						# upgrading the schema is required
 | 
				
			||||||
 | 
						osmo-hlr-db-tool -s -l "$DB" create
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check_upgrade_required() {
 | 
				
			||||||
 | 
						if ! [ -e "$DB" ]; then
 | 
				
			||||||
 | 
							msg "nothing to do (no existing database)"
 | 
				
			||||||
 | 
							exit 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if open_db 2>/dev/null; then
 | 
				
			||||||
 | 
							msg "nothing to do (database version is up to date)"
 | 
				
			||||||
 | 
							exit 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg "database upgrade is required"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stop_service() {
 | 
				
			||||||
 | 
						if systemctl is-active -q osmo-hlr; then
 | 
				
			||||||
 | 
							IS_ACTIVE=1
 | 
				
			||||||
 | 
							msg "stopping osmo-hlr service"
 | 
				
			||||||
 | 
							systemctl stop osmo-hlr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Verify that it stopped
 | 
				
			||||||
 | 
							for i in $(seq 1 100); do
 | 
				
			||||||
 | 
								if ! systemctl is-active -q osmo-hlr; then
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								fi
 | 
				
			||||||
 | 
								sleep 0.1
 | 
				
			||||||
 | 
							done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err "failed to stop osmo-hlr service"
 | 
				
			||||||
 | 
							exit 1
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							msg "osmo-hlr service is not running"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					create_backup() {
 | 
				
			||||||
 | 
						backup="$DB.$(date +%Y%m%d%H%M%S).bak"
 | 
				
			||||||
 | 
						msg "creating backup: $backup"
 | 
				
			||||||
 | 
						if [ -e "$backup" ]; then
 | 
				
			||||||
 | 
							err "backup already exists: $backup"
 | 
				
			||||||
 | 
							exit 1
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						cp "$DB" "$backup"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					upgrade() {
 | 
				
			||||||
 | 
						msg "performing database upgrade"
 | 
				
			||||||
 | 
						osmo-hlr-db-tool -s -U -l "$DB" create
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ! open_db 2>/dev/null; then
 | 
				
			||||||
 | 
							err "failed to open the database after upgrade"
 | 
				
			||||||
 | 
							err "osmo-hlr-db-tool output:"
 | 
				
			||||||
 | 
							open_db
 | 
				
			||||||
 | 
							# exit because of "set -e"
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msg "database upgrade successful"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					start_service() {
 | 
				
			||||||
 | 
						if [ "$IS_ACTIVE" = "1" ]; then
 | 
				
			||||||
 | 
							msg "starting osmo-hlr service"
 | 
				
			||||||
 | 
							systemctl start osmo-hlr
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					check_upgrade_required
 | 
				
			||||||
 | 
					stop_service
 | 
				
			||||||
 | 
					create_backup
 | 
				
			||||||
 | 
					upgrade
 | 
				
			||||||
 | 
					start_service
 | 
				
			||||||
							
								
								
									
										195
									
								
								contrib/osmo-hlr.spec.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								contrib/osmo-hlr.spec.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,195 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# spec file for package osmo-hlr
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 | 
				
			||||||
 | 
					# Copyright (c) 2016, Martin Hauke <mardnh@gmx.de>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# All modifications and additions to the file contributed by third parties
 | 
				
			||||||
 | 
					# remain the property of their copyright owners, unless otherwise agreed
 | 
				
			||||||
 | 
					# upon. The license for this file, and modifications and additions to the
 | 
				
			||||||
 | 
					# file, is the same license as for the pristine package itself (unless the
 | 
				
			||||||
 | 
					# license for the pristine package is not an Open Source License, in which
 | 
				
			||||||
 | 
					# case the license is the MIT License). An "Open Source License" is a
 | 
				
			||||||
 | 
					# license that conforms to the Open Source Definition (Version 1.9)
 | 
				
			||||||
 | 
					# published by the Open Source Initiative.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name:           osmo-hlr
 | 
				
			||||||
 | 
					Version:        @VERSION@
 | 
				
			||||||
 | 
					Release:        0
 | 
				
			||||||
 | 
					Summary:        Osmocom Home Location Register for GSUP protocol towards OsmoSGSN and OsmoCSCN
 | 
				
			||||||
 | 
					License:        AGPL-3.0-or-later AND GPL-2.0-or-later
 | 
				
			||||||
 | 
					Group:          Productivity/Telephony/Servers
 | 
				
			||||||
 | 
					URL:            https://osmocom.org/projects/osmo-hlr
 | 
				
			||||||
 | 
					Source:         %{name}-%{version}.tar.xz
 | 
				
			||||||
 | 
					BuildRequires:  autoconf
 | 
				
			||||||
 | 
					BuildRequires:  automake
 | 
				
			||||||
 | 
					BuildRequires:  libtool
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig >= 0.20
 | 
				
			||||||
 | 
					BuildRequires:  python3
 | 
				
			||||||
 | 
					%if 0%{?suse_version}
 | 
				
			||||||
 | 
					BuildRequires:  systemd-rpm-macros
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmoabis) >= 1.3.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmocore) >= 1.7.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmoctrl) >= 1.7.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmogsm) >= 1.7.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(libosmovty) >= 1.7.0
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(sqlite3)
 | 
				
			||||||
 | 
					BuildRequires:  pkgconfig(talloc) >= 2.0.1
 | 
				
			||||||
 | 
					# only needed for populate_hlr_db.pl
 | 
				
			||||||
 | 
					Requires:       libdbi-drivers-dbd-sqlite3
 | 
				
			||||||
 | 
					%{?systemd_requires}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description
 | 
				
			||||||
 | 
					The GSUP HLR is a stand-alone HLR (Home Location Register) for SIM
 | 
				
			||||||
 | 
					and USIM based subscribers which exposes the GSUP protocol towards
 | 
				
			||||||
 | 
					its users. OsmoSGSN supports this protocol.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-gsup-hlr is still very simplistic. It is a single-threaded
 | 
				
			||||||
 | 
					architecture and uses only sqlite3 tables as back-end.  It is suitable
 | 
				
			||||||
 | 
					for installations of the scale that OsmoNITB was able to handle.  It
 | 
				
			||||||
 | 
					also lacks various features like fine-grained control of subscribed
 | 
				
			||||||
 | 
					services (like supplementary services).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n libosmo-gsup-client0
 | 
				
			||||||
 | 
					Summary:        Osmocom GSUP (General Subscriber Update Protocol) client library
 | 
				
			||||||
 | 
					License:        GPL-2.0-or-later
 | 
				
			||||||
 | 
					Group:          System/Libraries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n libosmo-gsup-client0
 | 
				
			||||||
 | 
					This is a shared library that can be used to implement client programs for
 | 
				
			||||||
 | 
					the GSUP protocol. The typical GSUP server is OsmoHLR, with OsmoMSC, OsmoSGSN
 | 
				
			||||||
 | 
					and External USSD Entities (EUSEs) using this library to implement clients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n libosmo-gsup-client-devel
 | 
				
			||||||
 | 
					Summary:        Development files for the Osmocom GSUP client library
 | 
				
			||||||
 | 
					License:        GPL-2.0-or-later
 | 
				
			||||||
 | 
					Group:          Development/Libraries/C and C++
 | 
				
			||||||
 | 
					Requires:       libosmo-gsup-client0 = %{version}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n libosmo-gsup-client-devel
 | 
				
			||||||
 | 
					This is a shared library that can be used to implement client programs for
 | 
				
			||||||
 | 
					the GSUP protocol. The typical GSUP server is OsmoHLR, with OsmoMSC, OsmoSGSN
 | 
				
			||||||
 | 
					and External USSD Entities (EUSEs) using this library to implement clients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This subpackage contains libraries and header files for developing
 | 
				
			||||||
 | 
					applications that want to make use of libosmo-gsup-client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n libosmo-mslookup0
 | 
				
			||||||
 | 
					Summary:        Osmocom MS lookup library
 | 
				
			||||||
 | 
					License:        GPL-2.0-or-later
 | 
				
			||||||
 | 
					Group:          System/Libraries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n libosmo-mslookup0
 | 
				
			||||||
 | 
					This shared library contains routines for looking up mobile subscribers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n libosmo-mslookup-devel
 | 
				
			||||||
 | 
					Summary:        Development files for the Osmocom MS lookup library
 | 
				
			||||||
 | 
					License:        GPL-2.0-or-later
 | 
				
			||||||
 | 
					Group:          Development/Libraries/C and C++
 | 
				
			||||||
 | 
					Requires:       libosmo-mslookup0 = %{version}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n libosmo-mslookup-devel
 | 
				
			||||||
 | 
					This shared library contains routines for looking up mobile subscribers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This subpackage contains libraries and header files for developing
 | 
				
			||||||
 | 
					applications that want to make use of libosmo-mslookup.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%package -n osmo-mslookup-client
 | 
				
			||||||
 | 
					Summary:        Standalone program using libosmo-mslookup
 | 
				
			||||||
 | 
					License:        GPL-2.0-or-later
 | 
				
			||||||
 | 
					Group:          Development/Libraries/C and C++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%description -n osmo-mslookup-client
 | 
				
			||||||
 | 
					Standalone program using libosmo-mslookup to easily integrate with programs
 | 
				
			||||||
 | 
					that want to connect services (SIP, SMS,...) to the current location of a
 | 
				
			||||||
 | 
					subscriber.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%prep
 | 
				
			||||||
 | 
					%setup -q
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%build
 | 
				
			||||||
 | 
					echo "%{version}" >.tarball-version
 | 
				
			||||||
 | 
					autoreconf -fi
 | 
				
			||||||
 | 
					%configure \
 | 
				
			||||||
 | 
					  --docdir="%{_docdir}/%{name}" \
 | 
				
			||||||
 | 
					  --with-systemdsystemunitdir=%{_unitdir} \
 | 
				
			||||||
 | 
					  --enable-shared \
 | 
				
			||||||
 | 
					  --disable-static
 | 
				
			||||||
 | 
					make V=1 %{?_smp_mflags}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%install
 | 
				
			||||||
 | 
					%make_install
 | 
				
			||||||
 | 
					install -d "%{buildroot}/%{_localstatedir}/lib/osmocom"
 | 
				
			||||||
 | 
					find %{buildroot} -type f -name "*.la" -delete -print
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%check
 | 
				
			||||||
 | 
					make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%if 0%{?suse_version}
 | 
				
			||||||
 | 
					%preun
 | 
				
			||||||
 | 
					%service_del_preun %{name}.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%postun
 | 
				
			||||||
 | 
					%service_del_postun %{name}.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%pre
 | 
				
			||||||
 | 
					%service_add_pre %{name}.service
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%post
 | 
				
			||||||
 | 
					%if 0%{?suse_version}
 | 
				
			||||||
 | 
					%service_add_post %{name}.service
 | 
				
			||||||
 | 
					%endif
 | 
				
			||||||
 | 
					/usr/share/osmocom/osmo-hlr-post-upgrade.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%post   -n libosmo-gsup-client0 -p /sbin/ldconfig
 | 
				
			||||||
 | 
					%postun -n libosmo-gsup-client0 -p /sbin/ldconfig
 | 
				
			||||||
 | 
					%post   -n libosmo-mslookup0 -p /sbin/ldconfig
 | 
				
			||||||
 | 
					%postun -n libosmo-mslookup0 -p /sbin/ldconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files
 | 
				
			||||||
 | 
					%license COPYING
 | 
				
			||||||
 | 
					%dir %{_docdir}/%{name}
 | 
				
			||||||
 | 
					%dir %{_docdir}/%{name}/examples
 | 
				
			||||||
 | 
					%{_docdir}/%{name}/examples/osmo-hlr.cfg
 | 
				
			||||||
 | 
					%{_docdir}/%{name}/examples/osmo-hlr-dgsm.cfg
 | 
				
			||||||
 | 
					%dir %{_docdir}/%{name}/sql
 | 
				
			||||||
 | 
					%{_docdir}/%{name}/sql/hlr.sql
 | 
				
			||||||
 | 
					%{_docdir}/%{name}/sql//hlr_data.sql
 | 
				
			||||||
 | 
					%dir %{_sysconfdir}/osmocom
 | 
				
			||||||
 | 
					%dir %{_localstatedir}/lib/osmocom
 | 
				
			||||||
 | 
					%{_bindir}/osmo-hlr
 | 
				
			||||||
 | 
					%{_bindir}/osmo-hlr-db-tool
 | 
				
			||||||
 | 
					%dir %{_sysconfdir}/osmocom
 | 
				
			||||||
 | 
					%config %{_sysconfdir}/osmocom/osmo-hlr.cfg
 | 
				
			||||||
 | 
					%{_unitdir}/osmo-hlr.service
 | 
				
			||||||
 | 
					%dir %{_datadir}/osmocom
 | 
				
			||||||
 | 
					%{_datadir}/osmocom/osmo-hlr-post-upgrade.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n libosmo-gsup-client0
 | 
				
			||||||
 | 
					%{_libdir}/libosmo-gsup-client.so.0*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n libosmo-gsup-client-devel
 | 
				
			||||||
 | 
					%{_bindir}/osmo-euse-demo
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom/gsupclient
 | 
				
			||||||
 | 
					%{_includedir}/osmocom/gsupclient/*.h
 | 
				
			||||||
 | 
					%{_libdir}/libosmo-gsup-client.so
 | 
				
			||||||
 | 
					%{_libdir}/pkgconfig/libosmo-gsup-client.pc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n libosmo-mslookup0
 | 
				
			||||||
 | 
					%{_libdir}/libosmo-mslookup.so.0*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n libosmo-mslookup-devel
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom
 | 
				
			||||||
 | 
					%dir %{_includedir}/osmocom/mslookup
 | 
				
			||||||
 | 
					%{_includedir}/osmocom/mslookup/*.h
 | 
				
			||||||
 | 
					%{_libdir}/libosmo-mslookup.so
 | 
				
			||||||
 | 
					%{_libdir}/pkgconfig/libosmo-mslookup.pc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%files -n osmo-mslookup-client
 | 
				
			||||||
 | 
					%{_bindir}/osmo-mslookup-client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%changelog
 | 
				
			||||||
							
								
								
									
										6
									
								
								contrib/systemd/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								contrib/systemd/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					EXTRA_DIST = osmo-hlr.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if HAVE_SYSTEMD
 | 
				
			||||||
 | 
					systemdsystemunit_DATA = \
 | 
				
			||||||
 | 
					  osmo-hlr.service
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
							
								
								
									
										12
									
								
								contrib/systemd/osmo-hlr.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								contrib/systemd/osmo-hlr.service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					[Unit]
 | 
				
			||||||
 | 
					Description=Osmocom Home Location Register (OsmoHLR)
 | 
				
			||||||
 | 
					Documentation=https://osmocom.org/projects/osmo-hlr/wiki/OsmoHLR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Service]
 | 
				
			||||||
 | 
					Type=simple
 | 
				
			||||||
 | 
					Restart=always
 | 
				
			||||||
 | 
					ExecStart=/usr/bin/osmo-hlr -c /etc/osmocom/osmo-hlr.cfg -l /var/lib/osmocom/hlr.db
 | 
				
			||||||
 | 
					RestartSec=2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Install]
 | 
				
			||||||
 | 
					WantedBy=multi-user.target
 | 
				
			||||||
							
								
								
									
										536
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										536
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,536 @@
 | 
				
			|||||||
 | 
					osmo-hlr (1.5.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * treewide: remove FSF address
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * fixup: debian: remove unneeded dependency libdbd-sqlite3
 | 
				
			||||||
 | 
					  * debian: add new 'osmo-mslookup-utils' package
 | 
				
			||||||
 | 
					  * tests: use 'check_PROGRAMS' instead of 'noinst_PROGRAMS'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * ctrl: Mark function as static
 | 
				
			||||||
 | 
					  * tests: Allow specyfing specific ctrl test to run
 | 
				
			||||||
 | 
					  * tests/ctrl: Move ERROR test scenario to proper file
 | 
				
			||||||
 | 
					  * Fix db_subscr_create() not returning -EEXIST expected by VTY subscriber create cmd
 | 
				
			||||||
 | 
					  * ctrl: Introduce cmd SET subscriber.create <imsi>
 | 
				
			||||||
 | 
					  * ctrl: Introduce CTRL command subscriber.by-*.msisdn
 | 
				
			||||||
 | 
					  * cosmetic: hlr_vty_subscr.c: Fix trailing whitespace
 | 
				
			||||||
 | 
					  * ctrl: Introduce cmd SET subscriber.delete <imsi>
 | 
				
			||||||
 | 
					  * ctrl: Introduce CTRL command subscriber.by-*.aud2g <algo[,ki]>
 | 
				
			||||||
 | 
					  * ctrl: Introduce CTRL command subscriber.by-*.aud3g <algo[,KI,(op|opc),OP_C[,ind_bitlen]]>
 | 
				
			||||||
 | 
					  * doc: Document new subscriber CTRL commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * update git URLs (git -> https; gitea)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 28 Jun 2022 18:38:31 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (1.4.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Keith ]
 | 
				
			||||||
 | 
					  * Correct configuration written from vty
 | 
				
			||||||
 | 
					  * vty: enable show subscribers filtered by IMEI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * add README.md file as customary for cgit, github, gitlab, etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * Add post-upgrade script for automatic db upgrade
 | 
				
			||||||
 | 
					  * debian/control: remove dh-systemd build-depend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * db: Avoid use uninitialized rc if running 0 statements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * db v6: determine 3G AUC IND from VLR name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 16 Nov 2021 14:56:41 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (1.3.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Couzens ]
 | 
				
			||||||
 | 
					  * hlr: respect the num_auth_vectors requested
 | 
				
			||||||
 | 
					  * hlr: remove unused internal USSD list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * add libosmo-mslookup abstract client
 | 
				
			||||||
 | 
					  * add mDNS lookup method to libosmo-mslookup
 | 
				
			||||||
 | 
					  * Makefile.am: fix pkgconfig_DATA
 | 
				
			||||||
 | 
					  * add mDNS lookup method to libosmo-mslookup (#2)
 | 
				
			||||||
 | 
					  * contrib/dgsm/ add example esme and dialplan
 | 
				
			||||||
 | 
					  * mslookup_client.c: fix dereferencing null pointer
 | 
				
			||||||
 | 
					  * mdns_msg.c: always call va_end
 | 
				
			||||||
 | 
					  * mslookup_client_mdns.c: fix dereferencing null
 | 
				
			||||||
 | 
					  * osmo-mslookup-client.c: fix dereferencing null
 | 
				
			||||||
 | 
					  * osmo-mslookup-client: fix dereferencing null
 | 
				
			||||||
 | 
					  * mdns_sock.c: fix resource leak of sock
 | 
				
			||||||
 | 
					  * mdns_rfc.c: fix possible access of uninit. mem
 | 
				
			||||||
 | 
					  * mslookup_client_mdns_test: disable by default
 | 
				
			||||||
 | 
					  * mslookup_client_mdns_test: no automatic skip
 | 
				
			||||||
 | 
					  * Cosmetic: mention OS#4491 in location cancel code
 | 
				
			||||||
 | 
					  * hlr_vty_subscr: prettier output for last LU seen
 | 
				
			||||||
 | 
					  * contrib: import RPM spec
 | 
				
			||||||
 | 
					  * contrib: integrate RPM spec
 | 
				
			||||||
 | 
					  * Makefile.am: EXTRA_DIST: debian, contrib/*.spec.in
 | 
				
			||||||
 | 
					  * contrib/jenkins: don't build osmo-gsm-manuals
 | 
				
			||||||
 | 
					  * configure.ac: set -std=gnu11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * add osmo-mslookup-client program
 | 
				
			||||||
 | 
					  * add osmo-mslookup-client program (#2)
 | 
				
			||||||
 | 
					  * fix missing braces in LOGP_GSUP_FWD
 | 
				
			||||||
 | 
					  * gsup_client.c: fix deprecation for client create func
 | 
				
			||||||
 | 
					  * 1/2: refactor: add and use lu_fsm, osmo_gsup_req, osmo_ipa_name
 | 
				
			||||||
 | 
					  * 2/2: wrap ipa_name in osmo_cni_peer_id with type enum and union
 | 
				
			||||||
 | 
					  * gsup client: add up_down_cb(), add osmo_gsup_client_create3()
 | 
				
			||||||
 | 
					  * db v5: prep for D-GSM: add vlr_via_proxy and sgsn_via_proxy
 | 
				
			||||||
 | 
					  * enlarge the GSUP message headroom
 | 
				
			||||||
 | 
					  * test_nodes.vty: remove cruft
 | 
				
			||||||
 | 
					  * D-GSM 1/n: add mslookup server in osmo-hlr
 | 
				
			||||||
 | 
					  * D-GSM 2/n: implement mDNS method of mslookup server
 | 
				
			||||||
 | 
					  * D-GSM 3/n: implement roaming by mslookup in osmo-hlr
 | 
				
			||||||
 | 
					  * gsup_server: send routing error back to the correct peer
 | 
				
			||||||
 | 
					  * adoc: add D-GSM chapter to osmohlr-usermanual
 | 
				
			||||||
 | 
					  * drop error log for when a subscriber does not exist
 | 
				
			||||||
 | 
					  * vty: show subscriber: change format of 'last LU seen'
 | 
				
			||||||
 | 
					  * vty: show subscriber: show lu d,h,m,s ago, not just seconds
 | 
				
			||||||
 | 
					  * auc3g: officially wrap IND around IND_bitlen space
 | 
				
			||||||
 | 
					  * make osmo_cni_peer_id_cmp() NULL safe
 | 
				
			||||||
 | 
					  * osmo_gsup_req_new(): require from_peer != NULL
 | 
				
			||||||
 | 
					  * gsup_server.c: properly handle negative rc from osmo_gsup_conn_ccm_get()
 | 
				
			||||||
 | 
					  * osmo_mslookup_server_mdns_rx(): handle read() rc == 0
 | 
				
			||||||
 | 
					  * hlr_subscr_nam(): fix condition to fix nam=false notifications
 | 
				
			||||||
 | 
					  * esme_dgsm.py: add --always-fail option for debugging SMPP
 | 
				
			||||||
 | 
					  * osmo-mslookup-client: fix segfault for respond_error() caller
 | 
				
			||||||
 | 
					  * manual: describe subscriber import by SQL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * Revert "add osmo-mslookup-client program"
 | 
				
			||||||
 | 
					  * Revert "add mDNS lookup method to libosmo-mslookup"
 | 
				
			||||||
 | 
					  * Use OSMO_FD_* instead of deprecated BSC_FD_*
 | 
				
			||||||
 | 
					  * support the XOR algorithm for UMTS AKA
 | 
				
			||||||
 | 
					  * auc_test.c: Add some comments on what the test cases actually do
 | 
				
			||||||
 | 
					  * main: add --vty-ref-mode, use vty_dump_xml_ref_mode()
 | 
				
			||||||
 | 
					  * manuals: generate vty reference xml at build time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * db: fix possible SQLite3 allocated memory leak in db_open()
 | 
				
			||||||
 | 
					  * gsup_server: fix typo: s/omso_gsup_message/osmo_gsup_message/
 | 
				
			||||||
 | 
					  * debian/control: change maintainer to the Osmocom team / mailing list
 | 
				
			||||||
 | 
					  * cosmetic: fix spelling in logging message: existAnt -> existEnt
 | 
				
			||||||
 | 
					  * doc/manuals: fix s/There/The/ in 'USSD Configuration'
 | 
				
			||||||
 | 
					  * doc/manuals: re-organize description of internal USSD handlers
 | 
				
			||||||
 | 
					  * USSD: fix handle_ussd(): do not free() unconditionally
 | 
				
			||||||
 | 
					  * USSD: add special 'idle' handler to IUSE for testing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Eric ]
 | 
				
			||||||
 | 
					  * configure.ac: fix libtool issue  with clang and sanitizer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Philipp Maier ]
 | 
				
			||||||
 | 
					  * doc: do not use loglevel info for log category ss
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * configure.ac: Fix trailing whitespace
 | 
				
			||||||
 | 
					  * doc: Update VTY reference xml file
 | 
				
			||||||
 | 
					  * Support setting rt-prio and cpu-affinity mask through VTY
 | 
				
			||||||
 | 
					  * Set TCP NODELAY sockopt to GSUP cli and srv connections
 | 
				
			||||||
 | 
					  * contrib/jenkins: Enable parallel make in make distcheck
 | 
				
			||||||
 | 
					  * .gitignore: Ignore new autofoo tmp files
 | 
				
			||||||
 | 
					  * tests: Replace deprecated API log_set_print_filename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Keith ]
 | 
				
			||||||
 | 
					  * osmo-hlr-db-tool: Make import from osmo-nitb less "lossy"
 | 
				
			||||||
 | 
					  * Correct vty inline help for show subscriber
 | 
				
			||||||
 | 
					  * Add vty command to show summary of all or filtered subscribers
 | 
				
			||||||
 | 
					  * Fix Coverity Warnings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Tue, 23 Feb 2021 18:13:53 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (1.2.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Ruben Undheim ]
 | 
				
			||||||
 | 
					  * Fix test for return codes on mipsel and alpha archs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Thorsten Alteholz ]
 | 
				
			||||||
 | 
					  * fix spelling errors detected by lintian
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * tests: Fix db_test err file to expect error code name instead of value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * tests/test_nodes.vty: check less libosmocore cmds
 | 
				
			||||||
 | 
					  * tests/db_upgrade: disable for old sqlite versions
 | 
				
			||||||
 | 
					  * gitignore: add tests/db_upgrade/*.dump
 | 
				
			||||||
 | 
					  * gsup_client.h: fix license header: GPLv2+
 | 
				
			||||||
 | 
					  * tests/auc: change back to python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * fix double free in osmo_gsup_client_enc_send()
 | 
				
			||||||
 | 
					  * db upgrade to v2: log version 2, not 1
 | 
				
			||||||
 | 
					  * fix upgrade to version 2: imei column default value
 | 
				
			||||||
 | 
					  * add --db-check option
 | 
				
			||||||
 | 
					  * hlr.sql: move comment
 | 
				
			||||||
 | 
					  * add db_upgrade test
 | 
				
			||||||
 | 
					  * hlr db schema 3: hlr_number -> msc_number
 | 
				
			||||||
 | 
					  * db.c: code dup: add db_run_statements() for arrays of statements
 | 
				
			||||||
 | 
					  * move headers to include/osmocom/hlr
 | 
				
			||||||
 | 
					  * fix upgrade test in presence of ~/.sqliterc
 | 
				
			||||||
 | 
					  * db upgrade: remove some code dup
 | 
				
			||||||
 | 
					  * add osmo_gsup_msgb_alloc()
 | 
				
			||||||
 | 
					  * Makefile convenience: add VTY_TEST var to run only one test
 | 
				
			||||||
 | 
					  * remove gsup_test
 | 
				
			||||||
 | 
					  * test_nodes.vty: tweak: add some '?' checks
 | 
				
			||||||
 | 
					  * db v4: add column last_lu_seen_ps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * AUC: Add support for setting the AMF separation bit to '1' for EUTRAN
 | 
				
			||||||
 | 
					  * hlr: exit(2) on unsupported positional arguments on command line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Fri, 03 Jan 2020 12:37:35 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (1.1.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Oliver Smith ]
 | 
				
			||||||
 | 
					  * docs: running: document --db-upgrade
 | 
				
			||||||
 | 
					  * Add IMEI column to subscriber table
 | 
				
			||||||
 | 
					  * Optionally store IMEI in subscriber table
 | 
				
			||||||
 | 
					  * VTY tests: fill DB before running test
 | 
				
			||||||
 | 
					  * VTY: integrate IMEI
 | 
				
			||||||
 | 
					  * hlr.c: replace deprecated osmo_gsup_get_err_msg_type()
 | 
				
			||||||
 | 
					  * hlr.c: move hlr_ctx to the top
 | 
				
			||||||
 | 
					  * tests: use -no-install libtool flag to avoid ./lt-* scripts
 | 
				
			||||||
 | 
					  * Cosmetic: gsup_route_find: comment addr, addrlen
 | 
				
			||||||
 | 
					  * USSD: save MO USSD's originating MSC's vlr_number
 | 
				
			||||||
 | 
					  * USSD: don't use gsm0480_msgb_alloc_name()
 | 
				
			||||||
 | 
					  * hlr.c: forward GSUP messages between clients
 | 
				
			||||||
 | 
					  * db_hlr.c: db_subscr_create(): add flags argument
 | 
				
			||||||
 | 
					  * db_hlr.c: add db_subscr_exists_by_imsi()
 | 
				
			||||||
 | 
					  * Create subscribers on demand
 | 
				
			||||||
 | 
					  * Document subscribers create on demand feature
 | 
				
			||||||
 | 
					  * debian: create -doc subpackage with pdf manuals
 | 
				
			||||||
 | 
					  * db_test: set timezone to work around mktime bug
 | 
				
			||||||
 | 
					  * db_hlr: zero-initialize "struct tm"
 | 
				
			||||||
 | 
					  * rx_check_imei_req(): fix IMEI bounds checking
 | 
				
			||||||
 | 
					  * contrib/jenkins.sh: run "make maintainer-clean"
 | 
				
			||||||
 | 
					  * VTY: add subscriber update network-access-mode
 | 
				
			||||||
 | 
					  * manuals: improve subscribers create on demand
 | 
				
			||||||
 | 
					  * gitignore: ignore everything generated in db_test
 | 
				
			||||||
 | 
					  * db_auc.c: verify hex key sizes read from DB
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Max ]
 | 
				
			||||||
 | 
					  * Log ip:port when adding GSUP routes
 | 
				
			||||||
 | 
					  * Add link to project wiki to .service file
 | 
				
			||||||
 | 
					  * Enable statsd support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * hlr.c: properly terminate the process on SIGTERM
 | 
				
			||||||
 | 
					  * hlr.c: fix: also store the session state in read_cb_forward()
 | 
				
			||||||
 | 
					  * hlr.c: fix: properly print the original message type in read_cb_forward()
 | 
				
			||||||
 | 
					  * hlr.c: check the presence of msgb->l2h in read_cb()
 | 
				
			||||||
 | 
					  * hlr.c: fix possible msgb memleaks in read_cb()
 | 
				
			||||||
 | 
					  * db_hlr.c: add db_subscr_exists_by_msisdn()
 | 
				
			||||||
 | 
					  * src/db.h: use GSM23003_MSISDN_MAX_DIGITS for MSISDN buffer size
 | 
				
			||||||
 | 
					  * src/hlr.c: fix deprecation warning: use gsm48_decode_bcd_number2()
 | 
				
			||||||
 | 
					  * hlr_ussd.c: fix: properly pass invokeID in handle_ussd_own_msisdn()
 | 
				
			||||||
 | 
					  * hlr_ussd.c: rx_proc_ss_req(): fix NULL pointer dereference
 | 
				
			||||||
 | 
					  * build: fix mess with 'db_test_SOURCES' and 'db_test_LDADD'
 | 
				
			||||||
 | 
					  * tests/db_test: close the database when test is finished
 | 
				
			||||||
 | 
					  * src/db.c: integrate SQLite3 with talloc allocator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * USSD: fix routing to multiple MSC
 | 
				
			||||||
 | 
					  * fix error logging for GSUP route
 | 
				
			||||||
 | 
					  * add missing error log: invalid IMSI
 | 
				
			||||||
 | 
					  * osmo-hlr: allow configuring db path from cfg file
 | 
				
			||||||
 | 
					  * use new OSMO_IMSI_BUF_SIZE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Daniel Willmann ]
 | 
				
			||||||
 | 
					  * manuals: Add script to update vty/counter documentation from docker
 | 
				
			||||||
 | 
					  * manuals: Update vty documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * Remove undefined param passed to logging_vty_add_cmds
 | 
				
			||||||
 | 
					  * configure.ac: Require libosmocore 1.2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Wed, 07 Aug 2019 16:14:23 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (1.0.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Stefan Sperling ]
 | 
				
			||||||
 | 
					  * move creation of insert subscriber data messages to a common function
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * Return proper GSUP error in case of too short IMSI
 | 
				
			||||||
 | 
					  * disable blind subscriber insertion into every VLR/SGSN
 | 
				
			||||||
 | 
					  * gsup_server: Add "priv" pointer and make it point to 'struct hlr'
 | 
				
			||||||
 | 
					  * move osmo_gsup_addr_send() declaration from luop.h to gsup_router.h
 | 
				
			||||||
 | 
					  * gsup_router: Use "#pragma once" and add missing #includes
 | 
				
			||||||
 | 
					  * Add "show gsup-connections" VTY command
 | 
				
			||||||
 | 
					  * import gsup_client.c as new libosmo-gsup-client
 | 
				
			||||||
 | 
					  * gsup_client: rename gsup_client_* to osmo_gsup_client_*
 | 
				
			||||||
 | 
					  * GSUP: Log GSUP route add/remove
 | 
				
			||||||
 | 
					  * hlr: Export + Declare global g_hlr symbol
 | 
				
			||||||
 | 
					  * USSD: Add Core USSD handling + VTY routing config to HLR
 | 
				
			||||||
 | 
					  * USSD: Add basic dispatch + decode of GSUP-encapsulated SS/USSD
 | 
				
			||||||
 | 
					  * hlr_ussd: Introduce LOGPSS() macro
 | 
				
			||||||
 | 
					  * USSD: Send ReturnError component if USSD Code unknown / EUSE disconnected
 | 
				
			||||||
 | 
					  * USSD: Further unification of log output; Use LOGPSS when possible
 | 
				
			||||||
 | 
					  * osmo-hlr.cfg: Don't enable DEBUG logging by default
 | 
				
			||||||
 | 
					  * USSD: Add new "DSS" logging category and use it appropriately
 | 
				
			||||||
 | 
					  * USSD: fix null-pointer deref in "default-route" vty/config cmd
 | 
				
			||||||
 | 
					  * Add osmo-euse-demo as minimalistic test of a External USSD (EUSE) handler
 | 
				
			||||||
 | 
					  * USSD: Add support for internal USSD handlers
 | 
				
			||||||
 | 
					  * debian: Add sub-package for libosmo-gsup-client
 | 
				
			||||||
 | 
					  * pkg-config: Fix libosmo-gsup-client pkg-config file
 | 
				
			||||||
 | 
					  * gitignore: Add .tarball-version
 | 
				
			||||||
 | 
					  * debian: Make libosmo-gsup-client-dev depend on libosmo-gsup-client0
 | 
				
			||||||
 | 
					  * USSD: Fix "ussd default-route"
 | 
				
			||||||
 | 
					  * libosmo-gsup-client: License is GPLv2-or-later
 | 
				
			||||||
 | 
					  * osmo-hlr.cfg: Ensure well-formed config file example
 | 
				
			||||||
 | 
					  * test_nodes.vty: Since libosmocore 1.0.0, we only have one space
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Martin Hauke ]
 | 
				
			||||||
 | 
					  * sql/Makefile.am: Make docsdir completely configurable
 | 
				
			||||||
 | 
					  * debian: Fix typo in package description
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * debian: Avoid installing duplicate cfg file in /etc
 | 
				
			||||||
 | 
					  * sql/Makefile: Install hlr_data.sql as example together with hlr.sql
 | 
				
			||||||
 | 
					  * sql/Makefile: Install sql files under doc/.../sql subdir
 | 
				
			||||||
 | 
					  * sql/Makefile: Create empty /var/lib/osmocom directory at install time
 | 
				
			||||||
 | 
					  * Install systemd services with autotools
 | 
				
			||||||
 | 
					  * Move doc/Makefile.am to doc/examples/Makefile.am
 | 
				
			||||||
 | 
					  * Install sample cfg file to /etc/osmocom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Vadim Yanitskiy ]
 | 
				
			||||||
 | 
					  * hlr.c: move deinitialization code from SIGINT handler
 | 
				
			||||||
 | 
					  * hlr.c: free root talloc context on exit
 | 
				
			||||||
 | 
					  * hlr.c: track the use of talloc NULL memory contexts
 | 
				
			||||||
 | 
					  * src/db.c: fix: make sure the database is properly closed
 | 
				
			||||||
 | 
					  * src/db.c: don't ignore the result of db_bootstrap()
 | 
				
			||||||
 | 
					  * hlr_vty_subscr.c: fix subscriber creation command help
 | 
				
			||||||
 | 
					  * Update .gitignore: add missing build products
 | 
				
			||||||
 | 
					  * tests/Makefile.am: also remove temporary sqlite files
 | 
				
			||||||
 | 
					  * hlr_ussd.h: add #pragma once include guard
 | 
				
			||||||
 | 
					  * hlr_ussd.h: use proper libc headers
 | 
				
			||||||
 | 
					  * Update .gitignore: ignore osmo-euse-demo
 | 
				
			||||||
 | 
					  * hlr_ussd.h: drop meaningless forward declaration
 | 
				
			||||||
 | 
					  * USSD/hlr_vty.c: print error if EUSE is not found
 | 
				
			||||||
 | 
					  * hlr_ussd.c: fix: properly print a EUSE / IUSE name
 | 
				
			||||||
 | 
					  * hlr_ussd.c: avoid using CR and NL in IUSE responses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * fix build: adjust test_nodes.vty to logging change
 | 
				
			||||||
 | 
					  * tweak example config
 | 
				
			||||||
 | 
					  * make: always allow running python tests manually
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Harald Welte <laforge@gnumonks.org>  Sun, 20 Jan 2019 19:29:58 +0100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (0.2.1) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * fix luop crash: use buffer for APN that remains valid
 | 
				
			||||||
 | 
					  * add gsup_test to catch OS#3231
 | 
				
			||||||
 | 
					  * add error handling to osmo_gsup_configure_wildcard_apn()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Fri, 04 May 2018 18:41:35 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (0.2.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * vty: skip installing cmds now always installed by default
 | 
				
			||||||
 | 
					  * hlr_db_tool: fix error log strerror invocation
 | 
				
			||||||
 | 
					  * cosmetic: add comment on ignored return value
 | 
				
			||||||
 | 
					  * db-tool: add command 'create'
 | 
				
			||||||
 | 
					  * db-tool: cosmetic: tweak printf output
 | 
				
			||||||
 | 
					  * db-tool: error-exit on too many arguments
 | 
				
			||||||
 | 
					  * add --enable-sanitize config option
 | 
				
			||||||
 | 
					  * db_test: don't verify SQLite issued error messages, they might change
 | 
				
			||||||
 | 
					  * cosmetic: rx_send_auth_info(): decide error cause with switch()
 | 
				
			||||||
 | 
					  * return GMM_CAUSE_IMSI_UNKNOWN if there is no auth data
 | 
				
			||||||
 | 
					  * db_get_auth_data / db_get_auc: clarify return values
 | 
				
			||||||
 | 
					  * osmo-hlr: log details for unknown IMSI / no auth data / db error
 | 
				
			||||||
 | 
					  * db_test: also test db_get_auc() return values
 | 
				
			||||||
 | 
					  * fix test_subscriber_errors.ctrl after libosmocore change
 | 
				
			||||||
 | 
					  * fix debug log: put 'deriving 2G from 3G' in proper place
 | 
				
			||||||
 | 
					  * ctrl test: fix: adjust expectations after stricter ctrl parsing
 | 
				
			||||||
 | 
					  * fix build: db_test: missing LIBOSMOABIS_CFLAGS and _LIBS
 | 
				
			||||||
 | 
					  * configure: add --enable-werror
 | 
				
			||||||
 | 
					  * jenkins.sh: use --enable-werror configure flag, not CFLAGS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * hlr.c: Avoid overflow of lu_operation.subscr.imsi
 | 
				
			||||||
 | 
					  * Fix expected test output after new 'logging print file 1' vty command
 | 
				
			||||||
 | 
					  * osmo-hlr: Add talloc context introspection via VTY
 | 
				
			||||||
 | 
					  * vty: Don't print error if removing auth data while none present
 | 
				
			||||||
 | 
					  * Fix responses to PURGE MS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Couzens ]
 | 
				
			||||||
 | 
					  * debian: include systemd service osmo-hlr.service
 | 
				
			||||||
 | 
					  * doc: install example .cfg files to $(docdir)/examples/
 | 
				
			||||||
 | 
					  * debian: install osmo-hlr.cfg to /etc/osmocom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Max ]
 | 
				
			||||||
 | 
					  * Remove unused check
 | 
				
			||||||
 | 
					  * Remove unused ipa.py
 | 
				
			||||||
 | 
					  * Enable sanitize for CI tests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * luop.c: Transform FIXME from warning to pragma message
 | 
				
			||||||
 | 
					  * contrib:jenkins.sh: Enable Werror
 | 
				
			||||||
 | 
					  * use osmo_init_logging2
 | 
				
			||||||
 | 
					  * Remove unused src/db_test.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Huemer ]
 | 
				
			||||||
 | 
					  * Add missing build products in .gitignore
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Stefan Sperling ]
 | 
				
			||||||
 | 
					  * more robust usage of osmo_timer API for osmo-hlr luop timer
 | 
				
			||||||
 | 
					  * notify GSUP clients when HLR subscriber information changes
 | 
				
			||||||
 | 
					  * rewrite subscriber_update_notify() without calls into luop
 | 
				
			||||||
 | 
					  * don't forget to mark luop as a packet switched connection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Pau Espin Pedrol <pespin@sysmocom.de>  Thu, 03 May 2018 16:27:13 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (0.1.0) unstable; urgency=medium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Neels Hofmeyr ]
 | 
				
			||||||
 | 
					  * build with autoconf/automake, add jenkins.sh script
 | 
				
			||||||
 | 
					  * fix build on FreeBSD: eliminate implicitly declared functions
 | 
				
			||||||
 | 
					  * fix various compiler warnings
 | 
				
			||||||
 | 
					  * fix DLGSUP logging cat after change in libosmocore
 | 
				
			||||||
 | 
					  * build: recoin db_test as non-installable program
 | 
				
			||||||
 | 
					  * build: actually make sqlite mandatory
 | 
				
			||||||
 | 
					  * bump required libosmocore version to 0.9.5
 | 
				
			||||||
 | 
					  * gsup: send subscriber MSISDN
 | 
				
			||||||
 | 
					  * debug log: log computed vector kinds
 | 
				
			||||||
 | 
					  * log: move a log from info to debug level
 | 
				
			||||||
 | 
					  * hlr.sql: typo in comment
 | 
				
			||||||
 | 
					  * auc.c: typo in comment
 | 
				
			||||||
 | 
					  * main: add and use root talloc ctx
 | 
				
			||||||
 | 
					  * main: add option parsing with db file and default options
 | 
				
			||||||
 | 
					  * main: add VTY and '-c config-file' option
 | 
				
			||||||
 | 
					  * sql: fix 3g_auc's column K data type
 | 
				
			||||||
 | 
					  * cosmetic: sql: indicate VARCHAR size of key columns as 32
 | 
				
			||||||
 | 
					  * sql: auc_3g: set sqn NOT NULL DEFAULT 0
 | 
				
			||||||
 | 
					  * comment: sql: describe auc_2g and auc_3g columns
 | 
				
			||||||
 | 
					  * Add test suite skeleton with empty test (auc_3g_test)
 | 
				
			||||||
 | 
					  * tests: auc_3g_test: implement vector generation test
 | 
				
			||||||
 | 
					  * auth: verify test sets from 3GPP TS 55.205
 | 
				
			||||||
 | 
					  * sql: add unique constraints to IMSI and MSISDN
 | 
				
			||||||
 | 
					  * UMTS AKA resync: fix argument ordering
 | 
				
			||||||
 | 
					  * auc_3g_test: add AUTS resync test
 | 
				
			||||||
 | 
					  * auc_gen_vectors(): ensure sane arguments, test
 | 
				
			||||||
 | 
					  * auc_3g_test: allow to inc fake rand bytes upon rand request
 | 
				
			||||||
 | 
					  * auc_3g_test: add AUTS test with N vectors, to show bug
 | 
				
			||||||
 | 
					  * cosmetic: refactor auc_compute_vectors(), add debug log
 | 
				
			||||||
 | 
					  * auc_compute_vectors(): fix AUTS resync for multiple vectors
 | 
				
			||||||
 | 
					  * cosmetic: auc_3g_test: improve test debugging tools
 | 
				
			||||||
 | 
					  * cosmetic: rename auc_3g_test.c to auc_test.c
 | 
				
			||||||
 | 
					  * fix: properly handle error rc by osmo_gsup_conn_ccm_get()
 | 
				
			||||||
 | 
					  * auc tests: adjust cosmetically to prepare for SQN changes
 | 
				
			||||||
 | 
					  * auc tests: fix after SQN scheme changes from libosmocore
 | 
				
			||||||
 | 
					  * fix debug log: adjust to new SQN increment scheme
 | 
				
			||||||
 | 
					  * UMTS AKA: implement SQN increment according to SEQ and IND
 | 
				
			||||||
 | 
					  * debug log: output ind slot, previous sqn, and sqn db update
 | 
				
			||||||
 | 
					  * jenkins: add value_string termination check
 | 
				
			||||||
 | 
					  * fix db_subscr_ps error handling
 | 
				
			||||||
 | 
					  * add config example (mostly empty)
 | 
				
			||||||
 | 
					  * install hlr.sql in prefix/doc/osmo-hlr/
 | 
				
			||||||
 | 
					  * use OSMO_GSUP_PORT == 4222 instead of hardcoded 2222
 | 
				
			||||||
 | 
					  * add basic CTRL interface tests
 | 
				
			||||||
 | 
					  * add CTRL tests for enable-/disable-/status-ps
 | 
				
			||||||
 | 
					  * cosmetic: prepend DB_STMT_ to enum stmt_idx entries
 | 
				
			||||||
 | 
					  * cosmetic: rename db_subscr_get() to db_subscr_get_by_imsi()
 | 
				
			||||||
 | 
					  * cosmetic: refactor db_bind_imsi() as db_bind_text()
 | 
				
			||||||
 | 
					  * cosmetic: multi-line DB_STMT_AUC_BY_IMSI
 | 
				
			||||||
 | 
					  * cosmetic: log IMSI='<imsi>', log "no such subscriber"
 | 
				
			||||||
 | 
					  * cosmetic: log: "SQLite" with capital L
 | 
				
			||||||
 | 
					  * cosmetic: db_hlr: SL3_TXT: clarify indenting
 | 
				
			||||||
 | 
					  * ctrl_test_runner.py: use proper constant as test db path
 | 
				
			||||||
 | 
					  * gitignore: tests/package.m4
 | 
				
			||||||
 | 
					  * cosmetic: don't log about missing SQLite log cb
 | 
				
			||||||
 | 
					  * add db_bind_int() and db_bind_int64()
 | 
				
			||||||
 | 
					  * add db_subscr_create(), db_subscr_delete(), db_subscr_update_msisdn_by_imsi()
 | 
				
			||||||
 | 
					  * add initial db_test: creating and deleting subscribers
 | 
				
			||||||
 | 
					  * less noise: simplify db_remove_reset()
 | 
				
			||||||
 | 
					  * db: use int64_t as subscriber id
 | 
				
			||||||
 | 
					  * add db_subscr_get_by_msisdn() and db_subscr_get_by_id()
 | 
				
			||||||
 | 
					  * refactor db_subscr_ps() to db_subscr_nam()
 | 
				
			||||||
 | 
					  * refactor db_subscr_lu()
 | 
				
			||||||
 | 
					  * refactor db_subscr_purge
 | 
				
			||||||
 | 
					  * add db_subscr_update_aud_by_id(), complete db_subscr_delete_by_id()
 | 
				
			||||||
 | 
					  * refactor db_get_auth_data return val
 | 
				
			||||||
 | 
					  * code undup: use db_remove_reset() in db_auc.c
 | 
				
			||||||
 | 
					  * fix db_update_sqn(): reset stmt in all error cases
 | 
				
			||||||
 | 
					  * code undup: use db_bind_text() in db_get_auth_data()
 | 
				
			||||||
 | 
					  * debian: 'make check' needs sqlite3, add to Build-Depends
 | 
				
			||||||
 | 
					  * fix db_subscr_get_by_*(): clear output data; test in db_test.c
 | 
				
			||||||
 | 
					  * implement subscriber vty interface, tests
 | 
				
			||||||
 | 
					  * add test_nodes.vty
 | 
				
			||||||
 | 
					  * replace ctrl_test_runner.py with transcript test_subscriber.ctrl
 | 
				
			||||||
 | 
					  * add lu_op_free(), use in luop.c
 | 
				
			||||||
 | 
					  * luop: fix mem leak upon error in lu_op_alloc_conn()
 | 
				
			||||||
 | 
					  * fix mem leak in handle_cmd_ps(): free luop
 | 
				
			||||||
 | 
					  * api doc: say that lu_op_tx_del_subscr_data() doesn't free
 | 
				
			||||||
 | 
					  * add hlr_subsrc_nam to put GSUP client notification in proper API
 | 
				
			||||||
 | 
					  * vty: fix output of empty IMSI
 | 
				
			||||||
 | 
					  * db api: fix/add API docs
 | 
				
			||||||
 | 
					  * cosmetic: tweak params of hlr_controlif_setup()
 | 
				
			||||||
 | 
					  * ctrl: completely replace all CTRL commands
 | 
				
			||||||
 | 
					  * test_subscriber.ctrl: test against octal/hex interpretation of id
 | 
				
			||||||
 | 
					  * jenkins: use osmo-clean-workspace.sh before and after build
 | 
				
			||||||
 | 
					  * tests/Makefile: use test db var instead of repeating the path
 | 
				
			||||||
 | 
					  * db_test: fix *FLAGS
 | 
				
			||||||
 | 
					  * automatically create db tables on osmo-hlr invocation
 | 
				
			||||||
 | 
					  * cosmetic: sql/hlr.sql: move comments
 | 
				
			||||||
 | 
					  * cosmetic: rename SL3_TXT macro, use osmo_strlcpy()
 | 
				
			||||||
 | 
					  * fix default logging levels to NOTICE, not DEBUG
 | 
				
			||||||
 | 
					  * add osmo-hlr-db-tool, program to migrate from osmo-nitb db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Max ]
 | 
				
			||||||
 | 
					  * Add gerrit settings
 | 
				
			||||||
 | 
					  * Add hardcoded APN
 | 
				
			||||||
 | 
					  * Log error cause as a string
 | 
				
			||||||
 | 
					  * Move GSUP msg init into separate function
 | 
				
			||||||
 | 
					  * Use strings for GSUP message type
 | 
				
			||||||
 | 
					  * Move lu_operation into separate file
 | 
				
			||||||
 | 
					  * db: move duplicated code into helper functions
 | 
				
			||||||
 | 
					  * Fix compiler's warning about printf security
 | 
				
			||||||
 | 
					  * Add routines to update nam_ps
 | 
				
			||||||
 | 
					  * Add global HLR struct
 | 
				
			||||||
 | 
					  * Make subscr parameter to db_subscr_get() optional
 | 
				
			||||||
 | 
					  * Add CTRL interface
 | 
				
			||||||
 | 
					  * CTRL: add enable/disable packet service cmds
 | 
				
			||||||
 | 
					  * Add .deb packaging
 | 
				
			||||||
 | 
					  * deb: fix OBS build
 | 
				
			||||||
 | 
					  * debian: remove obsolete dependency
 | 
				
			||||||
 | 
					  * Attempt to fix .deb package
 | 
				
			||||||
 | 
					  * deb: use python in shebang
 | 
				
			||||||
 | 
					  * Another attempt at fixing .deb
 | 
				
			||||||
 | 
					  * Use release helper from libosmocore
 | 
				
			||||||
 | 
					  * Use value string check from osmo-ci
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Daniel Willmann ]
 | 
				
			||||||
 | 
					  * Add systemd service file
 | 
				
			||||||
 | 
					  * hlr_data.sql: Insert ki and opc instead of op to example data
 | 
				
			||||||
 | 
					  * tests/auc: Don't require python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Pau Espin Pedrol ]
 | 
				
			||||||
 | 
					  * VTY: Add hlr node and bind ip field
 | 
				
			||||||
 | 
					  * debian: remove unneeded dependency libdbd-sqlite3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Harald Welte ]
 | 
				
			||||||
 | 
					  * jenkins.sh: Proper error message if local environment isn't set up
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [ Alexander Couzens ]
 | 
				
			||||||
 | 
					  * debian/rules: show testsuite.log when tests are failing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Harald Welte <laforge@gnumonks.org>  Sat, 28 Oct 2017 20:37:33 +0200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo-hlr (0.0.1) UNRELEASED; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     * Initial release (Closes: OS#1948)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Max Suraev <msuraev@sysmocom.de>  Mon, 13 Mar 2017 16:26:41 +0200
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					9
 | 
				
			||||||
							
								
								
									
										100
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					Source: osmo-hlr
 | 
				
			||||||
 | 
					Section: net
 | 
				
			||||||
 | 
					Priority: optional
 | 
				
			||||||
 | 
					Maintainer: Osmocom team <openbsc@lists.osmocom.org>
 | 
				
			||||||
 | 
					Build-Depends: debhelper (>= 9),
 | 
				
			||||||
 | 
					               pkg-config,
 | 
				
			||||||
 | 
					               dh-autoreconf,
 | 
				
			||||||
 | 
					               autotools-dev,
 | 
				
			||||||
 | 
					               python3-minimal,
 | 
				
			||||||
 | 
					               libosmocore-dev (>= 1.7.0),
 | 
				
			||||||
 | 
					               libosmo-abis-dev (>= 1.3.0),
 | 
				
			||||||
 | 
					               libosmo-netif-dev (>= 1.2.0),
 | 
				
			||||||
 | 
					               libsqlite3-dev,
 | 
				
			||||||
 | 
					               sqlite3,
 | 
				
			||||||
 | 
					               osmo-gsm-manuals-dev (>= 1.3.0)
 | 
				
			||||||
 | 
					Standards-Version: 3.9.6
 | 
				
			||||||
 | 
					Vcs-Browser: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
 | 
				
			||||||
 | 
					Vcs-Git: https://gitea.osmocom.org/cellular-infrastructure/osmo-hlr
 | 
				
			||||||
 | 
					Homepage: https://projects.osmocom.org/projects/osmo-hlr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: osmo-hlr
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Depends: ${shlibs:Depends}, ${misc:Depends}
 | 
				
			||||||
 | 
					Description: Osmocom Home Location Register
 | 
				
			||||||
 | 
					 OsmoHLR is a Osmocom implementation of HLR (Home Location Registrar) which works over GSUP
 | 
				
			||||||
 | 
					 protocol. The subscribers are store in sqlite DB. It supports both 2G and 3G authentication.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: osmo-hlr-dbg
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Section: debug
 | 
				
			||||||
 | 
					Priority: extra
 | 
				
			||||||
 | 
					Depends: osmo-hlr (= ${binary:Version}), ${misc:Depends}
 | 
				
			||||||
 | 
					Description: Debug symbols for the osmo-hlr
 | 
				
			||||||
 | 
					 Make debugging possible
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: libosmo-gsup-client0
 | 
				
			||||||
 | 
					Section: libs
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Multi-Arch: same
 | 
				
			||||||
 | 
					Depends: ${shlibs:Depends},
 | 
				
			||||||
 | 
						 ${misc:Depends}
 | 
				
			||||||
 | 
					Pre-Depends: ${misc:Pre-Depends}
 | 
				
			||||||
 | 
					Description: Osmocom GSUP (General Subscriber Update Protocol) client library
 | 
				
			||||||
 | 
					  This is a shared library that can be used to implement client programs for
 | 
				
			||||||
 | 
					  the GSUP protocol.  The typical GSUP server is OsmoHLR, with OsmoMSC, OsmoSGSN
 | 
				
			||||||
 | 
					  and External USSD Entities (EUSEs) using this library to implement clients.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: libosmo-gsup-client-dev
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Multi-Arch: same
 | 
				
			||||||
 | 
					Depends: ${misc:Depends},
 | 
				
			||||||
 | 
						 libosmo-gsup-client0 (= ${binary:Version}),
 | 
				
			||||||
 | 
						 libosmocore-dev
 | 
				
			||||||
 | 
					Description: Development headers of Osmocom GSUP client library
 | 
				
			||||||
 | 
					  This is a shared library that can be used to implement client programs for
 | 
				
			||||||
 | 
					  the GSUP protocol.  The typical GSUP server is OsmoHLR, with OsmoMSC, OsmoSGSN
 | 
				
			||||||
 | 
					  and External USSD Entities (EUSEs) using this library to implement clients.
 | 
				
			||||||
 | 
					  .
 | 
				
			||||||
 | 
					  This package contains the development headers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: libosmo-mslookup0
 | 
				
			||||||
 | 
					Section: libs
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Multi-Arch: same
 | 
				
			||||||
 | 
					Depends: ${shlibs:Depends},
 | 
				
			||||||
 | 
					         ${misc:Depends}
 | 
				
			||||||
 | 
					Pre-Depends: ${misc:Pre-Depends}
 | 
				
			||||||
 | 
					Description: Osmocom MS lookup library
 | 
				
			||||||
 | 
					  This shared library contains routines for looking up mobile subscribers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: libosmo-mslookup-dev
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Multi-Arch: same
 | 
				
			||||||
 | 
					Depends: ${misc:Depends},
 | 
				
			||||||
 | 
						 libosmo-mslookup0 (= ${binary:Version}),
 | 
				
			||||||
 | 
						 libosmocore-dev
 | 
				
			||||||
 | 
					Pre-Depends: ${misc:Pre-Depends}
 | 
				
			||||||
 | 
					Description: Development headers of Osmocom MS lookup library
 | 
				
			||||||
 | 
					  This shared library contains routines for looking up mobile subscribers.
 | 
				
			||||||
 | 
					  .
 | 
				
			||||||
 | 
					  This package contains the development headers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: osmo-mslookup-utils
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Section: utils
 | 
				
			||||||
 | 
					Depends: ${shlibs:Depends},
 | 
				
			||||||
 | 
						 libosmo-mslookup0 (= ${binary:Version}),
 | 
				
			||||||
 | 
					         ${misc:Depends}
 | 
				
			||||||
 | 
					Multi-Arch: same
 | 
				
			||||||
 | 
					Description: Utilities for Osmocom MS lookup
 | 
				
			||||||
 | 
					  This package contains a simple MS lookup client utility.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: osmo-hlr-doc
 | 
				
			||||||
 | 
					Architecture: all
 | 
				
			||||||
 | 
					Section: doc
 | 
				
			||||||
 | 
					Priority: optional
 | 
				
			||||||
 | 
					Depends: ${misc:Depends}
 | 
				
			||||||
 | 
					Description: ${misc:Package} PDF documentation
 | 
				
			||||||
 | 
					 Various manuals: user manual, VTY reference manual and/or
 | 
				
			||||||
 | 
					 protocol/interface manuals.
 | 
				
			||||||
							
								
								
									
										21
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 | 
				
			||||||
 | 
					Upstream-Name: OsmoHLR
 | 
				
			||||||
 | 
					Source: http://cgit.osmocom.org/osmo-hlr/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: *
 | 
				
			||||||
 | 
					Copyright: 2016-2017 Sysmocom s. f. m. c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					License: AGPL-3+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					License: AGPL-3+
 | 
				
			||||||
 | 
					 This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 | 
				
			||||||
 | 
					 GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
							
								
								
									
										5
									
								
								debian/libosmo-gsup-client-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								debian/libosmo-gsup-client-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					usr/include/osmocom/gsupclient
 | 
				
			||||||
 | 
					usr/lib/*/libosmo-gsup-client*.a
 | 
				
			||||||
 | 
					usr/lib/*/libosmo-gsup-client*.so
 | 
				
			||||||
 | 
					usr/lib/*/libosmo-gsup-client*.la
 | 
				
			||||||
 | 
					usr/lib/*/pkgconfig/libosmo-gsup-client.pc
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/libosmo-gsup-client0.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/libosmo-gsup-client0.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					usr/lib/*/libosmo-gsup-client*.so.*
 | 
				
			||||||
							
								
								
									
										5
									
								
								debian/libosmo-mslookup-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								debian/libosmo-mslookup-dev.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					usr/include/osmocom/mslookup
 | 
				
			||||||
 | 
					usr/lib/*/libosmo-mslookup*.a
 | 
				
			||||||
 | 
					usr/lib/*/libosmo-mslookup*.so
 | 
				
			||||||
 | 
					usr/lib/*/libosmo-mslookup*.la
 | 
				
			||||||
 | 
					usr/lib/*/pkgconfig/libosmo-mslookup.pc
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/libosmo-mslookup0.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/libosmo-mslookup0.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					usr/lib/*/libosmo-mslookup*.so.*
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/osmo-hlr-doc.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-hlr-doc.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					usr/share/doc/osmo-hlr-doc/*.pdf
 | 
				
			||||||
							
								
								
									
										9
									
								
								debian/osmo-hlr.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								debian/osmo-hlr.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/etc/osmocom/osmo-hlr.cfg
 | 
				
			||||||
 | 
					/lib/systemd/system/osmo-hlr.service
 | 
				
			||||||
 | 
					/usr/bin/osmo-hlr
 | 
				
			||||||
 | 
					/usr/bin/osmo-hlr-db-tool
 | 
				
			||||||
 | 
					/usr/share/doc/osmo-hlr/sql/hlr.sql
 | 
				
			||||||
 | 
					/usr/share/doc/osmo-hlr/sql/hlr_data.sql
 | 
				
			||||||
 | 
					/usr/share/doc/osmo-hlr/examples/osmo-hlr.cfg
 | 
				
			||||||
 | 
					/usr/share/osmocom/osmo-hlr-post-upgrade.sh
 | 
				
			||||||
 | 
					/var/lib/osmocom
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/osmo-mslookup-utils.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/osmo-mslookup-utils.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					usr/bin/osmo-mslookup-client
 | 
				
			||||||
							
								
								
									
										5
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										5
									
								
								debian/postinst
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					#!/bin/sh -e
 | 
				
			||||||
 | 
					# Debian's postinst script is called on both installation and upgrade. Call the
 | 
				
			||||||
 | 
					# post-upgrade script in both cases, it won't do anything if there is nothing
 | 
				
			||||||
 | 
					# to do.
 | 
				
			||||||
 | 
					/usr/share/osmocom/osmo-hlr-post-upgrade.sh
 | 
				
			||||||
							
								
								
									
										24
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/make -f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#export DH_VERBOSE=1
 | 
				
			||||||
 | 
					export DEB_BUILD_MAINT_OPTIONS = hardening=+all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%:
 | 
				
			||||||
 | 
						dh $@ --with autoreconf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					override_dh_shlibdeps:
 | 
				
			||||||
 | 
						dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					override_dh_strip:
 | 
				
			||||||
 | 
						dh_strip --dbg-package=osmo-hlr-dbg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Print test results in case of a failure
 | 
				
			||||||
 | 
					override_dh_auto_test:
 | 
				
			||||||
 | 
						dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					override_dh_auto_configure:
 | 
				
			||||||
 | 
						dh_auto_configure -- --with-systemdsystemunitdir=/lib/systemd/system --enable-manuals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Don't create .pdf.gz files (barely saves space and they can't be opened directly by most pdf readers)
 | 
				
			||||||
 | 
					override_dh_compress:
 | 
				
			||||||
 | 
						dh_compress -X.pdf
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					3.0 (native)
 | 
				
			||||||
							
								
								
									
										4
									
								
								doc/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								doc/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					SUBDIRS = \
 | 
				
			||||||
 | 
						examples \
 | 
				
			||||||
 | 
						manuals \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
							
								
								
									
										27
									
								
								doc/examples/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								doc/examples/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					osmoconfdir = $(sysconfdir)/osmocom
 | 
				
			||||||
 | 
					osmoconf_DATA = osmo-hlr.cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_DIST = osmo-hlr.cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CFG_FILES = find $(srcdir) -name '*.cfg*' | sed -e 's,^$(srcdir),,'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dist-hook:
 | 
				
			||||||
 | 
						for f in $$($(CFG_FILES)); do \
 | 
				
			||||||
 | 
							j="$(distdir)/$$f" && \
 | 
				
			||||||
 | 
							mkdir -p "$$(dirname $$j)" && \
 | 
				
			||||||
 | 
							$(INSTALL_DATA) $(srcdir)/$$f $$j; \
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install-data-hook:
 | 
				
			||||||
 | 
						for f in $$($(CFG_FILES)); do \
 | 
				
			||||||
 | 
							j="$(DESTDIR)$(docdir)/examples/$$f" && \
 | 
				
			||||||
 | 
							mkdir -p "$$(dirname $$j)" && \
 | 
				
			||||||
 | 
							$(INSTALL_DATA) $(srcdir)/$$f $$j; \
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uninstall-hook:
 | 
				
			||||||
 | 
						@$(PRE_UNINSTALL)
 | 
				
			||||||
 | 
						for f in $$($(CFG_FILES)); do \
 | 
				
			||||||
 | 
							j="$(DESTDIR)$(docdir)/examples/$$f" && \
 | 
				
			||||||
 | 
							$(RM) $$j; \
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
							
								
								
									
										22
									
								
								doc/examples/osmo-hlr-dgsm.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								doc/examples/osmo-hlr-dgsm.cfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					# OsmoHLR example configuration for Distributed GSM (mslookup)
 | 
				
			||||||
 | 
					hlr
 | 
				
			||||||
 | 
					 gsup
 | 
				
			||||||
 | 
					  # For D-GSM roaming, osmo-hlr's GSUP must listen on a public IP:
 | 
				
			||||||
 | 
					  bind ip 10.9.8.7
 | 
				
			||||||
 | 
					  # Each HLR should identify with a distinct name
 | 
				
			||||||
 | 
					  ipa-name hlr-23
 | 
				
			||||||
 | 
					mslookup
 | 
				
			||||||
 | 
					 # Bind mslookup mDNS server and client on default multicast address and port:
 | 
				
			||||||
 | 
					 # 239.192.23.42 port 4266
 | 
				
			||||||
 | 
					 mdns bind
 | 
				
			||||||
 | 
					 # Tell the mslookup server in osmo-hlr which IP+ports to return when a
 | 
				
			||||||
 | 
					 # remote voice call or SMS wants to deliver to a local subscriber:
 | 
				
			||||||
 | 
					 server
 | 
				
			||||||
 | 
					  # local osmo-sip-connector SIP port
 | 
				
			||||||
 | 
					  service sip.voice at 10.9.8.7 5060
 | 
				
			||||||
 | 
					  # local osmo-msc SMPP port
 | 
				
			||||||
 | 
					  service smpp.sms at 10.9.8.7 2775
 | 
				
			||||||
 | 
					  # experimental: SMS-over-GSUP: this HLR's GSUP port
 | 
				
			||||||
 | 
					  service gsup.sms at 10.9.8.7 4222
 | 
				
			||||||
 | 
					  # only required if different from above 'gsup'/'bind ip':
 | 
				
			||||||
 | 
					  #service gsup.hlr at 10.9.8.7 4222
 | 
				
			||||||
							
								
								
									
										26
									
								
								doc/examples/osmo-hlr.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								doc/examples/osmo-hlr.cfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					!
 | 
				
			||||||
 | 
					! OsmoHLR example configuration
 | 
				
			||||||
 | 
					!
 | 
				
			||||||
 | 
					log stderr
 | 
				
			||||||
 | 
					 logging filter all 1
 | 
				
			||||||
 | 
					 logging color 1
 | 
				
			||||||
 | 
					 logging print category 1
 | 
				
			||||||
 | 
					 logging print category-hex 0
 | 
				
			||||||
 | 
					 logging print level 1
 | 
				
			||||||
 | 
					 logging print file basename last
 | 
				
			||||||
 | 
					 logging print extended-timestamp 1
 | 
				
			||||||
 | 
					 logging level main notice
 | 
				
			||||||
 | 
					 logging level db notice
 | 
				
			||||||
 | 
					 logging level auc notice
 | 
				
			||||||
 | 
					 logging level ss notice
 | 
				
			||||||
 | 
					 logging level linp error
 | 
				
			||||||
 | 
					!
 | 
				
			||||||
 | 
					line vty
 | 
				
			||||||
 | 
					 bind 127.0.0.1
 | 
				
			||||||
 | 
					ctrl
 | 
				
			||||||
 | 
					 bind 127.0.0.1
 | 
				
			||||||
 | 
					hlr
 | 
				
			||||||
 | 
					 gsup
 | 
				
			||||||
 | 
					  bind ip 127.0.0.1
 | 
				
			||||||
 | 
					 ussd route prefix *#100# internal own-msisdn
 | 
				
			||||||
 | 
					 ussd route prefix *#101# internal own-imsi
 | 
				
			||||||
							
								
								
									
										71
									
								
								doc/manuals/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								doc/manuals/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					EXTRA_DIST = \
 | 
				
			||||||
 | 
					    example_subscriber_add_update_delete.vty \
 | 
				
			||||||
 | 
					    example_subscriber_aud2g.ctrl \
 | 
				
			||||||
 | 
					    example_subscriber_aud3g.ctrl \
 | 
				
			||||||
 | 
					    example_subscriber_cs_ps_enabled.ctrl \
 | 
				
			||||||
 | 
					    example_subscriber_info.ctrl \
 | 
				
			||||||
 | 
					    example_subscriber_msisdn.ctrl \
 | 
				
			||||||
 | 
					    osmohlr-usermanual.adoc \
 | 
				
			||||||
 | 
					    osmohlr-usermanual-docinfo.xml \
 | 
				
			||||||
 | 
					    osmohlr-vty-reference.xml \
 | 
				
			||||||
 | 
					    regen_doc.sh \
 | 
				
			||||||
 | 
					    chapters \
 | 
				
			||||||
 | 
					    vty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if BUILD_MANUALS
 | 
				
			||||||
 | 
					  ASCIIDOC = osmohlr-usermanual.adoc
 | 
				
			||||||
 | 
					  ASCIIDOC_DEPS = $(srcdir)/chapters/*.adoc $(srcdir)/*.vty $(srcdir)/*.ctrl
 | 
				
			||||||
 | 
					  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.asciidoc.inc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  VTY_REFERENCE = osmohlr-vty-reference.xml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  BUILT_REFERENCE_XML = $(builddir)/vty/hlr_vty_reference.xml
 | 
				
			||||||
 | 
					  $(builddir)/vty/hlr_vty_reference.xml: $(top_builddir)/src/osmo-hlr
 | 
				
			||||||
 | 
						mkdir -p $(builddir)/vty
 | 
				
			||||||
 | 
						$(top_builddir)/src/osmo-hlr --vty-ref-xml > $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.vty-reference.inc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  OSMO_REPOSITORY = osmo-hlr
 | 
				
			||||||
 | 
					  include $(OSMO_GSM_MANUALS_DIR)/build/Makefile.common.inc
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TMP_DB = generated/hlr.db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					update-examples: update-examples-ctrl update-examples-vty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: found-update-deps
 | 
				
			||||||
 | 
					found-update-deps:
 | 
				
			||||||
 | 
						@if [ ! -f "$(top_srcdir)/sql/hlr.sql" ]; then \
 | 
				
			||||||
 | 
							echo "You need to define OSMO_HLR_PATH to point at an osmo-hlr.git"; \
 | 
				
			||||||
 | 
							exit 1; \
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						@if [ -z "$(shell which osmo-hlr)" ]; then \
 | 
				
			||||||
 | 
							echo "osmo-hlr needs to be installed / available in the PATH"; \
 | 
				
			||||||
 | 
							exit 1; \
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						@if [ -z "$(shell which osmo_verify_transcript_ctrl.py)" ]; then \
 | 
				
			||||||
 | 
							echo "You need to install git.osmocom.org/python/osmo-python-tests.git"; \
 | 
				
			||||||
 | 
							exit 1; \
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
						@if [ -z "$(shell which osmo_verify_transcript_vty.py)" ]; then \
 | 
				
			||||||
 | 
							echo "You need to install git.osmocom.org/python/osmo-python-tests.git"; \
 | 
				
			||||||
 | 
							exit 1; \
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					update-examples-ctrl: found-update-deps
 | 
				
			||||||
 | 
						mkdir -p generated
 | 
				
			||||||
 | 
						rm -f "$(TMP_DB)"
 | 
				
			||||||
 | 
						sqlite3 "$(TMP_DB)" < "$(top_srcdir)/sql/hlr.sql"
 | 
				
			||||||
 | 
						sqlite3 "$(TMP_DB)" < "$(top_srcdir)/tests/test_subscriber.sql"
 | 
				
			||||||
 | 
						osmo_verify_transcript_ctrl.py \
 | 
				
			||||||
 | 
							-r "osmo-hlr -l $(TMP_DB) -c $(top_srcdir)/doc/examples/osmo-hlr.cfg" \
 | 
				
			||||||
 | 
							-p 4259 --update *.ctrl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					update-examples-vty: found-update-deps
 | 
				
			||||||
 | 
						mkdir -p generated
 | 
				
			||||||
 | 
						rm -f "$(TMP_DB)"
 | 
				
			||||||
 | 
						sqlite3 "$(TMP_DB)" < "$(top_srcdir)/sql/hlr.sql"
 | 
				
			||||||
 | 
						osmo_verify_transcript_vty.py \
 | 
				
			||||||
 | 
							-r "osmo-hlr -l $(TMP_DB) -c $(top_srcdir)/doc/examples/osmo-hlr.cfg" \
 | 
				
			||||||
 | 
							-p 4258 --update *.vty
 | 
				
			||||||
							
								
								
									
										179
									
								
								doc/manuals/chapters/control.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								doc/manuals/chapters/control.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					[[hlr-ctrl]]
 | 
				
			||||||
 | 
					== Control interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The actual protocol is described in <<common-control-if>>, the variables common
 | 
				
			||||||
 | 
					to all programs using it are described in <<ctrl_common_vars>>. This section
 | 
				
			||||||
 | 
					describes the CTRL interface variables specific to OsmoHLR.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Subscribers can be created and deleted using the following SET commands:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Subscriber management commands available on OsmoHLR's Control interface
 | 
				
			||||||
 | 
					[options="header",width="100%",cols="35%,65%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|Command|Comment
 | 
				
			||||||
 | 
					|subscriber.create '123456'|Create a new subscriber with IMSI "123456" to the database. Returns database ID of the subscriber being created.
 | 
				
			||||||
 | 
					|subscriber.delete '123456'|Delete subscriber with IMSI "123456" from database. Returns database ID of the subscriber being deleted.
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All subscriber variables are available by different selectors, which are freely
 | 
				
			||||||
 | 
					interchangeable:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Subscriber selectors available on OsmoHLR's Control interface
 | 
				
			||||||
 | 
					[options="header",width="100%",cols="35%,65%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|Selector|Comment
 | 
				
			||||||
 | 
					|subscriber.*by-imsi-*'123456'.*|Subscriber selector by IMSI, replace "123456" with the actual IMSI
 | 
				
			||||||
 | 
					|subscriber.*by-msisdn-*'123456'.*|Subscriber selector by MSISDN
 | 
				
			||||||
 | 
					|subscriber.*by-id-*'123456'.*|Subscriber selector by database ID
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each of the above selectors feature all of these control variables:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Subscriber variables available on OsmoHLR's Control interface
 | 
				
			||||||
 | 
					[options="header",width="100%",cols="35%,8%,8%,8%,41%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|Name|Access|Trap|Value|Comment
 | 
				
			||||||
 | 
					|subscriber.by-\*.*info*|R|No||List (short) subscriber information
 | 
				
			||||||
 | 
					|subscriber.by-\*.*info-aud*|R|No||List subscriber authentication tokens
 | 
				
			||||||
 | 
					|subscriber.by-\*.*info-all*|R|No||List both 'info' and 'info-aud' in one
 | 
				
			||||||
 | 
					|subscriber.by-\*.*cs-enabled*|RW|No|'1' or '0'|Enable/disable circuit-switched access
 | 
				
			||||||
 | 
					|subscriber.by-\*.*ps-enabled*|RW|No|'1' or '0'|Enable/disable packet-switched access
 | 
				
			||||||
 | 
					|subscriber.by-\*.*msisdn*|RW|No|valid MSISDN string|Get/Set assigned MSISDN
 | 
				
			||||||
 | 
					|subscriber.by-\*.*aud2g*|RW|No|'algo[,KI]'|Get/Set 2g Authentication Data
 | 
				
			||||||
 | 
					|subscriber.by-\*.*aud2g*|RW|No|'algo[,KI,("op"|"opc"),OP_C[,ind_bitlen]]'|Get/Set 3g Authentication Data
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== subscriber.by-*.info, info-aud, info-all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Query the HLR database and return current subscriber record, in multiple lines
 | 
				
			||||||
 | 
					of the format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					name<tab>value
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To keep the reply as short as possible, some values are omitted if they are
 | 
				
			||||||
 | 
					empty. These are the returned values and their presence
 | 
				
			||||||
 | 
					modalities; for their meaning, see <<subscriber-params>>:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Returned values by OsmoHLR's 'info', 'info-all' and 'info-aud' commands
 | 
				
			||||||
 | 
					[options="header",width="100%",cols="15%,15%,30%,40%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|Returned by 'info-all' and|Name|Format|Presence
 | 
				
			||||||
 | 
					|'info'|id|-9223372036854775808 .. 9223372036854775807 (usually not negative)|always
 | 
				
			||||||
 | 
					|'info'|imsi|6 to 15 decimal digits|always
 | 
				
			||||||
 | 
					|'info'|msisdn|1 to 15 decimal digits|when non-empty
 | 
				
			||||||
 | 
					|'info'|nam_cs|'1' if CS is enabled, or '0'|always
 | 
				
			||||||
 | 
					|'info'|nam_ps|'1' if PS is enabled, or '0'|always
 | 
				
			||||||
 | 
					|'info'|vlr_number|up to 15 decimal digits|when non-empty
 | 
				
			||||||
 | 
					|'info'|sgsn_number|up to 15 decimal digits|when non-empty
 | 
				
			||||||
 | 
					|'info'|sgsn_address||when non-empty
 | 
				
			||||||
 | 
					|'info'|ms_purged_cs|'1' if CS is purged, or '0'|always
 | 
				
			||||||
 | 
					|'info'|ms_purged_ps|'1' if PS is purged, or '0'|always
 | 
				
			||||||
 | 
					|'info'|periodic_lu_timer|0..4294967295|always
 | 
				
			||||||
 | 
					|'info'|periodic_rau_tau_timer|0..4294967295|always
 | 
				
			||||||
 | 
					|'info'|lmsi|8 hex digits|always
 | 
				
			||||||
 | 
					|'info-aud'|aud2g.algo|one of 'comp128v1', 'comp128v2', 'comp128v3' or 'xor'|when valid 2G auth data is set
 | 
				
			||||||
 | 
					|'info-aud'|aud2g.ki|32 hexadecimal digits|when valid 2G auth data is set
 | 
				
			||||||
 | 
					|'info-aud'|aud3g.algo|so far always 'milenage'|when valid 3G auth data is set
 | 
				
			||||||
 | 
					|'info-aud'|aud3g.k|32 hexadecimal digits|when valid 3G auth data is set
 | 
				
			||||||
 | 
					|'info-aud'|aud3g.op|32 hexadecimal digits|when valid 3G auth data is set, *not* when OPC is set
 | 
				
			||||||
 | 
					|'info-aud'|aud3g.opc|32 hexadecimal digits|when valid 3G auth data is set, *not* when OP is set
 | 
				
			||||||
 | 
					|'info-aud'|aud3g.ind_bitlen|0..28|when valid 3G auth data is set
 | 
				
			||||||
 | 
					|'info-aud'|aud3g.sqn|0 .. 18446744073709551615|when valid 3G auth data is set
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is an example Control Interface transcript that illustrates the various
 | 
				
			||||||
 | 
					'info' commands:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					include::../example_subscriber_info.ctrl[]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== subscriber.by-*.ps-enabled, cs-enabled
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Disable or enable packet-/circuit-switched access for the given IMSI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* 'ps-enabled' switches access to GPRS or UMTS data services,
 | 
				
			||||||
 | 
					* 'cs-enabled' switches access to voice services.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When disabled, the next time this subscriber attempts to do a Location Updating
 | 
				
			||||||
 | 
					GSUP operation for the given domain (i.e. from the SGSN for 'ps-enabled', from
 | 
				
			||||||
 | 
					the MSC/VLR for 'cs-enabled'), it will be rejected by OsmoHLR. Currently
 | 
				
			||||||
 | 
					connected GSUP clients will be notified via GSUP when a subscriber is being
 | 
				
			||||||
 | 
					disabled, so that the subscriber can be dropped in case it is currently
 | 
				
			||||||
 | 
					attached.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The current 'ps-enabled'/'cs-enabled' status can be queried by 'GET' commands,
 | 
				
			||||||
 | 
					and also by looking at 'nam_ps' and 'nam_cs' in a 'subscriber.by-*.info'
 | 
				
			||||||
 | 
					response.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A value of "1" indicates that the given domain is enabled, which is the
 | 
				
			||||||
 | 
					default; a value of "0" disables access.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is an example transcript that illustrates 'ps-enabled' and 'cs-enabled'
 | 
				
			||||||
 | 
					commands:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					include::../example_subscriber_cs_ps_enabled.ctrl[]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== subscriber.by-*.msisdn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Get or set the MSISDN currently assigned to a subscriber.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is an example transcript that illustrates use of this command:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					include::../example_subscriber_msisdn.ctrl[]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== subscriber.by-*.aud2g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Get or set the 2G Authentication data of a subscriber.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The information is stored/retrieved as a comma separated list of fields:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					algo[,KI]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where::
 | 
				
			||||||
 | 
					* *KI* is the KI as a hexadecimal string.
 | 
				
			||||||
 | 
					* *algo* is one of the following algorithms: _none, xor, comp128v1, comp128v2,
 | 
				
			||||||
 | 
					  comp128v3_.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All values are case insensitive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is an example transcript that illustrates use of this command:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					include::../example_subscriber_aud2g.ctrl[]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== subscriber.by-*.aud3g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Get or set the 3G Authentication data of a subscriber.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The information is stored/retrieved as a comma separated list of fields:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					algo[,KI,("op"|"opc"),OP_C[,ind_bitlen]]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Where:
 | 
				
			||||||
 | 
					* *KI* is the KI as a hexadecimal string.
 | 
				
			||||||
 | 
					* *algo* is one of the following algorithms: _none, xor, milenage_.
 | 
				
			||||||
 | 
					* "op" or "opc" indicates whether next field is an OP or OPC value.
 | 
				
			||||||
 | 
					* *OP_C* contains an OP or OPC values as hexadecimal string, based on what the
 | 
				
			||||||
 | 
					  previous field specifies.
 | 
				
			||||||
 | 
					* *ind_bitlen* is set to 5 by default if not provided.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All values are case insensitive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is an example transcript that illustrates use of this command:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					include::../example_subscriber_aud3g.ctrl[]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
							
								
								
									
										491
									
								
								doc/manuals/chapters/dgsm.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										491
									
								
								doc/manuals/chapters/dgsm.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,491 @@
 | 
				
			|||||||
 | 
					== Distributed GSM / Multicast MS Lookup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Distributed GSM (D-GSM) allows independent mobile core network stacks to provide voice, SMS and Roaming services to each
 | 
				
			||||||
 | 
					other, without the need for centralised entities or administration authority, and in a way that is resilient against
 | 
				
			||||||
 | 
					unstable network links between sites.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					D-GSM aims at communal networks, where several independent sites, let's call them villages, each have a full mobile core
 | 
				
			||||||
 | 
					network infrastructure. It elegantly provides ad-hoc service for subscribers moving across villages, and allows villages
 | 
				
			||||||
 | 
					to dynamically join or leave the cooperative network without the need for configuration changes at other sites.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A challenge for linking separate sites is to find the current location of a subscriber. Typically, in mobile networks, a
 | 
				
			||||||
 | 
					centralized entity keeps track of where to Page for subscribers. Running several fully independent sites with unreliable
 | 
				
			||||||
 | 
					links between them makes it hard to provide such centralisation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					D-GSM finds subscribers by mslookup, a service provided by OsmoHLR, typically using multicast DNS queries.  This allows
 | 
				
			||||||
 | 
					routing Location Updating requests, calls, and SMS to the right site without administrative delay nor the need for a
 | 
				
			||||||
 | 
					reliable link to a central database.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					D-GSM is highly resilient against single sites or links becoming temporarily unavailable. Service between still
 | 
				
			||||||
 | 
					reachable sites simply continues; Service to a disconnected site resumes as soon as it becomes reachable again.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This brings an entirely new paradigm to mobile core network infrastructure: as sites become reachable on the IP network
 | 
				
			||||||
 | 
					and join the common IP multicast group, services between them become available immediately. Basically, the only premise
 | 
				
			||||||
 | 
					is that IP routing and multicast works across sites, and that each site uses unique IPA names in the GSUP config.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This chapter describes how D-GSM and mslookup work, and how to configure sites to use D-GSM, using Osmocom core network
 | 
				
			||||||
 | 
					infrastructure.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Finding Subscribers: mslookup Clients
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are two fundamentally distinct subscriber lookups provided by the mslookup service.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Find the Current Location of an MSISDN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[fig_dgsm_connect]]
 | 
				
			||||||
 | 
					.mslookup for connecting subscribers: Alice is visiting village C; a phone call gets routed directly to her current location independently from her resident village infrastructure
 | 
				
			||||||
 | 
					[graphviz]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					digraph G {
 | 
				
			||||||
 | 
					rankdir=LR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subgraph cluster_village_b {
 | 
				
			||||||
 | 
						label="Village B"
 | 
				
			||||||
 | 
						ms_bob [label="Bob\n(from village B)",shape=box]
 | 
				
			||||||
 | 
						pbx_b [label="SIP B"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subgraph cluster_village_c {
 | 
				
			||||||
 | 
						label="Village C"
 | 
				
			||||||
 | 
						ms_alice [label="Alice\n(from village A)",shape=box]
 | 
				
			||||||
 | 
						msc_c [label="MSC C"]
 | 
				
			||||||
 | 
						hlr_c [label="HLR C"]
 | 
				
			||||||
 | 
						sip_c [label="SIP C"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ms_alice -> msc_c [style=dashed,arrowhead=none]
 | 
				
			||||||
 | 
					msc_c -> hlr_c [label="attached",style=dashed,arrowhead=none]
 | 
				
			||||||
 | 
					ms_bob -> pbx_b [label="call Alice"]
 | 
				
			||||||
 | 
					pbx_b -> hlr_c [label="mslookup by MSISDN",style=dotted,dir=both]
 | 
				
			||||||
 | 
					pbx_b -> sip_c -> msc_c -> ms_alice [label="call"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For example, if a subscriber is currently visiting another village, establish a phone call / send SMS towards that
 | 
				
			||||||
 | 
					village.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- To deliver a phone call, a SIP agent integrates an mslookup client to request the SIP service of an MSISDN's current
 | 
				
			||||||
 | 
					  location (example: <<dgsm_conf_dialplan>>). It receives an IP address and port to send the SIP Invite to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- To deliver an SMS, an ESME integrates an mslookup client to request the SMPP service of an MSISDN's current location
 | 
				
			||||||
 | 
					  (example: <<dgsm_conf_esme_smpp>>).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The current location of a subscriber may change at any time, and, when moving across locations, a subscriber may
 | 
				
			||||||
 | 
					suddenly lose reception to the previous location without explicitly detaching. Hence an mslookup request for the current
 | 
				
			||||||
 | 
					location of an MSISDN may get numerous responses. To find the currently valid location, mslookup includes the age of the
 | 
				
			||||||
 | 
					subscriber record, i.e. how long ago the subscriber was last reached. The one response with the youngest age reflects
 | 
				
			||||||
 | 
					the current location.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In order to evaluate several responses, mslookup always waits for a fixed amount of time (1 second), and then evaluates
 | 
				
			||||||
 | 
					the available responses.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Services are not limited to SIP and SMPP, arbitrarily named services can be added to the mslookup configuration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Message sequence for locating an MSISDN to deliver a voice call
 | 
				
			||||||
 | 
					["mscgen"]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					msc {
 | 
				
			||||||
 | 
					  hscale="2";
 | 
				
			||||||
 | 
					  moms[label="MS,BSS\nvillage A"],momsc[label="MSC,MGW\nvillage A"],mosipcon[label="osmo-sip-connector\nvillage A"],mopbx[label="PBX\nvillage A"],mthlr[label="OsmoHLR\nvillage B"],mtsipcon[label="osmo-sip-connector\nvillage B"],mtmsc[label="MGW,MSC\nvillage B"],mtms[label="RAN,MS\nvillage B"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  moms =>> momsc [label="CC Setup"];
 | 
				
			||||||
 | 
					  momsc =>> mosipcon [label="MNCC_SETUP_IND"];
 | 
				
			||||||
 | 
					  mosipcon =>> mopbx [label="SIP INVITE"];
 | 
				
			||||||
 | 
					  mopbx rbox mopbx [label="dialplan: launch mslookup by MSISDN"];
 | 
				
			||||||
 | 
					  --- [label="multicast-DNS query to all connected sites"];
 | 
				
			||||||
 | 
					  ...;
 | 
				
			||||||
 | 
					  mopbx <<= mthlr [label="mDNS response\n(age)"];
 | 
				
			||||||
 | 
					  mopbx rbox mopbx [label="wait ~ 1s for more mDNS responses"];
 | 
				
			||||||
 | 
					  ...;
 | 
				
			||||||
 | 
					  mopbx =>> mtsipcon [label="SIP INVITE (MT)"];
 | 
				
			||||||
 | 
					  mtmsc <<= mtsipcon [label="MNCC_SETUP_REQ"];
 | 
				
			||||||
 | 
					  mtms <<= mtmsc [label="Paging (CC)"];
 | 
				
			||||||
 | 
					  moms rbox mtms [label="voice call commences"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Find the Home HLR for an IMSI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[fig_dgsm_roaming]]
 | 
				
			||||||
 | 
					.mslookup for Roaming: Alice visits village B; she can attach to the local mobile network, which proxies HLR administration to her home village.
 | 
				
			||||||
 | 
					[graphviz]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					digraph G {
 | 
				
			||||||
 | 
					rankdir=LR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subgraph cluster_village_b {
 | 
				
			||||||
 | 
						label="Village B"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ms_alice [label="Alice\n(from village A)",shape=box]
 | 
				
			||||||
 | 
						msc_b [label="MSC B"]
 | 
				
			||||||
 | 
						hlr_b [label="HLR B"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					subgraph cluster_village_a {
 | 
				
			||||||
 | 
						label="Village A"
 | 
				
			||||||
 | 
						hlr_alice [label="Alice's home HLR"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ms_alice -> msc_b -> hlr_b [label="Location\nUpdating"]
 | 
				
			||||||
 | 
					hlr_b -> hlr_alice [label="mslookup by IMSI",style=dotted,dir=both]
 | 
				
			||||||
 | 
					hlr_b -> hlr_alice [label="GSUP proxy forwarding"]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For example, when attaching to a local network, a local resident gets serviced directly by the local village's HLR,
 | 
				
			||||||
 | 
					while a visitor from another village gets serviced by the remote village's HLR (Roaming).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A home HLR typically stays the same for a given IMSI. If the home site is reachable, there should be exactly one
 | 
				
			||||||
 | 
					response to an mslookup request asking for it. The age of such a home-HLR response is always sent as zero.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If a response's age is zero, mslookup does not wait for further responses and immediately uses the result.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If there were more than one HLR accepting service for an IMSI, the one with the shortest response latency is used.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== mslookup Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR the main mslookup agent. It provides the responses for both current location services as well as for locating
 | 
				
			||||||
 | 
					the fixed home-HLR. But naturally, depending on the mslookup request's purpose, different OsmoHLR instances will respond
 | 
				
			||||||
 | 
					for a given subscriber.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- When querying the home HLR, it is always the (typically single) home HLR instance that sends the mslookup response. As
 | 
				
			||||||
 | 
					  soon as it finds the queried IMSI in the local HLR database, an OsmoHLR will respond to home-HLR requests.
 | 
				
			||||||
 | 
					  In <<fig_dgsm_roaming>>, Alice's home HLR responds to the Roaming request ("where is the home HLR?").
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- When querying the location of an MSISDN, it is always the HLR proxy nearest to the servicing MSC that sends the
 | 
				
			||||||
 | 
					  mslookup response. Even though the home HLR keeps the Location Updating record also for Roaming cases, it will only
 | 
				
			||||||
 | 
					  respond to an mslookup service request if the subscriber has attached at a directly connected MSC. If attached at a
 | 
				
			||||||
 | 
					  remote MSC, that MSC's remote HLR will be the GSUP proxy for the home HLR, and the remote HLR is responsible for
 | 
				
			||||||
 | 
					  responding to service requests.
 | 
				
			||||||
 | 
					  In <<fig_dgsm_roaming>>, HLR B is the nearest proxy and will answer all service requests ("where is this MSISDN?").
 | 
				
			||||||
 | 
					  Alice's home HLR will not answer service requests, because it detects that the servicing MSC is connected via another
 | 
				
			||||||
 | 
					  HLR proxy.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[dgsm_example_config]]
 | 
				
			||||||
 | 
					==== Example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Here is an osmo-hlr.cfg mslookup configuration example for one site, which is explained in subsequent chapters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 hlr
 | 
				
			||||||
 | 
					  gsup
 | 
				
			||||||
 | 
					   bind ip 10.9.8.7
 | 
				
			||||||
 | 
					   ipa-name hlr-23
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  mdns bind
 | 
				
			||||||
 | 
					  server
 | 
				
			||||||
 | 
					   service sip.voice at 10.9.8.7 5060
 | 
				
			||||||
 | 
					   service smpp.sms at 10.9.8.7 2775
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR has both an mslookup server and a client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The server responds to incoming service and home-HLR requests, when the local HLR is responsible.
 | 
				
			||||||
 | 
					- The client is used as GSUP proxy to a remote home HLR (found by mslookup upon a locally unknown IMSI).
 | 
				
			||||||
 | 
					- The client may also be used for forwarding SMS-over-GSUP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The mslookup service can be implemented by various methods.
 | 
				
			||||||
 | 
					At the time of writing, the only method implemented is mDNS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== mDNS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The stock mslookup method is mDNS, multicast DNS. It consists of standard DNS encoding according to <<ietf-rfc1035>> and
 | 
				
			||||||
 | 
					<<ietf-rfc3596>>, but sent and received on IP multicast. In the response, standard A and AAAA records return the
 | 
				
			||||||
 | 
					service's IP address, while additional TXT records provide the service's port number and the MS attach age.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TIP: To watch D-GSM mDNS conversations in wireshark, select "udp.port == 4266" (the default mslookup mDNS port
 | 
				
			||||||
 | 
					number), right click on the packet to "Decode as...", and select "DNS".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In OsmoHLR, the mDNS server and client are typically both enabled at the same time:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  mdns bind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Server and client can also be enabled/disabled individually:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  server
 | 
				
			||||||
 | 
					   mdns bind
 | 
				
			||||||
 | 
					  client
 | 
				
			||||||
 | 
					   mdns bind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These examples use the default mslookup multicast IP address and port. It is possible to configure custom IP address and
 | 
				
			||||||
 | 
					port, but beware that the IP address must be from a multicast range, see <<ietf-rfc5771>>:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  mdns bind 239.192.23.42 4266
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Domain names generated from mslookup queries (e.g. "sip.voice.123.msisdn") should not collide with IANA permitted
 | 
				
			||||||
 | 
					domains. Therefore we add the "mdns.osmocom.org" suffix. It can be overridden as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  mdns domain-suffix mdns.osmocom.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Server: Site Services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The mslookup server requires a list of service addresses provided at the local site, in order to respond to service
 | 
				
			||||||
 | 
					requests matching locally attached subscribers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  server
 | 
				
			||||||
 | 
					   service sip.voice at 10.9.8.7 5060
 | 
				
			||||||
 | 
					   service smpp.sms at 10.9.8.7 2775
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- "10.9.8.7 5060" are the IP address and port on which the local site's osmo-sip-connector is bound to receive SIP
 | 
				
			||||||
 | 
					  Invite requests.
 | 
				
			||||||
 | 
					- "10.9.8.7 2775" are the local site's OsmoMSC SMPP bind address and port.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Obviously, these IP addresses must be routable back to this site from all other sites. Using link-local or "ANY"
 | 
				
			||||||
 | 
					addresses, like 127.0.0.1 or 0.0.0.0, will not work here. Instead, each service config requires a public IP address that
 | 
				
			||||||
 | 
					all remote requestors are able to reach (not necessarily on the host that osmo-hlr is running on).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If a site has more than one MSC, services can also be configured for each MSC individually, keyed by the IPA unit name
 | 
				
			||||||
 | 
					that each MSC sends on the GSUP link:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  server
 | 
				
			||||||
 | 
					   msc ipa-name msc-262-42-0
 | 
				
			||||||
 | 
					    service sip.voice at 10.11.12.13 5060
 | 
				
			||||||
 | 
					    service smpp.sms at 10.11.12.13 2775
 | 
				
			||||||
 | 
					   msc ipa-name msc-901-70-0
 | 
				
			||||||
 | 
					    service sip.voice at 10.9.8.7 5060
 | 
				
			||||||
 | 
					    service smpp.sms at 10.9.8.7 2775
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Here, "msc-262-42-0" is the IPA name of a local OsmoMSC instance. To configure an OsmoMSC's IPA name on the GSUP link,
 | 
				
			||||||
 | 
					see osmo-msc.cfg, setting `hlr` / `ipa-name`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For mslookup service responses, only Location Updatings in the Circuit Switched domain are relevant. OsmoHLR does manage
 | 
				
			||||||
 | 
					IMSIs attaching in the Packet Switched domain (via an SGSN) similarly to Circuit Switched (via an MSC), but mslookup
 | 
				
			||||||
 | 
					completely ignores the Packet Switched attach status.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Server: Own GSUP Address
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When responding to home-HLR requests, OsmoHLR implicitly by default responds with its locally configured GSUP bind
 | 
				
			||||||
 | 
					address (setting `hlr` / `gsup` / `bind ip`). If required, an explicit local GSUP address and port can be configured,
 | 
				
			||||||
 | 
					for example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 hlr
 | 
				
			||||||
 | 
					  gsup
 | 
				
			||||||
 | 
					   bind ip 0.0.0.0
 | 
				
			||||||
 | 
					   ipa-name hlr-23
 | 
				
			||||||
 | 
					 mslookup
 | 
				
			||||||
 | 
					  server
 | 
				
			||||||
 | 
					   # osmo-hlr's own GSUP address to send in mslookup responses:
 | 
				
			||||||
 | 
					   service gsup.hlr at 10.9.8.7 4222
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The gsup.hlr service can only be configured globally (because requests come from arbitrary mDNS clients, before a
 | 
				
			||||||
 | 
					Location Updating has associated the IMSI with the requesting MSC).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Client IPA Naming
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For reliable GSUP proxy routing to a remote HLR (Roaming), it is important that each GSUP client, i.e. each HLR, MSC and
 | 
				
			||||||
 | 
					SGSN instance, has a unique IPA name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example for configuring an OsmoHLR instance's IPA name:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 hlr
 | 
				
			||||||
 | 
					  gsup
 | 
				
			||||||
 | 
					   ipa-name hlr-23
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Here, "hlr-23" is the unique identification of this OsmoHLR instance across all potentially connected D-GSM sites.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Furthermore, each MSC and SGSN must have a uniquely distinct IPA name across all sites (here "msc-262-42-0" and
 | 
				
			||||||
 | 
					"msc-901-70-0" are used as example IPA names for local MSCs).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When this OsmoHLR connects to a remote HLR, be it for GSUP proxying or SMS-over-GSUP, it communicates its own IPA name
 | 
				
			||||||
 | 
					(on GSUP link-up) as well as the IPA name of the requesting client MSC/SGSN (as Source Name in each message) to the
 | 
				
			||||||
 | 
					remote OsmoHLR GSUP server. These names are used to route GSUP responses back to the respective requesting peer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If two MSCs were accidentally configured with identical names, a problem will occur as soon as both MSCs attempt to
 | 
				
			||||||
 | 
					attach to the same OsmoHLR (either directly or via GSUP proxying). The MSC that shows up first will work normally, but
 | 
				
			||||||
 | 
					any duplicate that shows up later will be rejected, since a route for its name already exists.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Queries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In URL notation, typical mslookup queries look like:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 gsup.hlr.123456789.imsi
 | 
				
			||||||
 | 
					 sip.voice.123.msisdn
 | 
				
			||||||
 | 
					 smpp.sms.123.msisdn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A query consists of
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- a service name ("gsup.hlr"),
 | 
				
			||||||
 | 
					- an id ("123456789"),
 | 
				
			||||||
 | 
					- the id type ("imsi").
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The calling client also defines a timeout to wait for responses.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The mslookup ID types are fixed, while service names can be chosen arbitrarily.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mslookup ID types, no other ID types are understood by mslookup
 | 
				
			||||||
 | 
					[options="header",width="100%",cols="20%,80%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|ID Type|Description
 | 
				
			||||||
 | 
					|imsi|An IMSI as existing in an OsmoHLR subscriber database
 | 
				
			||||||
 | 
					|msisdn|A phone number as configured in an OsmoHLR subscriber database
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mslookup service name conventions, arbitrary service names can be added as required
 | 
				
			||||||
 | 
					[options="header",width="100%",cols="20%,20%,60%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|Service Name|Protocol|Description
 | 
				
			||||||
 | 
					|gsup.hlr | GSUP | Home HLR's GSUP server, to handle Location Updating related procedures
 | 
				
			||||||
 | 
					|sip.voice | SIP | OsmoSIPConnector, to receive a SIP Invite (MT side of a call)
 | 
				
			||||||
 | 
					|smpp.sms | SMPP | Destination OsmoMSC (or other SMPP server) to deliver an SMS to the recipient
 | 
				
			||||||
 | 
					|gsup.sms | GSUP | GSUP peer to deliver an SMS to the recipient using SMS-over-GSUP
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Arbitrarily named services can be added to the mslookup configuration and queried by mslookup clients; as soon as a
 | 
				
			||||||
 | 
					service name is present in osmo-hlr.cfg, it can be queried from any mslookup client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Service names should consist of a protocol name (like "sip", "gsup", "english") and an intended action/entity (like
 | 
				
			||||||
 | 
					"voice", "hlr", "greeting").
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Service Client Implementation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In principle, arbitrary services could query target addresses via mslookup, leaving it up to any and all kinds of
 | 
				
			||||||
 | 
					clients to find their respective destination addresses. But of course, mslookup was designed with specific services in
 | 
				
			||||||
 | 
					mind, namely:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- SIP call agents and
 | 
				
			||||||
 | 
					- SMS delivery (an ESME or SMSC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following chapters describe examples of setting up a working distributed core network providing SIP voice calls and
 | 
				
			||||||
 | 
					SMS forwarding across sites.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== mslookup Library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The OsmoHLR provides an mslookup client C library, libosmo-mslookup. Service lookups can be integrated directly
 | 
				
			||||||
 | 
					in client programs using this library. However, its mDNS implementation requires the libosmocore select() loop, which
 | 
				
			||||||
 | 
					can be challenging to integrate in practice. An alternative solution is the osmo-mslookup-client tool.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[dgsm_osmo_mslookup_client]]
 | 
				
			||||||
 | 
					==== osmo-mslookup-client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The mslookup C library is available, but often, a simpler approach for client implementations is desirable:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- When querying for a service address, the client is typically interested in the single final best result (youngest age
 | 
				
			||||||
 | 
					  / first responding home HLR).
 | 
				
			||||||
 | 
					- Voice call and SMS clients typically would block until an mslookup result is known. For example, the FreeSwitch
 | 
				
			||||||
 | 
					  dialplan integration expects a result synchronously, i.e. without waiting for mslookup responses via a select() loop.
 | 
				
			||||||
 | 
					- Integrating the libosmocore select() loop required for mDNS can break the already existing socket handling in the
 | 
				
			||||||
 | 
					  client program.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The osmo-mslookup-client cmdline tool provides a trivial way to synchronously acquire the single result for an mslookup
 | 
				
			||||||
 | 
					request. The service client can invoke an osmo-mslookup-client process per request and read the result from stdout.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each invocation obviously spawns a separate process and opens a multicast socket for mDNS. For better scalability,
 | 
				
			||||||
 | 
					osmo-mslookup-client can also be run as a daemon, providing results via a unix domain socket. Using synchronous write()
 | 
				
			||||||
 | 
					and recv() allows blocking until a result is received without interfering with the client program's select() setup.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By itself, osmo-mslookup-client is also helpful as a diagnostic tool:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					$ osmo-mslookup-client sip.voice.1001.msisdn
 | 
				
			||||||
 | 
					sip.voice.1001.msisdn	ok	10.9.8.7	5060
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ osmo-mslookup-client gsup.hlr.901700000014701.imsi
 | 
				
			||||||
 | 
					gsup.hlr.901700000014701.imsi	ok	10.9.8.7	4222
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ osmo-mslookup-client gsup.hlr.111111.imsi
 | 
				
			||||||
 | 
					gsup.hlr.111111.imsi	not-found
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ osmo-mslookup-client gsup.hlr.1001.msisdn sip.voice.1001.msisdn smpp.sms.1001.msisdn foo.1001.msisdn
 | 
				
			||||||
 | 
					gsup.hlr.1001.msisdn	ok	10.9.8.7	4222
 | 
				
			||||||
 | 
					foo.1001.msisdn	not-found
 | 
				
			||||||
 | 
					smpp.sms.1001.msisdn	ok	10.9.8.7	2775
 | 
				
			||||||
 | 
					sip.voice.1001.msisdn	ok	10.9.8.7	5060
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ osmo-mslookup-client --csv-headers gsup.hlr.901700000014701.imsi
 | 
				
			||||||
 | 
					QUERY	RESULT	V4_IP	V4_PORT	V6_IP	V6_PORT
 | 
				
			||||||
 | 
					gsup.hlr.901700000014701.imsi	ok	10.9.8.7	4222
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$ osmo-mslookup-client -f json gsup.hlr.901700000014701.imsi
 | 
				
			||||||
 | 
					{"query": "gsup.hlr.901700000014701.imsi", "result": "ok", "v4": ["10.9.8.7", "4222"]}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For full help including example client invocations in Python, see the output of:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 osmo-mslookup-client -h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== SIP Service Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[dgsm_conf_dialplan]]
 | 
				
			||||||
 | 
					===== FreeSwitch dialplan.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The FreeSWITCH PBX software <<freeswitch_pbx>> offers a Python integration to determine a SIP call recipient by a custom
 | 
				
			||||||
 | 
					dialplan implementation. An example dialplan implementation for FreeSWITCH that uses D-GSM mslookup is provided in the
 | 
				
			||||||
 | 
					osmo-hlr source tree under `contrib`, called `freeswitch_dialplan_dgsm.py`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To integrate it with your FREESWITCH setup, add a new `extension` block to your `dialplan/public.xml`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					    <extension name="outbound">
 | 
				
			||||||
 | 
					      <condition field="destination_number" expression=".*">
 | 
				
			||||||
 | 
						<action application="set" data="hangup_after_bridge=true"/>
 | 
				
			||||||
 | 
						<action application="set" data="session_in_hangup_hook=true"/>
 | 
				
			||||||
 | 
						<action application="set" data="ringback=%(2000, 4000, 440.0, 480.0)"/>
 | 
				
			||||||
 | 
						<action application="python" data="freeswitch_dialplan_dgsm"/>
 | 
				
			||||||
 | 
					      </condition>
 | 
				
			||||||
 | 
					    </extension>
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Make sure that the dir containing `freeswitch_dialplan_dgsm.py` is in your `PYTHONPATH` environment variable, and start
 | 
				
			||||||
 | 
					the server:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					$ export PYTHONPATH="$PYTHONPATH:/home/user/code/osmo-hlr/contrib/dgsm"
 | 
				
			||||||
 | 
					$ freeswitch -nf -nonat -nonatmap -nocal -nort -c
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== SMS Service Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[dgsm_conf_esme_smpp]]
 | 
				
			||||||
 | 
					===== SMS via SMPP Port
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					An example ESME using D-GSM mslookup, `esme_dgsm.py`, is provided in the osmo-hlr source tree under `contrib`. It
 | 
				
			||||||
 | 
					attaches to OsmoMSC's SMPP port to send SMS to recipients determined by mslookup.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoMSC should be configured as "smpp-first", so that all SMS routing is determined by mslookup. If configured without
 | 
				
			||||||
 | 
					smpp-first, OsmoMSC may try to deliver an SMS locally, even though the recipient has recently moved to a different site.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					An example OsmoMSC configuration to work with esme_dgsm.py:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					smpp
 | 
				
			||||||
 | 
					 local-tcp-ip 127.0.0.1 2775
 | 
				
			||||||
 | 
					 system-id test-msc
 | 
				
			||||||
 | 
					 policy closed
 | 
				
			||||||
 | 
					 smpp-first
 | 
				
			||||||
 | 
					 # outgoing to esme_dgsm.py
 | 
				
			||||||
 | 
					 esme OSMPP
 | 
				
			||||||
 | 
					  no alert-notifications
 | 
				
			||||||
 | 
					  password foo
 | 
				
			||||||
 | 
					  default-route
 | 
				
			||||||
 | 
					 # incoming from esme_dgsm.py
 | 
				
			||||||
 | 
					 esme ISMPP
 | 
				
			||||||
 | 
					  no alert-notifications
 | 
				
			||||||
 | 
					  password foo
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Launch esme_dgsm.py alongside OsmoMSC:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					./esme_dgsm.py --src-host 127.0.0.1
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					esme_dgsm.py will be notified via SMPP for each SMS to be delivered, and will forward them either to a remote
 | 
				
			||||||
 | 
					recipient, or back to the same OsmoMSC, depending on the mslookup result. If the MSISDN is not reachable (or
 | 
				
			||||||
 | 
					esme_dgsm.py can't handle the message for other reasons), it returns the RSYSERR code back to OsmoMSC.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that the esme_dgsm.py is a proof of concept and should not be used in production. It has several limitations, such
 | 
				
			||||||
 | 
					as not supporting multipart SMS messages.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					===== SMS-Over-GSUP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The GSUP protocol defines SMS delivery messages. When OsmoMSC is configured to deliver SMS via GSUP, MO SMS are directly
 | 
				
			||||||
 | 
					forwarded to the HLR, which will determine where to forward the SMS-over-GSUP messages using its mslookup client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FIXME implement this
 | 
				
			||||||
							
								
								
									
										69
									
								
								doc/manuals/chapters/overview.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								doc/manuals/chapters/overview.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					[[overview]]
 | 
				
			||||||
 | 
					== Overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This manual should help you getting started with OsmoHLR. It will cover
 | 
				
			||||||
 | 
					aspects of configuring and running the OsmoHLR.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[intro_overview]]
 | 
				
			||||||
 | 
					=== About OsmoHLR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR is Osmocom's minimal implementation of a Home Location Register (HLR)
 | 
				
			||||||
 | 
					for 2G and 3G GSM and UMTS mobile core networks. Its interfaces are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- GSUP, serving towards OsmoMSC and OsmoSGSN;
 | 
				
			||||||
 | 
					- A local SQLite database;
 | 
				
			||||||
 | 
					- The Osmocom typical telnet VTY and CTRL interfaces.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Originally, the OpenBSC project's OsmoNITB all-in-one implementation had an
 | 
				
			||||||
 | 
					integrated HLR, managing subscribers and SMS in the same local database. Along
 | 
				
			||||||
 | 
					with the separate OsmoMSC and its new VLR component, OsmoHLR was implemented
 | 
				
			||||||
 | 
					from scratch to alleviate various shortcomings of the internal HLR:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The separate HLR allows using centralized subscriber management for both
 | 
				
			||||||
 | 
					  circuit-switched and packet-switched domains (i.e. one OsmoHLR for both
 | 
				
			||||||
 | 
					  OsmoMSC and OsmoSGSN).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- VLR and HLR brought full UMTS AKA (Authentication and Key Agreement) support,
 | 
				
			||||||
 | 
					  i.e. Milenage authentication in both the full 3G variant as well as the
 | 
				
			||||||
 | 
					  backwards compatible 2G variant.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- In contrast to the OsmoNITB, the specific way the new OsmoMSC's VLR accesses
 | 
				
			||||||
 | 
					  OsmoHLR brings fully asynchronous subscriber database access.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Find the OsmoHLR issue tracker and wiki online at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- https://osmocom.org/projects/osmo-hlr
 | 
				
			||||||
 | 
					- https://osmocom.org/projects/osmo-hlr/wiki
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[fig-gsm]]
 | 
				
			||||||
 | 
					.Typical GSM network architecture used with OsmoHLR
 | 
				
			||||||
 | 
					[graphviz]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					digraph G {
 | 
				
			||||||
 | 
						rankdir=LR;
 | 
				
			||||||
 | 
						subgraph cluster_hlr {
 | 
				
			||||||
 | 
							label = "OsmoHLR";
 | 
				
			||||||
 | 
							GSUP [label="GSUP server"]
 | 
				
			||||||
 | 
							DB [label="SQLite DB"]
 | 
				
			||||||
 | 
							GSUP->DB
 | 
				
			||||||
 | 
							DB->CTRL [dir="back"]
 | 
				
			||||||
 | 
							DB->VTY [dir="back"]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Admin [label="Admin and\nMaintenance"]
 | 
				
			||||||
 | 
						SW [label="3rd party software\nintegration"]
 | 
				
			||||||
 | 
						VTY->Admin [dir="back"]
 | 
				
			||||||
 | 
						CTRL->SW [dir="back"]
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						MSC [label="MSC/VLR"]
 | 
				
			||||||
 | 
						MSC->GSUP  [label="GSUP"]
 | 
				
			||||||
 | 
						SGSN->GSUP [label="GSUP"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BSC->MSC
 | 
				
			||||||
 | 
						HNBGW->MSC
 | 
				
			||||||
 | 
						HNBGW->SGSN
 | 
				
			||||||
 | 
						PCU->SGSN
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										87
									
								
								doc/manuals/chapters/running.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								doc/manuals/chapters/running.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					== Running OsmoHLR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The OsmoHLR executable (`osmo-hlr`) offers the following command-line
 | 
				
			||||||
 | 
					arguments:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== SYNOPSIS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*osmo-hlr* [-h] [-c 'CONFIGFILE'] [-l 'DATABASE'] [-d 'DBGMASK'] [-D] [-s] [-T] [-e 'LOGLEVEL'] [-U] [-V]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== OPTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Keep the order the same as in osmo-hlr --help!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*-h, --help*::
 | 
				
			||||||
 | 
						Print a short help message about the supported options
 | 
				
			||||||
 | 
					*-c, --config-file 'CONFIGFILE'*::
 | 
				
			||||||
 | 
						Specify the file and path name of the configuration file to be
 | 
				
			||||||
 | 
						used. If none is specified, use `osmo-hlr.cfg` in the current
 | 
				
			||||||
 | 
						working directory.
 | 
				
			||||||
 | 
					*-l, --database 'DATABASE'*::
 | 
				
			||||||
 | 
						Specify the file name of the SQLite3 database to use as HLR/AUC
 | 
				
			||||||
 | 
						storage
 | 
				
			||||||
 | 
					*-d, --debug 'DBGMASK','DBGLEVELS'*::
 | 
				
			||||||
 | 
						Set the log subsystems and levels for logging to stderr. This
 | 
				
			||||||
 | 
						has mostly been superseded by VTY-based logging configuration,
 | 
				
			||||||
 | 
						see <<logging>> for further information.
 | 
				
			||||||
 | 
					*-D, --daemonize*::
 | 
				
			||||||
 | 
						Fork the process as a daemon into background.
 | 
				
			||||||
 | 
					*-s, --disable-color*::
 | 
				
			||||||
 | 
						Disable colors for logging to stderr. This has mostly been
 | 
				
			||||||
 | 
						deprecated by VTY based logging configuration, see <<logging>>
 | 
				
			||||||
 | 
						for more information.
 | 
				
			||||||
 | 
					*-T, --timestamp*::
 | 
				
			||||||
 | 
						Enable time-stamping of log messages to stderr. This has mostly
 | 
				
			||||||
 | 
						been deprecated by VTY based logging configuration, see
 | 
				
			||||||
 | 
						<<logging>> for more information.
 | 
				
			||||||
 | 
					*-e, --log-level 'LOGLEVEL'*::
 | 
				
			||||||
 | 
						Set the global log level for logging to stderr. This has mostly
 | 
				
			||||||
 | 
						been deprecated by VTY based logging configuration, see
 | 
				
			||||||
 | 
						<<logging>> for more information.
 | 
				
			||||||
 | 
					*-U, --db-upgrade*::
 | 
				
			||||||
 | 
						Allow HLR database schema upgrades. If OsmoHLR was updated and
 | 
				
			||||||
 | 
						requires a newer database schema, it will refuse to start unless
 | 
				
			||||||
 | 
						this option is specified. The updated database can not be
 | 
				
			||||||
 | 
						downgraded, make backups as necessary.
 | 
				
			||||||
 | 
					*-V, --version*::
 | 
				
			||||||
 | 
						Print the compile-time version number of the OsmoHLR program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Bootstrap the Database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If no database exists yet, OsmoHLR will automatically create and bootstrap a
 | 
				
			||||||
 | 
					database file with empty tables. If no `-l` command-line option is provided,
 | 
				
			||||||
 | 
					this database file will be created in the current working directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alternatively, you may use the `osmo-hlr-db-tool`, which is installed along
 | 
				
			||||||
 | 
					with `osmo-hlr`, to bootstrap an empty database, or to migrate subscriber data
 | 
				
			||||||
 | 
					from an old 'OsmoNITB' database. See <<db_import_nitb>>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Multiple instances
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Running multiple instances of `osmo-hlr` on the same computer is possible if
 | 
				
			||||||
 | 
					all interfaces (VTY, CTRL) are separated using the appropriate configuration
 | 
				
			||||||
 | 
					options. The IP based interfaces are binding to local host by default. In order
 | 
				
			||||||
 | 
					to separate the processes, the user has to bind those services to specific but
 | 
				
			||||||
 | 
					different IP addresses and/or ports.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The VTY and the Control interface can be bound to IP addresses from the loopback
 | 
				
			||||||
 | 
					address range, for example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					line vty
 | 
				
			||||||
 | 
					 bind 127.0.0.2
 | 
				
			||||||
 | 
					ctrl
 | 
				
			||||||
 | 
					 bind 127.0.0.2
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The GSUP interface can be bound to a specific IP address by the following
 | 
				
			||||||
 | 
					configuration options:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					hlr
 | 
				
			||||||
 | 
					 gsup
 | 
				
			||||||
 | 
					  bind ip 10.23.42.1
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: At the time of writing, OsmoHLR lacks a config option to change the GSUP
 | 
				
			||||||
 | 
					port, which is by default TCP port 4222.
 | 
				
			||||||
							
								
								
									
										209
									
								
								doc/manuals/chapters/subscribers.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								doc/manuals/chapters/subscribers.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
				
			|||||||
 | 
					== Managing Subscribers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Subscribers are kept in a local SQLite database file and can be managed via VTY
 | 
				
			||||||
 | 
					and CTRL interfaces.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This section provides some examples; also refer to the OsmoHLR VTY reference
 | 
				
			||||||
 | 
					manual <<vty-ref-osmohlr>> as well as the Control interface described in
 | 
				
			||||||
 | 
					<<hlr-ctrl>>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Example: Add/Update/Delete Subscriber via VTY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following telnet VTY session adds a subscriber complete with GSM (2G) and
 | 
				
			||||||
 | 
					UMTS (3G and 2G) authentication tokens, and finally removes the subscriber
 | 
				
			||||||
 | 
					again; it assumes that osmo-hlr is running and listening for telnet VTY
 | 
				
			||||||
 | 
					connections on localhost:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					$ telnet localhost 4258
 | 
				
			||||||
 | 
					include::../example_subscriber_add_update_delete.vty[]
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[subscriber-params]]
 | 
				
			||||||
 | 
					=== Subscriber Parameters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following parameters are managed for each subscriber of the HLR, modelled
 | 
				
			||||||
 | 
					roughly after 3GPP TS 23.008, version 13.3.0; note that not all of these
 | 
				
			||||||
 | 
					parameters are necessarily in active use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The `aud3g` table also applies to 2G networks: it provides UMTS AKA tokens for
 | 
				
			||||||
 | 
					Milenage authentication, which is available both on 3G and 2G networks. On 2G,
 | 
				
			||||||
 | 
					when both MS and network are R99 capable (like OsmoMSC and OsmoSGSN are), the
 | 
				
			||||||
 | 
					full UMTS AKA with Milenage keys from `aud_3g`, using AUTN and extended RES
 | 
				
			||||||
 | 
					tokens, is available. With pre-R99 MS or network configurations, the GSM AKA
 | 
				
			||||||
 | 
					compatible variant of Milenage, still using the Milenage keys from `aud_3g` but
 | 
				
			||||||
 | 
					transceiving only RAND and SRES, may be applicable. (See 3GPP TS 33.102, chapter
 | 
				
			||||||
 | 
					6.8.1, Authentication and key agreement of UMTS subscribers.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.OsmoHLR's subscriber parameters
 | 
				
			||||||
 | 
					[options="header",width="100%",cols="20%,20%,60%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|Name|Example|Description
 | 
				
			||||||
 | 
					|imsi|901700000014701|identity of the SIM/USIM, 3GPP TS 23.008 chapter 2.1.1.1
 | 
				
			||||||
 | 
					|msisdn|2342123|number to dial to reach this subscriber (multiple MSISDNs can be stored per subscriber), 3GPP TS 23.008 chapter 2.1.2
 | 
				
			||||||
 | 
					|imeisv|4234234234234275|identity of the mobile device and software version, 3GPP TS 23.008 chapter 2.2.3
 | 
				
			||||||
 | 
					|aud2g.algo|comp128v3|Authentication algorithm ID for GSM AKA, corresponds to enum osmo_auth_algo
 | 
				
			||||||
 | 
					|aud2g.ki||Subscriber's secret key (128bit)
 | 
				
			||||||
 | 
					|aud3g.algo|milenage|Authentication algorithm ID for UMTS AKA (applies to both 3G and 2G networks), corresponds to enum osmo_auth_algo
 | 
				
			||||||
 | 
					|aud3g.k|(32 hexadecimal digits)|Subscriber's secret key (128bit)
 | 
				
			||||||
 | 
					|aud3g.op|(32 hexadecimal digits)|Operator's secret key (128bit)
 | 
				
			||||||
 | 
					|aud3g.opc|(32 hexadecimal digits)|Secret key derived from OP and K (128bit), alternative to using OP which does not disclose OP to subscribers
 | 
				
			||||||
 | 
					|aud3g.sqn|123|Sequence number of last used key (64bit unsigned)
 | 
				
			||||||
 | 
					|aud3g.ind_bitlen|5|Nr of index bits at lower SQN end
 | 
				
			||||||
 | 
					|apn||
 | 
				
			||||||
 | 
					|vlr_number||3GPP TS 23.008 chapter 2.4.5
 | 
				
			||||||
 | 
					|msc_number||3GPP TS 23.008 chapter 2.4.6
 | 
				
			||||||
 | 
					|sgsn_number||3GPP TS 23.008 chapter 2.4.8.1
 | 
				
			||||||
 | 
					|sgsn_address||3GPP TS 23.008 chapter 2.13.10
 | 
				
			||||||
 | 
					|ggsn_number||3GPP TS 23.008 chapter 2.4.8.2
 | 
				
			||||||
 | 
					|gmlc_number||3GPP TS 23.008 chapter 2.4.9.2
 | 
				
			||||||
 | 
					|smsc_number||3GPP TS 23.008 chapter 2.4.23
 | 
				
			||||||
 | 
					|periodic_lu_tmr||3GPP TS 23.008 chapter 2.4.24
 | 
				
			||||||
 | 
					|periodic_rau_tau_tmr||3GPP TS 23.008 chapter 2.13.115
 | 
				
			||||||
 | 
					|nam_cs|1|Enable/disable voice access (3GPP TS 23.008 chapter 2.1.1.2: network access mode)
 | 
				
			||||||
 | 
					|nam_ps|0|Enable/disable data access (3GPP TS 23.008 chapter 2.1.1.2: network access mode)
 | 
				
			||||||
 | 
					|lmsi||3GPP TS 23.008 chapter 2.1.8
 | 
				
			||||||
 | 
					|ms_purged_cs|0|3GPP TS 23.008 chapter 2.7.5
 | 
				
			||||||
 | 
					|ms_purged_ps|1|3GPP TS 23.008 chapter 2.7.6
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Configuring the Subscribers Create on Demand Feature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usually a HLR will only allow mobile equipment (ME) on the network, if the HLR
 | 
				
			||||||
 | 
					has a subscriber entry with the ME's IMSI. But OsmoHLR can also be configured to
 | 
				
			||||||
 | 
					automatically create new entries for new IMSIs, with the
 | 
				
			||||||
 | 
					`subscriber-create-on-demand` VTY option. The obvious use case is creating the
 | 
				
			||||||
 | 
					new subscriber entry and then allowing the ME to use both the CS
 | 
				
			||||||
 | 
					(Circuit Switched) and PS (Packet Switched) NAM (Network Access Mode).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.osmo-hlr.cfg
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					hlr
 | 
				
			||||||
 | 
					 subscriber-create-on-demand 5 cs+ps
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On the other hand, operators might only want to give network access to IMSIs, of
 | 
				
			||||||
 | 
					which they know the owner. In order to do that, one can set the default NAM to
 | 
				
			||||||
 | 
					`none` and manually approve new subscribers by changing the NAM (e.g. over the
 | 
				
			||||||
 | 
					VTY, see the example below).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Oftentimes it is hard to know, which IMSI belongs to which ME, but the IMEI is
 | 
				
			||||||
 | 
					readily available. If you configure your MSC to send IMEI checking requests to
 | 
				
			||||||
 | 
					the HLR, before sending location update requests, the subscribers created on
 | 
				
			||||||
 | 
					demand can also have the IMEI stored in the HLR database. With OsmoMSC, this
 | 
				
			||||||
 | 
					is done by writing `check-imei-rqd early` in the `msc` section of osmo-msc.cfg.
 | 
				
			||||||
 | 
					Then enable storing the IMEI when receiving check IMEI requests with
 | 
				
			||||||
 | 
					`store-imei` in the OsmoHLR configuration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.osmo-msc.cfg
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					msc
 | 
				
			||||||
 | 
					 check-imei-rqd early
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.osmo-hlr.cfg
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					hlr
 | 
				
			||||||
 | 
					 subscriber-create-on-demand 5 none
 | 
				
			||||||
 | 
					 store-imei
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Example: Enabling CS and PS NAM via VTY for a known IMEI
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					OsmoHLR> enable
 | 
				
			||||||
 | 
					OsmoHLR# subscriber imei 35761300444848 show
 | 
				
			||||||
 | 
					    ID: 1
 | 
				
			||||||
 | 
					    IMSI: 123456789023000
 | 
				
			||||||
 | 
					    MSISDN: 58192 <1>
 | 
				
			||||||
 | 
					    IMEI: 35761300444848
 | 
				
			||||||
 | 
					    CS disabled <2>
 | 
				
			||||||
 | 
					    PS disabled <2>
 | 
				
			||||||
 | 
					OsmoHLR# subscriber imei 35761300444848 update network-access-mode cs+ps
 | 
				
			||||||
 | 
					OsmoHLR# subscriber imei 35761300444848 show
 | 
				
			||||||
 | 
					    ID: 1
 | 
				
			||||||
 | 
					    IMSI: 123456789023000
 | 
				
			||||||
 | 
					    MSISDN: 58192
 | 
				
			||||||
 | 
					    IMEI: 35761300444848
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					<1> Randomly generated 5 digit MSISDN
 | 
				
			||||||
 | 
					<2> Disabled CS and PS NAM prevent the subscriber from accessing the network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Import Subscriber Data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					==== Scripted Import
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WARNING: It is not generally a good idea to depend on the HLR database's internal table structure, but in the lack of an
 | 
				
			||||||
 | 
					automated import procedure, this example is provided as an ad-hoc method to aid automated subscriber import. This is not
 | 
				
			||||||
 | 
					guaranteed to remain valid.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: We may add CSV and other import methods to the `osmo-hlr-db-tool`, but so far that is not implemented. Contact the
 | 
				
			||||||
 | 
					community if you are interested in such a feature being implemented.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: `sqlite3` is available from your distribution packages or `sqlite.org`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Currently, probably the easiest way to automatically import subscribers to OsmoHLR is to write out a text file with SQL
 | 
				
			||||||
 | 
					commands per subscriber, and feed that to `sqlite3`, as described below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A difficulty is to always choose subscriber IDs that are not yet in use. For an initial import, the subscriber ID may be
 | 
				
			||||||
 | 
					incremented per subscriber record. If adding more subscribers to an existing database, it is necessary to choose
 | 
				
			||||||
 | 
					subscriber IDs that are not yet in use. Get the highest ID in use with:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					sqlite3 hlr.db 'select max(id) from subscriber'
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A full SQL example of adding a single subscriber with id 23, IMSI 001010123456789, MSISDN 1234, Ki for COMP128v1, and K
 | 
				
			||||||
 | 
					and OPC for Milenage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					INSERT subscriber (id, imsi, msisdn) VALUES (23, '001010123456789', '1234');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki)
 | 
				
			||||||
 | 
					VALUES(23, 1, '0123456789abcdef0123456789abcdef');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, op, opc)
 | 
				
			||||||
 | 
					VALUES(23, 5, '0123456789abcdef0123456789abcdef',NULL,'0123456789abcdef0123456789abcdef');
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Table entries to `auc_2g` and/or `auc_3g` may be omitted if no such key material is required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UMTS Milenage auth (on both 2G and 3G RAN) is configured by the `auc_3g` table. `algo_id_3g` must currently always be 5
 | 
				
			||||||
 | 
					(MILENAGE).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The algorithm IDs for `algo_id_2g` and `algo_id_3g` are:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Algorithm IDs in OsmoHLR's database
 | 
				
			||||||
 | 
					[options="header",width="50%",cols="40%,60%"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					|`algo_id_2g` / `algo_id_3g` | Authentication Algorithm
 | 
				
			||||||
 | 
					| 1 | COMP128v1
 | 
				
			||||||
 | 
					| 2 | COMP128v2
 | 
				
			||||||
 | 
					| 3 | COMP128v3
 | 
				
			||||||
 | 
					| 4 | XOR
 | 
				
			||||||
 | 
					| 5 | MILENAGE
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create an empty HLR database with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					osmo-hlr-db-tool -l hlr.db create
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Repeat above SQL commands per subscriber, incrementing the subscriber ID for each block, then feed the SQL commands for
 | 
				
			||||||
 | 
					the subscribers to be imported to the `sqlite3` command line tool:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					sqlite3 hlr.db < subscribers.sql
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[db_import_nitb]]
 | 
				
			||||||
 | 
					==== Import OsmoNITB database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To upgrade from old OsmoNITB to OsmoHLR, use `osmo-hlr-db-tool`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					osmo-hlr-db-tool -l hlr.db import-nitb-db nitb.db
 | 
				
			||||||
 | 
					----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Be aware that the import is lossy, only the IMSI, MSISDN, nam_cs/ps and 2G auth data are set.
 | 
				
			||||||
							
								
								
									
										92
									
								
								doc/manuals/chapters/ussd.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								doc/manuals/chapters/ussd.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					[[ussd]]
 | 
				
			||||||
 | 
					== Unstructured Supplementary Services Data (USSD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The _Unstructured Supplementary Services Data (USSD)_ is one service within
 | 
				
			||||||
 | 
					2G/3G networks next to other services such as circuit-switched voice, packet-switched
 | 
				
			||||||
 | 
					data and SMS (Short Message Service).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is on an abstract level quite similar to SMS in that USSD can be used to send
 | 
				
			||||||
 | 
					textual messages.  However, there are the following differences:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* USSD is between the MS (phone) and an USSD application on the network, while
 | 
				
			||||||
 | 
					  SMS is primarily between two subscribers identified by their MSISDN
 | 
				
			||||||
 | 
					* USSD is faster, as it doesn't suffer from the complicated three-layer CP/RP/TP
 | 
				
			||||||
 | 
					  protocol stack of SMS with it's acknowledgement of the acknowledged acknowledgement.
 | 
				
			||||||
 | 
					* USSD is session-oriented, i.e. a dialogue/session between subscriber and application
 | 
				
			||||||
 | 
					  can persist for the transfer of more than one message.  The dedicated radio channel
 | 
				
			||||||
 | 
					  on the RAN remains established throughout that dialogue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== USSD in Osmocom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Until August 2018, OsmoMSC contained some minimalistic internal USSD
 | 
				
			||||||
 | 
					handling with no
 | 
				
			||||||
 | 
					ability to attach/extend it with external USSD applications.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					From August 2018 onwards, OsmoMSC doesn't contain any internal USSD
 | 
				
			||||||
 | 
					handlers/applications anymore.  Instead, all USSD is transported to/from
 | 
				
			||||||
 | 
					OsmoHLR via the GSUP protocol.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR contains some intenal USSD handlers and can route USSD messages
 | 
				
			||||||
 | 
					to any number of external USSD entities (EUSEs).  The EUSE also use GSUP
 | 
				
			||||||
 | 
					to communicate USSD from/to OsmoHLR.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Each EUSE is identified by its name.  The name consists of a single-word
 | 
				
			||||||
 | 
					string preceding a currently fixed ("-00-00-00-00-00-00") suffix.
 | 
				
			||||||
 | 
					There is no authentication between EUSE and OsmoHLR: Any client program
 | 
				
			||||||
 | 
					able to connect to the GSUP port of OsmoHLR can register as any EUSE
 | 
				
			||||||
 | 
					(name).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE:: We plan to remove the requirement for this suffix as soon as we
 | 
				
			||||||
 | 
					are done resolving all more important issues.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== USSD Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USSD configuration in OsmoHLR happens within the `hlr` VTY node.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`euse foobar-00-00-00-00-00-00` defines an EUSE with the given name `foobar`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`ussd route prefix *123 external foobar-00-00-00-00-00-00` installs a
 | 
				
			||||||
 | 
					prefix route to the named EUSE.  All USSD short codes starting with *123 will be
 | 
				
			||||||
 | 
					routed to the named EUSE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`ussd route prefix *#100# internal own-msisdn` installs a prefix route
 | 
				
			||||||
 | 
					to the named internal USSD handler.  The above command will restore
 | 
				
			||||||
 | 
					the old behavior, in which *#100# will return a text message containing
 | 
				
			||||||
 | 
					the subscribers own phone number.  More information on internal USSD
 | 
				
			||||||
 | 
					handlers can be found in <<iuse_handlers>>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`ussd default-route external foobar-00-00-00-00-00-00` installs a
 | 
				
			||||||
 | 
					default route to the named EUSE.  This means that all USSD codes for
 | 
				
			||||||
 | 
					which no more specific route exists will be routed to the named EUSE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[iuse_handlers]]
 | 
				
			||||||
 | 
					=== Built-in USSD handlers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR has an Internal USSD Entity (IUSE) that allows to handle some
 | 
				
			||||||
 | 
					USSD requests internally.  It features a set of simple handlers, which
 | 
				
			||||||
 | 
					can be assigned to one or more USSD request prefixes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `own-msisdn` returns subscriber's MSISDN (if assigned);
 | 
				
			||||||
 | 
					* `own-imsi` returns subscriber's IMSI;
 | 
				
			||||||
 | 
					* `test-idle` keeps the session idle until the MS terminates it, or
 | 
				
			||||||
 | 
					  the guard timer expires (may be useful for testing).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Additional handlers can be added on request.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=== Example EUSE program
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We have provided an example EUSE developed in C language using existing
 | 
				
			||||||
 | 
					Osmocom libraries for GSUP protocol handling and USSD encoding/decoding.
 | 
				
			||||||
 | 
					It will register as `foobar` EUSE to OsmoHLR on localhost.  You can run
 | 
				
			||||||
 | 
					it on a different machine by specifying e.g. `osmo-euse-demo 1.2.3.4 5678`
 | 
				
			||||||
 | 
					to make it connect to OsmoHLR on IP address 1.2.3.4 and GSUP/TCP port
 | 
				
			||||||
 | 
					5678.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The idea is that you can use this as a template to develop your own USSD
 | 
				
			||||||
 | 
					applications, or any gateways to other protocols or interfaces.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can find it in `osmo-hlr/src/osmo-euse-demo.c` or online by
 | 
				
			||||||
 | 
					following the link to http://git.osmocom.org/osmo-hlr/tree/src/osmo-euse-demo.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This demonstration program will echo back any USSD message sent/routed
 | 
				
			||||||
 | 
					to it, quoted like _You sent "..."_.
 | 
				
			||||||
							
								
								
									
										34
									
								
								doc/manuals/example_subscriber_add_update_delete.vty
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								doc/manuals/example_subscriber_add_update_delete.vty
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					OsmoHLR> enable
 | 
				
			||||||
 | 
					OsmoHLR# subscriber imsi 123456789023000 create
 | 
				
			||||||
 | 
					% Created subscriber 123456789023000
 | 
				
			||||||
 | 
					    ID: 1
 | 
				
			||||||
 | 
					    IMSI: 123456789023000
 | 
				
			||||||
 | 
					    MSISDN: none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR# subscriber imsi 123456789023000 update msisdn 423
 | 
				
			||||||
 | 
					% Updated subscriber IMSI='123456789023000' to MSISDN='423'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR# subscriber msisdn 423 update aud3g milenage k deaf0ff1ced0d0dabbedd1ced1cef00d opc cededeffacedacefacedbadfadedbeef
 | 
				
			||||||
 | 
					OsmoHLR# subscriber msisdn 423 show
 | 
				
			||||||
 | 
					    ID: 1
 | 
				
			||||||
 | 
					    IMSI: 123456789023000
 | 
				
			||||||
 | 
					    MSISDN: 423
 | 
				
			||||||
 | 
					    3G auth: MILENAGE
 | 
				
			||||||
 | 
					             K=deaf0ff1ced0d0dabbedd1ced1cef00d
 | 
				
			||||||
 | 
					             OPC=cededeffacedacefacedbadfadedbeef
 | 
				
			||||||
 | 
					             IND-bitlen=5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR# subscriber msisdn 423 update aud2g comp128v3 ki beefedcafefaceacedaddeddecadefee
 | 
				
			||||||
 | 
					OsmoHLR# subscriber msisdn 423 show
 | 
				
			||||||
 | 
					    ID: 1
 | 
				
			||||||
 | 
					    IMSI: 123456789023000
 | 
				
			||||||
 | 
					    MSISDN: 423
 | 
				
			||||||
 | 
					    2G auth: COMP128v3
 | 
				
			||||||
 | 
					             KI=beefedcafefaceacedaddeddecadefee
 | 
				
			||||||
 | 
					    3G auth: MILENAGE
 | 
				
			||||||
 | 
					             K=deaf0ff1ced0d0dabbedd1ced1cef00d
 | 
				
			||||||
 | 
					             OPC=cededeffacedacefacedbadfadedbeef
 | 
				
			||||||
 | 
					             IND-bitlen=5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR# subscriber imsi 123456789023000 delete
 | 
				
			||||||
 | 
					% Deleted subscriber for IMSI '123456789023000'
 | 
				
			||||||
							
								
								
									
										14
									
								
								doc/manuals/example_subscriber_aud2g.ctrl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								doc/manuals/example_subscriber_aud2g.ctrl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					GET 1 subscriber.by-imsi-901991234567891.aud2g
 | 
				
			||||||
 | 
					GET_REPLY 1 subscriber.by-imsi-901991234567891.aud2g none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 2 subscriber.by-imsi-901991234567891.aud2g xor,c01ffedc1cadaeac1d1f1edacac1ab0a
 | 
				
			||||||
 | 
					SET_REPLY 2 subscriber.by-imsi-901991234567891.aud2g OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 3 subscriber.by-imsi-901991234567891.aud2g
 | 
				
			||||||
 | 
					GET_REPLY 3 subscriber.by-imsi-901991234567891.aud2g XOR,c01ffedc1cadaeac1d1f1edacac1ab0a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 4 subscriber.by-imsi-901991234567891.aud2g none
 | 
				
			||||||
 | 
					SET_REPLY 4 subscriber.by-imsi-901991234567891.aud2g OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 5 subscriber.by-imsi-901991234567891.aud2g
 | 
				
			||||||
 | 
					GET_REPLY 5 subscriber.by-imsi-901991234567891.aud2g none
 | 
				
			||||||
							
								
								
									
										20
									
								
								doc/manuals/example_subscriber_aud3g.ctrl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								doc/manuals/example_subscriber_aud3g.ctrl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					GET 117 subscriber.by-imsi-901991234567891.aud3g
 | 
				
			||||||
 | 
					GET_REPLY 117 subscriber.by-imsi-901991234567891.aud3g none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 118 subscriber.by-imsi-901991234567891.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OP,FB2A3D1B360F599ABAB99DB8669F8308
 | 
				
			||||||
 | 
					SET_REPLY 118 subscriber.by-imsi-901991234567891.aud3g OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 119 subscriber.by-imsi-901991234567891.aud3g
 | 
				
			||||||
 | 
					GET_REPLY 119 subscriber.by-imsi-901991234567891.aud3g MILENAGE,c01ffedc1cadaeac1d1f1edacac1ab0a,OP,fb2a3d1b360f599abab99db8669f8308,5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 120 subscriber.by-imsi-901991234567891.aud3g milenage,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,FB2A3D1B360F599ABAB99DB8669F8308,7
 | 
				
			||||||
 | 
					SET_REPLY 120 subscriber.by-imsi-901991234567891.aud3g OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 121 subscriber.by-imsi-901991234567891.aud3g
 | 
				
			||||||
 | 
					GET_REPLY 121 subscriber.by-imsi-901991234567891.aud3g MILENAGE,c01ffedc1cadaeac1d1f1edacac1ab0a,OPC,fb2a3d1b360f599abab99db8669f8308,7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 122 subscriber.by-imsi-901991234567891.aud3g none
 | 
				
			||||||
 | 
					SET_REPLY 122 subscriber.by-imsi-901991234567891.aud3g OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 123 subscriber.by-imsi-901991234567891.aud3g
 | 
				
			||||||
 | 
					GET_REPLY 123 subscriber.by-imsi-901991234567891.aud3g none
 | 
				
			||||||
							
								
								
									
										71
									
								
								doc/manuals/example_subscriber_cs_ps_enabled.ctrl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								doc/manuals/example_subscriber_cs_ps_enabled.ctrl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					GET 1 subscriber.by-msisdn-103.info
 | 
				
			||||||
 | 
					GET_REPLY 1 subscriber.by-msisdn-103.info 
 | 
				
			||||||
 | 
					id	3
 | 
				
			||||||
 | 
					imsi	901990000000003
 | 
				
			||||||
 | 
					msisdn	103
 | 
				
			||||||
 | 
					nam_cs	1
 | 
				
			||||||
 | 
					nam_ps	1
 | 
				
			||||||
 | 
					ms_purged_cs	0
 | 
				
			||||||
 | 
					ms_purged_ps	0
 | 
				
			||||||
 | 
					periodic_lu_timer	0
 | 
				
			||||||
 | 
					periodic_rau_tau_timer	0
 | 
				
			||||||
 | 
					lmsi	00000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 2 subscriber.by-msisdn-103.ps-enabled
 | 
				
			||||||
 | 
					GET_REPLY 2 subscriber.by-msisdn-103.ps-enabled 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 3 subscriber.by-msisdn-103.ps-enabled 0
 | 
				
			||||||
 | 
					SET_REPLY 3 subscriber.by-msisdn-103.ps-enabled OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 4 subscriber.by-msisdn-103.ps-enabled
 | 
				
			||||||
 | 
					GET_REPLY 4 subscriber.by-msisdn-103.ps-enabled 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 5 subscriber.by-msisdn-103.info
 | 
				
			||||||
 | 
					GET_REPLY 5 subscriber.by-msisdn-103.info 
 | 
				
			||||||
 | 
					id	3
 | 
				
			||||||
 | 
					imsi	901990000000003
 | 
				
			||||||
 | 
					msisdn	103
 | 
				
			||||||
 | 
					nam_cs	1
 | 
				
			||||||
 | 
					nam_ps	0
 | 
				
			||||||
 | 
					ms_purged_cs	0
 | 
				
			||||||
 | 
					ms_purged_ps	0
 | 
				
			||||||
 | 
					periodic_lu_timer	0
 | 
				
			||||||
 | 
					periodic_rau_tau_timer	0
 | 
				
			||||||
 | 
					lmsi	00000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 6 subscriber.by-msisdn-103.cs-enabled 0
 | 
				
			||||||
 | 
					SET_REPLY 6 subscriber.by-msisdn-103.cs-enabled OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 7 subscriber.by-msisdn-103.cs-enabled
 | 
				
			||||||
 | 
					GET_REPLY 7 subscriber.by-msisdn-103.cs-enabled 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 8 subscriber.by-msisdn-103.info
 | 
				
			||||||
 | 
					GET_REPLY 8 subscriber.by-msisdn-103.info 
 | 
				
			||||||
 | 
					id	3
 | 
				
			||||||
 | 
					imsi	901990000000003
 | 
				
			||||||
 | 
					msisdn	103
 | 
				
			||||||
 | 
					nam_cs	0
 | 
				
			||||||
 | 
					nam_ps	0
 | 
				
			||||||
 | 
					ms_purged_cs	0
 | 
				
			||||||
 | 
					ms_purged_ps	0
 | 
				
			||||||
 | 
					periodic_lu_timer	0
 | 
				
			||||||
 | 
					periodic_rau_tau_timer	0
 | 
				
			||||||
 | 
					lmsi	00000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 9 subscriber.by-msisdn-103.cs-enabled 1
 | 
				
			||||||
 | 
					SET_REPLY 9 subscriber.by-msisdn-103.cs-enabled OK
 | 
				
			||||||
 | 
					SET 10 subscriber.by-msisdn-103.ps-enabled 1
 | 
				
			||||||
 | 
					SET_REPLY 10 subscriber.by-msisdn-103.ps-enabled OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 11 subscriber.by-msisdn-103.info
 | 
				
			||||||
 | 
					GET_REPLY 11 subscriber.by-msisdn-103.info 
 | 
				
			||||||
 | 
					id	3
 | 
				
			||||||
 | 
					imsi	901990000000003
 | 
				
			||||||
 | 
					msisdn	103
 | 
				
			||||||
 | 
					nam_cs	1
 | 
				
			||||||
 | 
					nam_ps	1
 | 
				
			||||||
 | 
					ms_purged_cs	0
 | 
				
			||||||
 | 
					ms_purged_ps	0
 | 
				
			||||||
 | 
					periodic_lu_timer	0
 | 
				
			||||||
 | 
					periodic_rau_tau_timer	0
 | 
				
			||||||
 | 
					lmsi	00000000
 | 
				
			||||||
							
								
								
									
										42
									
								
								doc/manuals/example_subscriber_info.ctrl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								doc/manuals/example_subscriber_info.ctrl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					GET 1 subscriber.by-imsi-901990000000003.info
 | 
				
			||||||
 | 
					GET_REPLY 1 subscriber.by-imsi-901990000000003.info 
 | 
				
			||||||
 | 
					id	3
 | 
				
			||||||
 | 
					imsi	901990000000003
 | 
				
			||||||
 | 
					msisdn	103
 | 
				
			||||||
 | 
					nam_cs	1
 | 
				
			||||||
 | 
					nam_ps	1
 | 
				
			||||||
 | 
					ms_purged_cs	0
 | 
				
			||||||
 | 
					ms_purged_ps	0
 | 
				
			||||||
 | 
					periodic_lu_timer	0
 | 
				
			||||||
 | 
					periodic_rau_tau_timer	0
 | 
				
			||||||
 | 
					lmsi	00000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 2 subscriber.by-msisdn-103.info-aud
 | 
				
			||||||
 | 
					GET_REPLY 2 subscriber.by-msisdn-103.info-aud 
 | 
				
			||||||
 | 
					aud2g.algo	COMP128v1
 | 
				
			||||||
 | 
					aud2g.ki	000102030405060708090a0b0c0d0e0f
 | 
				
			||||||
 | 
					aud3g.algo	MILENAGE
 | 
				
			||||||
 | 
					aud3g.k	000102030405060708090a0b0c0d0e0f
 | 
				
			||||||
 | 
					aud3g.opc	101112131415161718191a1b1c1d1e1f
 | 
				
			||||||
 | 
					aud3g.ind_bitlen	5
 | 
				
			||||||
 | 
					aud3g.sqn	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 3 subscriber.by-id-3.info-all
 | 
				
			||||||
 | 
					GET_REPLY 3 subscriber.by-id-3.info-all 
 | 
				
			||||||
 | 
					id	3
 | 
				
			||||||
 | 
					imsi	901990000000003
 | 
				
			||||||
 | 
					msisdn	103
 | 
				
			||||||
 | 
					nam_cs	1
 | 
				
			||||||
 | 
					nam_ps	1
 | 
				
			||||||
 | 
					ms_purged_cs	0
 | 
				
			||||||
 | 
					ms_purged_ps	0
 | 
				
			||||||
 | 
					periodic_lu_timer	0
 | 
				
			||||||
 | 
					periodic_rau_tau_timer	0
 | 
				
			||||||
 | 
					lmsi	00000000
 | 
				
			||||||
 | 
					aud2g.algo	COMP128v1
 | 
				
			||||||
 | 
					aud2g.ki	000102030405060708090a0b0c0d0e0f
 | 
				
			||||||
 | 
					aud3g.algo	MILENAGE
 | 
				
			||||||
 | 
					aud3g.k	000102030405060708090a0b0c0d0e0f
 | 
				
			||||||
 | 
					aud3g.opc	101112131415161718191a1b1c1d1e1f
 | 
				
			||||||
 | 
					aud3g.ind_bitlen	5
 | 
				
			||||||
 | 
					aud3g.sqn	0
 | 
				
			||||||
							
								
								
									
										8
									
								
								doc/manuals/example_subscriber_msisdn.ctrl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								doc/manuals/example_subscriber_msisdn.ctrl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					GET 1 subscriber.by-imsi-901991234567891.msisdn
 | 
				
			||||||
 | 
					GET_REPLY 1 subscriber.by-imsi-901991234567891.msisdn none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SET 2 subscriber.by-imsi-901991234567891.msisdn 555666
 | 
				
			||||||
 | 
					SET_REPLY 2 subscriber.by-imsi-901991234567891.msisdn OK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GET 3 subscriber.by-imsi-901991234567891.msisdn
 | 
				
			||||||
 | 
					GET_REPLY 3 subscriber.by-imsi-901991234567891.msisdn 555666
 | 
				
			||||||
							
								
								
									
										47
									
								
								doc/manuals/osmohlr-usermanual-docinfo.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								doc/manuals/osmohlr-usermanual-docinfo.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					<revhistory>
 | 
				
			||||||
 | 
					  <revision>
 | 
				
			||||||
 | 
					    <revnumber>1</revnumber>
 | 
				
			||||||
 | 
					    <date>September 18th, 2017</date>
 | 
				
			||||||
 | 
					    <authorinitials>NH</authorinitials>
 | 
				
			||||||
 | 
					    <revremark>
 | 
				
			||||||
 | 
					      Initial version; based on OsmoNITB manual version 2.
 | 
				
			||||||
 | 
					    </revremark>
 | 
				
			||||||
 | 
					  </revision>
 | 
				
			||||||
 | 
					</revhistory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<authorgroup>
 | 
				
			||||||
 | 
					  <author>
 | 
				
			||||||
 | 
					    <firstname>Neels</firstname>
 | 
				
			||||||
 | 
					    <surname>Hofmeyr</surname>
 | 
				
			||||||
 | 
					    <email>nhofmeyr@sysmocom.de</email>
 | 
				
			||||||
 | 
					    <authorinitials>NH</authorinitials>
 | 
				
			||||||
 | 
					    <affiliation>
 | 
				
			||||||
 | 
					      <shortaffil>sysmocom</shortaffil>
 | 
				
			||||||
 | 
					      <orgname>sysmocom - s.f.m.c. GmbH</orgname>
 | 
				
			||||||
 | 
					      <jobtitle>Senior Developer</jobtitle>
 | 
				
			||||||
 | 
					    </affiliation>
 | 
				
			||||||
 | 
					  </author>
 | 
				
			||||||
 | 
					</authorgroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<copyright>
 | 
				
			||||||
 | 
					  <year>2017</year>
 | 
				
			||||||
 | 
					  <holder>sysmocom - s.f.m.c. GmbH</holder>
 | 
				
			||||||
 | 
					</copyright>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<legalnotice>
 | 
				
			||||||
 | 
					  <para>
 | 
				
			||||||
 | 
						Permission is granted to copy, distribute and/or modify this
 | 
				
			||||||
 | 
						document under the terms of the GNU Free Documentation License,
 | 
				
			||||||
 | 
						Version 1.3 or any later version published by the Free Software
 | 
				
			||||||
 | 
						Foundation; with the Invariant Sections being just 'Foreword',
 | 
				
			||||||
 | 
						'Acknowledgements' and 'Preface', with no Front-Cover Texts,
 | 
				
			||||||
 | 
						and no Back-Cover Texts.  A copy of the license is included in
 | 
				
			||||||
 | 
						the section entitled "GNU Free Documentation License".
 | 
				
			||||||
 | 
					  </para>
 | 
				
			||||||
 | 
					  <para>
 | 
				
			||||||
 | 
						The Asciidoc source code of this manual can be found at
 | 
				
			||||||
 | 
						<ulink url="http://git.osmocom.org/osmo-gsm-manuals/">
 | 
				
			||||||
 | 
							http://git.osmocom.org/osmo-gsm-manuals/
 | 
				
			||||||
 | 
						</ulink>
 | 
				
			||||||
 | 
					  </para>
 | 
				
			||||||
 | 
					</legalnotice>
 | 
				
			||||||
							
								
								
									
										39
									
								
								doc/manuals/osmohlr-usermanual.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								doc/manuals/osmohlr-usermanual.adoc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					:gfdl-enabled:
 | 
				
			||||||
 | 
					:program-name: OsmoHLR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OsmoHLR User Manual
 | 
				
			||||||
 | 
					====================
 | 
				
			||||||
 | 
					Neels Hofmeyr <nhofmeyr@sysmocom.de>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/preface.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/overview.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/running.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/subscribers.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/ussd.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/vty.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/logging.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/control.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/control_if.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::{srcdir}/chapters/dgsm.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/gsup.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/vty_cpu_sched.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/port_numbers.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/bibliography.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/glossary.adoc[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include::./common/chapters/gfdl.adoc[]
 | 
				
			||||||
							
								
								
									
										38
									
								
								doc/manuals/osmohlr-vty-reference.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								doc/manuals/osmohlr-vty-reference.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					  ex:ts=2:sw=42sts=2:et
 | 
				
			||||||
 | 
					  -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML 5.0//EN"
 | 
				
			||||||
 | 
					"http://docbook.org/xml/5.0/dtd/docbook.dtd" [
 | 
				
			||||||
 | 
					<!ENTITY chapter-vty      SYSTEM      "./common/chapters/vty.xml" >
 | 
				
			||||||
 | 
					<!ENTITY sections-vty     SYSTEM      "generated/docbook_vty.xml"  >
 | 
				
			||||||
 | 
					]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<book>
 | 
				
			||||||
 | 
					  <info>
 | 
				
			||||||
 | 
					    <revhistory>
 | 
				
			||||||
 | 
					        <revision>
 | 
				
			||||||
 | 
					            <revnumber>v1</revnumber>
 | 
				
			||||||
 | 
					            <date>18th September 2017</date>
 | 
				
			||||||
 | 
					            <authorinitials>nh</authorinitials>
 | 
				
			||||||
 | 
					            <revremark>Initial</revremark>
 | 
				
			||||||
 | 
					        </revision>
 | 
				
			||||||
 | 
					    </revhistory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <title>OsmoHLR VTY Reference</title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <copyright>
 | 
				
			||||||
 | 
					      <year>2017</year>
 | 
				
			||||||
 | 
					    </copyright>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <legalnotice>
 | 
				
			||||||
 | 
					      <para>This work is copyright by <orgname>sysmocom - s.f.m.c. GmbH</orgname>. All rights reserved.
 | 
				
			||||||
 | 
					      </para>
 | 
				
			||||||
 | 
					    </legalnotice>
 | 
				
			||||||
 | 
					  </info>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <!-- Main chapters-->
 | 
				
			||||||
 | 
					  &chapter-vty;
 | 
				
			||||||
 | 
					</book>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								doc/manuals/regen_doc.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										17
									
								
								doc/manuals/regen_doc.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					#!/bin/sh -x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$DOCKER_PLAYGROUND" ]; then
 | 
				
			||||||
 | 
						echo "You need to set DOCKER_PLAYGROUND"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SCRIPT=$(realpath "$0")
 | 
				
			||||||
 | 
					MANUAL_DIR=$(dirname "$SCRIPT")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COMMIT=${COMMIT:-$(git log -1 --format=format:%H)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd "$DOCKER_PLAYGROUND/scripts" || exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OSMO_HLR_BRANCH=$COMMIT ./regen_doc.sh osmo-hlr 4258 \
 | 
				
			||||||
 | 
						"$MANUAL_DIR/chapters/counters_generated.adoc" \
 | 
				
			||||||
 | 
						"$MANUAL_DIR/vty/hlr_vty_reference.xml"
 | 
				
			||||||
							
								
								
									
										2
									
								
								doc/manuals/vty/hlr_vty_additions.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								doc/manuals/vty/hlr_vty_additions.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					<vtydoc xmlns='urn:osmocom:xml:libosmocore:vty:doc:1.0'>
 | 
				
			||||||
 | 
					</vtydoc>
 | 
				
			||||||
							
								
								
									
										151
									
								
								git-version-gen
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										151
									
								
								git-version-gen
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					# Print a version string.
 | 
				
			||||||
 | 
					scriptversion=2010-01-28.01
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright (C) 2007-2010 Free Software Foundation, Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					# it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					# the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					# (at your option) any later version.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					# GNU General Public License for more details.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
 | 
				
			||||||
 | 
					# It may be run two ways:
 | 
				
			||||||
 | 
					# - from a git repository in which the "git describe" command below
 | 
				
			||||||
 | 
					#   produces useful output (thus requiring at least one signed tag)
 | 
				
			||||||
 | 
					# - from a non-git-repo directory containing a .tarball-version file, which
 | 
				
			||||||
 | 
					#   presumes this script is invoked like "./git-version-gen .tarball-version".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# In order to use intra-version strings in your project, you will need two
 | 
				
			||||||
 | 
					# separate generated version string files:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# .tarball-version - present only in a distribution tarball, and not in
 | 
				
			||||||
 | 
					#   a checked-out repository.  Created with contents that were learned at
 | 
				
			||||||
 | 
					#   the last time autoconf was run, and used by git-version-gen.  Must not
 | 
				
			||||||
 | 
					#   be present in either $(srcdir) or $(builddir) for git-version-gen to
 | 
				
			||||||
 | 
					#   give accurate answers during normal development with a checked out tree,
 | 
				
			||||||
 | 
					#   but must be present in a tarball when there is no version control system.
 | 
				
			||||||
 | 
					#   Therefore, it cannot be used in any dependencies.  GNUmakefile has
 | 
				
			||||||
 | 
					#   hooks to force a reconfigure at distribution time to get the value
 | 
				
			||||||
 | 
					#   correct, without penalizing normal development with extra reconfigures.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# .version - present in a checked-out repository and in a distribution
 | 
				
			||||||
 | 
					#   tarball.  Usable in dependencies, particularly for files that don't
 | 
				
			||||||
 | 
					#   want to depend on config.h but do want to track version changes.
 | 
				
			||||||
 | 
					#   Delete this file prior to any autoconf run where you want to rebuild
 | 
				
			||||||
 | 
					#   files to pick up a version string change; and leave it stale to
 | 
				
			||||||
 | 
					#   minimize rebuild time after unrelated changes to configure sources.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# It is probably wise to add these two files to .gitignore, so that you
 | 
				
			||||||
 | 
					# don't accidentally commit either generated file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Use the following line in your configure.ac, so that $(VERSION) will
 | 
				
			||||||
 | 
					# automatically be up-to-date each time configure is run (and note that
 | 
				
			||||||
 | 
					# since configure.ac no longer includes a version string, Makefile rules
 | 
				
			||||||
 | 
					# should not depend on configure.ac for version updates).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# AC_INIT([GNU project],
 | 
				
			||||||
 | 
					#         m4_esyscmd([build-aux/git-version-gen .tarball-version]),
 | 
				
			||||||
 | 
					#         [bug-project@example])
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Then use the following lines in your Makefile.am, so that .version
 | 
				
			||||||
 | 
					# will be present for dependencies, and so that .tarball-version will
 | 
				
			||||||
 | 
					# exist in distribution tarballs.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# BUILT_SOURCES = $(top_srcdir)/.version
 | 
				
			||||||
 | 
					# $(top_srcdir)/.version:
 | 
				
			||||||
 | 
					#	echo $(VERSION) > $@-t && mv $@-t $@
 | 
				
			||||||
 | 
					# dist-hook:
 | 
				
			||||||
 | 
					#	echo $(VERSION) > $(distdir)/.tarball-version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case $# in
 | 
				
			||||||
 | 
					    1) ;;
 | 
				
			||||||
 | 
					    *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tarball_version_file=$1
 | 
				
			||||||
 | 
					nl='
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# First see if there is a tarball-only version file.
 | 
				
			||||||
 | 
					# then try "git describe", then default.
 | 
				
			||||||
 | 
					if test -f $tarball_version_file
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    v=`cat $tarball_version_file` || exit 1
 | 
				
			||||||
 | 
					    case $v in
 | 
				
			||||||
 | 
						*$nl*) v= ;; # reject multi-line output
 | 
				
			||||||
 | 
						[0-9]*) ;;
 | 
				
			||||||
 | 
						*) v= ;;
 | 
				
			||||||
 | 
					    esac
 | 
				
			||||||
 | 
					    test -z "$v" \
 | 
				
			||||||
 | 
						&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test -n "$v"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    : # use $v
 | 
				
			||||||
 | 
					elif
 | 
				
			||||||
 | 
					       v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
 | 
				
			||||||
 | 
						  || git describe --abbrev=4 HEAD 2>/dev/null` \
 | 
				
			||||||
 | 
					    && case $v in
 | 
				
			||||||
 | 
						 [0-9]*) ;;
 | 
				
			||||||
 | 
						 v[0-9]*) ;;
 | 
				
			||||||
 | 
						 *) (exit 1) ;;
 | 
				
			||||||
 | 
					       esac
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
					    # Is this a new git that lists number of commits since the last
 | 
				
			||||||
 | 
					    # tag or the previous older version that did not?
 | 
				
			||||||
 | 
					    #   Newer: v6.10-77-g0f8faeb
 | 
				
			||||||
 | 
					    #   Older: v6.10-g0f8faeb
 | 
				
			||||||
 | 
					    case $v in
 | 
				
			||||||
 | 
						*-*-*) : git describe is okay three part flavor ;;
 | 
				
			||||||
 | 
						*-*)
 | 
				
			||||||
 | 
						    : git describe is older two part flavor
 | 
				
			||||||
 | 
						    # Recreate the number of commits and rewrite such that the
 | 
				
			||||||
 | 
						    # result is the same as if we were using the newer version
 | 
				
			||||||
 | 
						    # of git describe.
 | 
				
			||||||
 | 
						    vtag=`echo "$v" | sed 's/-.*//'`
 | 
				
			||||||
 | 
						    numcommits=`git rev-list "$vtag"..HEAD | wc -l`
 | 
				
			||||||
 | 
						    v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
 | 
				
			||||||
 | 
						    ;;
 | 
				
			||||||
 | 
					    esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Change the first '-' to a '.', so version-comparing tools work properly.
 | 
				
			||||||
 | 
					    # Remove the "g" in git describe's output string, to save a byte.
 | 
				
			||||||
 | 
					    v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    v=UNKNOWN
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					v=`echo "$v" |sed 's/^v//'`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Don't declare a version "dirty" merely because a time stamp has changed.
 | 
				
			||||||
 | 
					git status > /dev/null 2>&1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
 | 
				
			||||||
 | 
					case "$dirty" in
 | 
				
			||||||
 | 
					    '') ;;
 | 
				
			||||||
 | 
					    *) # Append the suffix only if there isn't one already.
 | 
				
			||||||
 | 
						case $v in
 | 
				
			||||||
 | 
						  *-dirty) ;;
 | 
				
			||||||
 | 
						  *) v="$v-dirty" ;;
 | 
				
			||||||
 | 
						esac ;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Omit the trailing newline, so that m4_esyscmd can use the result directly.
 | 
				
			||||||
 | 
					echo "$v" | tr -d '\012'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Local variables:
 | 
				
			||||||
 | 
					# eval: (add-hook 'write-file-hooks 'time-stamp)
 | 
				
			||||||
 | 
					# time-stamp-start: "scriptversion="
 | 
				
			||||||
 | 
					# time-stamp-format: "%:y-%02m-%02d.%02H"
 | 
				
			||||||
 | 
					# time-stamp-end: "$"
 | 
				
			||||||
 | 
					# End:
 | 
				
			||||||
							
								
								
									
										13
									
								
								include/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								include/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					SUBDIRS = osmocom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nobase_include_HEADERS = \
 | 
				
			||||||
 | 
						osmocom/gsupclient/cni_peer_id.h \
 | 
				
			||||||
 | 
						osmocom/gsupclient/gsup_client.h \
 | 
				
			||||||
 | 
						osmocom/gsupclient/gsup_req.h \
 | 
				
			||||||
 | 
						osmocom/mslookup/mdns.h \
 | 
				
			||||||
 | 
						osmocom/mslookup/mdns_sock.h \
 | 
				
			||||||
 | 
						osmocom/mslookup/mslookup_client_fake.h \
 | 
				
			||||||
 | 
						osmocom/mslookup/mslookup_client.h \
 | 
				
			||||||
 | 
						osmocom/mslookup/mslookup_client_mdns.h \
 | 
				
			||||||
 | 
						osmocom/mslookup/mslookup.h \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
							
								
								
									
										4
									
								
								include/osmocom/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								include/osmocom/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					SUBDIRS = \
 | 
				
			||||||
 | 
						hlr \
 | 
				
			||||||
 | 
						mslookup \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
							
								
								
									
										66
									
								
								include/osmocom/gsupclient/cni_peer_id.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								include/osmocom/gsupclient/cni_peer_id.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! IPA Name: Arbitrary length blob, not necessarily zero-terminated.
 | 
				
			||||||
 | 
					 * In osmo-hlr, struct hlr_subscriber is mostly used as static reference and cannot serve as talloc context, which is
 | 
				
			||||||
 | 
					 * why this is also implemented as a fixed-maximum-size buffer instead of a talloc'd arbitrary sized buffer.
 | 
				
			||||||
 | 
					 * NOTE: The length of val may be extended in the future if it becomes necessary.
 | 
				
			||||||
 | 
					 * At the time of writing, this holds IPA unit name strings of very limited length.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct osmo_ipa_name {
 | 
				
			||||||
 | 
						size_t len;
 | 
				
			||||||
 | 
						uint8_t val[128];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool osmo_ipa_name_is_empty(const struct osmo_ipa_name *ipa_name);
 | 
				
			||||||
 | 
					int osmo_ipa_name_set(struct osmo_ipa_name *ipa_name, const uint8_t *val, size_t len);
 | 
				
			||||||
 | 
					int osmo_ipa_name_set_str(struct osmo_ipa_name *ipa_name, const char *str_fmt, ...);
 | 
				
			||||||
 | 
					int osmo_ipa_name_cmp(const struct osmo_ipa_name *a, const struct osmo_ipa_name *b);
 | 
				
			||||||
 | 
					const char *osmo_ipa_name_to_str_c(void *ctx, const struct osmo_ipa_name *ipa_name);
 | 
				
			||||||
 | 
					const char *osmo_ipa_name_to_str(const struct osmo_ipa_name *ipa_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum osmo_cni_peer_id_type {
 | 
				
			||||||
 | 
						OSMO_CNI_PEER_ID_EMPTY=0,
 | 
				
			||||||
 | 
						OSMO_CNI_PEER_ID_IPA_NAME,
 | 
				
			||||||
 | 
						/* OSMO_CNI_PEER_ID_GLOBAL_TITLE, <-- currently not implemented, but likely future possibility */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string osmo_cni_peer_id_type_names[];
 | 
				
			||||||
 | 
					static inline const char *osmo_cni_peer_id_type_name(enum osmo_cni_peer_id_type val)
 | 
				
			||||||
 | 
					{ return get_value_string(osmo_cni_peer_id_type_names, val); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_cni_peer_id {
 | 
				
			||||||
 | 
						enum osmo_cni_peer_id_type type;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct osmo_ipa_name ipa_name;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool osmo_cni_peer_id_is_empty(const struct osmo_cni_peer_id *cni_peer_id);
 | 
				
			||||||
 | 
					int osmo_cni_peer_id_set(struct osmo_cni_peer_id *cni_peer_id, enum osmo_cni_peer_id_type type,
 | 
				
			||||||
 | 
								  const uint8_t *val, size_t len);
 | 
				
			||||||
 | 
					int osmo_cni_peer_id_set_str(struct osmo_cni_peer_id *cni_peer_id, enum osmo_cni_peer_id_type type,
 | 
				
			||||||
 | 
								      const char *str_fmt, ...);
 | 
				
			||||||
 | 
					int osmo_cni_peer_id_cmp(const struct osmo_cni_peer_id *a, const struct osmo_cni_peer_id *b);
 | 
				
			||||||
 | 
					const char *osmo_cni_peer_id_to_str(const struct osmo_cni_peer_id *cni_peer_id);
 | 
				
			||||||
 | 
					const char *osmo_cni_peer_id_to_str_c(void *ctx, const struct osmo_cni_peer_id *cni_peer_id);
 | 
				
			||||||
							
								
								
									
										101
									
								
								include/osmocom/gsupclient/gsup_client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								include/osmocom/gsupclient/gsup_client.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					/* GPRS Subscriber Update Protocol client */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2014 by Sysmocom s.f.m.c. GmbH
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Jacob Erlbeck
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/oap_client.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/ipa.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsup.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* a loss of GSUP between MSC and HLR is considered quite serious, let's try to recover as quickly as
 | 
				
			||||||
 | 
					 * possible.  Even one new connection attempt per second should be quite acceptable until the link is
 | 
				
			||||||
 | 
					 * re-established */
 | 
				
			||||||
 | 
					#define OSMO_GSUP_CLIENT_RECONNECT_INTERVAL 1
 | 
				
			||||||
 | 
					#define OSMO_GSUP_CLIENT_PING_INTERVAL 20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msgb;
 | 
				
			||||||
 | 
					struct ipa_client_conn;
 | 
				
			||||||
 | 
					struct osmo_gsup_client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Expects message in msg->l2h */
 | 
				
			||||||
 | 
					typedef int (*osmo_gsup_client_read_cb_t)(struct osmo_gsup_client *gsupc, struct msgb *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef bool (*osmo_gsup_client_up_down_cb_t)(struct osmo_gsup_client *gsupc, bool up);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_client {
 | 
				
			||||||
 | 
						const char *unit_name; /* same as ipa_dev->unit_name, for backwards compat */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ipa_client_conn *link;
 | 
				
			||||||
 | 
						osmo_gsup_client_read_cb_t read_cb;
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct osmo_oap_client_state oap_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct osmo_timer_list ping_timer;
 | 
				
			||||||
 | 
						struct osmo_timer_list connect_timer;
 | 
				
			||||||
 | 
						int is_connected;
 | 
				
			||||||
 | 
						int got_ipa_pong;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ipaccess_unit *ipa_dev; /* identification information sent to IPA server */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						osmo_gsup_client_up_down_cb_t up_down_cb;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_client_config {
 | 
				
			||||||
 | 
						/*! IP access unit which contains client identification information; must be allocated in talloc_ctx as well to
 | 
				
			||||||
 | 
						 * ensure it lives throughout the lifetime of the connection. */
 | 
				
			||||||
 | 
						struct ipaccess_unit *ipa_dev;
 | 
				
			||||||
 | 
						/*! GSUP server IP address to connect to. */
 | 
				
			||||||
 | 
						const char *ip_addr;
 | 
				
			||||||
 | 
						/*! GSUP server TCP port to connect to. */
 | 
				
			||||||
 | 
						unsigned int tcp_port;
 | 
				
			||||||
 | 
						/*! OPA client configuration, or NULL. */
 | 
				
			||||||
 | 
						struct osmo_oap_client_config *oapc_config;
 | 
				
			||||||
 | 
						/*! callback for reading from the GSUP connection. */
 | 
				
			||||||
 | 
						osmo_gsup_client_read_cb_t read_cb;
 | 
				
			||||||
 | 
						/*! Invoked when the GSUP link is ready for communication, and when the link drops. */
 | 
				
			||||||
 | 
						osmo_gsup_client_up_down_cb_t up_down_cb;
 | 
				
			||||||
 | 
						/*! User data stored in the returned gsupc->data, as context for the callbacks. */
 | 
				
			||||||
 | 
						void *data;
 | 
				
			||||||
 | 
						/*! Marker for future extension, always pass this as false. */
 | 
				
			||||||
 | 
						bool more;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					struct osmo_gsup_client *osmo_gsup_client_create3(void *talloc_ctx, struct osmo_gsup_client_config *config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_client *osmo_gsup_client_create2(void *talloc_ctx,
 | 
				
			||||||
 | 
											  struct ipaccess_unit *ipa_dev,
 | 
				
			||||||
 | 
											  const char *ip_addr,
 | 
				
			||||||
 | 
											  unsigned int tcp_port,
 | 
				
			||||||
 | 
											  osmo_gsup_client_read_cb_t read_cb,
 | 
				
			||||||
 | 
											  struct osmo_oap_client_config *oapc_config);
 | 
				
			||||||
 | 
					struct osmo_gsup_client *osmo_gsup_client_create(void *talloc_ctx,
 | 
				
			||||||
 | 
											 const char *unit_name,
 | 
				
			||||||
 | 
											 const char *ip_addr,
 | 
				
			||||||
 | 
											 unsigned int tcp_port,
 | 
				
			||||||
 | 
											 osmo_gsup_client_read_cb_t read_cb,
 | 
				
			||||||
 | 
											 struct osmo_oap_client_config *oapc_config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_gsup_client_destroy(struct osmo_gsup_client *gsupc);
 | 
				
			||||||
 | 
					int osmo_gsup_client_send(struct osmo_gsup_client *gsupc, struct msgb *msg);
 | 
				
			||||||
 | 
					int osmo_gsup_client_enc_send(struct osmo_gsup_client *gsupc,
 | 
				
			||||||
 | 
								      const struct osmo_gsup_message *gsup_msg);
 | 
				
			||||||
 | 
					struct msgb *osmo_gsup_client_msgb_alloc(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										119
									
								
								include/osmocom/gsupclient/gsup_req.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								include/osmocom/gsupclient/gsup_req.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsup.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/cni_peer_id.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_req;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_GSUP_REQ_CAT_SRC(req, subsys, level, file, line, fmt, args...) \
 | 
				
			||||||
 | 
						LOGPSRC(subsys, level, file, line, "GSUP %u: %s: IMSI-%s %s: " fmt, \
 | 
				
			||||||
 | 
							(req) ? (req)->nr : 0, \
 | 
				
			||||||
 | 
							(req) ? osmo_cni_peer_id_to_str(&(req)->source_name) : "NULL", \
 | 
				
			||||||
 | 
							(req) ? (req)->gsup.imsi : "NULL", \
 | 
				
			||||||
 | 
							(req) ? osmo_gsup_message_type_name((req)->gsup.message_type) : "NULL", \
 | 
				
			||||||
 | 
							##args)
 | 
				
			||||||
 | 
					#define LOG_GSUP_REQ_CAT(req, subsys, level, fmt, args...) \
 | 
				
			||||||
 | 
						LOG_GSUP_REQ_CAT_SRC(req, subsys, level, __FILE__, __LINE__, fmt, ##args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_GSUP_REQ_SRC(req, level, file, line, fmt, args...) \
 | 
				
			||||||
 | 
						LOG_GSUP_REQ_CAT_SRC(req, DLGSUP, level, file, line, fmt, ##args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_GSUP_REQ(req, level, fmt, args...) \
 | 
				
			||||||
 | 
						LOG_GSUP_REQ_SRC(req, level, __FILE__, __LINE__, fmt, ##args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*osmo_gsup_req_send_response_t)(struct osmo_gsup_req *req, struct osmo_gsup_message *response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Keep track of an incoming request, to route back a response when it is ready.
 | 
				
			||||||
 | 
					 * Particularly, a GSUP response to a request must contain various bits of information that need to be copied from the
 | 
				
			||||||
 | 
					 * request for proxy/routing to work and for session states to remain valid. That is the main reason why (almost) all
 | 
				
			||||||
 | 
					 * GSUP request/response should go through an osmo_gsup_req, even if it is handled synchronously.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct osmo_gsup_req {
 | 
				
			||||||
 | 
						/* The incoming GSUP message in decoded form. */
 | 
				
			||||||
 | 
						const struct osmo_gsup_message gsup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Decoding result code. If decoding failed, this will be != 0. */
 | 
				
			||||||
 | 
						int decode_rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The ultimate source of this message: the source_name form the GSUP message, or, if not present, then the
 | 
				
			||||||
 | 
						 * immediate GSUP peer. GSUP messages going via a proxy reflect the initial source in the source_name.
 | 
				
			||||||
 | 
						 * This source_name is implicitly added to the routes for the conn the message was received on. */
 | 
				
			||||||
 | 
						struct osmo_cni_peer_id source_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If the source_name is not an immediate GSUP peer, this is set to the closest intermediate peer between here
 | 
				
			||||||
 | 
						 * and source_name. */
 | 
				
			||||||
 | 
						struct osmo_cni_peer_id via_proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Identify this request by number, for logging. */
 | 
				
			||||||
 | 
						unsigned int nr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* osmo_gsup_req can be used by both gsup_server and gsup_client. The individual method of actually sending a
 | 
				
			||||||
 | 
						 * GSUP message is provided by this callback. */
 | 
				
			||||||
 | 
						osmo_gsup_req_send_response_t send_response_cb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* User supplied data pointer, may be used to provide context to send_response_cb(). */
 | 
				
			||||||
 | 
						void *cb_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* List entry that can be used to keep a list of osmo_gsup_req instances; not used directly by osmo_gsup_req.c,
 | 
				
			||||||
 | 
						 * it is up to using implementations to keep a list. If this is non-NULL, osmo_gsup_req_free() calls
 | 
				
			||||||
 | 
						 * llist_del() on this. */
 | 
				
			||||||
 | 
						struct llist_head entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A decoded GSUP message still points into the received msgb. For a decoded osmo_gsup_message to remain valid,
 | 
				
			||||||
 | 
						 * we also need to keep the msgb. */
 | 
				
			||||||
 | 
						struct msgb *msg;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_req *osmo_gsup_req_new(void *ctx, const struct osmo_cni_peer_id *from_peer, struct msgb *msg,
 | 
				
			||||||
 | 
										osmo_gsup_req_send_response_t send_response_cb, void *cb_data,
 | 
				
			||||||
 | 
										struct llist_head *add_to_list);
 | 
				
			||||||
 | 
					void osmo_gsup_req_free(struct osmo_gsup_req *req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! See _osmo_gsup_req_respond() for details.
 | 
				
			||||||
 | 
					 * Call _osmo_gsup_req_respond(), passing the caller's source file and line for logging. */
 | 
				
			||||||
 | 
					#define osmo_gsup_req_respond(REQ, RESPONSE, ERROR, FINAL_RESPONSE) \
 | 
				
			||||||
 | 
						_osmo_gsup_req_respond(REQ, RESPONSE, ERROR, FINAL_RESPONSE, __FILE__, __LINE__)
 | 
				
			||||||
 | 
					int _osmo_gsup_req_respond(struct osmo_gsup_req *req, struct osmo_gsup_message *response,
 | 
				
			||||||
 | 
								   bool error, bool final_response, const char *file, int line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! See _osmo_gsup_req_respond_msgt() for details.
 | 
				
			||||||
 | 
					 * Call _osmo_gsup_req_respond_msgt(), passing the caller's source file and line for logging. */
 | 
				
			||||||
 | 
					#define osmo_gsup_req_respond_msgt(REQ, MESSAGE_TYPE, FINAL_RESPONSE) \
 | 
				
			||||||
 | 
						_osmo_gsup_req_respond_msgt(REQ, MESSAGE_TYPE, FINAL_RESPONSE, __FILE__, __LINE__)
 | 
				
			||||||
 | 
					int _osmo_gsup_req_respond_msgt(struct osmo_gsup_req *req, enum osmo_gsup_message_type message_type,
 | 
				
			||||||
 | 
									bool final_response, const char *file, int line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! See _osmo_gsup_req_respond_err() for details.
 | 
				
			||||||
 | 
					 * Log an error message, and call _osmo_gsup_req_respond_err(), passing the caller's source file and line for logging.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define osmo_gsup_req_respond_err(REQ, CAUSE, FMT, args...) do { \
 | 
				
			||||||
 | 
							LOG_GSUP_REQ(REQ, LOGL_ERROR, "%s: " FMT "\n", \
 | 
				
			||||||
 | 
								     get_value_string(gsm48_gmm_cause_names, CAUSE), ##args); \
 | 
				
			||||||
 | 
							_osmo_gsup_req_respond_err(REQ, CAUSE, __FILE__, __LINE__); \
 | 
				
			||||||
 | 
						} while(0)
 | 
				
			||||||
 | 
					void _osmo_gsup_req_respond_err(struct osmo_gsup_req *req, enum gsm48_gmm_cause cause,
 | 
				
			||||||
 | 
									const char *file, int line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_gsup_make_response(struct osmo_gsup_message *reply,
 | 
				
			||||||
 | 
								    const struct osmo_gsup_message *rx, bool error, bool final_response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t osmo_gsup_message_to_str_buf(char *buf, size_t bufsize, const struct osmo_gsup_message *msg);
 | 
				
			||||||
 | 
					char *osmo_gsup_message_to_str_c(void *ctx, const struct osmo_gsup_message *msg);
 | 
				
			||||||
							
								
								
									
										20
									
								
								include/osmocom/hlr/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/osmocom/hlr/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					noinst_HEADERS = \
 | 
				
			||||||
 | 
						auc.h \
 | 
				
			||||||
 | 
						ctrl.h \
 | 
				
			||||||
 | 
						db.h \
 | 
				
			||||||
 | 
						dgsm.h \
 | 
				
			||||||
 | 
						gsup_router.h \
 | 
				
			||||||
 | 
						gsup_server.h \
 | 
				
			||||||
 | 
						hlr.h \
 | 
				
			||||||
 | 
						hlr_ussd.h \
 | 
				
			||||||
 | 
						hlr_vty.h \
 | 
				
			||||||
 | 
						hlr_vty_subscr.h \
 | 
				
			||||||
 | 
						logging.h \
 | 
				
			||||||
 | 
						lu_fsm.h \
 | 
				
			||||||
 | 
						mslookup_server.h \
 | 
				
			||||||
 | 
						mslookup_server_mdns.h \
 | 
				
			||||||
 | 
						proxy.h \
 | 
				
			||||||
 | 
						rand.h \
 | 
				
			||||||
 | 
						remote_hlr.h \
 | 
				
			||||||
 | 
						timestamp.h \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
							
								
								
									
										33
									
								
								include/osmocom/hlr/ctrl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								include/osmocom/hlr/ctrl.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					/* OsmoHLR Control Interface implementation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Max Suraev <msuraev@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/ctrl/control_if.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum hlr_ctrl_node {
 | 
				
			||||||
 | 
						CTRL_NODE_SUBSCR = _LAST_CTRL_NODE,
 | 
				
			||||||
 | 
						CTRL_NODE_SUBSCR_BY,
 | 
				
			||||||
 | 
						_LAST_CTRL_NODE_HLR
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr);
 | 
				
			||||||
							
								
								
									
										203
									
								
								include/osmocom/hlr/db.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								include/osmocom/hlr/db.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,203 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <sqlite3.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/cni_peer_id.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsup.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum stmt_idx {
 | 
				
			||||||
 | 
						DB_STMT_SEL_ALL,
 | 
				
			||||||
 | 
						DB_STMT_SEL_ALL_ORDER_LAST_SEEN,
 | 
				
			||||||
 | 
						DB_STMT_SEL_FILTER_MSISDN,
 | 
				
			||||||
 | 
						DB_STMT_SEL_FILTER_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_SEL_FILTER_IMEI,
 | 
				
			||||||
 | 
						DB_STMT_SEL_FILTER_CS,
 | 
				
			||||||
 | 
						DB_STMT_SEL_FILTER_PS,
 | 
				
			||||||
 | 
						DB_STMT_SEL_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_SEL_BY_MSISDN,
 | 
				
			||||||
 | 
						DB_STMT_SEL_BY_ID,
 | 
				
			||||||
 | 
						DB_STMT_SEL_BY_IMEI,
 | 
				
			||||||
 | 
						DB_STMT_UPD_VLR_BY_ID,
 | 
				
			||||||
 | 
						DB_STMT_UPD_SGSN_BY_ID,
 | 
				
			||||||
 | 
						DB_STMT_UPD_IMEI_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_AUC_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_AUC_UPD_SQN,
 | 
				
			||||||
 | 
						DB_STMT_UPD_PURGE_CS_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_UPD_PURGE_PS_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_UPD_NAM_PS_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_UPD_NAM_CS_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_SUBSCR_CREATE,
 | 
				
			||||||
 | 
						DB_STMT_DEL_BY_ID,
 | 
				
			||||||
 | 
						DB_STMT_SET_MSISDN_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_DELETE_MSISDN_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_AUC_2G_INSERT,
 | 
				
			||||||
 | 
						DB_STMT_AUC_2G_DELETE,
 | 
				
			||||||
 | 
						DB_STMT_AUC_3G_INSERT,
 | 
				
			||||||
 | 
						DB_STMT_AUC_3G_DELETE,
 | 
				
			||||||
 | 
						DB_STMT_SET_LAST_LU_SEEN,
 | 
				
			||||||
 | 
						DB_STMT_SET_LAST_LU_SEEN_PS,
 | 
				
			||||||
 | 
						DB_STMT_EXISTS_BY_IMSI,
 | 
				
			||||||
 | 
						DB_STMT_EXISTS_BY_MSISDN,
 | 
				
			||||||
 | 
						DB_STMT_IND_ADD,
 | 
				
			||||||
 | 
						DB_STMT_IND_SELECT,
 | 
				
			||||||
 | 
						DB_STMT_IND_DEL,
 | 
				
			||||||
 | 
						_NUM_DB_STMT
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct db_context {
 | 
				
			||||||
 | 
						char *fname;
 | 
				
			||||||
 | 
						sqlite3 *db;
 | 
				
			||||||
 | 
						sqlite3_stmt *stmt[_NUM_DB_STMT];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Optional feature to make SQLite3 using talloc */
 | 
				
			||||||
 | 
					#ifdef SQLITE_USE_TALLOC
 | 
				
			||||||
 | 
					int db_sqlite3_use_talloc(void *ctx);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void db_remove_reset(sqlite3_stmt *stmt);
 | 
				
			||||||
 | 
					bool db_bind_text(sqlite3_stmt *stmt, const char *param_name, const char *text);
 | 
				
			||||||
 | 
					bool db_bind_int(sqlite3_stmt *stmt, const char *param_name, int nr);
 | 
				
			||||||
 | 
					bool db_bind_int64(sqlite3_stmt *stmt, const char *param_name, int64_t nr);
 | 
				
			||||||
 | 
					bool db_bind_null(sqlite3_stmt *stmt, const char *param_name);
 | 
				
			||||||
 | 
					void db_close(struct db_context *dbc);
 | 
				
			||||||
 | 
					struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_logging, bool allow_upgrades);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/crypt/auth.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* obtain the authentication data for a given imsi */
 | 
				
			||||||
 | 
					int db_get_auth_data(struct db_context *dbc, const char *imsi,
 | 
				
			||||||
 | 
							     struct osmo_sub_auth_data *aud2g,
 | 
				
			||||||
 | 
							     struct osmo_sub_auth_data *aud3g,
 | 
				
			||||||
 | 
							     int64_t *subscr_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_update_sqn(struct db_context *dbc, int64_t id,
 | 
				
			||||||
 | 
							      uint64_t new_sqn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_get_auc(struct db_context *dbc, const char *imsi,
 | 
				
			||||||
 | 
						       unsigned int auc_3g_ind, struct osmo_auth_vector *vec,
 | 
				
			||||||
 | 
						       unsigned int num_vec, const uint8_t *rand_auts,
 | 
				
			||||||
 | 
						       const uint8_t *auts, bool separation_bit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_23_003.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* TODO: Get this from somewhere? */
 | 
				
			||||||
 | 
					#define GT_MAX_DIGITS	15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr_subscriber {
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int64_t		id;
 | 
				
			||||||
 | 
						char		imsi[GSM23003_IMSI_MAX_DIGITS+1];
 | 
				
			||||||
 | 
						char		msisdn[GSM23003_MSISDN_MAX_DIGITS+1];
 | 
				
			||||||
 | 
						/* imeisv? */
 | 
				
			||||||
 | 
						char		imei[GSM23003_IMEI_NUM_DIGITS+1];
 | 
				
			||||||
 | 
						char		vlr_number[32];
 | 
				
			||||||
 | 
						char		sgsn_number[32];
 | 
				
			||||||
 | 
						char		sgsn_address[GT_MAX_DIGITS+1];
 | 
				
			||||||
 | 
						/* ggsn number + address */
 | 
				
			||||||
 | 
						/* gmlc number */
 | 
				
			||||||
 | 
						/* smsc number */
 | 
				
			||||||
 | 
						uint32_t	periodic_lu_timer;
 | 
				
			||||||
 | 
						uint32_t	periodic_rau_tau_timer;
 | 
				
			||||||
 | 
						bool		nam_cs;
 | 
				
			||||||
 | 
						bool		nam_ps;
 | 
				
			||||||
 | 
						uint32_t	lmsi;
 | 
				
			||||||
 | 
						bool		ms_purged_cs;
 | 
				
			||||||
 | 
						bool		ms_purged_ps;
 | 
				
			||||||
 | 
						time_t		last_lu_seen;
 | 
				
			||||||
 | 
						time_t		last_lu_seen_ps;
 | 
				
			||||||
 | 
						/* talloc'd IPA unit name */
 | 
				
			||||||
 | 
						struct osmo_ipa_name	vlr_via_proxy;
 | 
				
			||||||
 | 
						struct osmo_ipa_name	sgsn_via_proxy;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A format string for use with strptime(3). This format string is
 | 
				
			||||||
 | 
					 * used to parse the last_lu_seen column stored in the HLR database.
 | 
				
			||||||
 | 
					 * See https://sqlite.org/lang_datefunc.html, function datetime(). */
 | 
				
			||||||
 | 
					#define DB_LAST_LU_SEEN_FMT "%Y-%m-%d %H:%M:%S"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Like struct osmo_sub_auth_data, but the keys are in hexdump representation.
 | 
				
			||||||
 | 
					 * This is useful because SQLite requires them in hexdump format, and callers
 | 
				
			||||||
 | 
					 * like the VTY and CTRL interface also have them available as hexdump to begin
 | 
				
			||||||
 | 
					 * with. In the binary format, a VTY command would first need to hexparse,
 | 
				
			||||||
 | 
					 * after which the db function would again hexdump, copying to separate
 | 
				
			||||||
 | 
					 * buffers. The roundtrip can be saved by providing char* to begin with. */
 | 
				
			||||||
 | 
					struct sub_auth_data_str {
 | 
				
			||||||
 | 
						enum osmo_sub_auth_type type;
 | 
				
			||||||
 | 
						enum osmo_auth_algo algo;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								const char *opc;
 | 
				
			||||||
 | 
								const char *k;
 | 
				
			||||||
 | 
								uint64_t sqn;
 | 
				
			||||||
 | 
								int opc_is_op;
 | 
				
			||||||
 | 
								unsigned int ind_bitlen;
 | 
				
			||||||
 | 
							} umts;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								const char *ki;
 | 
				
			||||||
 | 
							} gsm;
 | 
				
			||||||
 | 
						} u;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DB_SUBSCR_FLAG_NAM_CS	(1 << 1)
 | 
				
			||||||
 | 
					#define DB_SUBSCR_FLAG_NAM_PS	(1 << 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_subscr_create(struct db_context *dbc, const char *imsi, uint8_t flags);
 | 
				
			||||||
 | 
					int db_subscr_delete_by_id(struct db_context *dbc, int64_t subscr_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_subscr_update_msisdn_by_imsi(struct db_context *dbc, const char *imsi,
 | 
				
			||||||
 | 
									    const char *msisdn);
 | 
				
			||||||
 | 
					int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
 | 
				
			||||||
 | 
								       const struct sub_auth_data_str *aud);
 | 
				
			||||||
 | 
					int db_subscr_update_imei_by_imsi(struct db_context *dbc, const char* imsi, const char *imei);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_subscr_exists_by_imsi(struct db_context *dbc, const char *imsi);
 | 
				
			||||||
 | 
					int db_subscr_exists_by_msisdn(struct db_context *dbc, const char *msisdn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_subscrs_get(struct db_context *dbc, const char *filter_type, const char *filter,
 | 
				
			||||||
 | 
							   void (*get_cb)(struct hlr_subscriber *subscr, void *data), void *data,
 | 
				
			||||||
 | 
							   int *count, const char **err);
 | 
				
			||||||
 | 
					int db_subscr_get_by_imsi(struct db_context *dbc, const char *imsi,
 | 
				
			||||||
 | 
								  struct hlr_subscriber *subscr);
 | 
				
			||||||
 | 
					int db_subscr_get_by_msisdn(struct db_context *dbc, const char *msisdn,
 | 
				
			||||||
 | 
								    struct hlr_subscriber *subscr);
 | 
				
			||||||
 | 
					int db_subscr_get_by_id(struct db_context *dbc, int64_t id,
 | 
				
			||||||
 | 
								struct hlr_subscriber *subscr);
 | 
				
			||||||
 | 
					int db_subscr_get_by_imei(struct db_context *dbc, const char *imei, struct hlr_subscriber *subscr);
 | 
				
			||||||
 | 
					int db_subscr_nam(struct db_context *dbc, const char *imsi, bool nam_val, bool is_ps);
 | 
				
			||||||
 | 
					int db_subscr_lu(struct db_context *dbc, int64_t subscr_id,
 | 
				
			||||||
 | 
							 const struct osmo_ipa_name *vlr_name, bool is_ps,
 | 
				
			||||||
 | 
							 const struct osmo_ipa_name *via_proxy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_subscr_purge(struct db_context *dbc, const char *by_imsi,
 | 
				
			||||||
 | 
							    bool purge_val, bool is_ps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_ind(struct db_context *dbc, const struct osmo_cni_peer_id *vlr, unsigned int *ind);
 | 
				
			||||||
 | 
					int db_ind_del(struct db_context *dbc, const struct osmo_cni_peer_id *vlr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Call sqlite3_column_text() and copy result to a char[].
 | 
				
			||||||
 | 
					 * \param[out] buf  A char[] used as sizeof() arg(!) and osmo_strlcpy() target.
 | 
				
			||||||
 | 
					 * \param[in] stmt  An sqlite3_stmt*.
 | 
				
			||||||
 | 
					 * \param[in] idx   Index in stmt's returned columns.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define copy_sqlite3_text_to_buf(buf, stmt, idx) \
 | 
				
			||||||
 | 
						do { \
 | 
				
			||||||
 | 
							const char *_txt = (const char *) sqlite3_column_text(stmt, idx); \
 | 
				
			||||||
 | 
							osmo_strlcpy(buf, _txt, sizeof(buf)); \
 | 
				
			||||||
 | 
						} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Call sqlite3_column_text() and copy result to a struct osmo_ipa_name.
 | 
				
			||||||
 | 
					 * \param[out] ipa_name  A struct osmo_ipa_name* to write to.
 | 
				
			||||||
 | 
					 * \param[in] stmt  An sqlite3_stmt*.
 | 
				
			||||||
 | 
					 * \param[in] idx  Index in stmt's returned columns.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define copy_sqlite3_text_to_ipa_name(ipa_name, stmt, idx) \
 | 
				
			||||||
 | 
						do { \
 | 
				
			||||||
 | 
							const char *_txt = (const char *) sqlite3_column_text(stmt, idx); \
 | 
				
			||||||
 | 
							osmo_ipa_name_set_str(ipa_name, _txt); \
 | 
				
			||||||
 | 
						} while (0)
 | 
				
			||||||
							
								
								
									
										46
									
								
								include/osmocom/hlr/dgsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								include/osmocom/hlr/dgsm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/mslookup/mslookup.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/gsup_server.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/logging.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/cni_peer_id.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/gsup_req.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_DGSM(imsi, level, fmt, args...) \
 | 
				
			||||||
 | 
						LOGP(DDGSM, level, "(IMSI-%s) " fmt, imsi, ##args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct vty;
 | 
				
			||||||
 | 
					struct remote_hlr;
 | 
				
			||||||
 | 
					struct hlr_subscriber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void *dgsm_ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dgsm_init(void *ctx);
 | 
				
			||||||
 | 
					void dgsm_start(void *ctx);
 | 
				
			||||||
 | 
					void dgsm_stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool dgsm_check_forward_gsup_msg(struct osmo_gsup_req *req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dgsm_vty_init();
 | 
				
			||||||
 | 
					void dgsm_mdns_client_config_apply(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool hlr_subscr_lu_age(const struct hlr_subscriber *subscr, uint32_t *age_p);
 | 
				
			||||||
							
								
								
									
										33
									
								
								include/osmocom/hlr/gsup_router.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								include/osmocom/hlr/gsup_router.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/gsup_server.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_ipa_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsup_route {
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint8_t *addr;
 | 
				
			||||||
 | 
						struct osmo_gsup_conn *conn;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_conn *gsup_route_find(struct osmo_gsup_server *gs,
 | 
				
			||||||
 | 
										const uint8_t *addr, size_t addrlen);
 | 
				
			||||||
 | 
					struct osmo_gsup_conn *gsup_route_find_by_ipa_name(struct osmo_gsup_server *gs, const struct osmo_ipa_name *ipa_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct gsup_route *gsup_route_find_by_conn(const struct osmo_gsup_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* add a new route for the given address to the given conn */
 | 
				
			||||||
 | 
					int gsup_route_add_ipa_name(struct osmo_gsup_conn *conn, const struct osmo_ipa_name *ipa_name);
 | 
				
			||||||
 | 
					int gsup_route_add(struct osmo_gsup_conn *conn, const uint8_t *addr, size_t addrlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* delete all routes for the given connection */
 | 
				
			||||||
 | 
					int gsup_route_del_conn(struct osmo_gsup_conn *conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_gsup_addr_send(struct osmo_gsup_server *gs,
 | 
				
			||||||
 | 
								const uint8_t *addr, size_t addrlen,
 | 
				
			||||||
 | 
								struct msgb *msg);
 | 
				
			||||||
 | 
					int osmo_gsup_send_to_ipa_name(struct osmo_gsup_server *gs, const struct osmo_ipa_name *ipa_name, struct msgb *msg);
 | 
				
			||||||
 | 
					int osmo_gsup_enc_send_to_ipa_name(struct osmo_gsup_server *gs, const struct osmo_ipa_name *ipa_name,
 | 
				
			||||||
 | 
								  const struct osmo_gsup_message *gsup);
 | 
				
			||||||
							
								
								
									
										76
									
								
								include/osmocom/hlr/gsup_server.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								include/osmocom/hlr/gsup_server.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/abis/ipa.h>
 | 
				
			||||||
 | 
					#include <osmocom/abis/ipaccess.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsup.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/cni_peer_id.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/gsup_req.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN
 | 
				
			||||||
 | 
					#define OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN	43 /* TS 24.008 10.5.4.7 */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_conn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Expects message in msg->l2h */
 | 
				
			||||||
 | 
					typedef int (*osmo_gsup_read_cb_t)(struct osmo_gsup_conn *conn, struct msgb *msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_server {
 | 
				
			||||||
 | 
						/* private data of the application/user */
 | 
				
			||||||
 | 
						void *priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* list of osmo_gsup_conn */
 | 
				
			||||||
 | 
						struct llist_head clients;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ipa_server_link *link;
 | 
				
			||||||
 | 
						osmo_gsup_read_cb_t read_cb;
 | 
				
			||||||
 | 
						struct llist_head routes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Proxy requests from this server's clients to remote GSUP servers. */
 | 
				
			||||||
 | 
						struct proxy *proxy;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* a single connection to a given client (SGSN, MSC) */
 | 
				
			||||||
 | 
					struct osmo_gsup_conn {
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct osmo_gsup_server *server;
 | 
				
			||||||
 | 
						struct ipa_server_conn *conn;
 | 
				
			||||||
 | 
						//struct oap_state oap_state;
 | 
				
			||||||
 | 
						struct tlv_parsed ccm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set when Location Update is received: */
 | 
				
			||||||
 | 
						bool supports_cs; /* client supports OSMO_GSUP_CN_DOMAIN_CS */
 | 
				
			||||||
 | 
						bool supports_ps; /* client supports OSMO_GSUP_CN_DOMAIN_PS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The IPA unit name received on this link. Routes with more unit names serviced by this link may exist in
 | 
				
			||||||
 | 
						 * osmo_gsup_server->routes, but this is the name the immediate peer identified as in the IPA handshake. */
 | 
				
			||||||
 | 
						struct osmo_ipa_name peer_name;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msgb *osmo_gsup_msgb_alloc(const char *label);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_req *osmo_gsup_conn_rx(struct osmo_gsup_conn *conn, struct msgb *msg);
 | 
				
			||||||
 | 
					int osmo_gsup_conn_send(struct osmo_gsup_conn *conn, struct msgb *msg);
 | 
				
			||||||
 | 
					int osmo_gsup_conn_ccm_get(const struct osmo_gsup_conn *clnt, uint8_t **addr,
 | 
				
			||||||
 | 
								   uint8_t tag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_server *osmo_gsup_server_create(void *ctx,
 | 
				
			||||||
 | 
											 const char *ip_addr,
 | 
				
			||||||
 | 
											 uint16_t tcp_port,
 | 
				
			||||||
 | 
											 osmo_gsup_read_cb_t read_cb,
 | 
				
			||||||
 | 
											 void *priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_gsup_server_destroy(struct osmo_gsup_server *gsups);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_gsup_configure_wildcard_apn(struct osmo_gsup_message *gsup,
 | 
				
			||||||
 | 
									     uint8_t *apn_buf, size_t apn_buf_size);
 | 
				
			||||||
 | 
					int osmo_gsup_create_insert_subscriber_data_msg(struct osmo_gsup_message *gsup, const char *imsi, const char *msisdn,
 | 
				
			||||||
 | 
										    uint8_t *msisdn_enc, size_t msisdn_enc_size,
 | 
				
			||||||
 | 
									            uint8_t *apn_buf, size_t apn_buf_size,
 | 
				
			||||||
 | 
										    enum osmo_gsup_cn_domain cn_domain);
 | 
				
			||||||
 | 
					int osmo_gsup_forward_to_local_peer(struct osmo_gsup_server *server, const struct osmo_cni_peer_id *to_peer,
 | 
				
			||||||
 | 
									    struct osmo_gsup_req *req, struct osmo_gsup_message *modified_gsup);
 | 
				
			||||||
							
								
								
									
										121
									
								
								include/osmocom/hlr/hlr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								include/osmocom/hlr/hlr.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
				
			|||||||
 | 
					/* OsmoHLR generic header */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Max Suraev <msuraev@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/ipa.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/tdef.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/sockaddr_str.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/hlr/dgsm.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HLR_DEFAULT_DB_FILE_PATH "hlr.db"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr_euse;
 | 
				
			||||||
 | 
					struct osmo_gsup_conn;
 | 
				
			||||||
 | 
					enum osmo_gsup_message_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct osmo_tdef g_hlr_tdefs[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr {
 | 
				
			||||||
 | 
						/* GSUP server pointer */
 | 
				
			||||||
 | 
						struct osmo_gsup_server *gs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* DB context */
 | 
				
			||||||
 | 
						char *db_file_path;
 | 
				
			||||||
 | 
						struct db_context *dbc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Control Interface */
 | 
				
			||||||
 | 
						struct ctrl_handle *ctrl;
 | 
				
			||||||
 | 
						const char *ctrl_bind_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Local bind addr */
 | 
				
			||||||
 | 
						char *gsup_bind_addr;
 | 
				
			||||||
 | 
						struct ipaccess_unit gsup_unit_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct llist_head euse_list;
 | 
				
			||||||
 | 
						struct hlr_euse *euse_default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* NCSS (call independent) session guard timeout value */
 | 
				
			||||||
 | 
						int ncss_guard_timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct llist_head ussd_routes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct llist_head ss_sessions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool store_imei;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool subscr_create_on_demand;
 | 
				
			||||||
 | 
						/* Bitmask of DB_SUBSCR_FLAG_* */
 | 
				
			||||||
 | 
						uint8_t subscr_create_on_demand_flags;
 | 
				
			||||||
 | 
						unsigned int subscr_create_on_demand_rand_msisdn_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							bool allow_startup;
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								/* Whether the mslookup server should be active in general (all lookup methods) */
 | 
				
			||||||
 | 
								bool enable;
 | 
				
			||||||
 | 
								uint32_t local_attach_max_age;
 | 
				
			||||||
 | 
								struct llist_head local_site_services;
 | 
				
			||||||
 | 
								struct {
 | 
				
			||||||
 | 
									/* Whether the mDNS method of the mslookup server should be active. */
 | 
				
			||||||
 | 
									bool enable;
 | 
				
			||||||
 | 
									/* The mDNS bind address and domain suffix as set by the VTY, not necessarily in use. */
 | 
				
			||||||
 | 
									struct osmo_sockaddr_str bind_addr;
 | 
				
			||||||
 | 
									char *domain_suffix;
 | 
				
			||||||
 | 
									struct osmo_mslookup_server_mdns *running;
 | 
				
			||||||
 | 
								} mdns;
 | 
				
			||||||
 | 
							} server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* The mslookup client in osmo-hlr is used to find out which remote HLRs service a locally unknown IMSI.
 | 
				
			||||||
 | 
							 * (It may also be used to resolve recipients for SMS-over-GSUP in the future.) */
 | 
				
			||||||
 | 
							struct {
 | 
				
			||||||
 | 
								/* Whether to proxy/forward to remote HLRs */
 | 
				
			||||||
 | 
								bool enable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* If this is set, all GSUP for unknown IMSIs is forwarded directly to this GSUP address,
 | 
				
			||||||
 | 
								 * unconditionally. */
 | 
				
			||||||
 | 
								struct osmo_sockaddr_str gsup_gateway_proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* mslookup client request handling */
 | 
				
			||||||
 | 
								unsigned int result_timeout_milliseconds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								struct osmo_mslookup_client *client;
 | 
				
			||||||
 | 
								struct {
 | 
				
			||||||
 | 
									/* Whether to use mDNS for IMSI MS Lookup */
 | 
				
			||||||
 | 
									bool enable;
 | 
				
			||||||
 | 
									struct osmo_sockaddr_str query_addr;
 | 
				
			||||||
 | 
									char *domain_suffix;
 | 
				
			||||||
 | 
									struct osmo_mslookup_client_method *running;
 | 
				
			||||||
 | 
								} mdns;
 | 
				
			||||||
 | 
							} client;
 | 
				
			||||||
 | 
						} mslookup;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern struct hlr *g_hlr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr_subscriber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_hlr_subscriber_update_notify(struct hlr_subscriber *subscr);
 | 
				
			||||||
 | 
					int hlr_subscr_nam(struct hlr *hlr, struct hlr_subscriber *subscr, bool nam_val, bool is_ps);
 | 
				
			||||||
							
								
								
									
										60
									
								
								include/osmocom/hlr/hlr_ussd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								include/osmocom/hlr/hlr_ussd.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsup.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/hlr/gsup_server.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NCSS_GUARD_TIMEOUT_DEFAULT 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr_ussd_route {
 | 
				
			||||||
 | 
						/* g_hlr.routes */
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
						const char *prefix;
 | 
				
			||||||
 | 
						bool is_external;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct hlr_euse *euse;
 | 
				
			||||||
 | 
							const struct hlr_iuse *iuse;
 | 
				
			||||||
 | 
						} u;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr_euse {
 | 
				
			||||||
 | 
						/* list in the per-hlr list of EUSEs */
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
						struct hlr *hlr;
 | 
				
			||||||
 | 
						/* name (must match the IPA ID tag) */
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
						/* human-readable description */
 | 
				
			||||||
 | 
						const char *description;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* GSUP connection to the EUSE, if any */
 | 
				
			||||||
 | 
						struct osmo_gsup_conn *conn;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr_euse *euse_find(struct hlr *hlr, const char *name);
 | 
				
			||||||
 | 
					struct hlr_euse *euse_alloc(struct hlr *hlr, const char *name);
 | 
				
			||||||
 | 
					void euse_del(struct hlr_euse *euse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct hlr_iuse *iuse_find(const char *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct hlr_ussd_route *ussd_route_find_prefix(struct hlr *hlr, const char *prefix);
 | 
				
			||||||
 | 
					struct hlr_ussd_route *ussd_route_prefix_alloc_int(struct hlr *hlr, const char *prefix,
 | 
				
			||||||
 | 
											   const struct hlr_iuse *iuse);
 | 
				
			||||||
 | 
					struct hlr_ussd_route *ussd_route_prefix_alloc_ext(struct hlr *hlr, const char *prefix,
 | 
				
			||||||
 | 
											   struct hlr_euse *euse);
 | 
				
			||||||
 | 
					void ussd_route_del(struct hlr_ussd_route *rt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rx_proc_ss_req(struct osmo_gsup_req *req);
 | 
				
			||||||
 | 
					void rx_proc_ss_error(struct osmo_gsup_req *req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ss_session;
 | 
				
			||||||
 | 
					struct ss_request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Internal USSD Handler */
 | 
				
			||||||
 | 
					struct hlr_iuse {
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
						/* call-back to be called for any incoming USSD messages for this IUSE */
 | 
				
			||||||
 | 
						int (*handle_ussd)(struct ss_session *ss, const struct osmo_gsup_message *gsup, const struct ss_request *req);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										49
									
								
								include/osmocom/hlr/hlr_vty.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								include/osmocom/hlr/hlr_vty.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					/* OsmoHLR VTY implementation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2016 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/logging.h>
 | 
				
			||||||
 | 
					#include <osmocom/vty/vty.h>
 | 
				
			||||||
 | 
					#include <osmocom/vty/command.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/hlr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum hlr_vty_node {
 | 
				
			||||||
 | 
						HLR_NODE = _LAST_OSMOVTY_NODE + 1,
 | 
				
			||||||
 | 
						GSUP_NODE,
 | 
				
			||||||
 | 
						EUSE_NODE,
 | 
				
			||||||
 | 
						MSLOOKUP_NODE,
 | 
				
			||||||
 | 
						MSLOOKUP_SERVER_NODE,
 | 
				
			||||||
 | 
						MSLOOKUP_SERVER_MSC_NODE,
 | 
				
			||||||
 | 
						MSLOOKUP_CLIENT_NODE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define A38_XOR_MIN_KEY_LEN	12
 | 
				
			||||||
 | 
					#define A38_XOR_MAX_KEY_LEN	16
 | 
				
			||||||
 | 
					#define A38_COMP128_KEY_LEN	16
 | 
				
			||||||
 | 
					#define MILENAGE_KEY_LEN	16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int hlr_vty_is_config_node(struct vty *vty, int node);
 | 
				
			||||||
 | 
					int hlr_vty_go_parent(struct vty *vty);
 | 
				
			||||||
 | 
					void hlr_vty_init(void);
 | 
				
			||||||
 | 
					void dgsm_vty_init(void);
 | 
				
			||||||
							
								
								
									
										3
									
								
								include/osmocom/hlr/hlr_vty_subscr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								include/osmocom/hlr/hlr_vty_subscr.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void hlr_vty_subscriber_init(void);
 | 
				
			||||||
@@ -7,6 +7,11 @@ enum {
 | 
				
			|||||||
	DDB,
 | 
						DDB,
 | 
				
			||||||
	DGSUP,
 | 
						DGSUP,
 | 
				
			||||||
	DAUC,
 | 
						DAUC,
 | 
				
			||||||
 | 
						DSS,
 | 
				
			||||||
 | 
						DMSLOOKUP,
 | 
				
			||||||
 | 
						DLU,
 | 
				
			||||||
 | 
						DDGSM,
 | 
				
			||||||
 | 
						DCTRL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const struct log_info hlr_log_info;
 | 
					extern const struct log_info hlr_log_info;
 | 
				
			||||||
							
								
								
									
										22
									
								
								include/osmocom/hlr/lu_fsm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/osmocom/hlr/lu_fsm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void lu_rx_gsup(struct osmo_gsup_req *req);
 | 
				
			||||||
							
								
								
									
										72
									
								
								include/osmocom/hlr/mslookup_server.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								include/osmocom/hlr/mslookup_server.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/cni_peer_id.h>
 | 
				
			||||||
 | 
					#include <osmocom/mslookup/mslookup.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_query;
 | 
				
			||||||
 | 
					struct osmo_mslookup_result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! mslookup service name used for roaming/proxying between osmo-hlr instances. */
 | 
				
			||||||
 | 
					#define OSMO_MSLOOKUP_SERVICE_HLR_GSUP "gsup.hlr"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! What addresses to return to mslookup queries when a subscriber is attached at the local site.
 | 
				
			||||||
 | 
					 * Mapping of service name to IP address and port. This corresponds to the VTY config for
 | 
				
			||||||
 | 
					 * 'mslookup' / 'server' [/ 'msc MSC-1-2-3'] / 'service sip.voice at 1.2.3.4 1234'.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct mslookup_service_host {
 | 
				
			||||||
 | 
						struct llist_head entry;
 | 
				
			||||||
 | 
						char service[OSMO_MSLOOKUP_SERVICE_MAXLEN+1];
 | 
				
			||||||
 | 
						struct osmo_sockaddr_str host_v4;
 | 
				
			||||||
 | 
						struct osmo_sockaddr_str host_v6;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Sets of mslookup_service_host per connected MSC.
 | 
				
			||||||
 | 
					 * When there are more than one MSC connected to this osmo-hlr, this allows keeping separate sets of service addresses
 | 
				
			||||||
 | 
					 * for each MSC. The entry with mslookup_server_msc_wildcard as MSC name is used for all MSCs (if no match for that
 | 
				
			||||||
 | 
					 * particular MSC is found). This corresponds to the VTY config for
 | 
				
			||||||
 | 
					 * 'mslookup' / 'server' / 'msc MSC-1-2-3'.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct mslookup_server_msc_cfg {
 | 
				
			||||||
 | 
						struct llist_head entry;
 | 
				
			||||||
 | 
						struct osmo_ipa_name name;
 | 
				
			||||||
 | 
						struct llist_head service_hosts;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mslookup_service_host *mslookup_server_service_get(const struct osmo_ipa_name *msc_name, const char *service);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mslookup_service_host *mslookup_server_msc_service_get(struct mslookup_server_msc_cfg *msc, const char *service,
 | 
				
			||||||
 | 
												      bool create);
 | 
				
			||||||
 | 
					int mslookup_server_msc_service_set(struct mslookup_server_msc_cfg *msc, const char *service,
 | 
				
			||||||
 | 
									    const struct osmo_sockaddr_str *addr);
 | 
				
			||||||
 | 
					int mslookup_server_msc_service_del(struct mslookup_server_msc_cfg *msc, const char *service,
 | 
				
			||||||
 | 
									    const struct osmo_sockaddr_str *addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct osmo_ipa_name mslookup_server_msc_wildcard;
 | 
				
			||||||
 | 
					struct mslookup_server_msc_cfg *mslookup_server_msc_get(const struct osmo_ipa_name *msc_name, bool create);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct mslookup_service_host *mslookup_server_get_local_gsup_addr();
 | 
				
			||||||
 | 
					void mslookup_server_rx(const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
								     struct osmo_mslookup_result *result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool subscriber_has_done_lu_here(const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									 uint32_t *lu_age_p, struct osmo_ipa_name *local_msc_name,
 | 
				
			||||||
 | 
									 char *ret_imsi, size_t ret_imsi_len);
 | 
				
			||||||
							
								
								
									
										36
									
								
								include/osmocom/hlr/mslookup_server_mdns.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								include/osmocom/hlr/mslookup_server_mdns.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/sockaddr_str.h>
 | 
				
			||||||
 | 
					#include <osmocom/mslookup/mdns_sock.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_server_mdns {
 | 
				
			||||||
 | 
						struct osmo_mslookup_server *mslookup;
 | 
				
			||||||
 | 
						struct osmo_sockaddr_str bind_addr;
 | 
				
			||||||
 | 
						char *domain_suffix;
 | 
				
			||||||
 | 
						struct osmo_mdns_sock *sock;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_server_mdns *osmo_mslookup_server_mdns_start(void *ctx, const struct osmo_sockaddr_str *bind_addr,
 | 
				
			||||||
 | 
													  const char *domain_suffix);
 | 
				
			||||||
 | 
					void osmo_mslookup_server_mdns_stop(struct osmo_mslookup_server_mdns *server);
 | 
				
			||||||
 | 
					void mslookup_server_mdns_config_apply();
 | 
				
			||||||
							
								
								
									
										95
									
								
								include/osmocom/hlr/proxy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								include/osmocom/hlr/proxy.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_23_003.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/sockaddr_str.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsupclient/cni_peer_id.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/timestamp.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_req;
 | 
				
			||||||
 | 
					struct remote_hlr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct proxy {
 | 
				
			||||||
 | 
						struct llist_head subscr_list;
 | 
				
			||||||
 | 
						struct llist_head pending_gsup_reqs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* When messages arrive back from a remote HLR that this is the proxy for, reach the VLR to forward the response
 | 
				
			||||||
 | 
						 * to via this osmo_gsup_server. */
 | 
				
			||||||
 | 
						struct osmo_gsup_server *gsup_server_to_vlr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* How long to keep proxy entries without a refresh, in seconds. */
 | 
				
			||||||
 | 
						uint32_t fresh_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* How often to garbage collect the proxy cache, period in seconds.
 | 
				
			||||||
 | 
						 * To change this and take effect immediately, rather use proxy_set_gc_period(). */
 | 
				
			||||||
 | 
						uint32_t gc_period;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct osmo_timer_list gc_timer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct proxy_subscr_domain_state {
 | 
				
			||||||
 | 
						struct osmo_ipa_name vlr_name;
 | 
				
			||||||
 | 
						timestamp_t last_lu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* The name from which an Update Location Request was received. Copied to vlr_name as soon as the LU is
 | 
				
			||||||
 | 
						 * completed successfully. */
 | 
				
			||||||
 | 
						struct osmo_ipa_name vlr_name_preliminary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Set if this is a middle proxy, i.e. a proxy behind another proxy.
 | 
				
			||||||
 | 
						 * That is mostly to know whether the MS is attached at a local MSC/SGSN or further away.
 | 
				
			||||||
 | 
						 * It could be a boolean, but store the full name for logging. Set only at successful LU acceptance. */
 | 
				
			||||||
 | 
						struct osmo_ipa_name vlr_via_proxy;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct proxy_subscr {
 | 
				
			||||||
 | 
						char imsi[GSM23003_IMSI_MAX_DIGITS+1];
 | 
				
			||||||
 | 
						char msisdn[GSM23003_MSISDN_MAX_DIGITS+1];
 | 
				
			||||||
 | 
						struct osmo_sockaddr_str remote_hlr_addr;
 | 
				
			||||||
 | 
						struct proxy_subscr_domain_state cs, ps;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void proxy_init(struct osmo_gsup_server *gsup_server_to_vlr);
 | 
				
			||||||
 | 
					void proxy_del(struct proxy *proxy);
 | 
				
			||||||
 | 
					void proxy_set_gc_period(struct proxy *proxy, uint32_t gc_period);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The API to access / modify proxy entries keeps the implementation opaque, to make sure that we can easily move proxy
 | 
				
			||||||
 | 
					 * storage to SQLite db. */
 | 
				
			||||||
 | 
					int proxy_subscr_get_by_imsi(struct proxy_subscr *dst, struct proxy *proxy, const char *imsi);
 | 
				
			||||||
 | 
					int proxy_subscr_get_by_msisdn(struct proxy_subscr *dst, struct proxy *proxy, const char *msisdn);
 | 
				
			||||||
 | 
					void proxy_subscrs_get_by_remote_hlr(struct proxy *proxy, const struct osmo_sockaddr_str *remote_hlr_addr,
 | 
				
			||||||
 | 
									     bool (*yield)(struct proxy *proxy, const struct proxy_subscr *subscr, void *data),
 | 
				
			||||||
 | 
									     void *data);
 | 
				
			||||||
 | 
					int proxy_subscr_create_or_update(struct proxy *proxy, const struct proxy_subscr *proxy_subscr);
 | 
				
			||||||
 | 
					int proxy_subscr_del(struct proxy *proxy, const char *imsi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int proxy_subscr_forward_to_remote_hlr(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
 | 
				
			||||||
 | 
									       struct osmo_gsup_req *req);
 | 
				
			||||||
 | 
					void proxy_subscr_forward_to_remote_hlr_resolved(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
 | 
				
			||||||
 | 
											 struct remote_hlr *remote_hlr, struct osmo_gsup_req *req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int proxy_subscr_forward_to_vlr(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
 | 
				
			||||||
 | 
									const struct osmo_gsup_message *gsup, struct remote_hlr *from_remote_hlr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void proxy_subscr_remote_hlr_resolved(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
 | 
				
			||||||
 | 
									      const struct osmo_sockaddr_str *remote_hlr_addr);
 | 
				
			||||||
 | 
					void proxy_subscr_remote_hlr_up(struct proxy *proxy, const struct proxy_subscr *proxy_subscr,
 | 
				
			||||||
 | 
									struct remote_hlr *remote_hlr);
 | 
				
			||||||
							
								
								
									
										59
									
								
								include/osmocom/hlr/remote_hlr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								include/osmocom/hlr/remote_hlr.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/sockaddr_str.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_gsup_client;
 | 
				
			||||||
 | 
					struct osmo_gsup_message;
 | 
				
			||||||
 | 
					struct osmo_gsup_req;
 | 
				
			||||||
 | 
					struct msgb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_REMOTE_HLR(remote_hlr, level, fmt, args...) \
 | 
				
			||||||
 | 
						LOGP(DDGSM, level, "(Proxy HLR-" OSMO_SOCKADDR_STR_FMT ") " fmt, \
 | 
				
			||||||
 | 
						     OSMO_SOCKADDR_STR_FMT_ARGS((remote_hlr) ? &(remote_hlr)->addr : NULL), ##args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LOG_REMOTE_HLR_MSG(remote_hlr, gsup_msg, level, fmt, args...) \
 | 
				
			||||||
 | 
						LOG_REMOTE_HLR(remote_hlr, level, "%s: " fmt, osmo_gsup_message_type_name((gsup_msg)->message_type), ##args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* GSUP client link for proxying to a remote HLR. */
 | 
				
			||||||
 | 
					struct remote_hlr {
 | 
				
			||||||
 | 
						struct llist_head entry;
 | 
				
			||||||
 | 
						struct osmo_sockaddr_str addr;
 | 
				
			||||||
 | 
						struct osmo_gsup_client *gsupc;
 | 
				
			||||||
 | 
						struct llist_head pending_up_callbacks;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Receive a remote_hlr address when connecting succeeded, or remote_hlr == NULL on error.
 | 
				
			||||||
 | 
					 * \param addr  GSUP IP address and port for which the connection was requested.
 | 
				
			||||||
 | 
					 * \param remote_hlr  The connected remote_hlr ready for sending, or NULL if connecting failed.
 | 
				
			||||||
 | 
					 * \param data  Same a passed to remote_hlr_get_or_connect(). */
 | 
				
			||||||
 | 
					typedef void (*remote_hlr_connect_result_cb_t)(const struct osmo_sockaddr_str *addr, struct remote_hlr *remote_hlr, void *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct remote_hlr *remote_hlr_get_or_connect(const struct osmo_sockaddr_str *addr, bool connect,
 | 
				
			||||||
 | 
										     remote_hlr_connect_result_cb_t connect_result_cb, void *data);
 | 
				
			||||||
 | 
					void remote_hlr_destroy(struct remote_hlr *remote_hlr);
 | 
				
			||||||
 | 
					int remote_hlr_msgb_send(struct remote_hlr *remote_hlr, struct msgb *msg);
 | 
				
			||||||
 | 
					void remote_hlr_gsup_forward_to_remote_hlr(struct remote_hlr *remote_hlr, struct osmo_gsup_req *req,
 | 
				
			||||||
 | 
										   struct osmo_gsup_message *modified_gsup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool remote_hlr_is_up(struct remote_hlr *remote_hlr);
 | 
				
			||||||
							
								
								
									
										28
									
								
								include/osmocom/hlr/timestamp.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								include/osmocom/hlr/timestamp.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef time_t timestamp_t;
 | 
				
			||||||
 | 
					void timestamp_update(timestamp_t *timestamp);
 | 
				
			||||||
 | 
					bool timestamp_age(const timestamp_t *timestamp, uint32_t *age);
 | 
				
			||||||
							
								
								
									
										6
									
								
								include/osmocom/mslookup/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								include/osmocom/mslookup/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					# most headers here are installed, see /include/Makefile.am
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					noinst_HEADERS = \
 | 
				
			||||||
 | 
						mdns_msg.h \
 | 
				
			||||||
 | 
						mdns_rfc.h \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
							
								
								
									
										39
									
								
								include/osmocom/mslookup/mdns.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								include/osmocom/mslookup/mdns.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! \file mdns.h */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/mslookup/mslookup.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OSMO_MDNS_DOMAIN_SUFFIX_DEFAULT "mdns.osmocom.org"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msgb *osmo_mdns_query_encode(void *ctx, uint16_t packet_id, const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									    const char *domain_suffix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_query *osmo_mdns_query_decode(void *ctx, const uint8_t *data, size_t data_len,
 | 
				
			||||||
 | 
											   uint16_t *packet_id, const char *domain_suffix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct msgb *osmo_mdns_result_encode(void *ctx, uint16_t packet_id, const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									     const struct osmo_mslookup_result *result, const char *domain_suffix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_mdns_result_decode(void *ctx, const uint8_t *data, size_t data_len, uint16_t *packet_id,
 | 
				
			||||||
 | 
								    struct osmo_mslookup_query *query, struct osmo_mslookup_result *result,
 | 
				
			||||||
 | 
								    const char *domain_suffix);
 | 
				
			||||||
							
								
								
									
										54
									
								
								include/osmocom/mslookup/mdns_msg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								include/osmocom/mslookup/mdns_msg.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include "mdns_rfc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mdns_record {
 | 
				
			||||||
 | 
						struct llist_head list;
 | 
				
			||||||
 | 
						enum osmo_mdns_rfc_record_type type;
 | 
				
			||||||
 | 
						uint16_t length;
 | 
				
			||||||
 | 
						uint8_t *data;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mdns_msg_request {
 | 
				
			||||||
 | 
						uint16_t id;
 | 
				
			||||||
 | 
						char *domain;
 | 
				
			||||||
 | 
						enum osmo_mdns_rfc_record_type type;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mdns_msg_answer {
 | 
				
			||||||
 | 
						uint16_t id;
 | 
				
			||||||
 | 
						char *domain;
 | 
				
			||||||
 | 
						/*! list of osmo_mdns_record. */
 | 
				
			||||||
 | 
						struct llist_head records;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_mdns_msg_request_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_msg_request *req);
 | 
				
			||||||
 | 
					struct osmo_mdns_msg_request *osmo_mdns_msg_request_decode(void *ctx, const uint8_t *data, size_t data_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_mdns_msg_answer_init(struct osmo_mdns_msg_answer *answer);
 | 
				
			||||||
 | 
					int osmo_mdns_msg_answer_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_msg_answer *ans);
 | 
				
			||||||
 | 
					struct osmo_mdns_msg_answer *osmo_mdns_msg_answer_decode(void *ctx, const uint8_t *data, size_t data_len);
 | 
				
			||||||
 | 
					int osmo_mdns_result_from_answer(struct osmo_mslookup_result *result, const struct osmo_mdns_msg_answer *ans);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mdns_record *osmo_mdns_record_txt_keyval_encode(void *ctx, const char *key, const char *value_fmt, ...);
 | 
				
			||||||
 | 
					int osmo_mdns_record_txt_keyval_decode(const struct osmo_mdns_record *rec,
 | 
				
			||||||
 | 
									       char *key_buf, size_t key_size, char *value_buf, size_t value_size);
 | 
				
			||||||
							
								
								
									
										113
									
								
								include/osmocom/mslookup/mdns_rfc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								include/osmocom/mslookup/mdns_rfc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,113 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/endian.h>
 | 
				
			||||||
 | 
					#include <osmocom/mslookup/mdns.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RFC 1035 2.3.4 */
 | 
				
			||||||
 | 
					#define OSMO_MDNS_RFC_MAX_NAME_LEN 255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RFC 1035 3.3 <character-string> */
 | 
				
			||||||
 | 
					#define OSMO_MDNS_RFC_MAX_CHARACTER_STRING_LEN 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum osmo_mdns_rfc_record_type {
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_RECORD_TYPE_UNKNOWN = 0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RFC 1035 3.2.2 */
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_RECORD_TYPE_A = 1, /* IPv4 address */
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_RECORD_TYPE_TXT = 16, /* Text strings */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RFC 3596 2.1 */
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_RECORD_TYPE_AAAA = 28, /* IPv6 address */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RFC 1035 3.2.3 */
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_RECORD_TYPE_ALL = 255, /* Request only: ask for all */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum osmo_mdns_rfc_class {
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_CLASS_UNKNOWN = 0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RFC 1035 3.2.4 */
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_CLASS_IN = 1, /* Internet and IP networks */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* RFC 1035 3.2.5 */
 | 
				
			||||||
 | 
						OSMO_MDNS_RFC_CLASS_ALL = 255, /* Request only: ask for all */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RFC 1035 4.1.1 */
 | 
				
			||||||
 | 
					struct osmo_mdns_rfc_header {
 | 
				
			||||||
 | 
					#if OSMO_IS_LITTLE_ENDIAN
 | 
				
			||||||
 | 
						uint16_t id;
 | 
				
			||||||
 | 
						uint8_t rd:1,
 | 
				
			||||||
 | 
							tc:1,
 | 
				
			||||||
 | 
							aa:1,
 | 
				
			||||||
 | 
							opcode:4,
 | 
				
			||||||
 | 
							qr:1; /* QR (0: query, 1: response) */
 | 
				
			||||||
 | 
						uint8_t rcode:4,
 | 
				
			||||||
 | 
							z:3,
 | 
				
			||||||
 | 
							ra:1;
 | 
				
			||||||
 | 
						uint16_t qdcount; /* Number of questions */
 | 
				
			||||||
 | 
						uint16_t ancount; /* Number of answers */
 | 
				
			||||||
 | 
						uint16_t nscount; /* Number of authority records */
 | 
				
			||||||
 | 
						uint16_t arcount; /* Number of additional records */
 | 
				
			||||||
 | 
					#elif OSMO_IS_BIG_ENDIAN
 | 
				
			||||||
 | 
					/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
 | 
				
			||||||
 | 
						uint16_t id;
 | 
				
			||||||
 | 
						uint8_t qr:1, opcode:4, aa:1, tc:1, rd:1;
 | 
				
			||||||
 | 
						uint8_t ra:1, z:3, rcode:4;
 | 
				
			||||||
 | 
						uint16_t qdcount;
 | 
				
			||||||
 | 
						uint16_t ancount;
 | 
				
			||||||
 | 
						uint16_t nscount;
 | 
				
			||||||
 | 
						uint16_t arcount;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					} __attribute__ ((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RFC 1035 4.1.2 */
 | 
				
			||||||
 | 
					struct osmo_mdns_rfc_question {
 | 
				
			||||||
 | 
						char *domain; /* Domain to be encoded as qname (e.g. "gsup.hlr.1234567.imsi") */
 | 
				
			||||||
 | 
						enum osmo_mdns_rfc_record_type qtype;
 | 
				
			||||||
 | 
						enum osmo_mdns_rfc_class qclass;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* RFC 1035 4.1.3 */
 | 
				
			||||||
 | 
					struct osmo_mdns_rfc_record {
 | 
				
			||||||
 | 
						char *domain; /* Domain to be encoded as name (e.g. "gsup.hlr.1234567.imsi") */
 | 
				
			||||||
 | 
						enum osmo_mdns_rfc_record_type type;
 | 
				
			||||||
 | 
						enum osmo_mdns_rfc_class class;
 | 
				
			||||||
 | 
						uint32_t ttl;
 | 
				
			||||||
 | 
						uint16_t rdlength;
 | 
				
			||||||
 | 
						uint8_t *rdata;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char *osmo_mdns_rfc_qname_encode(void *ctx, const char *domain);
 | 
				
			||||||
 | 
					char *osmo_mdns_rfc_qname_decode(void *ctx, const char *qname, size_t qname_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_mdns_rfc_header_encode(struct msgb *msg, const struct osmo_mdns_rfc_header *hdr);
 | 
				
			||||||
 | 
					int osmo_mdns_rfc_header_decode(const uint8_t *data, size_t data_len, struct osmo_mdns_rfc_header *hdr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_mdns_rfc_question_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_question *qst);
 | 
				
			||||||
 | 
					struct osmo_mdns_rfc_question *osmo_mdns_rfc_question_decode(void *ctx, const uint8_t *data, size_t data_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_mdns_rfc_record_encode(void *ctx, struct msgb *msg, const struct osmo_mdns_rfc_record *rec);
 | 
				
			||||||
 | 
					struct osmo_mdns_rfc_record *osmo_mdns_rfc_record_decode(void *ctx, const uint8_t *data, size_t data_len,
 | 
				
			||||||
 | 
												 size_t *record_len);
 | 
				
			||||||
							
								
								
									
										33
									
								
								include/osmocom/mslookup/mdns_sock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								include/osmocom/mslookup/mdns_sock.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <netdb.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/msgb.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/select.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mdns_sock {
 | 
				
			||||||
 | 
						struct osmo_fd osmo_fd;
 | 
				
			||||||
 | 
						struct addrinfo *ai;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mdns_sock *osmo_mdns_sock_init(void *ctx, const char *ip, unsigned int port,
 | 
				
			||||||
 | 
										   int (*cb)(struct osmo_fd *fd, unsigned int what),
 | 
				
			||||||
 | 
										   void *data, unsigned int priv_nr);
 | 
				
			||||||
 | 
					int osmo_mdns_sock_send(const struct osmo_mdns_sock *mdns_sock, struct msgb *msg);
 | 
				
			||||||
 | 
					void osmo_mdns_sock_cleanup(struct osmo_mdns_sock *mdns_sock);
 | 
				
			||||||
							
								
								
									
										121
									
								
								include/osmocom/mslookup/mslookup.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								include/osmocom/mslookup/mslookup.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! \defgroup mslookup Distributed GSM: finding subscribers
 | 
				
			||||||
 | 
					 *  @{
 | 
				
			||||||
 | 
					 * \file mslookup.h
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/sockaddr_str.h>
 | 
				
			||||||
 | 
					#include <osmocom/gsm/protocol/gsm_23_003.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OSMO_MSLOOKUP_SERVICE_MAXLEN 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool osmo_mslookup_service_valid(const char *service);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum osmo_mslookup_id_type {
 | 
				
			||||||
 | 
						OSMO_MSLOOKUP_ID_NONE = 0,
 | 
				
			||||||
 | 
						OSMO_MSLOOKUP_ID_IMSI,
 | 
				
			||||||
 | 
						OSMO_MSLOOKUP_ID_MSISDN,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string osmo_mslookup_id_type_names[];
 | 
				
			||||||
 | 
					static inline const char *osmo_mslookup_id_type_name(enum osmo_mslookup_id_type val)
 | 
				
			||||||
 | 
					{ return get_value_string(osmo_mslookup_id_type_names, val); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_id {
 | 
				
			||||||
 | 
						enum osmo_mslookup_id_type type;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							char imsi[GSM23003_IMSI_MAX_DIGITS+1];
 | 
				
			||||||
 | 
							char msisdn[GSM23003_MSISDN_MAX_DIGITS+1];
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_mslookup_id_cmp(const struct osmo_mslookup_id *a, const struct osmo_mslookup_id *b);
 | 
				
			||||||
 | 
					bool osmo_mslookup_id_valid(const struct osmo_mslookup_id *id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum osmo_mslookup_result_code {
 | 
				
			||||||
 | 
						OSMO_MSLOOKUP_RC_NONE = 0,
 | 
				
			||||||
 | 
						/*! An intermediate valid result. The request is still open for more results. */
 | 
				
			||||||
 | 
						OSMO_MSLOOKUP_RC_RESULT,
 | 
				
			||||||
 | 
						/*! Returned when the final request timeout has elapsed without results. */
 | 
				
			||||||
 | 
						OSMO_MSLOOKUP_RC_NOT_FOUND,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const struct value_string osmo_mslookup_result_code_names[];
 | 
				
			||||||
 | 
					static inline const char *osmo_mslookup_result_code_name(enum osmo_mslookup_result_code val)
 | 
				
			||||||
 | 
					{ return get_value_string(osmo_mslookup_result_code_names, val); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Information to request from a lookup. */
 | 
				
			||||||
 | 
					struct osmo_mslookup_query {
 | 
				
			||||||
 | 
						/*! Which service to request, by freely invented names. For service name conventions (for voice, SMS, HLR,...),
 | 
				
			||||||
 | 
						 * refer to the OsmoHLR user's manual http://ftp.osmocom.org/docs/latest/osmohlr-usermanual.pdf */
 | 
				
			||||||
 | 
						char service[OSMO_MSLOOKUP_SERVICE_MAXLEN + 1];
 | 
				
			||||||
 | 
						/*! IMSI or MSISDN to look up. */
 | 
				
			||||||
 | 
						struct osmo_mslookup_id id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Caller provided private data, if desired. */
 | 
				
			||||||
 | 
						void *priv;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Result data as passed back to a lookup client that invoked an osmo_mslookup_client_request. */
 | 
				
			||||||
 | 
					struct osmo_mslookup_result {
 | 
				
			||||||
 | 
						/*! Outcome of the request. */
 | 
				
			||||||
 | 
						enum osmo_mslookup_result_code rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! IP address and port to reach the given service via IPv4, if any. */
 | 
				
			||||||
 | 
						struct osmo_sockaddr_str host_v4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! IP address and port to reach the given service via IPv6, if any. */
 | 
				
			||||||
 | 
						struct osmo_sockaddr_str host_v6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! How long ago the service last verified presence of the subscriber, in seconds, or zero if the presence is
 | 
				
			||||||
 | 
						 * invariable (like the home HLR record for an IMSI).
 | 
				
			||||||
 | 
						 * If a subscriber has recently moved to a different location, we get multiple replies and want to choose the
 | 
				
			||||||
 | 
						 * most recent one. If this were a timestamp, firstly the time zones would need to be taken care of.
 | 
				
			||||||
 | 
						 * Even if we choose UTC, a service provider with an inaccurate date/time would end up affecting the result.
 | 
				
			||||||
 | 
						 * The least susceptible to configuration errors or difference in local and remote clock is a value that
 | 
				
			||||||
 | 
						 * indicates the actual age of the record in seconds. The time that the lookup query took to be answered should
 | 
				
			||||||
 | 
						 * be neglectable here, since we would typically wait one second (or very few seconds) for lookup replies,
 | 
				
			||||||
 | 
						 * while typical Location Updating periods are in the range of 15 minutes. */
 | 
				
			||||||
 | 
						uint32_t age;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Whether this is the last result returned for this request. */
 | 
				
			||||||
 | 
						bool last;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int osmo_mslookup_query_init_from_domain_str(struct osmo_mslookup_query *q, const char *domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t osmo_mslookup_id_name_buf(char *buf, size_t buflen, const struct osmo_mslookup_id *id);
 | 
				
			||||||
 | 
					char *osmo_mslookup_id_name_c(void *ctx, const struct osmo_mslookup_id *id);
 | 
				
			||||||
 | 
					char *osmo_mslookup_id_name_b(char *buf, size_t buflen, const struct osmo_mslookup_id *id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t osmo_mslookup_result_to_str_buf(char *buf, size_t buflen,
 | 
				
			||||||
 | 
									     const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									     const struct osmo_mslookup_result *result);
 | 
				
			||||||
 | 
					char *osmo_mslookup_result_name_c(void *ctx,
 | 
				
			||||||
 | 
									  const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									  const struct osmo_mslookup_result *result);
 | 
				
			||||||
 | 
					char *osmo_mslookup_result_name_b(char *buf, size_t buflen,
 | 
				
			||||||
 | 
									  const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									  const struct osmo_mslookup_result *result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @} */
 | 
				
			||||||
							
								
								
									
										132
									
								
								include/osmocom/mslookup/mslookup_client.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								include/osmocom/mslookup/mslookup_client.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/core/linuxlist.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/timer.h>
 | 
				
			||||||
 | 
					#include <osmocom/core/sockaddr_str.h>
 | 
				
			||||||
 | 
					#include <osmocom/mslookup/mslookup.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_client;
 | 
				
			||||||
 | 
					struct osmo_mslookup_result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void (*osmo_mslookup_cb_t)(struct osmo_mslookup_client *client,
 | 
				
			||||||
 | 
									   uint32_t request_handle,
 | 
				
			||||||
 | 
									   const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									   const struct osmo_mslookup_result *result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! This handling information is passed along with a lookup request.
 | 
				
			||||||
 | 
					 * It tells the osmo_mslookup_client layer how to handle responses received from various mslookup methods (at the time
 | 
				
			||||||
 | 
					 * of writing only mDNS exists as a method, but the intention is to easily allow adding other methods in the future).
 | 
				
			||||||
 | 
					 * This query handling info is not seen by the individual method implementations, to clarify that it is the
 | 
				
			||||||
 | 
					 * osmo_mslookup_client layer that takes care of these details. */
 | 
				
			||||||
 | 
					struct osmo_mslookup_query_handling {
 | 
				
			||||||
 | 
						/*! Wait at least this long before returning any results.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * If nonzero, result_cb will be called as soon as this delay has elapsed, either with the so far youngest age
 | 
				
			||||||
 | 
						 * result, or with a "not found yet" result. After this delay has elapsed, receiving results will continue
 | 
				
			||||||
 | 
						 * until result_timeout_milliseconds has elapsed.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * If zero, responses are fed to the result_cb right from the start, every time a younger aged result than
 | 
				
			||||||
 | 
						 * before comes in.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * If a result with age == 0 is received, min_wait_milliseconds is ignored, the result is returned immediately
 | 
				
			||||||
 | 
						 * and listening for responses ends.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Rationale: If a subscriber has recently moved between sites, multiple results will arrive, and the youngest
 | 
				
			||||||
 | 
						 * age wins. It can make sense to wait a minimum time for responses before determining the winning result.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * However, if no result or no valid result has arrived within a short period, the subscriber may be at a site
 | 
				
			||||||
 | 
						 * that is far away or that is currently experiencing high latency. It is thus a good safety net to still
 | 
				
			||||||
 | 
						 * receive results for an extended period of time.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * For some services, it is possible to establish links to every received result, and whichever link succeeds
 | 
				
			||||||
 | 
						 * will be used (for example for SIP calls: first to pick up the call gets connected, the others are dropped
 | 
				
			||||||
 | 
						 * silently).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						uint32_t min_wait_milliseconds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Total time in milliseconds to listen for lookup responses.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * When this timeout elapses, osmo_mslookup_client_request_cancel() is called implicitly; Manually invoking
 | 
				
			||||||
 | 
						 * osmo_mslookup_client_request_cancel() after result_timeout_milliseconds has elapsed is not necessary, but is
 | 
				
			||||||
 | 
						 * still safe to do anyway.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * If zero, min_wait_milliseconds is also used as result_timeout_milliseconds; if that is also zero, a default
 | 
				
			||||||
 | 
						 * timeout value is used.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * If result_timeout_milliseconds <= min_wait_milliseconds, then min_wait_milliseconds is used as
 | 
				
			||||||
 | 
						 * result_timeout_milliseconds, i.e. the timeout triggers as soon as min_wait_milliseconds hits.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * osmo_mslookup_client_request_cancel() can be called any time to end the request.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						uint32_t result_timeout_milliseconds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Invoked every time a result with a younger age than the previous result has arrived.
 | 
				
			||||||
 | 
						 * To stop receiving results before result_timeout_milliseconds has elapsed, call
 | 
				
			||||||
 | 
						 * osmo_mslookup_client_request_cancel().
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						osmo_mslookup_cb_t result_cb;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t osmo_mslookup_client_request(struct osmo_mslookup_client *client,
 | 
				
			||||||
 | 
									      const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
									      const struct osmo_mslookup_query_handling *handling);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_mslookup_client_request_cancel(struct osmo_mslookup_client *client, uint32_t request_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_client *osmo_mslookup_client_new(void *ctx);
 | 
				
			||||||
 | 
					bool osmo_mslookup_client_active(struct osmo_mslookup_client *client);
 | 
				
			||||||
 | 
					void osmo_mslookup_client_free(struct osmo_mslookup_client *client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! Describe a specific mslookup client method implementation. This struct is only useful for a lookup method
 | 
				
			||||||
 | 
					 * implementation to add itself to an osmo_mslookup_client, see for example osmo_mslookup_client_add_mdns(). */
 | 
				
			||||||
 | 
					struct osmo_mslookup_client_method {
 | 
				
			||||||
 | 
						struct llist_head entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Human readable name of this lookup method. */
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Private data for the lookup method implementation. */
 | 
				
			||||||
 | 
						void *priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Backpointer to the client this method is added to. */
 | 
				
			||||||
 | 
						struct osmo_mslookup_client *client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! Launch a lookup query. Called from osmo_mslookup_client_request().
 | 
				
			||||||
 | 
						 * The implementation returns results by calling osmo_mslookup_client_rx_result(). */
 | 
				
			||||||
 | 
						void (*request)(struct osmo_mslookup_client_method *method,
 | 
				
			||||||
 | 
								const struct osmo_mslookup_query *query,
 | 
				
			||||||
 | 
								uint32_t request_handle);
 | 
				
			||||||
 | 
						/*! End a lookup query. Called from osmo_mslookup_client_request_cancel(). It is guaranteed to be called
 | 
				
			||||||
 | 
						 * exactly once per above request() invocation. (The API user is required to invoke
 | 
				
			||||||
 | 
						 * osmo_mslookup_client_request_cancel() exactly once per osmo_mslookup_client_request().) */
 | 
				
			||||||
 | 
						void (*request_cleanup)(struct osmo_mslookup_client_method *method,
 | 
				
			||||||
 | 
									uint32_t request_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*! The mslookup_client is removing this method, clean up all open requests, lists and allocations. */
 | 
				
			||||||
 | 
						void (*destruct)(struct osmo_mslookup_client_method *method);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void osmo_mslookup_client_method_add(struct osmo_mslookup_client *client,
 | 
				
			||||||
 | 
									     struct osmo_mslookup_client_method *method);
 | 
				
			||||||
 | 
					bool osmo_mslookup_client_method_del(struct osmo_mslookup_client *client,
 | 
				
			||||||
 | 
									     struct osmo_mslookup_client_method *method);
 | 
				
			||||||
 | 
					void osmo_mslookup_client_rx_result(struct osmo_mslookup_client *client, uint32_t request_handle,
 | 
				
			||||||
 | 
									    const struct osmo_mslookup_result *result);
 | 
				
			||||||
							
								
								
									
										34
									
								
								include/osmocom/mslookup/mslookup_client_fake.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/osmocom/mslookup/mslookup_client_fake.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! MS lookup fake API for testing purposes. */
 | 
				
			||||||
 | 
					#include <osmocom/mslookup/mslookup_client.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_fake_response {
 | 
				
			||||||
 | 
						struct timeval time_to_reply;
 | 
				
			||||||
 | 
						struct osmo_mslookup_id for_id;
 | 
				
			||||||
 | 
						const char *for_service;
 | 
				
			||||||
 | 
						struct osmo_mslookup_result result;
 | 
				
			||||||
 | 
						bool sent;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_client_method *osmo_mslookup_client_add_fake(struct osmo_mslookup_client *client,
 | 
				
			||||||
 | 
													  struct osmo_mslookup_fake_response *responses,
 | 
				
			||||||
 | 
													  size_t responses_len);
 | 
				
			||||||
							
								
								
									
										38
									
								
								include/osmocom/mslookup/mslookup_client_mdns.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								include/osmocom/mslookup/mslookup_client_mdns.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_client;
 | 
				
			||||||
 | 
					struct osmo_mslookup_client_method;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! MS Lookup mDNS server bind default IP. Taken from the Administratevly Scoped block, particularly the Organizational
 | 
				
			||||||
 | 
					 * Scoped range, https://tools.ietf.org/html/rfc2365 . */
 | 
				
			||||||
 | 
					#define OSMO_MSLOOKUP_MDNS_IP4 "239.192.23.42"
 | 
				
			||||||
 | 
					#define OSMO_MSLOOKUP_MDNS_IP6 "ff08::23:42" // <-- TODO: sane?
 | 
				
			||||||
 | 
					#define OSMO_MSLOOKUP_MDNS_PORT 4266
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct osmo_mslookup_client_method *osmo_mslookup_client_add_mdns(struct osmo_mslookup_client *client, const char *ip,
 | 
				
			||||||
 | 
													  uint16_t port, int initial_packet_id,
 | 
				
			||||||
 | 
													  const char *domain_suffix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct osmo_sockaddr_str *osmo_mslookup_client_method_mdns_get_bind_addr(struct osmo_mslookup_client_method *dns_method);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char *osmo_mslookup_client_method_mdns_get_domain_suffix(struct osmo_mslookup_client_method *dns_method);
 | 
				
			||||||
							
								
								
									
										11
									
								
								libosmo-gsup-client.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								libosmo-gsup-client.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					prefix=@prefix@
 | 
				
			||||||
 | 
					exec_prefix=@exec_prefix@
 | 
				
			||||||
 | 
					libdir=@libdir@
 | 
				
			||||||
 | 
					includedir=@includedir@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name: Osmocom GSUP Client Library
 | 
				
			||||||
 | 
					Description: C Utility Library
 | 
				
			||||||
 | 
					Version: @VERSION@
 | 
				
			||||||
 | 
					Libs: -L${libdir} -losmo-gsup-client
 | 
				
			||||||
 | 
					Cflags: -I${includedir}/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								libosmo-mslookup.pc.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								libosmo-mslookup.pc.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					prefix=@prefix@
 | 
				
			||||||
 | 
					exec_prefix=@exec_prefix@
 | 
				
			||||||
 | 
					libdir=@libdir@
 | 
				
			||||||
 | 
					includedir=@includedir@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name: Osmocom MS Lookup Library
 | 
				
			||||||
 | 
					Description: C Utility Library
 | 
				
			||||||
 | 
					Version: @VERSION@
 | 
				
			||||||
 | 
					Libs: -L${libdir} @TALLOC_LIBS@ -losmogsm -losmo-mslookup -losmocore
 | 
				
			||||||
 | 
					Cflags: -I${includedir}/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								sql/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								sql/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					EXTRA_DIST = \
 | 
				
			||||||
 | 
						hlr_data.sql \
 | 
				
			||||||
 | 
						hlr.sql \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sqldir = $(docdir)/sql
 | 
				
			||||||
 | 
					sql_DATA = $(srcdir)/hlr.sql $(srcdir)/hlr_data.sql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					install-data-local:
 | 
				
			||||||
 | 
						$(MKDIR_P) $(DESTDIR)$(localstatedir)/lib/osmocom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uninstall-hook:
 | 
				
			||||||
 | 
						rm -rf $(DESTDIR)$(localstatedir)/lib/osmocom
 | 
				
			||||||
							
								
								
									
										60
									
								
								sql/hlr.sql
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								sql/hlr.sql
									
									
									
									
									
								
							@@ -1,17 +1,18 @@
 | 
				
			|||||||
--modelled roughly after TS 23.008 version 13.3.0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE subscriber (
 | 
					CREATE TABLE subscriber (
 | 
				
			||||||
 | 
					-- OsmoHLR's DB scheme is modelled roughly after TS 23.008 version 13.3.0
 | 
				
			||||||
	id		INTEGER PRIMARY KEY,
 | 
						id		INTEGER PRIMARY KEY,
 | 
				
			||||||
	-- Chapter 2.1.1.1
 | 
						-- Chapter 2.1.1.1
 | 
				
			||||||
	imsi		VARCHAR(15) NOT NULL,
 | 
						imsi		VARCHAR(15) UNIQUE NOT NULL,
 | 
				
			||||||
	-- Chapter 2.1.2
 | 
						-- Chapter 2.1.2
 | 
				
			||||||
	msisdn		VARCHAR(15),
 | 
						msisdn		VARCHAR(15) UNIQUE,
 | 
				
			||||||
	-- Chapter 2.2.3: Most recent / current IMEI
 | 
						-- Chapter 2.2.3: Most recent / current IMEISV
 | 
				
			||||||
	imeisv		VARCHAR,
 | 
						imeisv		VARCHAR,
 | 
				
			||||||
 | 
						-- Chapter 2.1.9: Most recent / current IMEI
 | 
				
			||||||
 | 
						imei		VARCHAR(14),
 | 
				
			||||||
	-- Chapter 2.4.5
 | 
						-- Chapter 2.4.5
 | 
				
			||||||
	vlr_number	VARCHAR(15),
 | 
						vlr_number	VARCHAR(15),
 | 
				
			||||||
	-- Chapter 2.4.6
 | 
						-- Chapter 2.4.6
 | 
				
			||||||
	hlr_number	VARCHAR(15),
 | 
						msc_number	VARCHAR(15),
 | 
				
			||||||
	-- Chapter 2.4.8.1
 | 
						-- Chapter 2.4.8.1
 | 
				
			||||||
	sgsn_number	VARCHAR(15),
 | 
						sgsn_number	VARCHAR(15),
 | 
				
			||||||
	-- Chapter 2.13.10
 | 
						-- Chapter 2.13.10
 | 
				
			||||||
@@ -37,7 +38,17 @@ CREATE TABLE subscriber (
 | 
				
			|||||||
	-- Chapter 2.7.5
 | 
						-- Chapter 2.7.5
 | 
				
			||||||
	ms_purged_cs	BOOLEAN NOT NULL DEFAULT 0,
 | 
						ms_purged_cs	BOOLEAN NOT NULL DEFAULT 0,
 | 
				
			||||||
	-- Chapter 2.7.6
 | 
						-- Chapter 2.7.6
 | 
				
			||||||
	ms_purged_ps	BOOLEAN NOT NULL DEFAULT 0
 | 
						ms_purged_ps	BOOLEAN NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						-- Timestamp of last location update seen from subscriber
 | 
				
			||||||
 | 
						-- The value is a string which encodes a UTC timestamp in granularity of seconds.
 | 
				
			||||||
 | 
						last_lu_seen TIMESTAMP default NULL,
 | 
				
			||||||
 | 
						last_lu_seen_ps TIMESTAMP default NULL,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						-- When a LU was received via a proxy, that proxy's hlr_number is stored here,
 | 
				
			||||||
 | 
						-- while vlr_number reflects the MSC on the far side of that proxy.
 | 
				
			||||||
 | 
						vlr_via_proxy	VARCHAR,
 | 
				
			||||||
 | 
						sgsn_via_proxy	VARCHAR
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE subscriber_apn (
 | 
					CREATE TABLE subscriber_apn (
 | 
				
			||||||
@@ -45,26 +56,39 @@ CREATE TABLE subscriber_apn (
 | 
				
			|||||||
	apn		VARCHAR(256) NOT NULL
 | 
						apn		VARCHAR(256) NOT NULL
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Chapter 2.1.3
 | 
					 | 
				
			||||||
CREATE TABLE subscriber_multi_msisdn (
 | 
					CREATE TABLE subscriber_multi_msisdn (
 | 
				
			||||||
 | 
					-- Chapter 2.1.3
 | 
				
			||||||
	subscriber_id	INTEGER,		-- subscriber.id
 | 
						subscriber_id	INTEGER,		-- subscriber.id
 | 
				
			||||||
	msisdn		VARCHAR(15) NOT NULL
 | 
						msisdn		VARCHAR(15) NOT NULL
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE auc_2g (
 | 
					CREATE TABLE auc_2g (
 | 
				
			||||||
	subscriber_id	INTEGER PRIMARY KEY,	-- subscriber.id
 | 
						subscriber_id	INTEGER PRIMARY KEY,	-- subscriber.id
 | 
				
			||||||
	algo_id_2g	INTEGER NOT NULL,
 | 
						algo_id_2g	INTEGER NOT NULL,	-- enum osmo_auth_algo value
 | 
				
			||||||
	ki		VARCHAR NOT NULL
 | 
						ki		VARCHAR(32) NOT NULL	-- hex string: subscriber's secret key (128bit)
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE auc_3g (
 | 
					CREATE TABLE auc_3g (
 | 
				
			||||||
	subscriber_id	INTEGER PRIMARY KEY,	-- subscrbier.id
 | 
						subscriber_id	INTEGER PRIMARY KEY,	-- subscriber.id
 | 
				
			||||||
	algo_id_3g	INTEGER NOT NULL,
 | 
						algo_id_3g	INTEGER NOT NULL,	-- enum osmo_auth_algo value
 | 
				
			||||||
	k		INTEGER NOT NULL,
 | 
						k		VARCHAR(32) NOT NULL,	-- hex string: subscriber's secret key (128bit)
 | 
				
			||||||
	op		VARCHAR,
 | 
						op		VARCHAR(32),		-- hex string: operator's secret key (128bit)
 | 
				
			||||||
	opc		VARCHAR,
 | 
						opc		VARCHAR(32),		-- hex string: derived from OP and K (128bit)
 | 
				
			||||||
	sqn		INTEGER
 | 
						sqn		INTEGER NOT NULL DEFAULT 0,	-- sequence number of key usage
 | 
				
			||||||
 | 
						-- nr of index bits at lower SQN end
 | 
				
			||||||
 | 
						ind_bitlen	INTEGER NOT NULL DEFAULT 5
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_subscr_imsi ON subscriber (imsi);
 | 
					CREATE TABLE ind (
 | 
				
			||||||
-- SELECT algo_id_2g, ki, algo_id_3g, k, op, opc, sqn FROM subscriber LEFT JOIN auc_2g ON auc_2g.subscriber_id = subscriber.id LEFT JOIN auc_3g ON auc_3g.subscriber_id = subscriber.id WHERE imsi = ?
 | 
						-- 3G auth IND pool to be used for this VLR
 | 
				
			||||||
 | 
						ind     INTEGER PRIMARY KEY,
 | 
				
			||||||
 | 
						-- VLR identification, usually the GSUP source_name
 | 
				
			||||||
 | 
						vlr     TEXT NOT NULL,
 | 
				
			||||||
 | 
						UNIQUE (vlr)
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Set HLR database schema version number
 | 
				
			||||||
 | 
					-- Note: This constant is currently duplicated in src/db.c and must be kept in sync!
 | 
				
			||||||
 | 
					PRAGMA user_version = 6;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,9 @@ INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki) VALUES (1, 1, '00010203040506
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
-- 3G only subscriber
 | 
					-- 3G only subscriber
 | 
				
			||||||
INSERT INTO subscriber (id, imsi) VALUES (2, '901990000000002');
 | 
					INSERT INTO subscriber (id, imsi) VALUES (2, '901990000000002');
 | 
				
			||||||
INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, op, sqn) VALUES (2, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 0);
 | 
					INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, opc, sqn) VALUES (2, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- 2G + 3G subscriber
 | 
					-- 2G + 3G subscriber
 | 
				
			||||||
INSERT INTO subscriber (id, imsi) VALUES (3, '901990000000003');
 | 
					INSERT INTO subscriber (id, imsi) VALUES (3, '901990000000003');
 | 
				
			||||||
INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki) VALUES (3, 1, '000102030405060708090a0b0c0d0e0f');
 | 
					INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki) VALUES (3, 1, '000102030405060708090a0b0c0d0e0f');
 | 
				
			||||||
INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, op, sqn) VALUES (3, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 0);
 | 
					INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, opc, sqn) VALUES (3, 5, '000102030405060708090a0b0c0d0e0f', '101112131415161718191a1b1c1d1e1f', 0);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								src/Makefile
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/Makefile
									
									
									
									
									
								
							@@ -1,18 +0,0 @@
 | 
				
			|||||||
LDFLAGS += -losmocore -losmogsm -losmoabis -lsqlite3 -ltalloc
 | 
					 | 
				
			||||||
CFLAGS += -g -Wall
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
OBJS = auc.o db.o db_auc.o db_hlr.o logging.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
all: db_test hlr
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
db_test: db_test.o rand_fake.o $(OBJS)
 | 
					 | 
				
			||||||
	$(CC) -o $@ $^ $(LDFLAGS)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
hlr: hlr.o gsup_server.o gsup_router.o rand_urandom.o $(OBJS)
 | 
					 | 
				
			||||||
	$(CC) -o $@ $^ $(LDFLAGS)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%.o: %.c
 | 
					 | 
				
			||||||
	$(CC) $(CFLAGS) -o $@ -c $^
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
clean:
 | 
					 | 
				
			||||||
	rm -f *.o db_test
 | 
					 | 
				
			||||||
							
								
								
									
										118
									
								
								src/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								src/Makefile.am
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
				
			|||||||
 | 
					SUBDIRS = \
 | 
				
			||||||
 | 
						gsupclient \
 | 
				
			||||||
 | 
						mslookup \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AM_CFLAGS = \
 | 
				
			||||||
 | 
						-Wall \
 | 
				
			||||||
 | 
						$(LIBOSMOCORE_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOGSM_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOVTY_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOCTRL_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOMSLOOKUP_CFLAGS) \
 | 
				
			||||||
 | 
						$(LIBOSMOABIS_CFLAGS) \
 | 
				
			||||||
 | 
						$(SQLITE3_CFLAGS) \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AM_CPPFLAGS = -I$(top_srcdir)/include \
 | 
				
			||||||
 | 
						-I$(top_builddir)/include \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_DIST = \
 | 
				
			||||||
 | 
						populate_hlr_db.pl \
 | 
				
			||||||
 | 
						db_sql2c.sed \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BUILT_SOURCES = \
 | 
				
			||||||
 | 
						db_bootstrap.h \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					CLEANFILES = $(BUILT_SOURCES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					noinst_HEADERS = \
 | 
				
			||||||
 | 
						db_bootstrap.h \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bin_PROGRAMS = \
 | 
				
			||||||
 | 
						osmo-hlr \
 | 
				
			||||||
 | 
						osmo-hlr-db-tool \
 | 
				
			||||||
 | 
						osmo-euse-demo \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo_hlr_SOURCES = \
 | 
				
			||||||
 | 
						auc.c \
 | 
				
			||||||
 | 
						ctrl.c \
 | 
				
			||||||
 | 
						db.c \
 | 
				
			||||||
 | 
						db_auc.c \
 | 
				
			||||||
 | 
						db_hlr.c \
 | 
				
			||||||
 | 
						gsup_router.c \
 | 
				
			||||||
 | 
						gsup_server.c \
 | 
				
			||||||
 | 
						hlr.c \
 | 
				
			||||||
 | 
						logging.c \
 | 
				
			||||||
 | 
						rand_urandom.c \
 | 
				
			||||||
 | 
						hlr_vty.c \
 | 
				
			||||||
 | 
						hlr_vty_subscr.c \
 | 
				
			||||||
 | 
						gsup_send.c \
 | 
				
			||||||
 | 
						hlr_ussd.c \
 | 
				
			||||||
 | 
						proxy.c \
 | 
				
			||||||
 | 
						dgsm.c \
 | 
				
			||||||
 | 
						remote_hlr.c \
 | 
				
			||||||
 | 
						lu_fsm.c \
 | 
				
			||||||
 | 
						timestamp.c \
 | 
				
			||||||
 | 
						mslookup_server.c \
 | 
				
			||||||
 | 
						mslookup_server_mdns.c \
 | 
				
			||||||
 | 
						dgsm_vty.c \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo_hlr_LDADD = \
 | 
				
			||||||
 | 
						$(top_builddir)/src/gsupclient/libosmo-gsup-client.la \
 | 
				
			||||||
 | 
						$(top_builddir)/src/mslookup/libosmo-mslookup.la \
 | 
				
			||||||
 | 
						$(LIBOSMOCORE_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOGSM_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOVTY_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOCTRL_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOMSLOOKUP_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOABIS_LIBS) \
 | 
				
			||||||
 | 
						$(SQLITE3_LIBS) \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo_hlr_db_tool_SOURCES = \
 | 
				
			||||||
 | 
						hlr_db_tool.c \
 | 
				
			||||||
 | 
						db.c \
 | 
				
			||||||
 | 
						db_hlr.c \
 | 
				
			||||||
 | 
						logging.c \
 | 
				
			||||||
 | 
						rand_urandom.c \
 | 
				
			||||||
 | 
						dbd_decode_binary.c \
 | 
				
			||||||
 | 
						$(srcdir)/gsupclient/cni_peer_id.c \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo_hlr_db_tool_LDADD = \
 | 
				
			||||||
 | 
						$(LIBOSMOCORE_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOGSM_LIBS) \
 | 
				
			||||||
 | 
						$(SQLITE3_LIBS) \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo_euse_demo_SOURCES = \
 | 
				
			||||||
 | 
						osmo-euse-demo.c \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					osmo_euse_demo_LDADD = \
 | 
				
			||||||
 | 
						$(top_builddir)/src/gsupclient/libosmo-gsup-client.la \
 | 
				
			||||||
 | 
						$(LIBOSMOCORE_LIBS) \
 | 
				
			||||||
 | 
						$(LIBOSMOGSM_LIBS) \
 | 
				
			||||||
 | 
						$(NULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if DB_SQLITE_DEBUG
 | 
				
			||||||
 | 
					osmo_hlr_SOURCES += db_debug.c
 | 
				
			||||||
 | 
					osmo_hlr_db_tool_SOURCES += db_debug.c
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOTSTRAP_SQL = $(top_srcdir)/sql/hlr.sql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					db_bootstrap.h: $(BOOTSTRAP_SQL) $(srcdir)/db_sql2c.sed
 | 
				
			||||||
 | 
						echo "/* DO NOT EDIT THIS FILE. It is generated from files in osmo-hlr.git/sql/ */" > "$@"
 | 
				
			||||||
 | 
						echo "#pragma once" >> "$@"
 | 
				
			||||||
 | 
						echo "static const char *stmt_bootstrap_sql[] = {" >> "$@"
 | 
				
			||||||
 | 
						cat "$(BOOTSTRAP_SQL)" \
 | 
				
			||||||
 | 
							| sed -f "$(srcdir)/db_sql2c.sed" \
 | 
				
			||||||
 | 
							>> "$@"
 | 
				
			||||||
 | 
						echo "};" >> "$@"
 | 
				
			||||||
							
								
								
									
										147
									
								
								src/auc.c
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								src/auc.c
									
									
									
									
									
								
							@@ -18,15 +18,19 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/core/utils.h>
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
#include <osmocom/crypt/auth.h>
 | 
					#include <osmocom/crypt/auth.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "logging.h"
 | 
					#include <osmocom/hlr/logging.h>
 | 
				
			||||||
#include "rand.h"
 | 
					#include <osmocom/hlr/rand.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define hexb(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
 | 
				
			||||||
 | 
					#define hex(buf,sz) osmo_hexdump_nospc((void*)buf, sz)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* compute given number of vectors using either aud2g or aud2g or a combination
 | 
					/* compute given number of vectors using either aud2g or aud2g or a combination
 | 
				
			||||||
 * of both.  Handles re-synchrnization if rand_auts and auts are set */
 | 
					 * of both.  Handles re-synchronization if rand_auts and auts are set */
 | 
				
			||||||
int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
 | 
					int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
 | 
				
			||||||
			struct osmo_sub_auth_data *aud2g,
 | 
								struct osmo_sub_auth_data *aud2g,
 | 
				
			||||||
			struct osmo_sub_auth_data *aud3g,
 | 
								struct osmo_sub_auth_data *aud3g,
 | 
				
			||||||
@@ -34,17 +38,71 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
	uint8_t rand[16];
 | 
						uint8_t rand[16];
 | 
				
			||||||
 | 
						struct osmo_auth_vector vtmp;
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (aud2g->algo == OSMO_AUTH_ALG_NONE)
 | 
						/* no need to iterate the log categories all the time */
 | 
				
			||||||
 | 
						int dbg = log_check_level(DAUC, LOGL_DEBUG);
 | 
				
			||||||
 | 
					#define DBGP(args ...) if (dbg) DEBUGP(DAUC, ##args)
 | 
				
			||||||
 | 
					#define DBGVB(member) DBGP("vector [%u]: " #member " = %s\n", \
 | 
				
			||||||
 | 
								   i, hexb(vec[i].member))
 | 
				
			||||||
 | 
					#define DBGVV(fmt, member) DBGP("vector [%u]: " #member " = " fmt "\n", \
 | 
				
			||||||
 | 
								        i, vec[i].member)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aud2g && (aud2g->algo == OSMO_AUTH_ALG_NONE
 | 
				
			||||||
 | 
							      || aud2g->type == OSMO_AUTH_TYPE_NONE))
 | 
				
			||||||
		aud2g = NULL;
 | 
							aud2g = NULL;
 | 
				
			||||||
	if (aud3g->algo == OSMO_AUTH_ALG_NONE)
 | 
						if (aud3g && (aud3g->algo == OSMO_AUTH_ALG_NONE
 | 
				
			||||||
 | 
							      || aud3g->type == OSMO_AUTH_TYPE_NONE))
 | 
				
			||||||
		aud3g = NULL;
 | 
							aud3g = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!aud2g && !aud3g)
 | 
						if (!aud2g && !aud3g) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "auc_compute_vectors() called"
 | 
				
			||||||
 | 
							     " with neither 2G nor 3G auth data available\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aud2g && aud2g->type != OSMO_AUTH_TYPE_GSM) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "auc_compute_vectors() called"
 | 
				
			||||||
 | 
							     " with non-2G auth data passed for aud2g arg\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aud3g && aud3g->type != OSMO_AUTH_TYPE_UMTS) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "auc_compute_vectors() called"
 | 
				
			||||||
 | 
							     " with non-3G auth data passed for aud3g arg\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((rand_auts != NULL) != (auts != NULL)) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "auc_compute_vectors() with only one"
 | 
				
			||||||
 | 
							     " of AUTS and AUTS_RAND given, need both or neither\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (auts && !aud3g) {
 | 
				
			||||||
 | 
							LOGP(DAUC, LOGL_ERROR, "auc_compute_vectors() with AUTS called"
 | 
				
			||||||
 | 
							     " but no 3G auth data passed\n");
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DBGP("Computing %d auth vector%s: %s%s\n",
 | 
				
			||||||
 | 
						     num_vec, num_vec == 1 ? "" : "s",
 | 
				
			||||||
 | 
						     aud3g? (aud2g? "3G + separate 2G"
 | 
				
			||||||
 | 
							     : "3G only (2G derived from 3G keys)")
 | 
				
			||||||
 | 
						     : "2G only",
 | 
				
			||||||
 | 
						     auts? ", with AUTS resync" : "");
 | 
				
			||||||
 | 
						if (aud3g) {
 | 
				
			||||||
 | 
							DBGP("3G: k = %s\n", hexb(aud3g->u.umts.k));
 | 
				
			||||||
 | 
							DBGP("3G: %s = %s\n",
 | 
				
			||||||
 | 
							     aud3g->u.umts.opc_is_op? "OP" : "opc",
 | 
				
			||||||
 | 
							     hexb(aud3g->u.umts.opc));
 | 
				
			||||||
 | 
							DBGP("3G: for sqn ind %u, previous sqn was %" PRIu64 "\n",
 | 
				
			||||||
 | 
							     aud3g->u.umts.ind, aud3g->u.umts.sqn);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (aud2g)
 | 
				
			||||||
 | 
							DBGP("2G: ki = %s\n", hexb(aud2g->u.gsm.ki));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* compute quintuples */
 | 
					 | 
				
			||||||
	for (i = 0; i < num_vec; i++) {
 | 
						for (i = 0; i < num_vec; i++) {
 | 
				
			||||||
		rc = rand_get(rand, sizeof(rand));
 | 
							rc = rand_get(rand, sizeof(rand));
 | 
				
			||||||
		if (rc != sizeof(rand)) {
 | 
							if (rc != sizeof(rand)) {
 | 
				
			||||||
@@ -52,43 +110,76 @@ int auc_compute_vectors(struct osmo_auth_vector *vec, unsigned int num_vec,
 | 
				
			|||||||
			     "bytes: rc=%d\n", sizeof(rand), rc);
 | 
								     "bytes: rc=%d\n", sizeof(rand), rc);
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							DBGP("vector [%u]: rand = %s\n", i, hexb(rand));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (aud2g && !aud3g) {
 | 
							if (aud3g) {
 | 
				
			||||||
			/* 2G only case: output directly to vec */
 | 
					 | 
				
			||||||
			rc = osmo_auth_gen_vec(vec+i, aud2g, rand);
 | 
					 | 
				
			||||||
			if (rc < 0) {
 | 
					 | 
				
			||||||
				LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
 | 
					 | 
				
			||||||
				     "generation: %d\n", rc);
 | 
					 | 
				
			||||||
				goto out;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else if (aud3g) {
 | 
					 | 
				
			||||||
			/* 3G or 3G + 2G case */
 | 
								/* 3G or 3G + 2G case */
 | 
				
			||||||
			if (rand_auts && auts)
 | 
					
 | 
				
			||||||
				rc = osmo_auth_gen_vec_auts(vec+i, aud3g,
 | 
								/* Do AUTS only for the first vector or we would use
 | 
				
			||||||
							    rand_auts,
 | 
								 * the same SQN for each following key. */
 | 
				
			||||||
							    auts, rand);
 | 
								if ((i == 0) && auts) {
 | 
				
			||||||
			else
 | 
									DBGP("vector [%u]: resync: auts = %s\n",
 | 
				
			||||||
 | 
									     i, hex(auts, 14));
 | 
				
			||||||
 | 
									DBGP("vector [%u]: resync: rand_auts = %s\n",
 | 
				
			||||||
 | 
									     i, hex(rand_auts, 16));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									rc = osmo_auth_gen_vec_auts(vec+i, aud3g, auts,
 | 
				
			||||||
 | 
												    rand_auts, rand);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				rc = osmo_auth_gen_vec(vec+i, aud3g, rand);
 | 
									rc = osmo_auth_gen_vec(vec+i, aud3g, rand);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			if (rc < 0) {
 | 
								if (rc < 0) {
 | 
				
			||||||
				LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
 | 
									LOGP(DAUC, LOGL_ERROR, "Error in 3G vector "
 | 
				
			||||||
				     "generation: %d\n", rc);
 | 
									     "generation: [%u]: rc = %d\n", i, rc);
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
								DBGP("vector [%u]: sqn = %" PRIu64 "\n",
 | 
				
			||||||
		if (aud2g && aud3g) {
 | 
								     i, aud3g->u.umts.sqn);
 | 
				
			||||||
			/* separate 2G + 3G case: patch 2G into 3G */
 | 
					
 | 
				
			||||||
			struct osmo_auth_vector vtmp;
 | 
								DBGVB(autn);
 | 
				
			||||||
 | 
								DBGVB(ck);
 | 
				
			||||||
 | 
								DBGVB(ik);
 | 
				
			||||||
 | 
								DBGVB(res);
 | 
				
			||||||
 | 
								DBGVV("%u", res_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!aud2g) {
 | 
				
			||||||
 | 
									/* use the 2G tokens from 3G keys */
 | 
				
			||||||
 | 
									DBGP("vector [%u]: deriving 2G from 3G\n", i);
 | 
				
			||||||
 | 
									DBGVB(kc);
 | 
				
			||||||
 | 
									DBGVB(sres);
 | 
				
			||||||
 | 
									DBGVV("0x%x", auth_types);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								/* calculate 2G separately */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								DBGP("vector [%u]: calculating 2G separately\n", i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			rc = osmo_auth_gen_vec(&vtmp, aud2g, rand);
 | 
								rc = osmo_auth_gen_vec(&vtmp, aud2g, rand);
 | 
				
			||||||
			if (rc < 0) {
 | 
								if (rc < 0) {
 | 
				
			||||||
				LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
 | 
									LOGP(DAUC, LOGL_ERROR, "Error in 2G vector"
 | 
				
			||||||
				     "generation: %d\n", rc);
 | 
									     "generation: [%u]: rc = %d\n", i, rc);
 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			memcpy(&vec[i].kc, vtmp.kc, sizeof(vec[i].kc));
 | 
								memcpy(&vec[i].kc, vtmp.kc, sizeof(vec[i].kc));
 | 
				
			||||||
			memcpy(&vec[i].sres, vtmp.sres, sizeof(vec[i].sres));
 | 
								memcpy(&vec[i].sres, vtmp.sres, sizeof(vec[i].sres));
 | 
				
			||||||
			vec[i].auth_types |= OSMO_AUTH_TYPE_GSM;
 | 
								vec[i].auth_types |= OSMO_AUTH_TYPE_GSM;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* 2G only case */
 | 
				
			||||||
 | 
								rc = osmo_auth_gen_vec(vec+i, aud2g, rand);
 | 
				
			||||||
 | 
								if (rc < 0) {
 | 
				
			||||||
 | 
									LOGP(DAUC, LOGL_ERROR, "Error in 2G vector "
 | 
				
			||||||
 | 
									     "generation: [%u]: rc = %d\n", i, rc);
 | 
				
			||||||
 | 
									goto out;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							DBGVB(kc);
 | 
				
			||||||
 | 
							DBGVB(sres);
 | 
				
			||||||
 | 
							DBGVV("0x%x", auth_types);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return i;
 | 
						return i;
 | 
				
			||||||
 | 
					#undef DBGVV
 | 
				
			||||||
 | 
					#undef DBGVB
 | 
				
			||||||
 | 
					#undef DBGP
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										787
									
								
								src/ctrl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										787
									
								
								src/ctrl.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,787 @@
 | 
				
			|||||||
 | 
					/* OsmoHLR Control Interface implementation */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Max Suraev <msuraev@sysmocom.de>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/gsm/gsm23003.h>
 | 
				
			||||||
 | 
					#include <osmocom/ctrl/ports.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <osmocom/hlr/hlr.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/ctrl.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/db.h>
 | 
				
			||||||
 | 
					#include <osmocom/hlr/hlr_vty.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEL_BY "by-"
 | 
				
			||||||
 | 
					#define SEL_BY_IMSI SEL_BY "imsi-"
 | 
				
			||||||
 | 
					#define SEL_BY_MSISDN SEL_BY "msisdn-"
 | 
				
			||||||
 | 
					#define SEL_BY_ID SEL_BY "id-"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern bool auth_algo_parse(const char *alg_str, enum osmo_auth_algo *algo,
 | 
				
			||||||
 | 
								    int *minlen, int *maxlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define hexdump_buf(buf) osmo_hexdump_nospc((void*)buf, sizeof(buf))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool startswith(const char *str, const char *start)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return strncmp(str, start, strlen(start)) == 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int _get_subscriber(struct db_context *dbc,
 | 
				
			||||||
 | 
								   const char *by_selector,
 | 
				
			||||||
 | 
								   struct hlr_subscriber *subscr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *val;
 | 
				
			||||||
 | 
						if (startswith(by_selector, SEL_BY_IMSI)) {
 | 
				
			||||||
 | 
							val = by_selector + strlen(SEL_BY_IMSI);
 | 
				
			||||||
 | 
							if (!osmo_imsi_str_valid(val))
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
							return db_subscr_get_by_imsi(dbc, val, subscr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (startswith(by_selector, SEL_BY_MSISDN)) {
 | 
				
			||||||
 | 
							val = by_selector + strlen(SEL_BY_MSISDN);
 | 
				
			||||||
 | 
							if (!osmo_msisdn_str_valid(val))
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
							return db_subscr_get_by_msisdn(dbc, val, subscr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (startswith(by_selector, SEL_BY_ID)) {
 | 
				
			||||||
 | 
							int64_t id;
 | 
				
			||||||
 | 
							char *endptr;
 | 
				
			||||||
 | 
							val = by_selector + strlen(SEL_BY_ID);
 | 
				
			||||||
 | 
							if (*val == '+')
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
							errno = 0;
 | 
				
			||||||
 | 
							id = strtoll(val, &endptr, 10);
 | 
				
			||||||
 | 
							if (errno || *endptr)
 | 
				
			||||||
 | 
								return -EINVAL;
 | 
				
			||||||
 | 
							return db_subscr_get_by_id(dbc, id, subscr);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return -ENOTSUP;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool get_subscriber(struct db_context *dbc,
 | 
				
			||||||
 | 
								   const char *by_selector,
 | 
				
			||||||
 | 
								   struct hlr_subscriber *subscr,
 | 
				
			||||||
 | 
								   struct ctrl_cmd *cmd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc = _get_subscriber(dbc, by_selector, subscr);
 | 
				
			||||||
 | 
						switch (rc) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						case -ENOTSUP:
 | 
				
			||||||
 | 
							cmd->reply = "Not a known subscriber 'by-xxx-' selector.";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						case -EINVAL:
 | 
				
			||||||
 | 
							cmd->reply = "Invalid value part of 'by-xxx-value' selector.";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						case -ENOENT:
 | 
				
			||||||
 | 
							cmd->reply = "No such subscriber.";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							cmd->reply = "An unknown error has occurred during get_subscriber().";
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Optimization: if a subscriber operation is requested by-imsi, just return
 | 
				
			||||||
 | 
					 * the IMSI right back. */
 | 
				
			||||||
 | 
					static const char *get_subscriber_imsi(struct db_context *dbc,
 | 
				
			||||||
 | 
									       const char *by_selector,
 | 
				
			||||||
 | 
									       struct ctrl_cmd *cmd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (startswith(by_selector, SEL_BY_IMSI))
 | 
				
			||||||
 | 
							return by_selector + strlen(SEL_BY_IMSI);
 | 
				
			||||||
 | 
						if (!get_subscriber(dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						return subscr.imsi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* printf fmt and arg to completely omit a string if it is empty. */
 | 
				
			||||||
 | 
					#define FMT_S "%s%s%s%s"
 | 
				
			||||||
 | 
					#define ARG_S(name, val) \
 | 
				
			||||||
 | 
						(val) && *(val) ? "\n" : "", \
 | 
				
			||||||
 | 
						(val) && *(val) ? name : "", \
 | 
				
			||||||
 | 
						(val) && *(val) ? "\t" : "", \
 | 
				
			||||||
 | 
						(val) && *(val) ? (val) : "" \
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* printf fmt and arg to completely omit bool of given value. */
 | 
				
			||||||
 | 
					#define FMT_BOOL "%s"
 | 
				
			||||||
 | 
					#define ARG_BOOL(name, val) \
 | 
				
			||||||
 | 
						val ? "\n" name "\t1" : "\n" name "\t0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void print_subscr_info(struct ctrl_cmd *cmd,
 | 
				
			||||||
 | 
								      struct hlr_subscriber *subscr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ctrl_cmd_reply_printf(cmd,
 | 
				
			||||||
 | 
							"\nid\t%" PRIu64
 | 
				
			||||||
 | 
							FMT_S
 | 
				
			||||||
 | 
							FMT_S
 | 
				
			||||||
 | 
							FMT_BOOL
 | 
				
			||||||
 | 
							FMT_BOOL
 | 
				
			||||||
 | 
							FMT_S
 | 
				
			||||||
 | 
							FMT_S
 | 
				
			||||||
 | 
							FMT_S
 | 
				
			||||||
 | 
							FMT_BOOL
 | 
				
			||||||
 | 
							FMT_BOOL
 | 
				
			||||||
 | 
							"\nperiodic_lu_timer\t%u"
 | 
				
			||||||
 | 
							"\nperiodic_rau_tau_timer\t%u"
 | 
				
			||||||
 | 
							"\nlmsi\t%08x"
 | 
				
			||||||
 | 
							,
 | 
				
			||||||
 | 
							subscr->id,
 | 
				
			||||||
 | 
							ARG_S("imsi", subscr->imsi),
 | 
				
			||||||
 | 
							ARG_S("msisdn", subscr->msisdn),
 | 
				
			||||||
 | 
							ARG_BOOL("nam_cs", subscr->nam_cs),
 | 
				
			||||||
 | 
							ARG_BOOL("nam_ps", subscr->nam_ps),
 | 
				
			||||||
 | 
							ARG_S("vlr_number", subscr->vlr_number),
 | 
				
			||||||
 | 
							ARG_S("sgsn_number", subscr->sgsn_number),
 | 
				
			||||||
 | 
							ARG_S("sgsn_address", subscr->sgsn_address),
 | 
				
			||||||
 | 
							ARG_BOOL("ms_purged_cs", subscr->ms_purged_cs),
 | 
				
			||||||
 | 
							ARG_BOOL("ms_purged_ps", subscr->ms_purged_ps),
 | 
				
			||||||
 | 
							subscr->periodic_lu_timer,
 | 
				
			||||||
 | 
							subscr->periodic_rau_tau_timer,
 | 
				
			||||||
 | 
							subscr->lmsi
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void print_subscr_info_aud2g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (aud->algo == OSMO_AUTH_ALG_NONE)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						ctrl_cmd_reply_printf(cmd,
 | 
				
			||||||
 | 
							"\naud2g.algo\t%s"
 | 
				
			||||||
 | 
							"\naud2g.ki\t%s"
 | 
				
			||||||
 | 
							,
 | 
				
			||||||
 | 
							osmo_auth_alg_name(aud->algo),
 | 
				
			||||||
 | 
							hexdump_buf(aud->u.gsm.ki));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void print_subscr_info_aud3g(struct ctrl_cmd *cmd, struct osmo_sub_auth_data *aud)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (aud->algo == OSMO_AUTH_ALG_NONE)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						ctrl_cmd_reply_printf(cmd,
 | 
				
			||||||
 | 
							"\naud3g.algo\t%s"
 | 
				
			||||||
 | 
							"\naud3g.k\t%s"
 | 
				
			||||||
 | 
							,
 | 
				
			||||||
 | 
							osmo_auth_alg_name(aud->algo),
 | 
				
			||||||
 | 
							hexdump_buf(aud->u.umts.k));
 | 
				
			||||||
 | 
						/* hexdump uses a static string buffer, hence only one hexdump per
 | 
				
			||||||
 | 
						 * printf(). */
 | 
				
			||||||
 | 
						ctrl_cmd_reply_printf(cmd,
 | 
				
			||||||
 | 
							"\naud3g.%s\t%s"
 | 
				
			||||||
 | 
							"\naud3g.ind_bitlen\t%u"
 | 
				
			||||||
 | 
							"\naud3g.sqn\t%" PRIu64
 | 
				
			||||||
 | 
							,
 | 
				
			||||||
 | 
							aud->u.umts.opc_is_op? "op" : "opc",
 | 
				
			||||||
 | 
							hexdump_buf(aud->u.umts.opc),
 | 
				
			||||||
 | 
							aud->u.umts.ind_bitlen,
 | 
				
			||||||
 | 
							aud->u.umts.sqn);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE_WO_NOVRF(subscr_create, "create");
 | 
				
			||||||
 | 
					static int set_subscr_create(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *imsi = cmd->value;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!osmo_imsi_str_valid(imsi)) {
 | 
				
			||||||
 | 
							cmd->reply = "Invalid IMSI value.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Create the subscriber in the DB */
 | 
				
			||||||
 | 
						rc = db_subscr_create(g_hlr->dbc, imsi, DB_SUBSCR_FLAG_NAM_CS | DB_SUBSCR_FLAG_NAM_PS);
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							if (rc == -EEXIST)
 | 
				
			||||||
 | 
								cmd->reply = "Subscriber already exists.";
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								cmd->reply = "Cannot create subscriber.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DCTRL, LOGL_INFO, "Created subscriber IMSI='%s'\n",
 | 
				
			||||||
 | 
						     imsi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Retrieve data of newly created subscriber: */
 | 
				
			||||||
 | 
						rc = db_subscr_get_by_imsi(hlr->dbc, imsi, &subscr);
 | 
				
			||||||
 | 
						if (rc < 0) {
 | 
				
			||||||
 | 
							cmd->reply = "Failed retrieving ID of newly created subscriber.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = talloc_asprintf(cmd, "%" PRIu64, subscr.id);
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE_WO_NOVRF(subscr_delete, "delete");
 | 
				
			||||||
 | 
					static int set_subscr_delete(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *imsi = cmd->value;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!osmo_imsi_str_valid(imsi)) {
 | 
				
			||||||
 | 
							cmd->reply = "Invalid IMSI value.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Retrieve data of newly created subscriber: */
 | 
				
			||||||
 | 
						rc = db_subscr_get_by_imsi(hlr->dbc, imsi, &subscr);
 | 
				
			||||||
 | 
						if (rc < 0) {
 | 
				
			||||||
 | 
							cmd->reply = "Subscriber doesn't exist.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Create the subscriber in the DB */
 | 
				
			||||||
 | 
						rc = db_subscr_delete_by_id(g_hlr->dbc, subscr.id);
 | 
				
			||||||
 | 
						if (rc) {
 | 
				
			||||||
 | 
							cmd->reply = "Cannot delete subscriber.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DCTRL, LOGL_INFO, "Deleted subscriber IMSI='%s'\n",
 | 
				
			||||||
 | 
						     imsi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = talloc_asprintf(cmd, "%" PRIu64, subscr.id);
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE_RO(subscr_info, "info");
 | 
				
			||||||
 | 
					static int get_subscr_info(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print_subscr_info(cmd, &subscr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE_RO(subscr_info_aud, "info-aud");
 | 
				
			||||||
 | 
					static int get_subscr_info_aud(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *imsi;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud2g;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud3g;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						imsi = get_subscriber_imsi(hlr->dbc, by_selector, cmd);
 | 
				
			||||||
 | 
						if (!imsi)
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_get_auth_data(hlr->dbc, imsi, &aud2g, &aud3g, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (rc) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case -ENOENT:
 | 
				
			||||||
 | 
						case -ENOKEY:
 | 
				
			||||||
 | 
							/* No auth data found, tell the print*() functions about it. */
 | 
				
			||||||
 | 
							aud2g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
							aud3g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							cmd->reply = "Error retrieving authentication data.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print_subscr_info_aud2g(cmd, &aud2g);
 | 
				
			||||||
 | 
						print_subscr_info_aud3g(cmd, &aud3g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE_RO(subscr_info_all, "info-all");
 | 
				
			||||||
 | 
					static int get_subscr_info_all(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud2g;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud3g;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_get_auth_data(hlr->dbc, subscr.imsi, &aud2g, &aud3g, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (rc) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case -ENOENT:
 | 
				
			||||||
 | 
						case -ENOKEY:
 | 
				
			||||||
 | 
							/* No auth data found, tell the print*() functions about it. */
 | 
				
			||||||
 | 
							aud2g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
							aud3g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							cmd->reply = "Error retrieving authentication data.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print_subscr_info(cmd, &subscr);
 | 
				
			||||||
 | 
						print_subscr_info_aud2g(cmd, &aud2g);
 | 
				
			||||||
 | 
						print_subscr_info_aud3g(cmd, &aud3g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int verify_subscr_cs_ps_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!value || !*value
 | 
				
			||||||
 | 
						    || (strcmp(value, "0") && strcmp(value, "1")))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int get_subscr_cs_ps_enabled(struct ctrl_cmd *cmd, void *data,
 | 
				
			||||||
 | 
									    bool is_ps)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = (is_ps ? subscr.nam_ps : subscr.nam_cs)
 | 
				
			||||||
 | 
							     ? "1" : "0";
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int set_subscr_cs_ps_enabled(struct ctrl_cmd *cmd, void *data,
 | 
				
			||||||
 | 
									    bool is_ps)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *imsi;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						imsi = get_subscriber_imsi(hlr->dbc, by_selector, cmd);
 | 
				
			||||||
 | 
						if (!imsi)
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						if (db_subscr_nam(hlr->dbc, imsi, strcmp(cmd->value, "1") == 0, is_ps))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						cmd->reply = "OK";
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE(subscr_ps_enabled, "ps-enabled");
 | 
				
			||||||
 | 
					static int verify_subscr_ps_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return verify_subscr_cs_ps_enabled(cmd, value, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int get_subscr_ps_enabled(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_subscr_cs_ps_enabled(cmd, data, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int set_subscr_ps_enabled(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return set_subscr_cs_ps_enabled(cmd, data, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE(subscr_cs_enabled, "cs-enabled");
 | 
				
			||||||
 | 
					static int verify_subscr_cs_enabled(struct ctrl_cmd *cmd, const char *value, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return verify_subscr_cs_ps_enabled(cmd, value, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int get_subscr_cs_enabled(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return get_subscr_cs_ps_enabled(cmd, data, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int set_subscr_cs_enabled(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return set_subscr_cs_ps_enabled(cmd, data, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE(subscr_msisdn, "msisdn");
 | 
				
			||||||
 | 
					static int verify_subscr_msisdn(struct ctrl_cmd *cmd, const char *value, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						if (!value)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (strlen(value) > sizeof(subscr.msisdn) - 1)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (strcmp(value, "none") != 0 && !osmo_msisdn_str_valid(value))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int get_subscr_msisdn(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (strlen(subscr.msisdn) == 0)
 | 
				
			||||||
 | 
							snprintf(subscr.msisdn, sizeof(subscr.msisdn), "none");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = talloc_asprintf(cmd, "%s", subscr.msisdn);
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int set_subscr_msisdn(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
						const char *msisdn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (strcmp(cmd->value, "none") == 0)
 | 
				
			||||||
 | 
							msisdn = NULL;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							msisdn = cmd->value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (db_subscr_update_msisdn_by_imsi(g_hlr->dbc, subscr.imsi, msisdn)) {
 | 
				
			||||||
 | 
							cmd->reply = "Update MSISDN failed";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = "OK";
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* value format: <algo[,KI]> */
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE(subscr_aud2g, "aud2g");
 | 
				
			||||||
 | 
					static int verify_subscr_aud2g(struct ctrl_cmd *cmd, const char *value, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!value)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (strcasecmp(value, "none") != 0 && !strchr(value, ','))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int get_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud2g;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud3g_unused;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_get_auth_data(hlr->dbc, subscr.imsi, &aud2g, &aud3g_unused, NULL);
 | 
				
			||||||
 | 
						switch (rc) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case -ENOENT:
 | 
				
			||||||
 | 
						case -ENOKEY:
 | 
				
			||||||
 | 
							aud2g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							cmd->reply = "Error retrieving data from database.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aud2g.algo ==  OSMO_AUTH_ALG_NONE) {
 | 
				
			||||||
 | 
							cmd->reply = "none";
 | 
				
			||||||
 | 
							return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = talloc_asprintf(cmd, "%s,%s", osmo_auth_alg_name(aud2g.algo),
 | 
				
			||||||
 | 
									     hexdump_buf(aud2g.u.gsm.ki));
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int set_subscr_aud2g(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
						char *tmp = NULL, *tok, *saveptr;
 | 
				
			||||||
 | 
						int minlen = 0;
 | 
				
			||||||
 | 
						int maxlen = 0;
 | 
				
			||||||
 | 
						struct sub_auth_data_str aud2g = {
 | 
				
			||||||
 | 
							.type = OSMO_AUTH_TYPE_GSM
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmp = talloc_strdup(cmd, cmd->value);
 | 
				
			||||||
 | 
						if (!tmp) {
 | 
				
			||||||
 | 
							cmd->reply = "OOM";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse alg_type: */
 | 
				
			||||||
 | 
						tok = strtok_r(tmp, ",", &saveptr);
 | 
				
			||||||
 | 
						if (!tok) {
 | 
				
			||||||
 | 
							cmd->reply = "Invalid format";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (strcmp(tok, "none") == 0) {
 | 
				
			||||||
 | 
							aud2g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
						} else if (!auth_algo_parse(tok, &aud2g.algo, &minlen, &maxlen)) {
 | 
				
			||||||
 | 
							cmd->reply = "Unknown auth algorithm.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aud2g.algo != OSMO_AUTH_ALG_NONE) {
 | 
				
			||||||
 | 
							tok = strtok_r(NULL, "\0", &saveptr);
 | 
				
			||||||
 | 
							if (!tok) {
 | 
				
			||||||
 | 
								cmd->reply = "Invalid format.";
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							aud2g.u.gsm.ki = tok;
 | 
				
			||||||
 | 
							if (!osmo_is_hexstr(aud2g.u.gsm.ki, minlen * 2, maxlen * 2, true)) {
 | 
				
			||||||
 | 
								cmd->reply = "Invalid KI.";
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud2g)) {
 | 
				
			||||||
 | 
							cmd->reply = "Update aud2g failed.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = "OK";
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* value format: <algo[,KI,(op|opc),OP_C[,ind_bitlen]]> */
 | 
				
			||||||
 | 
					CTRL_CMD_DEFINE(subscr_aud3g, "aud3g");
 | 
				
			||||||
 | 
					static int verify_subscr_aud3g(struct ctrl_cmd *cmd, const char *value, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!value)
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						if (strcasecmp(value, "none") != 0 && !strchr(value, ','))
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int get_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud2g_unused;
 | 
				
			||||||
 | 
						struct osmo_sub_auth_data aud3g;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_get_auth_data(hlr->dbc, subscr.imsi, &aud2g_unused, &aud3g, NULL);
 | 
				
			||||||
 | 
						switch (rc) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case -ENOENT:
 | 
				
			||||||
 | 
						case -ENOKEY:
 | 
				
			||||||
 | 
							aud3g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							cmd->reply = "Error retrieving data from database.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aud3g.algo ==  OSMO_AUTH_ALG_NONE) {
 | 
				
			||||||
 | 
							cmd->reply = "none";
 | 
				
			||||||
 | 
							return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = talloc_asprintf(cmd, "%s,%s,%s,%s,%u", osmo_auth_alg_name(aud3g.algo),
 | 
				
			||||||
 | 
									     osmo_hexdump_nospc_c(cmd, aud3g.u.umts.k, sizeof(aud3g.u.umts.k)),
 | 
				
			||||||
 | 
									     aud3g.u.umts.opc_is_op ? "OP" : "OPC",
 | 
				
			||||||
 | 
									     osmo_hexdump_nospc_c(cmd, aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc)),
 | 
				
			||||||
 | 
									     aud3g.u.umts.ind_bitlen);
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static int set_subscr_aud3g(struct ctrl_cmd *cmd, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hlr_subscriber subscr;
 | 
				
			||||||
 | 
						struct hlr *hlr = data;
 | 
				
			||||||
 | 
						const char *by_selector = cmd->node;
 | 
				
			||||||
 | 
						char *tmp = NULL, *tok, *saveptr;
 | 
				
			||||||
 | 
						int minlen = 0;
 | 
				
			||||||
 | 
						int maxlen = 0;
 | 
				
			||||||
 | 
						struct sub_auth_data_str aud3g = {
 | 
				
			||||||
 | 
							.type = OSMO_AUTH_TYPE_UMTS,
 | 
				
			||||||
 | 
							.u.umts = {
 | 
				
			||||||
 | 
								.ind_bitlen = 5,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						bool ind_bitlen_present;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!get_subscriber(hlr->dbc, by_selector, &subscr, cmd))
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tmp = talloc_strdup(cmd, cmd->value);
 | 
				
			||||||
 | 
						if (!tmp) {
 | 
				
			||||||
 | 
							cmd->reply = "OOM";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Parse alg_type: */
 | 
				
			||||||
 | 
						tok = strtok_r(tmp, ",", &saveptr);
 | 
				
			||||||
 | 
						if (!tok) {
 | 
				
			||||||
 | 
							cmd->reply = "Invalid format.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (strcmp(tok, "none") == 0) {
 | 
				
			||||||
 | 
							aud3g.algo = OSMO_AUTH_ALG_NONE;
 | 
				
			||||||
 | 
						} else if (!auth_algo_parse(tok, &aud3g.algo, &minlen, &maxlen)) {
 | 
				
			||||||
 | 
							cmd->reply = "Unknown auth algorithm.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aud3g.algo != OSMO_AUTH_ALG_NONE) {
 | 
				
			||||||
 | 
							/* Parse K */
 | 
				
			||||||
 | 
							tok = strtok_r(NULL, ",", &saveptr);
 | 
				
			||||||
 | 
							if (!tok) {
 | 
				
			||||||
 | 
								cmd->reply = "Invalid format.";
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							aud3g.u.umts.k = tok;
 | 
				
			||||||
 | 
							if (!osmo_is_hexstr(aud3g.u.umts.k, minlen * 2, maxlen * 2, true)) {
 | 
				
			||||||
 | 
								cmd->reply = "Invalid KI.";
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Parse OP/OPC choice */
 | 
				
			||||||
 | 
							tok = strtok_r(NULL, ",", &saveptr);
 | 
				
			||||||
 | 
							if (!tok) {
 | 
				
			||||||
 | 
								cmd->reply = "Invalid format.";
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (strcasecmp(tok, "op") == 0) {
 | 
				
			||||||
 | 
								aud3g.u.umts.opc_is_op = true;
 | 
				
			||||||
 | 
							} else if (strcasecmp(tok, "opc") == 0) {
 | 
				
			||||||
 | 
								aud3g.u.umts.opc_is_op = false;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								cmd->reply = "Invalid format.";
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Parse OP/OPC value */
 | 
				
			||||||
 | 
							ind_bitlen_present = !!strchr(saveptr, ',');
 | 
				
			||||||
 | 
							tok = strtok_r(NULL, ind_bitlen_present ? "," : "\0", &saveptr);
 | 
				
			||||||
 | 
							if (!tok) {
 | 
				
			||||||
 | 
								cmd->reply = "Invalid format.";
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							aud3g.u.umts.opc = tok;
 | 
				
			||||||
 | 
							if (!osmo_is_hexstr(aud3g.u.umts.opc, MILENAGE_KEY_LEN * 2, MILENAGE_KEY_LEN * 2, true)) {
 | 
				
			||||||
 | 
								cmd->reply = talloc_asprintf(cmd, "Invalid OP/OPC.");
 | 
				
			||||||
 | 
								return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ind_bitlen_present) {
 | 
				
			||||||
 | 
								/* Parse bitlen_ind */
 | 
				
			||||||
 | 
								tok = strtok_r(NULL, "\0", &saveptr);
 | 
				
			||||||
 | 
								if (!tok || tok[0] == '\0') {
 | 
				
			||||||
 | 
									cmd->reply = "Invalid format.";
 | 
				
			||||||
 | 
									return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								aud3g.u.umts.ind_bitlen = atoi(tok);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g)) {
 | 
				
			||||||
 | 
							cmd->reply = "Update aud3g failed.";
 | 
				
			||||||
 | 
							return CTRL_CMD_ERROR;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd->reply = "OK";
 | 
				
			||||||
 | 
						return CTRL_CMD_REPLY;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hlr_ctrl_node_lookup(void *data, vector vline, int *node_type,
 | 
				
			||||||
 | 
									void **node_data, int *i)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *token = vector_slot(vline, *i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (*node_type) {
 | 
				
			||||||
 | 
						case CTRL_NODE_ROOT:
 | 
				
			||||||
 | 
							if (strcmp(token, "subscriber") != 0)
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							*node_data = NULL;
 | 
				
			||||||
 | 
							*node_type = CTRL_NODE_SUBSCR;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case CTRL_NODE_SUBSCR:
 | 
				
			||||||
 | 
							if (!startswith(token, "by-"))
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							*node_data = (void*)token;
 | 
				
			||||||
 | 
							*node_type = CTRL_NODE_SUBSCR_BY;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hlr_ctrl_cmds_install()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR, &cmd_subscr_create);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR, &cmd_subscr_delete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_aud);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_info_all);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_ps_enabled);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_cs_enabled);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_msisdn);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud2g);
 | 
				
			||||||
 | 
						rc |= ctrl_cmd_install(CTRL_NODE_SUBSCR_BY, &cmd_subscr_aud3g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ctrl_handle *hlr_controlif_setup(struct hlr *hlr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						struct ctrl_handle *hdl = ctrl_interface_setup_dynip2(hlr,
 | 
				
			||||||
 | 
												      hlr->ctrl_bind_addr,
 | 
				
			||||||
 | 
												      OSMO_CTRL_PORT_HLR,
 | 
				
			||||||
 | 
												      hlr_ctrl_node_lookup,
 | 
				
			||||||
 | 
												      _LAST_CTRL_NODE_HLR);
 | 
				
			||||||
 | 
						if (!hdl)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = hlr_ctrl_cmds_install();
 | 
				
			||||||
 | 
						if (rc) /* FIXME: close control interface? */
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return hdl;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										590
									
								
								src/db.c
									
									
									
									
									
								
							
							
						
						
									
										590
									
								
								src/db.c
									
									
									
									
									
								
							@@ -19,19 +19,83 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <osmocom/core/utils.h>
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <sqlite3.h>
 | 
					#include <sqlite3.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "logging.h"
 | 
					#include <osmocom/hlr/logging.h>
 | 
				
			||||||
#include "db.h"
 | 
					#include <osmocom/hlr/db.h>
 | 
				
			||||||
 | 
					#include "db_bootstrap.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
 | 
				
			||||||
 | 
					#define CURRENT_SCHEMA_VERSION	6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEL_COLUMNS \
 | 
				
			||||||
 | 
						"id," \
 | 
				
			||||||
 | 
						"imsi," \
 | 
				
			||||||
 | 
						"msisdn," \
 | 
				
			||||||
 | 
						"imei," \
 | 
				
			||||||
 | 
						"vlr_number," \
 | 
				
			||||||
 | 
						"sgsn_number," \
 | 
				
			||||||
 | 
						"sgsn_address," \
 | 
				
			||||||
 | 
						"periodic_lu_tmr," \
 | 
				
			||||||
 | 
						"periodic_rau_tau_tmr," \
 | 
				
			||||||
 | 
						"nam_cs," \
 | 
				
			||||||
 | 
						"nam_ps," \
 | 
				
			||||||
 | 
						"lmsi," \
 | 
				
			||||||
 | 
						"ms_purged_cs," \
 | 
				
			||||||
 | 
						"ms_purged_ps," \
 | 
				
			||||||
 | 
						"last_lu_seen," \
 | 
				
			||||||
 | 
						"last_lu_seen_ps," \
 | 
				
			||||||
 | 
						"vlr_via_proxy," \
 | 
				
			||||||
 | 
						"sgsn_via_proxy"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *stmt_sql[] = {
 | 
					static const char *stmt_sql[] = {
 | 
				
			||||||
	[SEL_BY_IMSI] = "SELECT id,imsi,msisdn,vlr_number,sgsn_number,sgsn_address,periodic_lu_tmr,periodic_rau_tau_tmr,nam_cs,nam_ps,lmsi,ms_purged_cs,ms_purged_ps FROM subscriber WHERE imsi = ?",
 | 
						[DB_STMT_SEL_ALL] = "SELECT " SEL_COLUMNS " FROM subscriber;",
 | 
				
			||||||
	[UPD_VLR_BY_ID] = "UPDATE subscriber SET vlr_number = ? WHERE id = ?",
 | 
						[DB_STMT_SEL_ALL_ORDER_LAST_SEEN] = "SELECT " SEL_COLUMNS " FROM subscriber "
 | 
				
			||||||
	[UPD_SGSN_BY_ID] = "UPDATE subscriber SET sgsn_number = ? WHERE id = ?",
 | 
							"WHERE last_lu_seen IS NOT NULL ORDER BY last_lu_seen;",
 | 
				
			||||||
	[AUC_BY_IMSI] = "SELECT id, algo_id_2g, ki, algo_id_3g, k, op, opc, sqn FROM subscriber LEFT JOIN auc_2g ON auc_2g.subscriber_id = subscriber.id LEFT JOIN auc_3g ON auc_3g.subscriber_id = subscriber.id WHERE imsi = ?",
 | 
						[DB_STMT_SEL_FILTER_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn LIKE $search ORDER BY msisdn",
 | 
				
			||||||
	[AUC_UPD_SQN] = "UPDATE auc_3g SET sqn = ? WHERE subscriber_id = ?",
 | 
						[DB_STMT_SEL_FILTER_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi LIKE $search ORDER BY imsi",
 | 
				
			||||||
	[UPD_PURGE_CS_BY_IMSI] = "UPDATE subscriber SET ms_purged_cs=1 WHERE imsi = ?",
 | 
						[DB_STMT_SEL_FILTER_IMEI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imei LIKE $search ORDER BY imei",
 | 
				
			||||||
	[UPD_PURGE_PS_BY_IMSI] = "UPDATE subscriber SET ms_purged_ps=1 WHERE imsi = ?",
 | 
						[DB_STMT_SEL_FILTER_CS] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE nam_cs = $search ORDER BY last_lu_seen",
 | 
				
			||||||
 | 
						[DB_STMT_SEL_FILTER_PS] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE nam_ps = $search ORDER BY last_lu_seen",
 | 
				
			||||||
 | 
						[DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?",
 | 
				
			||||||
 | 
						[DB_STMT_SEL_BY_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn = ?",
 | 
				
			||||||
 | 
						[DB_STMT_SEL_BY_ID] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE id = ?",
 | 
				
			||||||
 | 
						[DB_STMT_SEL_BY_IMEI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imei = ?",
 | 
				
			||||||
 | 
						[DB_STMT_UPD_VLR_BY_ID] = "UPDATE subscriber SET vlr_number = $number, vlr_via_proxy = $proxy WHERE id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_UPD_SGSN_BY_ID] = "UPDATE subscriber SET sgsn_number = $number, sgsn_via_proxy = $proxy WHERE id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_UPD_IMEI_BY_IMSI] = "UPDATE subscriber SET imei = $imei WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_AUC_BY_IMSI] =
 | 
				
			||||||
 | 
							"SELECT id, algo_id_2g, ki, algo_id_3g, k, op, opc, sqn, ind_bitlen"
 | 
				
			||||||
 | 
							" FROM subscriber"
 | 
				
			||||||
 | 
							" LEFT JOIN auc_2g ON auc_2g.subscriber_id = subscriber.id"
 | 
				
			||||||
 | 
							" LEFT JOIN auc_3g ON auc_3g.subscriber_id = subscriber.id"
 | 
				
			||||||
 | 
							" WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_AUC_UPD_SQN] = "UPDATE auc_3g SET sqn = $sqn WHERE subscriber_id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_UPD_PURGE_CS_BY_IMSI] = "UPDATE subscriber SET ms_purged_cs = $val WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_UPD_PURGE_PS_BY_IMSI] = "UPDATE subscriber SET ms_purged_ps = $val WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_UPD_NAM_CS_BY_IMSI] = "UPDATE subscriber SET nam_cs = $val WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_UPD_NAM_PS_BY_IMSI] = "UPDATE subscriber SET nam_ps = $val WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_SUBSCR_CREATE] = "INSERT INTO subscriber (imsi, nam_cs, nam_ps) VALUES ($imsi, $nam_cs, $nam_ps)",
 | 
				
			||||||
 | 
						[DB_STMT_DEL_BY_ID] = "DELETE FROM subscriber WHERE id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_SET_MSISDN_BY_IMSI] = "UPDATE subscriber SET msisdn = $msisdn WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_DELETE_MSISDN_BY_IMSI] = "UPDATE subscriber SET msisdn = NULL WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_AUC_2G_INSERT] =
 | 
				
			||||||
 | 
							"INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki)"
 | 
				
			||||||
 | 
							" VALUES($subscriber_id, $algo_id_2g, $ki)",
 | 
				
			||||||
 | 
						[DB_STMT_AUC_2G_DELETE] = "DELETE FROM auc_2g WHERE subscriber_id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_AUC_3G_INSERT] =
 | 
				
			||||||
 | 
							"INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, op, opc, ind_bitlen)"
 | 
				
			||||||
 | 
							" VALUES($subscriber_id, $algo_id_3g, $k, $op, $opc, $ind_bitlen)",
 | 
				
			||||||
 | 
						[DB_STMT_AUC_3G_DELETE] = "DELETE FROM auc_3g WHERE subscriber_id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_SET_LAST_LU_SEEN_PS] = "UPDATE subscriber SET last_lu_seen_ps = datetime($val, 'unixepoch') WHERE id = $subscriber_id",
 | 
				
			||||||
 | 
						[DB_STMT_EXISTS_BY_IMSI] = "SELECT 1 FROM subscriber WHERE imsi = $imsi",
 | 
				
			||||||
 | 
						[DB_STMT_EXISTS_BY_MSISDN] = "SELECT 1 FROM subscriber WHERE msisdn = $msisdn",
 | 
				
			||||||
 | 
						[DB_STMT_IND_ADD] = "INSERT INTO ind (vlr) VALUES ($vlr)",
 | 
				
			||||||
 | 
						[DB_STMT_IND_SELECT] = "SELECT ind FROM ind WHERE vlr = $vlr",
 | 
				
			||||||
 | 
						[DB_STMT_IND_DEL] = "DELETE FROM ind WHERE vlr = $vlr",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void sql3_error_log_cb(void *arg, int err_code, const char *msg)
 | 
					static void sql3_error_log_cb(void *arg, int err_code, const char *msg)
 | 
				
			||||||
@@ -46,7 +110,7 @@ static void sql3_sql_log_cb(void *arg, sqlite3 *s3, const char *stmt, int type)
 | 
				
			|||||||
		LOGP(DDB, LOGL_DEBUG, "Opened database\n");
 | 
							LOGP(DDB, LOGL_DEBUG, "Opened database\n");
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 1:
 | 
						case 1:
 | 
				
			||||||
		LOGP(DDB, LOGL_DEBUG, stmt);
 | 
							LOGP(DDB, LOGL_DEBUG, "%s\n", stmt);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 2:
 | 
						case 2:
 | 
				
			||||||
		LOGP(DDB, LOGL_DEBUG, "Closed database\n");
 | 
							LOGP(DDB, LOGL_DEBUG, "Closed database\n");
 | 
				
			||||||
@@ -57,43 +121,479 @@ static void sql3_sql_log_cb(void *arg, sqlite3 *s3, const char *stmt, int type)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* remove bindings and reset statement to be re-executed */
 | 
				
			||||||
 | 
					void db_remove_reset(sqlite3_stmt *stmt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						sqlite3_clear_bindings(stmt);
 | 
				
			||||||
 | 
						/* sqlite3_reset() just repeats an error code already evaluated during sqlite3_step(). */
 | 
				
			||||||
 | 
						/* coverity[CHECKED_RETURN] */
 | 
				
			||||||
 | 
						sqlite3_reset(stmt);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** bind text arg and do proper cleanup in case of failure. If param_name is
 | 
				
			||||||
 | 
					 * NULL, bind to the first parameter (useful for SQL statements that have only
 | 
				
			||||||
 | 
					 * one parameter). */
 | 
				
			||||||
 | 
					bool db_bind_text(sqlite3_stmt *stmt, const char *param_name, const char *text)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1;
 | 
				
			||||||
 | 
						if (idx < 1) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n",
 | 
				
			||||||
 | 
							     param_name);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rc = sqlite3_bind_text(stmt, idx, text, -1, SQLITE_STATIC);
 | 
				
			||||||
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error binding text to SQL parameter %s: %d\n",
 | 
				
			||||||
 | 
							     param_name ? param_name : "#1", rc);
 | 
				
			||||||
 | 
							db_remove_reset(stmt);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** bind int arg and do proper cleanup in case of failure. If param_name is
 | 
				
			||||||
 | 
					 * NULL, bind to the first parameter (useful for SQL statements that have only
 | 
				
			||||||
 | 
					 * one parameter). */
 | 
				
			||||||
 | 
					bool db_bind_int(sqlite3_stmt *stmt, const char *param_name, int nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1;
 | 
				
			||||||
 | 
						if (idx < 1) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n",
 | 
				
			||||||
 | 
							     param_name);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rc = sqlite3_bind_int(stmt, idx, nr);
 | 
				
			||||||
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error binding int64 to SQL parameter %s: %d\n",
 | 
				
			||||||
 | 
							     param_name ? param_name : "#1", rc);
 | 
				
			||||||
 | 
							db_remove_reset(stmt);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** bind int64 arg and do proper cleanup in case of failure. If param_name is
 | 
				
			||||||
 | 
					 * NULL, bind to the first parameter (useful for SQL statements that have only
 | 
				
			||||||
 | 
					 * one parameter). */
 | 
				
			||||||
 | 
					bool db_bind_int64(sqlite3_stmt *stmt, const char *param_name, int64_t nr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1;
 | 
				
			||||||
 | 
						if (idx < 1) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n",
 | 
				
			||||||
 | 
							     param_name);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rc = sqlite3_bind_int64(stmt, idx, nr);
 | 
				
			||||||
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error binding int64 to SQL parameter %s: %d\n",
 | 
				
			||||||
 | 
							     param_name ? param_name : "#1", rc);
 | 
				
			||||||
 | 
							db_remove_reset(stmt);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool db_bind_null(sqlite3_stmt *stmt, const char *param_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1;
 | 
				
			||||||
 | 
						if (idx < 1) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n",
 | 
				
			||||||
 | 
							     param_name);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rc = sqlite3_bind_null(stmt, idx);
 | 
				
			||||||
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Error binding NULL to SQL parameter %s: %d\n",
 | 
				
			||||||
 | 
							     param_name ? param_name : "#1", rc);
 | 
				
			||||||
 | 
							db_remove_reset(stmt);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void db_close(struct db_context *dbc)
 | 
					void db_close(struct db_context *dbc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) {
 | 
						for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) {
 | 
				
			||||||
		/* it is ok to call finalize on NULL */
 | 
							/* it is ok to call finalize on NULL */
 | 
				
			||||||
		sqlite3_finalize(dbc->stmt[i]);
 | 
							sqlite3_finalize(dbc->stmt[i]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	sqlite3_close(dbc->db);
 | 
					
 | 
				
			||||||
 | 
						/* Ask sqlite3 to close DB */
 | 
				
			||||||
 | 
						rc = sqlite3_close(dbc->db);
 | 
				
			||||||
 | 
						if (rc != SQLITE_OK) { /* Make sure it's actually closed! */
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Couldn't close database: (rc=%d) %s\n",
 | 
				
			||||||
 | 
								rc, sqlite3_errmsg(dbc->db));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	talloc_free(dbc);
 | 
						talloc_free(dbc);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct db_context *db_open(void *ctx, const char *fname)
 | 
					static int db_run_statements(struct db_context *dbc, const char **statements, size_t statements_count)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc = 0;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < statements_count; i++) {
 | 
				
			||||||
 | 
							const char *stmt_str = statements[i];
 | 
				
			||||||
 | 
							sqlite3_stmt *stmt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rc = sqlite3_prepare_v2(dbc->db, stmt_str, -1, &stmt, NULL);
 | 
				
			||||||
 | 
							if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_str);
 | 
				
			||||||
 | 
								return rc;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rc = sqlite3_step(stmt);
 | 
				
			||||||
 | 
							db_remove_reset(stmt);
 | 
				
			||||||
 | 
							sqlite3_finalize(stmt);
 | 
				
			||||||
 | 
							if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_ERROR, "SQL error: (%d) %s, during stmt '%s'",
 | 
				
			||||||
 | 
								     rc, sqlite3_errmsg(dbc->db), stmt_str);
 | 
				
			||||||
 | 
								return rc;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int db_bootstrap(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc = db_run_statements(dbc, stmt_bootstrap_sql, ARRAY_SIZE(stmt_bootstrap_sql));
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Cannot bootstrap database\n");
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return SQLITE_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* https://www.sqlite.org/fileformat2.html#storage_of_the_sql_database_schema */
 | 
				
			||||||
 | 
					static bool db_table_exists(struct db_context *dbc, const char *table_name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *table_exists_sql = "SELECT name FROM sqlite_master WHERE type='table' AND name=?";
 | 
				
			||||||
 | 
						sqlite3_stmt *stmt;
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = sqlite3_prepare_v2(dbc->db, table_exists_sql, -1, &stmt, NULL);
 | 
				
			||||||
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", table_exists_sql);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!db_bind_text(stmt, NULL, table_name))
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = sqlite3_step(stmt);
 | 
				
			||||||
 | 
						db_remove_reset(stmt);
 | 
				
			||||||
 | 
						sqlite3_finalize(stmt);
 | 
				
			||||||
 | 
						return (rc == SQLITE_ROW);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Indicate whether the database is initialized with tables for schema version 0.
 | 
				
			||||||
 | 
					 * We only check for the 'subscriber' table here because Neels said so. */
 | 
				
			||||||
 | 
					static bool db_is_bootstrapped_v0(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!db_table_exists(dbc, "subscriber")) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_DEBUG, "Table 'subscriber' not found in database '%s'\n", dbc->fname);
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					db_upgrade_v1(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						const char *statements[] = {
 | 
				
			||||||
 | 
							"ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL",
 | 
				
			||||||
 | 
							"PRAGMA user_version = 1",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 1\n");
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int db_upgrade_v2(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						const char *statements[] = {
 | 
				
			||||||
 | 
							"ALTER TABLE subscriber ADD COLUMN imei VARCHAR(14)",
 | 
				
			||||||
 | 
							"PRAGMA user_version = 2",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 2\n");
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int db_upgrade_v3(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* A newer SQLite version would allow simply 'ATLER TABLE subscriber RENAME COLUMN hlr_number TO msc_number'.
 | 
				
			||||||
 | 
						 * This is a really expensive workaround for that in order to cover earlier SQLite versions as well:
 | 
				
			||||||
 | 
						 * Create a new table with the new column name and copy the data over (https://www.sqlite.org/faq.html#q11).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					#define SUBSCR_V3_CREATE  \
 | 
				
			||||||
 | 
					"(\n" \
 | 
				
			||||||
 | 
					"-- OsmoHLR's DB scheme is modelled roughly after TS 23.008 version 13.3.0\n" \
 | 
				
			||||||
 | 
					"	id		INTEGER PRIMARY KEY,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.1.1.1\n" \
 | 
				
			||||||
 | 
					"	imsi		VARCHAR(15) UNIQUE NOT NULL,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.1.2\n" \
 | 
				
			||||||
 | 
					"	msisdn		VARCHAR(15) UNIQUE,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.2.3: Most recent / current IMEISV\n" \
 | 
				
			||||||
 | 
					"	imeisv		VARCHAR,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.1.9: Most recent / current IMEI\n" \
 | 
				
			||||||
 | 
					"	imei		VARCHAR(14),\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.4.5\n" \
 | 
				
			||||||
 | 
					"	vlr_number	VARCHAR(15),\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.4.6\n" \
 | 
				
			||||||
 | 
					"	msc_number	VARCHAR(15),\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.4.8.1\n" \
 | 
				
			||||||
 | 
					"	sgsn_number	VARCHAR(15),\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.13.10\n" \
 | 
				
			||||||
 | 
					"	sgsn_address	VARCHAR,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.4.8.2\n" \
 | 
				
			||||||
 | 
					"	ggsn_number	VARCHAR(15),\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.4.9.2\n" \
 | 
				
			||||||
 | 
					"	gmlc_number	VARCHAR(15),\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.4.23\n" \
 | 
				
			||||||
 | 
					"	smsc_number	VARCHAR(15),\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.4.24\n" \
 | 
				
			||||||
 | 
					"	periodic_lu_tmr	INTEGER,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.13.115\n" \
 | 
				
			||||||
 | 
					"	periodic_rau_tau_tmr INTEGER,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.1.1.2: network access mode\n" \
 | 
				
			||||||
 | 
					"	nam_cs		BOOLEAN NOT NULL DEFAULT 1,\n" \
 | 
				
			||||||
 | 
					"	nam_ps		BOOLEAN NOT NULL DEFAULT 1,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.1.8\n" \
 | 
				
			||||||
 | 
					"	lmsi		INTEGER,\n" \
 | 
				
			||||||
 | 
					 \
 | 
				
			||||||
 | 
					"	-- The below purged flags might not even be stored non-volatile,\n" \
 | 
				
			||||||
 | 
					"	-- refer to TS 23.012 Chapter 3.6.1.4\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.7.5\n" \
 | 
				
			||||||
 | 
					"	ms_purged_cs	BOOLEAN NOT NULL DEFAULT 0,\n" \
 | 
				
			||||||
 | 
					"	-- Chapter 2.7.6\n" \
 | 
				
			||||||
 | 
					"	ms_purged_ps	BOOLEAN NOT NULL DEFAULT 0,\n" \
 | 
				
			||||||
 | 
					 \
 | 
				
			||||||
 | 
					"	-- Timestamp of last location update seen from subscriber\n" \
 | 
				
			||||||
 | 
					"	-- The value is a string which encodes a UTC timestamp in granularity of seconds.\n" \
 | 
				
			||||||
 | 
					"	last_lu_seen TIMESTAMP default NULL\n" \
 | 
				
			||||||
 | 
					")\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SUBSCR_V2_COLUMN_NAMES \
 | 
				
			||||||
 | 
						"id," \
 | 
				
			||||||
 | 
						"imsi," \
 | 
				
			||||||
 | 
						"msisdn," \
 | 
				
			||||||
 | 
						"imeisv," \
 | 
				
			||||||
 | 
						"imei," \
 | 
				
			||||||
 | 
						"vlr_number," \
 | 
				
			||||||
 | 
						"hlr_number," \
 | 
				
			||||||
 | 
						"sgsn_number," \
 | 
				
			||||||
 | 
						"sgsn_address," \
 | 
				
			||||||
 | 
						"ggsn_number," \
 | 
				
			||||||
 | 
						"gmlc_number," \
 | 
				
			||||||
 | 
						"smsc_number," \
 | 
				
			||||||
 | 
						"periodic_lu_tmr," \
 | 
				
			||||||
 | 
						"periodic_rau_tau_tmr," \
 | 
				
			||||||
 | 
						"nam_cs," \
 | 
				
			||||||
 | 
						"nam_ps," \
 | 
				
			||||||
 | 
						"lmsi," \
 | 
				
			||||||
 | 
						"ms_purged_cs," \
 | 
				
			||||||
 | 
						"ms_purged_ps," \
 | 
				
			||||||
 | 
						"last_lu_seen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SUBSCR_V3_COLUMN_NAMES \
 | 
				
			||||||
 | 
						"id," \
 | 
				
			||||||
 | 
						"imsi," \
 | 
				
			||||||
 | 
						"msisdn," \
 | 
				
			||||||
 | 
						"imeisv," \
 | 
				
			||||||
 | 
						"imei," \
 | 
				
			||||||
 | 
						"vlr_number," \
 | 
				
			||||||
 | 
						"msc_number," \
 | 
				
			||||||
 | 
						"sgsn_number," \
 | 
				
			||||||
 | 
						"sgsn_address," \
 | 
				
			||||||
 | 
						"ggsn_number," \
 | 
				
			||||||
 | 
						"gmlc_number," \
 | 
				
			||||||
 | 
						"smsc_number," \
 | 
				
			||||||
 | 
						"periodic_lu_tmr," \
 | 
				
			||||||
 | 
						"periodic_rau_tau_tmr," \
 | 
				
			||||||
 | 
						"nam_cs," \
 | 
				
			||||||
 | 
						"nam_ps," \
 | 
				
			||||||
 | 
						"lmsi," \
 | 
				
			||||||
 | 
						"ms_purged_cs," \
 | 
				
			||||||
 | 
						"ms_purged_ps," \
 | 
				
			||||||
 | 
						"last_lu_seen"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const char *statements[] = {
 | 
				
			||||||
 | 
							"BEGIN TRANSACTION",
 | 
				
			||||||
 | 
							"CREATE TEMPORARY TABLE subscriber_backup" SUBSCR_V3_CREATE,
 | 
				
			||||||
 | 
							"INSERT INTO subscriber_backup SELECT " SUBSCR_V2_COLUMN_NAMES " FROM subscriber",
 | 
				
			||||||
 | 
							"DROP TABLE subscriber",
 | 
				
			||||||
 | 
							"CREATE TABLE subscriber" SUBSCR_V3_CREATE,
 | 
				
			||||||
 | 
							"INSERT INTO subscriber SELECT " SUBSCR_V3_COLUMN_NAMES " FROM subscriber_backup",
 | 
				
			||||||
 | 
							"DROP TABLE subscriber_backup",
 | 
				
			||||||
 | 
							"COMMIT",
 | 
				
			||||||
 | 
							"PRAGMA user_version = 3",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 3\n");
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int db_upgrade_v4(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						const char *statements[] = {
 | 
				
			||||||
 | 
							"ALTER TABLE subscriber ADD COLUMN last_lu_seen_ps TIMESTAMP default NULL",
 | 
				
			||||||
 | 
							"PRAGMA user_version = 4",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 4\n");
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int db_upgrade_v5(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						const char *statements[] = {
 | 
				
			||||||
 | 
							"ALTER TABLE subscriber ADD COLUMN vlr_via_proxy VARCHAR",
 | 
				
			||||||
 | 
							"ALTER TABLE subscriber ADD COLUMN sgsn_via_proxy VARCHAR",
 | 
				
			||||||
 | 
							"PRAGMA user_version = 5",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 5\n");
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int db_upgrade_v6(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int rc;
 | 
				
			||||||
 | 
						const char *statements[] = {
 | 
				
			||||||
 | 
							"CREATE TABLE ind (\n"
 | 
				
			||||||
 | 
							"	-- 3G auth IND pool to be used for this VLR\n"
 | 
				
			||||||
 | 
							"	ind     INTEGER PRIMARY KEY,\n"
 | 
				
			||||||
 | 
							"	-- VLR identification, usually the GSUP source_name\n"
 | 
				
			||||||
 | 
							"	vlr     TEXT NOT NULL,\n"
 | 
				
			||||||
 | 
							"	UNIQUE (vlr)\n"
 | 
				
			||||||
 | 
							")"
 | 
				
			||||||
 | 
							,
 | 
				
			||||||
 | 
							"PRAGMA user_version = 6",
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = db_run_statements(dbc, statements, ARRAY_SIZE(statements));
 | 
				
			||||||
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 6\n");
 | 
				
			||||||
 | 
							return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return rc;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef int (*db_upgrade_func_t)(struct db_context *dbc);
 | 
				
			||||||
 | 
					static db_upgrade_func_t db_upgrade_path[] = {
 | 
				
			||||||
 | 
						db_upgrade_v1,
 | 
				
			||||||
 | 
						db_upgrade_v2,
 | 
				
			||||||
 | 
						db_upgrade_v3,
 | 
				
			||||||
 | 
						db_upgrade_v4,
 | 
				
			||||||
 | 
						db_upgrade_v5,
 | 
				
			||||||
 | 
						db_upgrade_v6,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int db_get_user_version(struct db_context *dbc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const char *user_version_sql = "PRAGMA user_version";
 | 
				
			||||||
 | 
						sqlite3_stmt *stmt;
 | 
				
			||||||
 | 
						int version, rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rc = sqlite3_prepare_v2(dbc->db, user_version_sql, -1, &stmt, NULL);
 | 
				
			||||||
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", user_version_sql);
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rc = sqlite3_step(stmt);
 | 
				
			||||||
 | 
						if (rc == SQLITE_ROW) {
 | 
				
			||||||
 | 
							version = sqlite3_column_int(stmt, 0);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "SQL statement '%s' failed: %d\n", user_version_sql, rc);
 | 
				
			||||||
 | 
							version = -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						db_remove_reset(stmt);
 | 
				
			||||||
 | 
						sqlite3_finalize(stmt);
 | 
				
			||||||
 | 
						return version;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logging, bool allow_upgrade)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct db_context *dbc = talloc_zero(ctx, struct db_context);
 | 
						struct db_context *dbc = talloc_zero(ctx, struct db_context);
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
						bool has_sqlite_config_sqllog = false;
 | 
				
			||||||
 | 
						int version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DDB, LOGL_NOTICE, "using database: %s\n", fname);
 | 
				
			||||||
	LOGP(DDB, LOGL_INFO, "Compiled against SQLite3 lib version %s\n", SQLITE_VERSION);
 | 
						LOGP(DDB, LOGL_INFO, "Compiled against SQLite3 lib version %s\n", SQLITE_VERSION);
 | 
				
			||||||
	LOGP(DDB, LOGL_INFO, "Running with SQLite3 lib version %s\n", sqlite3_libversion());
 | 
						LOGP(DDB, LOGL_INFO, "Running with SQLite3 lib version %s\n", sqlite3_libversion());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef SQLITE_USE_TALLOC
 | 
				
			||||||
 | 
						/* Configure SQLite3 to use talloc memory allocator */
 | 
				
			||||||
 | 
						rc = db_sqlite3_use_talloc(ctx);
 | 
				
			||||||
 | 
						if (rc == SQLITE_OK) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_NOTICE, "SQLite3 is configured to use talloc\n");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Failed to configure SQLite3 "
 | 
				
			||||||
 | 
							     "to use talloc, using default memory allocator\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dbc->fname = talloc_strdup(dbc, fname);
 | 
						dbc->fname = talloc_strdup(dbc, fname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < 0xfffff; i++) {
 | 
						for (i = 0; i < 0xfffff; i++) {
 | 
				
			||||||
		const char *o = sqlite3_compileoption_get(i);
 | 
							const char *o = sqlite3_compileoption_get(i);
 | 
				
			||||||
		if (!o)
 | 
							if (!o)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		LOGP(DDB, LOGL_DEBUG, "SQlite3 compiled with '%s'\n", o);
 | 
							LOGP(DDB, LOGL_DEBUG, "SQLite3 compiled with '%s'\n", o);
 | 
				
			||||||
 | 
							if (!strcmp(o, "ENABLE_SQLLOG"))
 | 
				
			||||||
 | 
								has_sqlite_config_sqllog = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = sqlite3_config(SQLITE_CONFIG_LOG, sql3_error_log_cb, NULL);
 | 
						if (enable_sqlite_logging) {
 | 
				
			||||||
	if (rc != SQLITE_OK)
 | 
							rc = sqlite3_config(SQLITE_CONFIG_LOG, sql3_error_log_cb, NULL);
 | 
				
			||||||
		LOGP(DDB, LOGL_NOTICE, "Unable to set SQlite3 error log callback\n");
 | 
							if (rc != SQLITE_OK)
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_NOTICE, "Unable to set SQLite3 error log callback\n");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = sqlite3_config(SQLITE_CONFIG_SQLLOG, sql3_sql_log_cb, NULL);
 | 
						if (has_sqlite_config_sqllog) {
 | 
				
			||||||
	if (rc != SQLITE_OK)
 | 
							rc = sqlite3_config(SQLITE_CONFIG_SQLLOG, sql3_sql_log_cb, NULL);
 | 
				
			||||||
		LOGP(DDB, LOGL_NOTICE, "Unable to set SQlite3 SQL statement log callback\n");
 | 
							if (rc != SQLITE_OK)
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_NOTICE, "Unable to set SQLite3 SQL log callback\n");
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_DEBUG, "Not setting SQL log callback:"
 | 
				
			||||||
 | 
								     " SQLite3 compiled without support for it\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = sqlite3_open(dbc->fname, &dbc->db);
 | 
						rc = sqlite3_open(dbc->fname, &dbc->db);
 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
@@ -105,13 +605,61 @@ struct db_context *db_open(void *ctx, const char *fname)
 | 
				
			|||||||
	/* enable extended result codes */
 | 
						/* enable extended result codes */
 | 
				
			||||||
	rc = sqlite3_extended_result_codes(dbc->db, 1);
 | 
						rc = sqlite3_extended_result_codes(dbc->db, 1);
 | 
				
			||||||
	if (rc != SQLITE_OK)
 | 
						if (rc != SQLITE_OK)
 | 
				
			||||||
		LOGP(DDB, LOGL_ERROR, "Unable to enable SQlite3 extended result codes\n");
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to enable SQLite3 extended result codes\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char *err_msg;
 | 
						char *err_msg;
 | 
				
			||||||
	rc = sqlite3_exec(dbc->db, "PRAGMA journal_mode=WAL; PRAGMA synchonous = NORMAL;", 0, 0, &err_msg);
 | 
						rc = sqlite3_exec(dbc->db, "PRAGMA journal_mode=WAL; PRAGMA synchonous = NORMAL;", 0, 0, &err_msg);
 | 
				
			||||||
	if (rc != SQLITE_OK)
 | 
						if (rc != SQLITE_OK) {
 | 
				
			||||||
		LOGP(DDB, LOGL_ERROR, "Unable to set Write-Ahead Logging: %s\n",
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to set Write-Ahead Logging: %s\n",
 | 
				
			||||||
			err_msg);
 | 
								err_msg);
 | 
				
			||||||
 | 
							sqlite3_free(err_msg);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						version = db_get_user_version(dbc);
 | 
				
			||||||
 | 
						if (version < 0) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_ERROR, "Unable to read user version number from database '%s'\n", dbc->fname);
 | 
				
			||||||
 | 
							goto out_free;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* An empty database will always report version zero. */
 | 
				
			||||||
 | 
						if (version == 0 && !db_is_bootstrapped_v0(dbc)) {
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_NOTICE, "Missing database tables detected; Bootstrapping database '%s'\n", dbc->fname);
 | 
				
			||||||
 | 
							rc = db_bootstrap(dbc);
 | 
				
			||||||
 | 
							if (rc != SQLITE_OK) {
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_ERROR, "Failed to bootstrap DB: (rc=%d) %s\n",
 | 
				
			||||||
 | 
								     rc, sqlite3_errmsg(dbc->db));
 | 
				
			||||||
 | 
								goto out_free;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							version = CURRENT_SCHEMA_VERSION;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGP(DDB, LOGL_NOTICE, "Database '%s' has HLR DB schema version %d\n", dbc->fname, version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (; allow_upgrade && (version < ARRAY_SIZE(db_upgrade_path)); version++) {
 | 
				
			||||||
 | 
							db_upgrade_func_t upgrade_func = db_upgrade_path[version];
 | 
				
			||||||
 | 
							rc = upgrade_func(dbc);
 | 
				
			||||||
 | 
							if (rc != SQLITE_DONE) {
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version %d: (rc=%d) %s\n",
 | 
				
			||||||
 | 
								     version+1, rc, sqlite3_errmsg(dbc->db));
 | 
				
			||||||
 | 
								goto out_free;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							LOGP(DDB, LOGL_NOTICE, "Database '%s' has been upgraded to HLR DB schema version %d\n",
 | 
				
			||||||
 | 
							     dbc->fname, version+1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (version != CURRENT_SCHEMA_VERSION) {
 | 
				
			||||||
 | 
							if (version < CURRENT_SCHEMA_VERSION) {
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_NOTICE, "HLR DB schema version %d is outdated\n", version);
 | 
				
			||||||
 | 
								if (!allow_upgrade) {
 | 
				
			||||||
 | 
									LOGP(DDB, LOGL_ERROR, "Not upgrading HLR database to schema version %d; "
 | 
				
			||||||
 | 
									     "use the --db-upgrade option to allow HLR database upgrades\n",
 | 
				
			||||||
 | 
									     CURRENT_SCHEMA_VERSION);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else
 | 
				
			||||||
 | 
								LOGP(DDB, LOGL_ERROR, "HLR DB schema version %d is unknown\n", version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							goto out_free;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* prepare all SQL statements */
 | 
						/* prepare all SQL statements */
 | 
				
			||||||
	for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) {
 | 
						for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										78
									
								
								src/db.h
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								src/db.h
									
									
									
									
									
								
							@@ -1,78 +0,0 @@
 | 
				
			|||||||
#pragma once
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdbool.h>
 | 
					 | 
				
			||||||
#include <sqlite3.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum stmt_idx {
 | 
					 | 
				
			||||||
	SEL_BY_IMSI	= 0,
 | 
					 | 
				
			||||||
	UPD_VLR_BY_ID	= 1,
 | 
					 | 
				
			||||||
	UPD_SGSN_BY_ID	= 2,
 | 
					 | 
				
			||||||
	AUC_BY_IMSI	= 3,
 | 
					 | 
				
			||||||
	AUC_UPD_SQN	= 4,
 | 
					 | 
				
			||||||
	UPD_PURGE_CS_BY_IMSI,
 | 
					 | 
				
			||||||
	UPD_PURGE_PS_BY_IMSI,
 | 
					 | 
				
			||||||
	_NUM_STMT
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct db_context {
 | 
					 | 
				
			||||||
	char *fname;
 | 
					 | 
				
			||||||
	sqlite3 *db;
 | 
					 | 
				
			||||||
	sqlite3_stmt *stmt[_NUM_STMT];
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void db_close(struct db_context *dbc);
 | 
					 | 
				
			||||||
struct db_context *db_open(void *ctx, const char *fname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/crypt/auth.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* obtain the authentication data for a given imsi */
 | 
					 | 
				
			||||||
int db_get_auth_data(struct db_context *dbc, const char *imsi,
 | 
					 | 
				
			||||||
		     struct osmo_sub_auth_data *aud2g,
 | 
					 | 
				
			||||||
		     struct osmo_sub_auth_data *aud3g,
 | 
					 | 
				
			||||||
		     uint64_t *suscr_id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int db_update_sqn(struct db_context *dbc, uint64_t id,
 | 
					 | 
				
			||||||
		      uint64_t new_sqn);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int db_get_auc(struct db_context *dbc, const char *imsi,
 | 
					 | 
				
			||||||
	    struct osmo_auth_vector *vec, unsigned int num_vec,
 | 
					 | 
				
			||||||
	    const uint8_t *rand_auts, const uint8_t *auts);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <osmocom/core/linuxlist.h>
 | 
					 | 
				
			||||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* TODO: Get this from somewhere? */
 | 
					 | 
				
			||||||
#define GT_MAX_DIGITS	15
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct hlr_subscriber {
 | 
					 | 
				
			||||||
	struct llist_head list;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	uint64_t	id;
 | 
					 | 
				
			||||||
	char		imsi[GSM23003_IMSI_MAX_DIGITS+1];
 | 
					 | 
				
			||||||
	char		msisdn[GT_MAX_DIGITS+1];
 | 
					 | 
				
			||||||
	/* imeisv? */
 | 
					 | 
				
			||||||
	char		vlr_number[GT_MAX_DIGITS+1];
 | 
					 | 
				
			||||||
	char		sgsn_number[GT_MAX_DIGITS+1];
 | 
					 | 
				
			||||||
	char		sgsn_address[GT_MAX_DIGITS+1];
 | 
					 | 
				
			||||||
	/* ggsn number + address */
 | 
					 | 
				
			||||||
	/* gmlc number */
 | 
					 | 
				
			||||||
	/* smsc number */
 | 
					 | 
				
			||||||
	uint32_t	periodic_lu_timer;
 | 
					 | 
				
			||||||
	uint32_t	periodic_rau_tau_timer;
 | 
					 | 
				
			||||||
	bool		nam_cs;
 | 
					 | 
				
			||||||
	bool		nam_ps;
 | 
					 | 
				
			||||||
	uint32_t	lmsi;
 | 
					 | 
				
			||||||
	bool		ms_purged_cs;
 | 
					 | 
				
			||||||
	bool		ms_purged_ps;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int db_subscr_get(struct db_context *dbc, const char *imsi,
 | 
					 | 
				
			||||||
		  struct hlr_subscriber *subscr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int db_subscr_lu(struct db_context *dbc,
 | 
					 | 
				
			||||||
		 const struct hlr_subscriber *subscr,
 | 
					 | 
				
			||||||
		 const char *vlr_or_sgsn_number,
 | 
					 | 
				
			||||||
		 bool lu_is_ps);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int db_subscr_purge(struct db_context *dbc,
 | 
					 | 
				
			||||||
		const char *imsi, bool is_ps);
 | 
					 | 
				
			||||||
							
								
								
									
										207
									
								
								src/db_auc.c
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								src/db_auc.c
									
									
									
									
									
								
							@@ -18,91 +18,115 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <inttypes.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <osmocom/core/utils.h>
 | 
					#include <osmocom/core/utils.h>
 | 
				
			||||||
#include <osmocom/crypt/auth.h>
 | 
					#include <osmocom/crypt/auth.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sqlite3.h>
 | 
					#include <sqlite3.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "logging.h"
 | 
					#include <osmocom/hlr/logging.h>
 | 
				
			||||||
#include "db.h"
 | 
					#include <osmocom/hlr/db.h>
 | 
				
			||||||
#include "auc.h"
 | 
					#include <osmocom/hlr/auc.h>
 | 
				
			||||||
#include "rand.h"
 | 
					#include <osmocom/hlr/rand.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define LOGAUC(imsi, level, fmt, args ...)	LOGP(DAUC, level, "%s: " fmt, imsi, ## args)
 | 
					#define LOGAUC(imsi, level, fmt, args ...)	LOGP(DAUC, level, "IMSI='%s': " fmt, imsi, ## args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* update the SQN for a given subscriber ID */
 | 
					/* update the SQN for a given subscriber ID */
 | 
				
			||||||
int db_update_sqn(struct db_context *dbc, uint64_t id,
 | 
					int db_update_sqn(struct db_context *dbc, int64_t subscr_id, uint64_t new_sqn)
 | 
				
			||||||
		      uint64_t new_sqn)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	sqlite3_stmt *stmt = dbc->stmt[AUC_UPD_SQN];
 | 
						sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_UPD_SQN];
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* bind new SQN and subscriber ID */
 | 
						if (!db_bind_int64(stmt, "$sqn", new_sqn))
 | 
				
			||||||
	rc = sqlite3_bind_int64(stmt, 1, new_sqn);
 | 
							return -EIO;
 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
					 | 
				
			||||||
		LOGP(DAUC, LOGL_ERROR, "Error binding SQN: %d\n", rc);
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = sqlite3_bind_int64(stmt, 2, id);
 | 
						if (!db_bind_int64(stmt, "$subscriber_id", subscr_id))
 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
							return -EIO;
 | 
				
			||||||
		LOGP(DAUC, LOGL_ERROR, "Error binding Subscrber ID: %d\n", rc);
 | 
					 | 
				
			||||||
		return -1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* execute the statement */
 | 
						/* execute the statement */
 | 
				
			||||||
	rc = sqlite3_step(stmt);
 | 
						rc = sqlite3_step(stmt);
 | 
				
			||||||
	if (rc != SQLITE_DONE) {
 | 
						if (rc != SQLITE_DONE) {
 | 
				
			||||||
		LOGP(DAUC, LOGL_ERROR, "Error updating SQN: %d\n", rc);
 | 
							LOGP(DAUC, LOGL_ERROR, "Cannot update SQN for subscriber ID=%" PRId64
 | 
				
			||||||
		return -2;
 | 
							     ": SQL error: (%d) %s\n",
 | 
				
			||||||
 | 
							     subscr_id, rc, sqlite3_errmsg(dbc->db));
 | 
				
			||||||
 | 
							ret = -EIO;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* remove bindings and reset statement to be re-executed */
 | 
						/* verify execution result */
 | 
				
			||||||
	rc = sqlite3_clear_bindings(stmt);
 | 
						rc = sqlite3_changes(dbc->db);
 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
						if (!rc) {
 | 
				
			||||||
		LOGP(DAUC, LOGL_ERROR, "Error clerearing bindings: %d\n", rc);
 | 
							LOGP(DAUC, LOGL_ERROR, "Cannot update SQN for subscriber ID=%" PRId64
 | 
				
			||||||
	}
 | 
							     ": no auc_3g entry for such subscriber\n", subscr_id);
 | 
				
			||||||
	rc = sqlite3_reset(stmt);
 | 
							ret = -ENOENT;
 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
						} else if (rc != 1) {
 | 
				
			||||||
		LOGP(DAUC, LOGL_ERROR, "Error in sqlite3_reset: %d\n", rc);
 | 
							LOGP(DAUC, LOGL_ERROR, "Update SQN for subscriber ID=%" PRId64
 | 
				
			||||||
 | 
							     ": SQL modified %d rows (expected 1)\n", subscr_id, rc);
 | 
				
			||||||
 | 
							ret = -EIO;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						db_remove_reset(stmt);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* hexparse a specific column of a sqlite prepared statement into dst (with length check)
 | 
				
			||||||
 | 
					 * returns 0 for success, -EIO on error */
 | 
				
			||||||
 | 
					static int hexparse_stmt(uint8_t *dst, size_t dst_len, sqlite3_stmt *stmt, int col, const char *col_name,
 | 
				
			||||||
 | 
								 const char *imsi)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const uint8_t *text;
 | 
				
			||||||
 | 
						size_t col_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bytes are stored as hex strings in database, hence divide length by two */
 | 
				
			||||||
 | 
						col_len = sqlite3_column_bytes(stmt, col) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (col_len != dst_len) {
 | 
				
			||||||
 | 
							LOGAUC(imsi, LOGL_ERROR, "Error reading %s, expected length %lu but has length %lu\n", col_name,
 | 
				
			||||||
 | 
							       dst_len, col_len);
 | 
				
			||||||
 | 
							return -EIO;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						text = sqlite3_column_text(stmt, col);
 | 
				
			||||||
 | 
						if (!text) {
 | 
				
			||||||
 | 
							LOGAUC(imsi, LOGL_ERROR, "Error reading %s\n", col_name);
 | 
				
			||||||
 | 
							return -EIO;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						osmo_hexparse((void *)text, dst, dst_len);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* obtain the authentication data for a given imsi
 | 
					/* obtain the authentication data for a given imsi
 | 
				
			||||||
 * returns -1 in case of error, 0 for unknown IMSI, 1 for success */
 | 
					 * returns 0 for success, negative value on error:
 | 
				
			||||||
 | 
					 * -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data,
 | 
				
			||||||
 | 
					 * -EIO on db failure */
 | 
				
			||||||
int db_get_auth_data(struct db_context *dbc, const char *imsi,
 | 
					int db_get_auth_data(struct db_context *dbc, const char *imsi,
 | 
				
			||||||
		     struct osmo_sub_auth_data *aud2g,
 | 
							     struct osmo_sub_auth_data *aud2g,
 | 
				
			||||||
		     struct osmo_sub_auth_data *aud3g,
 | 
							     struct osmo_sub_auth_data *aud3g,
 | 
				
			||||||
		     uint64_t *subscr_id)
 | 
							     int64_t *subscr_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	sqlite3_stmt *stmt = dbc->stmt[AUC_BY_IMSI];
 | 
						sqlite3_stmt *stmt = dbc->stmt[DB_STMT_AUC_BY_IMSI];
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(aud2g, 0, sizeof(*aud2g));
 | 
						memset(aud2g, 0, sizeof(*aud2g));
 | 
				
			||||||
	memset(aud3g, 0, sizeof(*aud3g));
 | 
						memset(aud3g, 0, sizeof(*aud3g));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* bind the IMSI value */
 | 
						if (!db_bind_text(stmt, "$imsi", imsi))
 | 
				
			||||||
	rc = sqlite3_bind_text(stmt, 1, imsi, -1,
 | 
							return -EIO;
 | 
				
			||||||
				SQLITE_STATIC);
 | 
					 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
					 | 
				
			||||||
		LOGAUC(imsi, LOGL_ERROR, "Error binding IMSI: %d\n", rc);
 | 
					 | 
				
			||||||
		ret = -1;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* execute the statement */
 | 
						/* execute the statement */
 | 
				
			||||||
	rc = sqlite3_step(stmt);
 | 
						rc = sqlite3_step(stmt);
 | 
				
			||||||
	if (rc == SQLITE_DONE) {
 | 
						if (rc == SQLITE_DONE) {
 | 
				
			||||||
		LOGAUC(imsi, LOGL_INFO, "Unknown\n");
 | 
							LOGAUC(imsi, LOGL_INFO, "No such subscriber\n");
 | 
				
			||||||
		ret = 0;
 | 
							ret = -ENOENT;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	} else if (rc != SQLITE_ROW) {
 | 
						} else if (rc != SQLITE_ROW) {
 | 
				
			||||||
		LOGAUC(imsi, LOGL_ERROR, "Error executing SQL: %d\n", rc);
 | 
							LOGAUC(imsi, LOGL_ERROR, "Error executing SQL: %d\n", rc);
 | 
				
			||||||
		ret = -1;
 | 
							ret = -EIO;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,89 +139,85 @@ int db_get_auth_data(struct db_context *dbc, const char *imsi,
 | 
				
			|||||||
	/* obtain result values using sqlite3_column_*() */
 | 
						/* obtain result values using sqlite3_column_*() */
 | 
				
			||||||
	if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
 | 
						if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
 | 
				
			||||||
		/* we do have some 2G authentication data */
 | 
							/* we do have some 2G authentication data */
 | 
				
			||||||
		const uint8_t *ki;
 | 
							if (hexparse_stmt(aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki), stmt, 2, "Ki", imsi))
 | 
				
			||||||
 | 
					 | 
				
			||||||
		aud2g->algo = sqlite3_column_int(stmt, 1);
 | 
					 | 
				
			||||||
		ki = sqlite3_column_text(stmt, 2);
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
		if (sqlite3_column_bytes(stmt, 2) != sizeof(aud2g->u.gsm.ki)) {
 | 
					 | 
				
			||||||
			LOGAUC(imsi, LOGL_ERROR, "Error reading Ki: %d\n", rc);
 | 
					 | 
				
			||||||
			goto end_2g;
 | 
								goto end_2g;
 | 
				
			||||||
		}
 | 
							aud2g->algo = sqlite3_column_int(stmt, 1);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		osmo_hexparse(ki, &aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki));
 | 
					 | 
				
			||||||
		aud2g->type = OSMO_AUTH_TYPE_GSM;
 | 
							aud2g->type = OSMO_AUTH_TYPE_GSM;
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		LOGAUC(imsi, LOGL_DEBUG, "No 2G Auth Data\n");
 | 
							LOGAUC(imsi, LOGL_DEBUG, "No 2G Auth Data\n");
 | 
				
			||||||
//end_2g:
 | 
					end_2g:
 | 
				
			||||||
	if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
 | 
						if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
 | 
				
			||||||
		/* we do have some 3G authentication data */
 | 
							/* we do have some 3G authentication data */
 | 
				
			||||||
		const uint8_t *k, *op, *opc;
 | 
							if (hexparse_stmt(aud3g->u.umts.k, sizeof(aud3g->u.umts.k), stmt, 4, "K", imsi)) {
 | 
				
			||||||
 | 
								ret = -EIO;
 | 
				
			||||||
		aud3g->algo = sqlite3_column_int(stmt, 3);
 | 
					 | 
				
			||||||
		k = sqlite3_column_text(stmt, 4);
 | 
					 | 
				
			||||||
		if (!k) {
 | 
					 | 
				
			||||||
			LOGAUC(imsi, LOGL_ERROR, "Error reading K: %d\n", rc);
 | 
					 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		osmo_hexparse(k, &aud3g->u.umts.k, sizeof(aud3g->u.umts.k));
 | 
							aud3g->algo = sqlite3_column_int(stmt, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* UMTS Subscribers can have either OP or OPC */
 | 
							/* UMTS Subscribers can have either OP or OPC */
 | 
				
			||||||
		op = sqlite3_column_text(stmt, 5);
 | 
							if (sqlite3_column_text(stmt, 5)) {
 | 
				
			||||||
		if (!op) {
 | 
								if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 5, "OP", imsi)) {
 | 
				
			||||||
			opc = sqlite3_column_text(stmt, 6);
 | 
									ret = -EIO;
 | 
				
			||||||
			if (!opc) {
 | 
					 | 
				
			||||||
				LOGAUC(imsi, LOGL_ERROR, "Error reading OPC: %d\n", rc);
 | 
					 | 
				
			||||||
				goto out;
 | 
									goto out;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			osmo_hexparse(opc, &aud3g->u.umts.opc,
 | 
					 | 
				
			||||||
					sizeof(aud3g->u.umts.opc));
 | 
					 | 
				
			||||||
			aud3g->u.umts.opc_is_op = 0;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			osmo_hexparse(op, &aud3g->u.umts.opc,
 | 
					 | 
				
			||||||
					sizeof(aud3g->u.umts.opc));
 | 
					 | 
				
			||||||
			aud3g->u.umts.opc_is_op = 1;
 | 
								aud3g->u.umts.opc_is_op = 1;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (hexparse_stmt(aud3g->u.umts.opc, sizeof(aud3g->u.umts.opc), stmt, 6, "OPC", imsi)) {
 | 
				
			||||||
 | 
									ret = -EIO;
 | 
				
			||||||
 | 
									goto out;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								aud3g->u.umts.opc_is_op = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
 | 
							aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
 | 
				
			||||||
 | 
							aud3g->u.umts.ind_bitlen = sqlite3_column_int(stmt, 8);
 | 
				
			||||||
		/* FIXME: amf? */
 | 
							/* FIXME: amf? */
 | 
				
			||||||
		aud3g->type = OSMO_AUTH_TYPE_UMTS;
 | 
							aud3g->type = OSMO_AUTH_TYPE_UMTS;
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		LOGAUC(imsi, LOGL_DEBUG, "No 3G Auth Data\n");
 | 
							LOGAUC(imsi, LOGL_DEBUG, "No 3G Auth Data\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (aud2g->type == 0 && aud3g->type == 0)
 | 
						if (aud2g->type == 0 && aud3g->type == 0)
 | 
				
			||||||
		ret = -1;
 | 
							ret = -ENOKEY;
 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		ret = 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	/* remove bindings and reset statement to be re-executed */
 | 
						db_remove_reset(stmt);
 | 
				
			||||||
	rc = sqlite3_clear_bindings(stmt);
 | 
					 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
					 | 
				
			||||||
		LOGAUC(imsi, LOGL_ERROR, "Error in sqlite3_clear_bindings(): %d\n", rc);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rc = sqlite3_reset(stmt);
 | 
					 | 
				
			||||||
	if (rc != SQLITE_OK) {
 | 
					 | 
				
			||||||
		LOGAUC(imsi, LOGL_ERROR, "Error in sqlite3_reset(): %d\n", rc);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* return -1 in case of error, 0 for unknown imsi, positive for number
 | 
					/* return number of vectors generated, negative value on error:
 | 
				
			||||||
 * of vectors generated */
 | 
					 * -ENOENT if the IMSI is not known, -ENOKEY if the IMSI is known but has no auth data,
 | 
				
			||||||
 | 
					 * -EIO on db failure */
 | 
				
			||||||
int db_get_auc(struct db_context *dbc, const char *imsi,
 | 
					int db_get_auc(struct db_context *dbc, const char *imsi,
 | 
				
			||||||
	    struct osmo_auth_vector *vec, unsigned int num_vec,
 | 
						       unsigned int auc_3g_ind, struct osmo_auth_vector *vec,
 | 
				
			||||||
	    const uint8_t *rand_auts, const uint8_t *auts)
 | 
						       unsigned int num_vec, const uint8_t *rand_auts,
 | 
				
			||||||
 | 
						       const uint8_t *auts, bool separation_bit)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct osmo_sub_auth_data aud2g, aud3g;
 | 
						struct osmo_sub_auth_data aud2g, aud3g;
 | 
				
			||||||
	uint64_t subscr_id;
 | 
						int64_t subscr_id;
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = db_get_auth_data(dbc, imsi, &aud2g, &aud3g, &subscr_id);
 | 
						rc = db_get_auth_data(dbc, imsi, &aud2g, &aud3g, &subscr_id);
 | 
				
			||||||
	if (rc <= 0)
 | 
						if (rc)
 | 
				
			||||||
		return rc;
 | 
							return rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	LOGAUC(imsi, LOGL_INFO, "Calling to generate %u vectors\n", num_vec);
 | 
						/* modulo by the IND bitlen value range. For example, ind_bitlen == 5 would modulo 32:
 | 
				
			||||||
 | 
						 * 1 << 5 == 0b0100000 == 32
 | 
				
			||||||
 | 
						 * - 1 == 0b0011111 == bitmask of 5 lowest bits
 | 
				
			||||||
 | 
						 * x &= 0b0011111 == modulo 32
 | 
				
			||||||
 | 
						 * Why do this? osmo-hlr cannot possibly choose individual VLR INDs always matching all subscribers' IND_bitlen,
 | 
				
			||||||
 | 
						 * which might vary wildly. Instead, let hlr.c pass in an arbitrarily high number here, and the modulo does a
 | 
				
			||||||
 | 
						 * round-robin if the IND pools that this subscriber has available. */
 | 
				
			||||||
 | 
						auc_3g_ind &= (1U << aud3g.u.umts.ind_bitlen) - 1;
 | 
				
			||||||
 | 
						aud3g.u.umts.ind = auc_3g_ind;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* the first bit (bit0) cannot be used as AMF anymore, but has been
 | 
				
			||||||
 | 
						 * re-appropriated as the separation bit.  See 3GPP TS 33.102 Annex H
 | 
				
			||||||
 | 
						 * together with 3GPP TS 33.401 / 33.402 / 33.501 */
 | 
				
			||||||
 | 
						aud3g.u.umts.amf[0] = aud3g.u.umts.amf[0] & 0x7f;
 | 
				
			||||||
 | 
						if (separation_bit)
 | 
				
			||||||
 | 
							aud3g.u.umts.amf[0] |= 0x80;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOGAUC(imsi, LOGL_DEBUG, "Calling to generate %u vectors\n", num_vec);
 | 
				
			||||||
	rc = auc_compute_vectors(vec, num_vec, &aud2g, &aud3g, rand_auts, auts);
 | 
						rc = auc_compute_vectors(vec, num_vec, &aud2g, &aud3g, rand_auts, auts);
 | 
				
			||||||
	if (rc < 0) {
 | 
						if (rc < 0) {
 | 
				
			||||||
		num_vec = 0;
 | 
							num_vec = 0;
 | 
				
			||||||
@@ -210,7 +230,8 @@ int db_get_auc(struct db_context *dbc, const char *imsi,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/* Update SQN in database, as needed */
 | 
						/* Update SQN in database, as needed */
 | 
				
			||||||
	if (aud3g.algo) {
 | 
						if (aud3g.algo) {
 | 
				
			||||||
		LOGAUC(imsi, LOGL_DEBUG, "Updating SQN in DB\n");
 | 
							LOGAUC(imsi, LOGL_DEBUG, "Updating SQN=%" PRIu64 " in DB\n",
 | 
				
			||||||
 | 
							       aud3g.u.umts.sqn);
 | 
				
			||||||
		rc = db_update_sqn(dbc, subscr_id, aud3g.u.umts.sqn);
 | 
							rc = db_update_sqn(dbc, subscr_id, aud3g.u.umts.sqn);
 | 
				
			||||||
		/* don't tell caller we generated any triplets in case of
 | 
							/* don't tell caller we generated any triplets in case of
 | 
				
			||||||
		 * update error */
 | 
							 * update error */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										86
									
								
								src/db_debug.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/db_debug.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * libtalloc based memory allocator for SQLite3.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * (C) 2019 by Vadim Yanitskiy <axilirator@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * All Rights Reserved
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation; either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <sqlite3.h>
 | 
				
			||||||
 | 
					#include <talloc.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Dedicated talloc context for SQLite */
 | 
				
			||||||
 | 
					static void *db_sqlite_ctx = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void *tall_xMalloc(int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return talloc_size(db_sqlite_ctx, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tall_xFree(void *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						talloc_free(ptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void *tall_xRealloc(void *ptr, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return talloc_realloc_fn(db_sqlite_ctx, ptr, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int tall_xSize(void *ptr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return talloc_total_size(ptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* DUMMY: talloc doesn't round up the allocation size */
 | 
				
			||||||
 | 
					static int tall_xRoundup(int size) { return size; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* DUMMY: nothing to initialize */
 | 
				
			||||||
 | 
					static int tall_xInit(void *data) { return 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* DUMMY: nothing to deinitialize */
 | 
				
			||||||
 | 
					static void tall_xShutdown(void *data) {  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Interface between SQLite and talloc memory allocator */
 | 
				
			||||||
 | 
					static const struct sqlite3_mem_methods tall_sqlite_if = {
 | 
				
			||||||
 | 
						/* Memory allocation function */
 | 
				
			||||||
 | 
						.xMalloc = &tall_xMalloc,
 | 
				
			||||||
 | 
						/* Free a prior allocation */
 | 
				
			||||||
 | 
						.xFree = &tall_xFree,
 | 
				
			||||||
 | 
						/* Resize an allocation */
 | 
				
			||||||
 | 
						.xRealloc = &tall_xRealloc,
 | 
				
			||||||
 | 
						/* Return the size of an allocation */
 | 
				
			||||||
 | 
						.xSize = &tall_xSize,
 | 
				
			||||||
 | 
						/* Round up request size to allocation size */
 | 
				
			||||||
 | 
						.xRoundup = &tall_xRoundup,
 | 
				
			||||||
 | 
						/* Initialize the memory allocator */
 | 
				
			||||||
 | 
						.xInit = &tall_xInit,
 | 
				
			||||||
 | 
						/* Deinitialize the memory allocator */
 | 
				
			||||||
 | 
						.xShutdown = &tall_xShutdown,
 | 
				
			||||||
 | 
						/* Argument to xInit() and xShutdown() */
 | 
				
			||||||
 | 
						.pAppData = NULL,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int db_sqlite3_use_talloc(void *ctx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (db_sqlite_ctx != NULL)
 | 
				
			||||||
 | 
							return -EEXIST;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						db_sqlite_ctx = talloc_named_const(ctx, 0, "SQLite3");
 | 
				
			||||||
 | 
						return sqlite3_config(SQLITE_CONFIG_MALLOC, &tall_sqlite_if);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user