├── .gitignore ├── .gitreview ├── LICENSE ├── Makefile ├── NEWS-05-30-2008 ├── NEWS-08-12-2008 ├── NEWS-08-23-2006 ├── NEWS-09-11-2006 ├── NEWS-09-27-2006 ├── README ├── build_tools ├── make_version └── make_version_c ├── isup.c ├── isup.h ├── libss7.h ├── mtp2.c ├── mtp2.h ├── mtp3.c ├── mtp3.h ├── parser_debug.c ├── ss7.c ├── ss7_internal.h ├── ss7_sched.c ├── ss7linktest.c └── ss7test.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.o.d 3 | *.lo 4 | *.so 5 | *.a 6 | libss7.so.* 7 | parser_debug 8 | ss7linktest 9 | ss7test 10 | version.c 11 | 12 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=gerrit.asterisk.org 3 | port=29418 4 | project=libss7.git 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | GNU GENERAL PUBLIC LICENSE 3 | Version 2, June 1991 4 | 5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | Preamble 11 | 12 | The licenses for most software are designed to take away your 13 | freedom to share and change it. By contrast, the GNU General Public 14 | License is intended to guarantee your freedom to share and change free 15 | software--to make sure the software is free for all its users. This 16 | General Public License applies to most of the Free Software 17 | Foundation's software and to any other program whose authors commit to 18 | using it. (Some other Free Software Foundation software is covered by 19 | the GNU Library General Public License instead.) You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | this service if you wish), that you receive source code or can get it 26 | if you want it, that you can change the software or use pieces of it 27 | in new free programs; and that you know you can do these things. 28 | 29 | To protect your rights, we need to make restrictions that forbid 30 | anyone to deny you these rights or to ask you to surrender the rights. 31 | These restrictions translate to certain responsibilities for you if you 32 | distribute copies of the software, or if you modify it. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must give the recipients all the rights that 36 | you have. You must make sure that they, too, receive or can get the 37 | source code. And you must show them these terms so they know their 38 | rights. 39 | 40 | We protect your rights with two steps: (1) copyright the software, and 41 | (2) offer you this license which gives you legal permission to copy, 42 | distribute and/or modify the software. 43 | 44 | Also, for each author's protection and ours, we want to make certain 45 | that everyone understands that there is no warranty for this free 46 | software. If the software is modified by someone else and passed on, we 47 | want its recipients to know that what they have is not the original, so 48 | that any problems introduced by others will not reflect on the original 49 | authors' reputations. 50 | 51 | Finally, any free program is threatened constantly by software 52 | patents. We wish to avoid the danger that redistributors of a free 53 | program will individually obtain patent licenses, in effect making the 54 | program proprietary. To prevent this, we have made it clear that any 55 | patent must be licensed for everyone's free use or not licensed at all. 56 | 57 | The precise terms and conditions for copying, distribution and 58 | modification follow. 59 | 60 | GNU GENERAL PUBLIC LICENSE 61 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 62 | 63 | 0. This License applies to any program or other work which contains 64 | a notice placed by the copyright holder saying it may be distributed 65 | under the terms of this General Public License. The "Program", below, 66 | refers to any such program or work, and a "work based on the Program" 67 | means either the Program or any derivative work under copyright law: 68 | that is to say, a work containing the Program or a portion of it, 69 | either verbatim or with modifications and/or translated into another 70 | language. (Hereinafter, translation is included without limitation in 71 | the term "modification".) Each licensee is addressed as "you". 72 | 73 | Activities other than copying, distribution and modification are not 74 | covered by this License; they are outside its scope. The act of 75 | running the Program is not restricted, and the output from the Program 76 | is covered only if its contents constitute a work based on the 77 | Program (independent of having been made by running the Program). 78 | Whether that is true depends on what the Program does. 79 | 80 | 1. You may copy and distribute verbatim copies of the Program's 81 | source code as you receive it, in any medium, provided that you 82 | conspicuously and appropriately publish on each copy an appropriate 83 | copyright notice and disclaimer of warranty; keep intact all the 84 | notices that refer to this License and to the absence of any warranty; 85 | and give any other recipients of the Program a copy of this License 86 | along with the Program. 87 | 88 | You may charge a fee for the physical act of transferring a copy, and 89 | you may at your option offer warranty protection in exchange for a fee. 90 | 91 | 2. You may modify your copy or copies of the Program or any portion 92 | of it, thus forming a work based on the Program, and copy and 93 | distribute such modifications or work under the terms of Section 1 94 | above, provided that you also meet all of these conditions: 95 | 96 | a) You must cause the modified files to carry prominent notices 97 | stating that you changed the files and the date of any change. 98 | 99 | b) You must cause any work that you distribute or publish, that in 100 | whole or in part contains or is derived from the Program or any 101 | part thereof, to be licensed as a whole at no charge to all third 102 | parties under the terms of this License. 103 | 104 | c) If the modified program normally reads commands interactively 105 | when run, you must cause it, when started running for such 106 | interactive use in the most ordinary way, to print or display an 107 | announcement including an appropriate copyright notice and a 108 | notice that there is no warranty (or else, saying that you provide 109 | a warranty) and that users may redistribute the program under 110 | these conditions, and telling the user how to view a copy of this 111 | License. (Exception: if the Program itself is interactive but 112 | does not normally print such an announcement, your work based on 113 | the Program is not required to print an announcement.) 114 | 115 | These requirements apply to the modified work as a whole. If 116 | identifiable sections of that work are not derived from the Program, 117 | and can be reasonably considered independent and separate works in 118 | themselves, then this License, and its terms, do not apply to those 119 | sections when you distribute them as separate works. But when you 120 | distribute the same sections as part of a whole which is a work based 121 | on the Program, the distribution of the whole must be on the terms of 122 | this License, whose permissions for other licensees extend to the 123 | entire whole, and thus to each and every part regardless of who wrote it. 124 | 125 | Thus, it is not the intent of this section to claim rights or contest 126 | your rights to work written entirely by you; rather, the intent is to 127 | exercise the right to control the distribution of derivative or 128 | collective works based on the Program. 129 | 130 | In addition, mere aggregation of another work not based on the Program 131 | with the Program (or with a work based on the Program) on a volume of 132 | a storage or distribution medium does not bring the other work under 133 | the scope of this License. 134 | 135 | 3. You may copy and distribute the Program (or a work based on it, 136 | under Section 2) in object code or executable form under the terms of 137 | Sections 1 and 2 above provided that you also do one of the following: 138 | 139 | a) Accompany it with the complete corresponding machine-readable 140 | source code, which must be distributed under the terms of Sections 141 | 1 and 2 above on a medium customarily used for software interchange; or, 142 | 143 | b) Accompany it with a written offer, valid for at least three 144 | years, to give any third party, for a charge no more than your 145 | cost of physically performing source distribution, a complete 146 | machine-readable copy of the corresponding source code, to be 147 | distributed under the terms of Sections 1 and 2 above on a medium 148 | customarily used for software interchange; or, 149 | 150 | c) Accompany it with the information you received as to the offer 151 | to distribute corresponding source code. (This alternative is 152 | allowed only for noncommercial distribution and only if you 153 | received the program in object code or executable form with such 154 | an offer, in accord with Subsection b above.) 155 | 156 | The source code for a work means the preferred form of the work for 157 | making modifications to it. For an executable work, complete source 158 | code means all the source code for all modules it contains, plus any 159 | associated interface definition files, plus the scripts used to 160 | control compilation and installation of the executable. However, as a 161 | special exception, the source code distributed need not include 162 | anything that is normally distributed (in either source or binary 163 | form) with the major components (compiler, kernel, and so on) of the 164 | operating system on which the executable runs, unless that component 165 | itself accompanies the executable. 166 | 167 | If distribution of executable or object code is made by offering 168 | access to copy from a designated place, then offering equivalent 169 | access to copy the source code from the same place counts as 170 | distribution of the source code, even though third parties are not 171 | compelled to copy the source along with the object code. 172 | 173 | 4. You may not copy, modify, sublicense, or distribute the Program 174 | except as expressly provided under this License. Any attempt 175 | otherwise to copy, modify, sublicense or distribute the Program is 176 | void, and will automatically terminate your rights under this License. 177 | However, parties who have received copies, or rights, from you under 178 | this License will not have their licenses terminated so long as such 179 | parties remain in full compliance. 180 | 181 | 5. You are not required to accept this License, since you have not 182 | signed it. However, nothing else grants you permission to modify or 183 | distribute the Program or its derivative works. These actions are 184 | prohibited by law if you do not accept this License. Therefore, by 185 | modifying or distributing the Program (or any work based on the 186 | Program), you indicate your acceptance of this License to do so, and 187 | all its terms and conditions for copying, distributing or modifying 188 | the Program or works based on it. 189 | 190 | 6. Each time you redistribute the Program (or any work based on the 191 | Program), the recipient automatically receives a license from the 192 | original licensor to copy, distribute or modify the Program subject to 193 | these terms and conditions. You may not impose any further 194 | restrictions on the recipients' exercise of the rights granted herein. 195 | You are not responsible for enforcing compliance by third parties to 196 | this License. 197 | 198 | 7. If, as a consequence of a court judgment or allegation of patent 199 | infringement or for any other reason (not limited to patent issues), 200 | conditions are imposed on you (whether by court order, agreement or 201 | otherwise) that contradict the conditions of this License, they do not 202 | excuse you from the conditions of this License. If you cannot 203 | distribute so as to satisfy simultaneously your obligations under this 204 | License and any other pertinent obligations, then as a consequence you 205 | may not distribute the Program at all. For example, if a patent 206 | license would not permit royalty-free redistribution of the Program by 207 | all those who receive copies directly or indirectly through you, then 208 | the only way you could satisfy both it and this License would be to 209 | refrain entirely from distribution of the Program. 210 | 211 | If any portion of this section is held invalid or unenforceable under 212 | any particular circumstance, the balance of the section is intended to 213 | apply and the section as a whole is intended to apply in other 214 | circumstances. 215 | 216 | It is not the purpose of this section to induce you to infringe any 217 | patents or other property right claims or to contest validity of any 218 | such claims; this section has the sole purpose of protecting the 219 | integrity of the free software distribution system, which is 220 | implemented by public license practices. Many people have made 221 | generous contributions to the wide range of software distributed 222 | through that system in reliance on consistent application of that 223 | system; it is up to the author/donor to decide if he or she is willing 224 | to distribute software through any other system and a licensee cannot 225 | impose that choice. 226 | 227 | This section is intended to make thoroughly clear what is believed to 228 | be a consequence of the rest of this License. 229 | 230 | 8. If the distribution and/or use of the Program is restricted in 231 | certain countries either by patents or by copyrighted interfaces, the 232 | original copyright holder who places the Program under this License 233 | may add an explicit geographical distribution limitation excluding 234 | those countries, so that distribution is permitted only in or among 235 | countries not thus excluded. In such case, this License incorporates 236 | the limitation as if written in the body of this License. 237 | 238 | 9. The Free Software Foundation may publish revised and/or new versions 239 | of the General Public License from time to time. Such new versions will 240 | be similar in spirit to the present version, but may differ in detail to 241 | address new problems or concerns. 242 | 243 | Each version is given a distinguishing version number. If the Program 244 | specifies a version number of this License which applies to it and "any 245 | later version", you have the option of following the terms and conditions 246 | either of that version or of any later version published by the Free 247 | Software Foundation. If the Program does not specify a version number of 248 | this License, you may choose any version ever published by the Free Software 249 | Foundation. 250 | 251 | 10. If you wish to incorporate parts of the Program into other free 252 | programs whose distribution conditions are different, write to the author 253 | to ask for permission. For software which is copyrighted by the Free 254 | Software Foundation, write to the Free Software Foundation; we sometimes 255 | make exceptions for this. Our decision will be guided by the two goals 256 | of preserving the free status of all derivatives of our free software and 257 | of promoting the sharing and reuse of software generally. 258 | 259 | NO WARRANTY 260 | 261 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 262 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 263 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 264 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 265 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 266 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 267 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 268 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 269 | REPAIR OR CORRECTION. 270 | 271 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 272 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 273 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 274 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 275 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 276 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 277 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 278 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 279 | POSSIBILITY OF SUCH DAMAGES. 280 | 281 | END OF TERMS AND CONDITIONS 282 | 283 | How to Apply These Terms to Your New Programs 284 | 285 | If you develop a new program, and you want it to be of the greatest 286 | possible use to the public, the best way to achieve this is to make it 287 | free software which everyone can redistribute and change under these terms. 288 | 289 | To do so, attach the following notices to the program. It is safest 290 | to attach them to the start of each source file to most effectively 291 | convey the exclusion of warranty; and each file should have at least 292 | the "copyright" line and a pointer to where the full notice is found. 293 | 294 | 295 | Copyright (C) 19yy 296 | 297 | This program is free software; you can redistribute it and/or modify 298 | it under the terms of the GNU General Public License as published by 299 | the Free Software Foundation; either version 2 of the License, or 300 | (at your option) any later version. 301 | 302 | This program is distributed in the hope that it will be useful, 303 | but WITHOUT ANY WARRANTY; without even the implied warranty of 304 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 305 | GNU General Public License for more details. 306 | 307 | You should have received a copy of the GNU General Public License 308 | along with this program; if not, write to the Free Software 309 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 310 | 311 | 312 | Also add information on how to contact you by electronic and paper mail. 313 | 314 | If the program is interactive, make it output a short notice like this 315 | when it starts in an interactive mode: 316 | 317 | Gnomovision version 69, Copyright (C) 19yy name of author 318 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 319 | This is free software, and you are welcome to redistribute it 320 | under certain conditions; type `show c' for details. 321 | 322 | The hypothetical commands `show w' and `show c' should show the appropriate 323 | parts of the General Public License. Of course, the commands you use may 324 | be called something other than `show w' and `show c'; they could even be 325 | mouse-clicks or menu items--whatever suits your program. 326 | 327 | You should also get your employer (if you work as a programmer) or your 328 | school, if any, to sign a "copyright disclaimer" for the program, if 329 | necessary. Here is a sample; alter the names: 330 | 331 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 332 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 333 | 334 | , 1 April 1989 335 | Ty Coon, President of Vice 336 | 337 | This General Public License does not permit incorporating your program into 338 | proprietary programs. If your program is a subroutine library, you may 339 | consider it more useful to permit linking proprietary applications with the 340 | library. If this is what you want to do, use the GNU Library General 341 | Public License instead of this License. 342 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # libss7: An implementation of Signaling System 7 (SS7) 3 | # 4 | # Written by Mark Spencer 5 | # 6 | # Copyright (C) 2001, Linux Support Services, Inc. 7 | # All Rights Reserved. 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program; if not, write to the Free Software 21 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 | 23 | CC=gcc 24 | GREP=grep 25 | AWK=awk 26 | 27 | OSARCH=$(shell uname -s) 28 | PROC?=$(shell uname -m) 29 | 30 | # SONAME version; should be changed on every ABI change 31 | # please don't change it needlessly; it's perfectly fine to have a SONAME 32 | # of 1.0 and a version of 1.4.x 33 | SONAME:=2.0 34 | 35 | STATIC_LIBRARY=libss7.a 36 | DYNAMIC_LIBRARY:=libss7.so.$(SONAME) 37 | STATIC_OBJS= \ 38 | isup.o \ 39 | mtp2.o \ 40 | mtp3.o \ 41 | ss7.o \ 42 | ss7_sched.o \ 43 | version.o 44 | DYNAMIC_OBJS= \ 45 | $(STATIC_OBJS) 46 | CFLAGS ?= -g 47 | CFLAGS += $(CPPFLAGS) 48 | CFLAGS += -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes 49 | CFLAGS += -fPIC $(LIBSS7_OPT) $(COVERAGE_CFLAGS) 50 | INSTALL_PREFIX=$(DESTDIR) 51 | INSTALL_BASE=/usr 52 | libdir?=$(INSTALL_BASE)/lib 53 | ifneq ($(findstring Darwin,$(OSARCH)),) 54 | SOFLAGS=$(LDFLAGS) -dynamic -bundle -Xlinker -macosx_version_min -Xlinker 10.4 -Xlinker -undefined -Xlinker dynamic_lookup -force_flat_namespace 55 | ifeq ($(shell /usr/bin/sw_vers -productVersion | cut -c1-4),10.6) 56 | SOFLAGS+=/usr/lib/bundle1.o 57 | endif 58 | LDCONFIG=/usr/bin/true 59 | else 60 | SOFLAGS=$(LDFLAGS) -shared -Wl,-h$(DYNAMIC_LIBRARY) $(COVERAGE_LDFLAGS) 61 | LDCONFIG = /sbin/ldconfig 62 | endif 63 | ifneq (,$(findstring X$(OSARCH)X, XLinuxX XGNU/kFreeBSDX XGNUX)) 64 | LDCONFIG_FLAGS=-n 65 | else 66 | ifeq (${OSARCH},FreeBSD) 67 | LDCONFIG_FLAGS=-m 68 | #CFLAGS += -I../zaptel -I../zapata 69 | INSTALL_BASE=/usr/local 70 | endif 71 | endif 72 | ifeq (${OSARCH},SunOS) 73 | #CFLAGS += -DSOLARIS -I../zaptel-solaris 74 | CFLAGS += -DSOLARIS 75 | LDCONFIG = 76 | LDCONFIG_FLAGS = \# # Trick to comment out the period in the command below 77 | #INSTALL_PREFIX = /opt/asterisk # Uncomment out to install in standard Solaris location for 3rd party code 78 | endif 79 | 80 | UTILITIES=parser_debug 81 | 82 | ifneq ($(wildcard /usr/include/dahdi/user.h),) 83 | UTILITIES+=ss7test ss7linktest 84 | endif 85 | 86 | export SS7VERSION 87 | 88 | SS7VERSION:=$(shell GREP=$(GREP) AWK=$(AWK) build_tools/make_version .) 89 | 90 | #The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only. 91 | #This works for even old (2.96) versions of gcc and provides a small boost either way. 92 | #A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesnt support it. 93 | ifeq ($(PROC),sparc64) 94 | PROC=ultrasparc 95 | LIBSS7_OPT = -mtune=$(PROC) -O3 -pipe -fomit-frame-pointer -mcpu=v8 96 | else 97 | ifneq ($(CODE_COVERAGE),) 98 | LIBSS7_OPT= 99 | COVERAGE_CFLAGS=-ftest-coverage -fprofile-arcs 100 | COVERAGE_LDFLAGS=-ftest-coverage -fprofile-arcs 101 | else 102 | LIBSS7_OPT=-O2 103 | endif 104 | endif 105 | 106 | ifeq ($(CPUARCH),i686) 107 | CFLAGS += -m32 108 | SOFLAGS += -m32 109 | endif 110 | 111 | all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY) $(UTILITIES) 112 | 113 | update: 114 | @if [ -d .svn ]; then \ 115 | echo "Updating from Subversion..." ; \ 116 | fromrev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \ 117 | svn update | tee update.out; \ 118 | torev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \ 119 | echo "`date` Updated from revision $${fromrev} to $${torev}." >> update.log; \ 120 | rm -f .version; \ 121 | if [ `grep -c ^C update.out` -gt 0 ]; then \ 122 | echo ; echo "The following files have conflicts:" ; \ 123 | grep ^C update.out | cut -b4- ; \ 124 | fi ; \ 125 | rm -f update.out; \ 126 | else \ 127 | echo "Not under version control"; \ 128 | fi 129 | 130 | install: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY) 131 | mkdir -p $(INSTALL_PREFIX)$(libdir) 132 | mkdir -p $(INSTALL_PREFIX)$(INSTALL_BASE)/include 133 | ifneq (${OSARCH},SunOS) 134 | install -m 644 libss7.h $(INSTALL_PREFIX)$(INSTALL_BASE)/include 135 | install -m 755 $(DYNAMIC_LIBRARY) $(INSTALL_PREFIX)$(libdir) 136 | #if [ -x /usr/sbin/sestatus ] && ( /usr/sbin/sestatus | grep "SELinux status:" | grep -q "enabled"); then /sbin/restorecon -v $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY); fi 137 | ( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf $(DYNAMIC_LIBRARY) libss7.so) 138 | ifeq ($(SONAME),1.0) 139 | # Add this link for historic reasons 140 | ( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf $(DYNAMIC_LIBRARY) libss7.so.1) 141 | endif 142 | install -m 644 $(STATIC_LIBRARY) $(INSTALL_PREFIX)$(libdir) 143 | if test $$(id -u) = 0; then $(LDCONFIG) $(LDCONFIG_FLAGS) $(INSTALL_PREFIX)$(libdir); fi 144 | else 145 | install -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include -m 644 libss7.h 146 | install -f $(INSTALL_PREFIX)$(libdir) -m 755 $(DYNAMIC_LIBRARY) 147 | ( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf $(DYNAMIC_LIBRARY) libss7.so) 148 | ifeq ($(SONAME),1.0) 149 | # Add this link for historic reasons 150 | ( cd $(INSTALL_PREFIX)$(libdir) ; ln -sf $(DYNAMIC_LIBRARY) libss7.so.1) 151 | endif 152 | install -f $(INSTALL_PREFIX)$(libdir) -m 644 $(STATIC_LIBRARY) 153 | endif 154 | 155 | uninstall: 156 | @echo "Removing Libss7" 157 | rm -f $(INSTALL_PREFIX)$(libdir)/$(STATIC_LIBRARY) 158 | rm -f $(INSTALL_PREFIX)$(libdir)/libss7.so 159 | ifeq ($(SONAME),1.0) 160 | rm -f $(INSTALL_PREFIX)$(libdir)/libss7.so.1 161 | endif 162 | rm -f $(INSTALL_PREFIX)$(libdir)/$(DYNAMIC_LIBRARY) 163 | rm -f $(INSTALL_PREFIX)$(INSTALL_BASE)/include/libss7.h 164 | 165 | ss7test: ss7test.o $(STATIC_LIBRARY) 166 | $(CC) -o $@ $< $(STATIC_LIBRARY) -lpthread $(CFLAGS) 167 | 168 | ss7linktest: ss7linktest.o $(STATIC_LIBRARY) 169 | $(CC) -o $@ $< $(STATIC_LIBRARY) -lpthread $(CFLAGS) 170 | 171 | parser_debug: parser_debug.o $(STATIC_LIBRARY) 172 | $(CC) -o $@ $< $(STATIC_LIBRARY) $(CFLAGS) 173 | 174 | MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP 175 | 176 | %.o: %.c 177 | $(CC) $(CFLAGS) $(MAKE_DEPS) -c -o $@ $< 178 | 179 | %.lo: %.c 180 | $(CC) $(CFLAGS) $(MAKE_DEPS) -c -o $@ $< 181 | 182 | $(STATIC_LIBRARY): $(STATIC_OBJS) 183 | ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS) 184 | ranlib $(STATIC_LIBRARY) 185 | 186 | $(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS) 187 | $(CC) $(SOFLAGS) -o $@ $(DYNAMIC_OBJS) 188 | $(LDCONFIG) $(LDCONFIG_FLAGS) . 189 | ln -sf $(DYNAMIC_LIBRARY) libss7.so 190 | ifeq ($(SONAME),1.0) 191 | # Add this link for historic reasons 192 | ln -sf $(DYNAMIC_LIBRARY) libss7.so.1 193 | endif 194 | 195 | version.c: FORCE 196 | @build_tools/make_version_c > $@.tmp 197 | @cmp -s $@.tmp $@ || mv $@.tmp $@ 198 | @rm -f $@.tmp 199 | 200 | clean: 201 | rm -f *.o *.so *.lo 202 | ifeq ($(SONAME),1.0) 203 | rm -f *.so.1 204 | endif 205 | rm -f $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY) 206 | rm -f parser_debug ss7linktest ss7test 207 | rm -f .*.d 208 | 209 | .PHONY: 210 | 211 | FORCE: 212 | 213 | ifneq ($(wildcard .*.d),) 214 | include .*.d 215 | endif 216 | -------------------------------------------------------------------------------- /NEWS-05-30-2008: -------------------------------------------------------------------------------- 1 | Hey all, 2 | 3 | It has been a while since I have made a status update with regards to libss7, so I think it is about time that I should do so. 4 | 5 | Library Related Updates: 6 | ======================== 7 | 8 | Many things have changed since the last status update. Some of the highlights include are listed. 9 | 10 | Lots of additional parameters and messages are supported and dumped.... 11 | Many new channel variables are now added in chan_zap to receive SS7 specific information: 12 | 13 | SS7_CHARGE_NUMBER 14 | SS7_GENERIC_ADDRESS 15 | SS7_JIP 16 | SS7_GENERIC_DIGITS 17 | SS7_GENERIC_DIGTYPE (type of generic digits) 18 | SS7_GENERIC_DIGSCHEME 19 | SS7_ORIG_CALLED_NUM 20 | 21 | SS7_LSPI_IDENT (these three are used for RLT support on DMS switches) 22 | SS7_CALLREF_IDENT 23 | SS7_CALLREF_PC 24 | 25 | SS7_CALLING_PARTY_CATEGORY 26 | SS7_REDIRECTING_NUMBER 27 | SS7_GENERIC_NAME 28 | 29 | Most are fairly self explanatory as far as what they contain. It is also possible to set many of these parameters on outbound calls as well by prefixing the variable with an '_' when you set it. 30 | 31 | In addition, ANSI SS7 support has been improved extensively, thanks to Alan McMillan and Joseph (on this list). RLT support has been added for DMS switch types. 32 | 33 | *NOTE*: It is also recommended to all of you that are still using the trunk version of Asterisk for SS7 support to switch to the 1.6.0 branch (http://svn.digium.com/svn/asterisk/branches/1.6.0 to checkout via svn). When it is released it will be the first release branch to contain SS7 support. I am continuing to maintain and bugfix both 1.6.0 and trunk branches. 34 | 35 | Cool New Feature That You Should Use: 36 | ===================================== 37 | 38 | Also, as many of you may have noticed, there was a new Zaptel release (1.4.11). So you maybe asking yourself, "Why should I care about a new Zaptel release, this is the asterisk-ss7 mailing list". In case you were, this is why: 39 | 40 | I recently added a new channel type to zaptel which performs most of the real time work required to keep an MTP2 link alive in the kernel instead of in Asterisk/libss7. What does this mean for you? It means your links are going to be much more stable under system load. 41 | 42 | For most cases, the only thing now that will be able to knock your SS7 link down is if you are trying to echo cancel more channels than your CPU can handle (as echo cancellation is done in the same place as the kernel level MTP2). So if you have link stability problems still, it is likely your echo cancellation load is too high and you need to get a better CPU or a hardware echo canceller. 43 | 44 | Now, in order to update to use it, you need to get the latest version of Zaptel (1.4.11), libss7, and asterisk-1.6.0 (or Asterisk-trunk if you really still want to use it). Compile them in that order, and in zaptel.conf where you have the "dchan=" line for the signalling channel, change that to "mtp2=", run ztcfg, and, Voila!, it is done. Your existing zapata.conf should require no changes. 45 | 46 | This update is highly recommended, since the kernel is a much more appropriate place to do the work of a real time task like keeping FISUs and LSSUs constantly being sent on the line. 47 | 48 | For those that want the technical details of the new channel type, here is an explanation. 49 | 50 | Basically, it is similar to a dchan, so it does all you HDLC encoding and decoding, as well as CRC calculation and checking. The difference is that when you write messages on that channel, it automatically repeats the last one written. On the receive side, it compares the most recently received message with the last one received off the signalling link, and if it is different, it wakes up the Asterisk/libss7 process. If it is the same, it ignores it (so as not to have excessive and unnecessary user/kernel context switches). 51 | 52 | As always, if you have any questions, I am available on this list to answer them. 53 | -------------------------------------------------------------------------------- /NEWS-08-12-2008: -------------------------------------------------------------------------------- 1 | Hey all, 2 | 3 | It's that time again, time for a news/status update for what's going on 4 | with libss7. 5 | 6 | 1.0.0 Release: 7 | ============== 8 | First of all, to let everyone know, we had a 1.0.0 release of libss7 a 9 | few weeks ago (and recently a 1.0.1 as well), so that's a good thing. I 10 | also would like to thank all of you that have had issues that have come 11 | to me with them. Because of one person on this list in particular, I 12 | think we have eliminating all the remaining critical bugs in libss7 that 13 | were causing crash related problems (under particular circumstances). 14 | 15 | Astricon 2008: 16 | ============== 17 | For all of you that did not see my post about it earlier, I would love 18 | to see as many of you as can show up at Astricon this year (end of 19 | September). Like I mentioned, I'm going to be giving a talk about 20 | Asterisk and SS7. I'm planning on discussing basic configuration setup, 21 | common configuration problems that people run into and debugging 22 | techniques which can be used, as well as advanced topics such as the 23 | current "state of the art" with where libss7 is and some potential 24 | directions for future development with Asterisk and SS7. 25 | 26 | Also, I would like to (if there is enough interest) try to get together 27 | with some of you sometime that week to talk about the status of Asterisk 28 | and SS7 and what kinds of things that we can improve upon and work on in 29 | the future. 30 | 31 | Confidence Boosters: 32 | ==================== 33 | There are some very good and very interesting things that have been 34 | happening. If any of you know Joseph on this list, he works for a 35 | mobile phone company in Kentucky. He is using Asterisk with libss7 to 36 | provide voicemail services to his mobile subscribers. 37 | 38 | He has quite a good setup for helping me find issues, and is also a good 39 | indicator for how well libss7 is doing stability and scalability wise. 40 | Well the news is that running a current version of libss7/Asterisk-1.6.0 41 | branch he has been running a load over 100,000 calls per day for close 42 | to a month, with no link related stability problems and no Asterisk issues. 43 | 44 | I have heard much positive feedback from many of you about the more 45 | recent versions of libss7/Asterisk-1.6.0. If there are any of you out 46 | there with a setup that you would like to share about (especially if you 47 | think your setup is unusual in any way, whether it be high number of 48 | T1/E1s or high volume of call traffic) I personally would be very 49 | interested in hearing about them, publicly or privately if you do not 50 | feel you can disclose it to the list. 51 | 52 | New Features and Changes: 53 | ========================= 54 | - Aside from the few outstanding bugs that were fixed, there is not much 55 | to talk about. We are getting quite a robust set of supported messages 56 | and parameters, which is making this section less prone to change. :-) 57 | 58 | As always, any of you have any questions or concern, please let me know. 59 | You can get in contact with me with my contact information below. 60 | 61 | -------------------------------------------------------------------------------- /NEWS-08-23-2006: -------------------------------------------------------------------------------- 1 | Hey all, just wanted to let anybody know that attempted to test libss7/asterisk-ss7 this last weekend, that if you had any build problems, they should be resolved now. In the course of some major merges that went into asterisk-trunk this last weekend, automerge failed on most of the developer branches (including my asterisk-ss7 branch). I just got it fixed this morning, so everything should work now and build properly. 2 | 3 | For the record, in case nobody noticed, thanks to Luciano Ramos on the asterisk-ss7 list, libss7 was tested and successfully was able to receive a call on a Siemens EWSD switch running the ITU variant of SS7. I added a section to the README file which gives the tested switch types that I have tested libss7 on. As soon as we got that done, I started working on circuit blocking/unblocking support. That should be in the asterisk-ss7 branch now to be tested. I still haven't gotten an ANSI link to work on, so that is still in the works, however I seem to be getting a lot of good feedback and interest from everybody for testing. Also, if nobody noticed the message I wrote this last week, I added another option to zapata.conf called defaultdpc which is for layer4 message routing, in case your desired destination point code is not the same as your adjacent node's point code (i.e. you have an STP or something between you and the remote end of your bearer channels, or simple A link support). That's pretty much all I can remember for now, but I'll try to keep the feature list documented in the README file for libss7. For all of you that offered links and resources, thanks again! You have been a tremendous help. Stay tuned for more soon :-) 4 | 5 | Matthew Fredrickson 6 | -------------------------------------------------------------------------------- /NEWS-09-11-2006: -------------------------------------------------------------------------------- 1 | Hey all, long time no see, but I just wanted to give a status update on what is going on with libss7. Last week I was able to commit my alarm detection code (in case you get an alarm on your spans that have signalling channels). It should restart the link when it comes out of alarm fine. I think I need to get some more testing in though, since I mostly just wrote the code and did very rudimentary testing on it. I also just added today support in zapata.conf for national_spare and international_spare networkindicator options in case your link uses the spare network indicator values (someone on the list today had a problem with that). 2 | 3 | On an entirely different note, I got an ANSI style link working this week!!!! I didn't ask permission to see if they minded being mentioned, so I won't mention any names for now, however it was a night to remember. It was over a 56kbps link channel, using an older switch. It went surprisingly easier than I thought it would. MTP2 was already working well, MTP3 only had slight modifications, and ISUP had the most changes. Other than the fact that I'd never seen a 56kbps link before. Basically, the difference was that they don't use the top bit in a DS0 timeslot for HDLC code. So if you want to try out libss7 on your ANSI link, this is how you do it: 4 | 5 | Disclaimer: You have to be using either a TE2xxp or TE4xxp for this to work, since I used the hardware hdlc features of the framer of that card to do the 56kbps link. 6 | 7 | Get current zaptel-trunk, libss7, and asterisk-ss7 from svn (You may also have to get libpri, I haven't checked if chan_zap compiles cleanly without libpri installed) 8 | Build them, and install them. 9 | 10 | If you are using 56kbps links, when you load the wct4xxp.ko module, you have to pass it the parameter hardhdlcmode=0x7f and instead of using "dchan" in zaptel.conf for your signalling channel, you need to use "hardhdlc" on that channel. 11 | 12 | In zapata.conf, setup your link following the pattern in the sample zapata.conf that comes with asterisk-ss7 and set your ss7type=ansi. That should pretty much be it. All the rest of the configuration is the same. 13 | 14 | As always, if you have any more questions, comments, requests, or anything else that matter, let me know. I'd love to get feedback. 15 | 16 | Matthew Fredrickson 17 | -------------------------------------------------------------------------------- /NEWS-09-27-2006: -------------------------------------------------------------------------------- 1 | Hey all, long time no update. I've had a lot of my time caught up in other projects of late, so I haven't had quite as much time to make major changes, however, here is a short list of things that have changed. First of all, if you haven't been monitoring the threads, with the release of the 1.4 beta branch, I was able to commit all of my asterisk-ss7 branch changes back into trunk. No, this does not mean that it will be in 1.4, but I'll probably be maintaining a 1.4 based branch with the ss7 changes once 1.4 is officially release. For now, if you want to play with libss7 and Asterisk, you will need to check out the trunk version of asterisk (`svn co http://svn.digium.com/svn/asterisk/trunk asterisk-trunk). You still need to have the trunk versions of zaptel (`svn co http://svn.digium.com/svn/zaptel/trunk zaptel-trunk`) or the 1.4 beta release as well as the trunk version of libss7 (`svn co http://svn.digium.com/svn/libss7/trunk libss7`). 2 | 3 | Feature wise, I just added support for doing remote block requests from the asterisk command line, with the "ss7 block cic " syntax. The first number is the linkset that you want to block the CIC on (from zapata.conf) and the second is the CIC on that linkset you wish to block. There is also a parallel unblock command (ss7 unblock cic ). I have been working some more on multilink support, so that's something we'll see in the future. I actually had a conference call with a couple of members of the community about SS7 and future development directions all over an ANSI ss7 link using libss7 and asterisk. It was a quite satisfying experience :-) The primary topics of conversation were regarding making asterisk be able to handle more trunks from one point code. These were the two basic directions for doing that that we thought of: 4 | 5 | The first was to add support in chan_zap (or a layer below that) for talking to MGCP gateways and being able to control them through that interface. The CICs on them would exist as "virtual" zap channels, and would be controlled as such. The media would just come in as RTP to asterisk, and everything would work very similarly to how things work right now. RTP re-invites could probably be done do take Asterisk out of the media as needed. It would require very little functionality changes within asterisk and the dialplan for that to work. 6 | 7 | The other direction was to add support for M3UA or a similar protocol to pass ISUP messages on a signalling gateway to other Asterisk boxes that actually terminate the CIC that is relevant to that particular message. This is useful, because then you could use asterisk as a media gateway as well as a signalling gateway, and is very much how asterisk likes to be anyways. 8 | 9 | On the whole it was fairly productive, as I have thought more about the second path, but the first one I had trouble conceptualizing how it would easily integrate in until we had that call. Now it seems to be a very technically attainable idea. As always, if anyone has any comments or suggestions, peer review is always welcome. 10 | 11 | Matthew Fredrickson 12 | 13 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | libss7: 2 | ======= 3 | libss7 is a userspace library that is used for providing SS7 protocol 4 | services to applications. It has a working MTP2, MTP3, and ISUP for 5 | ITU and ANSI style SS7, however it was written in a manner that will easily 6 | allow support for other various national specific variants 7 | in the future. For a working reference implementation, see the various 8 | link test programs, as well as the Asterisk Open Source PBX. 9 | 10 | License: 11 | ======== 12 | libss7 is covered under the GNU GPL (General Public License) version 2. For more 13 | information, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 14 | 15 | A few tested switches: 16 | ====================== 17 | Siemens EWSD - (ITU style) MTP2 and MTP3 comes up, ISUP inbound and outbound calls work as well. 18 | DTI DXC 4K - (ANSI style) 56kbps link, MTP2 and MTP3 come up, ISUP inbound and outbound calls work as well. 19 | Huawei M800 - (ITU style) MTP2 and MTP3 comes up, ISUP National, International inbound and outbound calls work as well, CallerID presentation&screening work. 20 | 21 | and many more... 22 | 23 | Some carriers integrated with: 24 | ============================== 25 | T-Systems Germany 26 | Etel 27 | COLT 28 | 29 | Thanks to: 30 | ========== 31 | Mark Spencer, for writing Asterisk and libpri and being such a great friend and boss. 32 | 33 | Luciano Ramos, for donating a link in getting the first "real" ITU switch working. 34 | 35 | Collin Rose and John Lodden, John for introducing me to Collin, and Collin for the first 36 | "real" ANSI link and for holding my hand through the remaining changes that had to be 37 | done for ANSI switches. 38 | 39 | Alan McMillan for numerous ANSI related updates, changes, testing, and additional parameter support. 40 | 41 | To Use: 42 | ======= 43 | In order to use libss7, you must get at least the following versions of DAHDI and Asterisk: 44 | DAHDI: 2.0.x 45 | libss7: 1.0.x 46 | Asterisk: 1.6.x 47 | 48 | You must then do a `make; make install` in each of the directories that you installed 49 | in the given order (DAHDI first, libss7 second, and Asterisk last). 50 | 51 | NOTE: In order to check out the code, you must have the subversion client installed. This 52 | is how to check them out from the public subversion server. 53 | 54 | These are the commands you would type to install them: 55 | 56 | `svn co http://svn.digium.com/svn/dahdi/linux/trunk dahdi-trunk` 57 | `cd dahdi-trunk` 58 | `make; make install` 59 | 60 | `svn co http://svn.digium.com/svn/dahdi/tools/trunk dahdi-tools` 61 | `cd dahdi-tools` 62 | `./configure; make; make install` 63 | 64 | `svn co http://svn.digium.com/svn/libss7/trunk libss7-trunk` 65 | `cd libss7-trunk` 66 | `make; make install` 67 | 68 | `svn co http://svn.digium.com/svn/asterisk/branches/1.6.0 asterisk-1.6.0` 69 | `cd asterisk-1.6.0` 70 | `./configure; make; make install;` 71 | 72 | This should build DAHDI, libss7, and Asterisk with SS7 support. 73 | 74 | In the past, there was a special asterisk-ss7 branch to use which contained the SS7 code. 75 | That code has been merged back into the trunk version of Asterisk, and the old asterisk-ss7 76 | branch has been deprecated and removed. If you are still using the asterisk-ss7 branch, it 77 | will not work against the current version of libss7, and you should switch to asterisk-trunk 78 | instead. 79 | 80 | CONFIGURATION: 81 | In /etc/dahdi/system.conf, your signalling channel(s) should be a "mtp2" (or "dchan" with a 82 | non Digium card) and your bearers should be set as "bchan". 83 | 84 | For example: 85 | span=1,1,0,esf,b8zs 86 | bchan=1-15,17-31 87 | mtp2=16 88 | #dchan=16 for non Digium cards 89 | 90 | NOTE: For 56k ANSI links, you must additionally set in /etc/dahdi/system.conf "56k=[channel number]" 91 | where 56k is like a flag for the mtp2 or dchan. 92 | 93 | For example: 94 | span=1,1,0,esf,b8zs 95 | bchan=1-23 96 | mtp2=24 97 | 56k=24 98 | 99 | In the sample config file in Asterisk-1.6, there is a sample SS7 setup which you can 100 | use to configured your link. 101 | 102 | In brief, here is a simple ss7 linkset setup: 103 | 104 | chan_dahdi.conf 105 | =========== 106 | signalling = ss7 107 | ss7type = itu ; or ansi if you are using an ANSI link 108 | 109 | linkset = 1 ; Pick a number for your linkset identifier in chan_dahdi.conf 110 | 111 | pointcode = 28 ; The decimal form of your point code. If you are using an 112 | ; ANSI linkset, you can use the xxx-xxx-xxx notation for 113 | ; specifying your linkset pointcode. 114 | adjpointcode = 2 ; The point code of the switch adjacent to your linkset 115 | 116 | defaultdpc = 3 ; The point code of the switch you want to send your ISUP 117 | ; traffic to. A lot of the time, this is the same as your 118 | ; adjpointcode. 119 | 120 | ; Now we configure our Bearer channels (CICs) 121 | 122 | cicbeginswith = 1 ; Number to start counting the CICs from. So if DAHDI/1 to 123 | ; DAHDI/15 are CICs 1-15, you would set this to 1 before you 124 | ; declare channel=1-15 125 | 126 | channel=1-15 ; Use DAHDI/1-15 and assign them to CICs 1-15 127 | 128 | cicbeginswith = 17 ; Now for DAHDI/17 to DAHDI/31, they are CICs 17-31 so we initialize 129 | ; cicbeginswith to 17 before we declare those channels 130 | 131 | channel = 17-31 ; This assigns CICs 17-31 to channels 17-31 132 | 133 | sigchan = 16 ; This is where you declare which DAHDI channel is your signalling 134 | ; channel. In our case it is DAHDI/16. You can add redundant 135 | ; signalling channels by adding additional sigchan= lines. 136 | 137 | ; If we want an alternate redundant signalling channel add this 138 | 139 | sigchan = 48 ; This would put two signalling channels in our linkset, one at 140 | ; DAHDI/16 and one at DAHDI/48 which both would be used to send/receive 141 | ; ISUP traffic. 142 | 143 | ; End of chan_dahdi.conf 144 | 145 | This is how a basic linkset is setup. For more detailed chan_dahdi.conf SS7 config information 146 | as well as other options available for that file, see the default chan_dahdi.conf that comes 147 | with the samples in asterisk. If you would like, you can do a `make samples` in your 148 | asterisk directory and it will install a sample chan_dahdi.conf for you that contains 149 | more information about SS7 setup. 150 | 151 | Asterisk channel variables which map to SS7 parameters: 152 | ======================================================= 153 | SS7_CHARGE_NUMBER 154 | SS7_GENERIC_ADDRESS 155 | SS7_JIP 156 | SS7_GENERIC_DIGITS 157 | SS7_GENERIC_DIGTYPE (type of generic digits) 158 | SS7_GENERIC_DIGSCHEME 159 | SS7_ORIG_CALLED_NUM 160 | 161 | SS7_LSPI_IDENT (these three are used for RLT support on DMS switches) 162 | SS7_CALLREF_IDENT 163 | SS7_CALLREF_PC 164 | 165 | SS7_CALLING_PARTY_CATEGORY 166 | SS7_REDIRECTING_NUMBER 167 | SS7_GENERIC_NAME 168 | 169 | Most are fairly self explanatory as far as what they contain. It is also possible to set 170 | many of these parameters on outbound calls as well by prefixing the variable with an '_' 171 | when you set it. 172 | 173 | 174 | Completed: 175 | ========== 176 | MTP2 - Retransmissions are done correctly now from both sides. 177 | Basic MTP3 178 | Basic call messages (IAM, ACM, ANM, REL, RLC) 179 | CIC Reset (GRS, GRA, RSC) 180 | Connect message (CON) 181 | CIC Blocking/Unblocking (CGB, CGBA, CGU, CGUA, BLO, BLA) 182 | Continuity Check (COT, CCR) 183 | Call Progress message (CPG) 184 | ANSI MTP2, MTP3, and ISUP, inbound and outbound calling works now. 185 | ITU style SS7 support 186 | ANSI-style signalling support 187 | Called and Calling Nature of Address Indicator 188 | CallerID presentation&screening 189 | UCIC and LPA messages 190 | ANI2 - Originating line interface parameter (ANSI) 191 | Charge number parameter (ANSI) 192 | Hop counter parameter 193 | Carrier identification parameter - (very simple, not configurable) 194 | SS7 debug looks *MUCH* nicer 195 | Kernel level MTP2 support (woohoo!) - See NEWS-05-30-2008 for more info 196 | * Many more messages are supported than are listed. isup.c is the best place to look. 197 | 198 | 199 | TODO: 200 | ===== 201 | short term: 202 | SUS/RES 203 | RDNIS 204 | Timer for last SU received so we know if layer2 goes out under us 205 | 206 | long term: 207 | SCTP support (seems more people are interested in that than SCCP) 208 | 209 | For more information, please use the Asterisk-ss7 or Asterisk-dev mailing 210 | lists (I monitor them regularly) or email me directly. 211 | 212 | Matthew Fredrickson 213 | creslin@digium.com 214 | 215 | -------------------------------------------------------------------------------- /build_tools/make_version: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -f ${1}/.version ]; then 4 | cat ${1}/.version 5 | elif [ -d .svn ]; then 6 | PARTS=`LANG=C svn info ${1} | ${GREP} URL | ${AWK} '{print $2;}' | sed -e 's:^.*/svn/libss7/::' | sed -e 's:/: :g'` 7 | BRANCH=0 8 | TEAM=0 9 | TAG=0 10 | 11 | REV=`svnversion -c ${1} | cut -d: -f2` 12 | 13 | BASE=`LANG=C svn pg svnmerge-integrated ${1} | cut -d: -f1` 14 | 15 | if [ "${PARTS}" = "trunk" ] ; then 16 | echo SVN-trunk-r${REV} 17 | exit 0 18 | fi 19 | 20 | for PART in $PARTS ; do 21 | if [ ${TAG} != 0 ] ; then 22 | if [ "${PART}" = "autotag_for_be" ] ; then 23 | continue 24 | fi 25 | if [ "${PART}" = "autotag_for_sx00i" ] ; then 26 | continue 27 | fi 28 | RESULT="${PART}" 29 | break 30 | fi 31 | 32 | if [ ${BRANCH} != 0 ] ; then 33 | if [ -z ${RESULT} ] ; then 34 | RESULT="${PART}" 35 | else 36 | RESULT="${RESULT}-${PART}" 37 | fi 38 | break 39 | fi 40 | 41 | if [ ${TEAM} != 0 ] ; then 42 | if [ -z ${RESULT} ] ; then 43 | RESULT="${PART}" 44 | else 45 | RESULT="${RESULT}-${PART}" 46 | fi 47 | continue 48 | fi 49 | 50 | if [ "${PART}" = "branches" ] ; then 51 | BRANCH=1 52 | RESULT="branch" 53 | continue 54 | fi 55 | 56 | if [ "${PART}" = "tags" ] ; then 57 | TAG=1 58 | continue 59 | fi 60 | 61 | if [ "${PART}" = "team" ] ; then 62 | TEAM=1 63 | continue 64 | fi 65 | done 66 | 67 | if [ ${TAG} != 0 ] ; then 68 | echo ${RESULT} 69 | else 70 | echo SVN-${RESULT}-r${REV}${BASE:+-${BASE}} 71 | fi 72 | fi 73 | -------------------------------------------------------------------------------- /build_tools/make_version_c: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ ! -f ../.flavor ]; then 3 | EXTRA="" 4 | else 5 | aadkver=`cat ../.version` 6 | aadkflavor=`cat ../.flavor` 7 | EXTRA=" (${aadkflavor} ${aadkver})" 8 | fi 9 | cat << END 10 | /* 11 | * version.c 12 | * Automatically generated 13 | */ 14 | 15 | #include "libss7.h" 16 | 17 | static const char ss7_version[] = "${SS7VERSION}${EXTRA}"; 18 | 19 | const char *ss7_get_version(void) 20 | { 21 | return ss7_version; 22 | } 23 | 24 | END 25 | -------------------------------------------------------------------------------- /isup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #ifndef _SS7_ISUP_H 33 | #define _SS7_ISUP_H 34 | 35 | #include "ss7_internal.h" 36 | 37 | /* ISUP messages */ 38 | #define ISUP_IAM 0x01 /*!< Initial address */ 39 | #define ISUP_SAM 0x02 /*!< Subsequent address */ 40 | #define ISUP_INR 0x03 /*!< Information request (national use) */ 41 | #define ISUP_INF 0x04 /*!< Information (national use) */ 42 | #define ISUP_COT 0x05 /*!< Continuity */ 43 | #define ISUP_ACM 0x06 /*!< Address complete */ 44 | #define ISUP_CON 0x07 /*!< Connect */ 45 | #define ISUP_FOT 0x08 /*!< Forward transfer */ 46 | #define ISUP_ANM 0x09 /*!< Answer */ 47 | #define ISUP_REL 0x0c /*!< Release */ 48 | #define ISUP_SUS 0x0d /*!< Suspend */ 49 | #define ISUP_RES 0x0e /*!< Resume */ 50 | #define ISUP_RLC 0x10 /*!< Release complete */ 51 | #define ISUP_CCR 0x11 /*!< Continuity check request */ 52 | #define ISUP_RSC 0x12 /*!< Reset circuit */ 53 | #define ISUP_BLO 0x13 /*!< Blocking */ 54 | #define ISUP_UBL 0x14 /*!< Unblocking */ 55 | #define ISUP_BLA 0x15 /*!< Blocking acknowledgement */ 56 | #define ISUP_UBA 0x16 /*!< Unblocking acknowledgement */ 57 | #define ISUP_GRS 0x17 /*!< Circuit group reset */ 58 | #define ISUP_CGB 0x18 /*!< Circuit group blocking */ 59 | #define ISUP_CGU 0x19 /*!< Circuit group unblocking */ 60 | #define ISUP_CGBA 0x1a /*!< Circuit group blocking acknowledgement */ 61 | #define ISUP_CGUA 0x1b /*!< Circuit group unblocking acknowledgement */ 62 | #define ISUP_CMR 0x1c /*!< Reserved (used in 1988 version) */ 63 | #define ISUP_CMC 0x1d /*!< Reserved (used in 1988 version) */ 64 | #define ISUP_CMRJ 0x1e /*!< Reserved (used in 1988 version) */ 65 | #define ISUP_FAR 0x1f /*!< Facility request */ 66 | #define ISUP_FAA 0x20 /*!< Facility accepted */ 67 | #define ISUP_FRJ 0x21 /*!< Facility reject */ 68 | #define ISUP_FAD 0x22 /*!< Reserved (used in 1984 version) */ 69 | #define ISUP_FAI 0x23 /*!< Reserved (used in 1984 version) */ 70 | #define ISUP_LPA 0x24 /*!< Loop back acknowledgement (national use) */ 71 | #define ISUP_CSVR 0x25 /*!< Reserved (used in 1984 version) */ 72 | #define ISUP_CSVS 0x26 /*!< Reserved (used in 1984 version) */ 73 | #define ISUP_DRS 0x27 /*!< Reserved (used in 1988 version) */ 74 | #define ISUP_PAM 0x28 /*!< Pass-along (national use) */ 75 | #define ISUP_GRA 0x29 /*!< Circuit group reset acknowledgement */ 76 | #define ISUP_CQM 0x2a /*!< Circuit group query (national use) */ 77 | #define ISUP_CQR 0x2b /*!< Circuit group query response (national use) */ 78 | #define ISUP_CPG 0x2c /*!< Call progress */ 79 | #define ISUP_USR 0x2d /*!< User-to-user information */ 80 | #define ISUP_UCIC 0x2e /*!< Unequipped CIC (national use) */ 81 | #define ISUP_CFN 0x2f /*!< Confusion */ 82 | #define ISUP_OLM 0x30 /*!< Overload (national use) */ 83 | #define ISUP_CRG 0x31 /*!< Charge information (national use) */ 84 | #define ISUP_FAC 0x33 /*!< Facility */ 85 | #define ISUP_CRA 0xe9 /*!< ??? */ 86 | #define ISUP_CRM 0xea /*!< ??? */ 87 | #define ISUP_CVR 0xeb /*!< ???Used??? */ 88 | #define ISUP_CVT 0xec /*!< ???Used??? */ 89 | #define ISUP_EXM 0xed /*!< ??? */ 90 | 91 | 92 | /* ISUP Parameters ITU-T Q.763 */ 93 | #define ISUP_PARM_CALL_REF 0x01 94 | #define ISUP_PARM_TRANSMISSION_MEDIUM_REQS 0x02 95 | #define ISUP_PARM_ACCESS_TRANS 0x03 96 | #define ISUP_PARM_CALLED_PARTY_NUM 0x04 97 | #define ISUP_PARM_SUBSEQUENT_NUMBER 0x05 98 | #define ISUP_PARM_NATURE_OF_CONNECTION_IND 0x06 99 | #define ISUP_PARM_FORWARD_CALL_IND 0x07 100 | #define ISUP_PARM_OPT_FORWARD_CALL_INDICATOR 0x08 101 | #define ISUP_PARM_CALLING_PARTY_CAT 0x09 102 | #define ISUP_PARM_CALLING_PARTY_NUM 0x0a 103 | #define ISUP_PARM_REDIRECTING_NUMBER 0x0b 104 | #define ISUP_PARM_REDIRECTION_NUMBER 0x0c 105 | #define ISUP_PARM_CONNECTION_REQ 0x0d 106 | #define ISUP_PARM_INR_IND 0x0e 107 | #define ISUP_PARM_INF_IND 0x0f 108 | #define ISUP_PARM_CONTINUITY_IND 0x10 109 | #define ISUP_PARM_BACKWARD_CALL_IND 0x11 110 | #define ISUP_PARM_CAUSE 0x12 111 | #define ISUP_PARM_REDIRECTION_INFO 0x13 112 | /* 0x14 is Reserved / Event information */ 113 | #define ISUP_PARM_CIRCUIT_GROUP_SUPERVISION_IND 0x15 114 | #define ISUP_PARM_RANGE_AND_STATUS 0x16 115 | #define ISUP_PARM_CALL_MODIFICATION_IND 0x17 116 | #define ISUP_PARM_FACILITY_IND 0x18 117 | /* 0x19 is Reserved */ 118 | #define ISUP_PARM_CUG_INTERLOCK_CODE 0x1a 119 | /* 0x1b is Reserved */ 120 | /* 0x1c is Reserved */ 121 | #define ISUP_PARM_USER_SERVICE_INFO 0x1d 122 | #define ISUP_PARM_SIGNALLING_PC 0x1e 123 | /* 0x1f is Reserved */ 124 | #define ISUP_PARM_USER_TO_USER_INFO 0x20 125 | #define ISUP_CONNECTED_NUMBER 0x21 126 | #define ISUP_PARM_SUSPEND_RESUME_IND 0x22 127 | #define ISUP_PARM_TRANSIT_NETWORK_SELECTION 0x23 128 | #define ISUP_PARM_EVENT_INFO 0x24 129 | #define ISUP_PARM_CIRCUIT_ASSIGNMENT_MAP 0x25 130 | #define ISUP_PARM_CIRCUIT_STATE_IND 0x26 131 | #define ISUP_PARAM_AUTOMATIC_CONGESTION_LEVEL 0x27 132 | #define ISUP_PARM_ORIGINAL_CALLED_NUM 0x28 133 | #define ISUP_PARM_OPT_BACKWARD_CALL_IND 0x29 134 | #define ISUP_PARM_USER_TO_USER_IND 0x2a 135 | #define ISUP_PARM_ORIGINATION_ISC_PC 0x2b 136 | #define ISUP_PARM_GENERIC_NOTIFICATION_IND 0x2c 137 | #define ISUP_PARM_CALL_HISTORY_INFO 0x2d 138 | #define ISUP_PARM_ACCESS_DELIVERY_INFO 0x2e 139 | #define ISUP_PARM_NETWORK_SPECIFIC_FACILITY 0x2f 140 | #define ISUP_PARM_USER_SERVICE_INFO_PRIME 0x30 141 | #define ISUP_PARM_PROPAGATION_DELAY 0x31 142 | #define ISUP_PARM_REMOTE_OPERATIONS 0x32 143 | #define ISUP_PARM_SERVICE_ACTIVATION 0x33 144 | #define ISUP_PARM_USER_TELESERVICE_INFO 0x34 145 | #define ISUP_PARM_TRANSMISSION_MEDIUM_USED 0x35 146 | #define ISUP_PARM_CALL_DIVERSION_INFO 0x36 147 | #define ISUP_PARM_ECHO_CONTROL_INFO 0x37 148 | #define ISUP_PARM_MESSAGE_COMPAT_INFO 0x38 149 | #define ISUP_PARM_PARAMETER_COMPAT_INFO 0x39 150 | #define ISUP_PARM_MLPP_PRECEDENCE 0x3a 151 | #define ISUP_PARM_MCID_REQUEST_IND 0x3b 152 | #define ISUP_PARM_MCID_RESPONSE_IND 0x3c 153 | #define ISUP_PARM_HOP_COUNTER 0x3d 154 | #define ISUP_PARM_TRANSMISSION_MEDIUM_REQ_PRIME 0x3e 155 | #define ISUP_PARM_LOCATION_NUMBER 0x3f 156 | 157 | #define ISUP_PARM_REDIRECTION_NUM_RESTRICTION 0x40 158 | 159 | #define ISUP_PARM_CALL_TRANSFER_REFERENCE 0x43 160 | #define ISUP_PARM_LOOP_PREVENTION_IND 0x44 161 | #define ISUP_PARM_CALL_TRANSFER_NUMBER 0x45 162 | 163 | #define ISUP_PARM_CCSS 0x4b 164 | #define ISUP_PARM_FORWARD_GVNS 0x4c 165 | #define ISUP_PARM_BACKWARD_GVNS 0x4d 166 | #define ISUP_PARM_REDIRECT_CAPABILITY 0x4e 167 | 168 | #define ISUP_PARM_NETWORK_MANAGEMENT_CONTROL 0x5b 169 | 170 | #define ISUP_PARM_CORRELATION_ID 0x65 171 | #define ISUP_PARM_SCF_ID 0x66 172 | 173 | #define ISUP_PARM_CALL_DIVERSION_TREATMENT_IND 0x6e 174 | #define ISUP_PARM_CALLED_IN_NUMBER 0x6f 175 | #define ISUP_PARM_CALL_OFFERING_TREATMENT_IND 0x70 176 | #define ISUP_PARM_CHARGED_PARTY_IDENT 0x71 177 | #define ISUP_PARM_CONFERENCE_TREATMENT_IND 0x72 178 | #define ISUP_PARM_DISPLAY_INFO 0x73 179 | #define ISUP_PARM_UID_ACTION_IND 0x74 180 | #define ISUP_PARM_UID_CAPABILITY_IND 0x75 181 | 182 | #define ISUP_PARM_REDIRECT_COUNTER 0x77 183 | #define ISUP_PARM_APPLICATION_TRANSPORT 0x78 184 | #define ISUP_PARM_COLLECT_CALL_REQUEST 0x79 185 | #define ISUP_PARM_CCNR_POSSIBLE_IND 0x7a 186 | #define ISUP_PARM_PIVOT_CAPABILITY 0x7b 187 | #define ISUP_PARM_PIVOT_ROUTING_IND 0x7c 188 | #define ISUP_PARM_CALLED_DIRECTORY_NUMBER 0x7d 189 | 190 | #define ISUP_PARM_ORIGINAL_CALLED_IN_NUM 0x7f 191 | /* 0x80 reserved for future extension */ 192 | #define ISUP_PARM_CALLING_GEODETIC_LOCATION 0x81 193 | #define ISUP_PARM_HTR_INFO 0x82 194 | 195 | #define ISUP_PARM_NETWORK_ROUTING_NUMBER 0x84 196 | #define ISUP_PARM_QUERY_ON_RELEASE_CAPABILITY 0x85 197 | #define ISUP_PARM_PIVOT_STATUS 0x86 198 | #define ISUP_PARM_PIVOT_COUNTER 0x87 199 | #define ISUP_PARM_PIVOT_ROUTING_FORWARD_IND 0x88 200 | #define ISUP_PARM_PIVOT_ROUTING_BACKWARD_IND 0x89 201 | #define ISUP_PARM_REDIRECT_STATUS 0x8a 202 | #define ISUP_PARM_REDIRECT_FORWARD_INFO 0x8b 203 | #define ISUP_PARM_REDIRECT_BACKWARD_INFO 0x8c 204 | #define ISUP_PARM_NUM_PORTABILITY_FORWARD_INFO 0x8d 205 | 206 | #define ISUP_PARM_GENERIC_ADDR 0xc0 207 | #define ISUP_PARM_GENERIC_DIGITS 0xc1 208 | 209 | #define ISUP_PARM_EGRESS_SERV 0xc3 210 | #define ISUP_PARM_JIP 0xc4 211 | #define ISUP_PARM_CARRIER_ID 0xc5 212 | #define ISUP_PARM_BUSINESS_GRP 0xc6 213 | #define ISUP_PARM_GENERIC_NAME 0xc7 214 | 215 | #define ISUP_PARM_LOCAL_SERVICE_PROVIDER_IDENTIFICATION 0xe4 216 | 217 | #define ISUP_PARM_ORIG_LINE_INFO 0xea 218 | #define ISUP_PARM_CHARGE_NUMBER 0xeb 219 | 220 | #define ISUP_PARM_SELECTION_INFO 0xee 221 | 222 | 223 | /* ISUP TIMERS */ 224 | #define ISUP_TIMER_T1 1 225 | #define ISUP_TIMER_T2 2 226 | #define ISUP_TIMER_T5 5 227 | #define ISUP_TIMER_T6 6 228 | #define ISUP_TIMER_T7 7 229 | #define ISUP_TIMER_T8 8 230 | #define ISUP_TIMER_T10 10 231 | #define ISUP_TIMER_T12 12 232 | #define ISUP_TIMER_T13 13 233 | #define ISUP_TIMER_T14 14 234 | #define ISUP_TIMER_T15 15 235 | #define ISUP_TIMER_T16 16 236 | #define ISUP_TIMER_T17 17 237 | #define ISUP_TIMER_T18 18 238 | #define ISUP_TIMER_T19 19 239 | #define ISUP_TIMER_T20 20 240 | #define ISUP_TIMER_T21 21 241 | #define ISUP_TIMER_T22 22 242 | #define ISUP_TIMER_T23 23 243 | #define ISUP_TIMER_T27 27 244 | #define ISUP_TIMER_T33 33 245 | #define ISUP_TIMER_T35 35 246 | 247 | /* ISUP Parameter Pseudo-type */ 248 | struct isup_parm_opt { 249 | unsigned char type; 250 | unsigned char len; 251 | unsigned char data[0]; 252 | }; 253 | 254 | struct isup_h { 255 | unsigned char cic[2]; 256 | unsigned char type; 257 | unsigned char data[0]; /* This is the contents of the message */ 258 | }; 259 | 260 | #define CIC_SIZE 2 261 | #define ISUP_MAX_NUM 64 262 | /* From GR-317 for the generic name filed: 15 + 1 */ 263 | #define ISUP_MAX_NAME 16 264 | 265 | struct mtp2; 266 | 267 | struct isup_call { 268 | char called_party_num[ISUP_MAX_NUM]; 269 | unsigned char called_nai; 270 | char calling_party_num[ISUP_MAX_NUM]; 271 | unsigned char calling_party_cat; 272 | unsigned char calling_nai; 273 | unsigned char presentation_ind; 274 | unsigned char screening_ind; 275 | char charge_number[ISUP_MAX_NUM]; 276 | unsigned char charge_nai; 277 | unsigned char charge_num_plan; 278 | unsigned char gen_add_num_plan; 279 | unsigned char gen_add_nai; 280 | char gen_add_number[ISUP_MAX_NUM]; 281 | unsigned char gen_add_pres_ind; 282 | unsigned char gen_add_type; 283 | char gen_dig_number[ISUP_MAX_NUM]; 284 | unsigned char gen_dig_type; 285 | unsigned char gen_dig_scheme; 286 | char jip_number[ISUP_MAX_NUM]; 287 | unsigned char lspi_type; 288 | unsigned char lspi_scheme; 289 | unsigned char lspi_context; 290 | unsigned char lspi_spare; 291 | char lspi_ident[ISUP_MAX_NUM]; 292 | int oli_ani2; 293 | unsigned int call_ref_ident; 294 | unsigned int call_ref_pc; 295 | char orig_called_num[ISUP_MAX_NUM]; 296 | unsigned char orig_called_nai; 297 | unsigned char orig_called_pres_ind; 298 | unsigned char orig_called_screening_ind; 299 | char redirecting_num[ISUP_MAX_NUM]; 300 | unsigned char redirecting_num_nai; 301 | unsigned char redirecting_num_presentation_ind; 302 | unsigned char redirecting_num_screening_ind; 303 | unsigned char redirect_counter; 304 | unsigned char redirect_info; 305 | unsigned char redirect_info_ind; 306 | unsigned char redirect_info_orig_reas; 307 | unsigned char redirect_info_counter; 308 | unsigned char redirect_info_reas; 309 | unsigned char generic_name_typeofname; 310 | unsigned char generic_name_avail; 311 | unsigned char generic_name_presentation; 312 | char connected_num[ISUP_MAX_NUM]; 313 | unsigned char connected_nai; 314 | unsigned char connected_presentation_ind; 315 | unsigned char connected_screening_ind; 316 | char generic_name[ISUP_MAX_NAME]; 317 | int range; 318 | unsigned char sent_cgb_status[255]; 319 | unsigned char sent_cgu_status[255]; 320 | unsigned char status[255]; 321 | int transcap; 322 | int l1prot; 323 | int cause; 324 | int causecode; 325 | int causeloc; 326 | int cot_check_passed; 327 | int cot_check_required; 328 | int cot_performed_on_previous_cic; 329 | int cicgroupsupervisiontype; 330 | unsigned char event_info; 331 | unsigned short cic; 332 | unsigned char sls; 333 | unsigned long got_sent_msg; /* flags for sent msgs */ 334 | int sent_cgb_type; 335 | int sent_cgu_type; 336 | int sent_grs_endcic; 337 | int sent_cgb_endcic; 338 | int sent_cgu_endcic; 339 | struct isup_call *next; 340 | /* set DPC according to CIC's DPC, not linkset */ 341 | unsigned int dpc; 342 | /* Backward Call Indicator variables */ 343 | unsigned char called_party_status_ind; 344 | unsigned char local_echocontrol_ind; 345 | unsigned char echocontrol_ind; 346 | /* Suspend/Resume Indicator */ 347 | int network_isdn_indicator; 348 | unsigned char inr_ind[2]; 349 | unsigned char inf_ind[2]; 350 | unsigned char cug_indicator; 351 | unsigned col_req; 352 | char cug_interlock_ni[5]; 353 | unsigned short cug_interlock_code; 354 | unsigned char interworking_indicator; 355 | unsigned char forward_indicator_pmbits; 356 | int timer[ISUP_MAX_TIMERS]; 357 | }; 358 | 359 | int isup_receive(struct ss7 *ss7, struct mtp2 *sl, struct routing_label *rl, unsigned char *sif, int len); 360 | 361 | int isup_dump(struct ss7 *ss7, struct mtp2 *sl, unsigned char *sif, int len); 362 | 363 | void isup_free_all_calls(struct ss7 *ss7); 364 | 365 | #endif /* _SS7_ISUP_H */ 366 | -------------------------------------------------------------------------------- /libss7.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #ifndef _LIBSS7_H 33 | #define _LIBSS7_H 34 | 35 | /*! 36 | * Bump this for each libss7 Application Binary Interface (ABI) 37 | * change that makes the ABI/API incompatible with previous 38 | * versions. This is expected to just be the major version of 39 | * the libss7 branches. 40 | */ 41 | #define LIBSS7_ABI_COMPATIBILITY 2 42 | 43 | 44 | /* Internal -- MTP2 events */ 45 | #define SS7_EVENT_UP 1 /*!< SS7 link up */ 46 | #define SS7_EVENT_DOWN 2 /*!< SS7 link down */ 47 | #define MTP2_LINK_UP 3 /*!< MTP layer 2 up */ 48 | #define MTP2_LINK_DOWN 4 /*!< MTP layer 2 down */ 49 | #define ISUP_EVENT_IAM 5 /*!< Initial address */ 50 | #define ISUP_EVENT_ACM 6 /*!< Address complete */ 51 | #define ISUP_EVENT_ANM 7 /*!< Answer */ 52 | #define ISUP_EVENT_REL 8 /*!< Release */ 53 | #define ISUP_EVENT_RLC 9 /*!< Release complete */ 54 | #define ISUP_EVENT_GRS 10 /*!< Circuit group reset */ 55 | #define ISUP_EVENT_GRA 11 /*!< Circuit group reset acknowledgement */ 56 | #define ISUP_EVENT_CON 12 /*!< Connect */ 57 | #define ISUP_EVENT_COT 13 /*!< Continuity */ 58 | #define ISUP_EVENT_CCR 14 /*!< Continuity check request */ 59 | #define ISUP_EVENT_BLO 15 /*!< Blocking */ 60 | #define ISUP_EVENT_UBL 16 /*!< Unblocking */ 61 | #define ISUP_EVENT_BLA 17 /*!< Blocking acknowledgement */ 62 | #define ISUP_EVENT_UBA 18 /*!< Unblocking acknowledgement */ 63 | #define ISUP_EVENT_CGB 19 /*!< Circuit group blocking */ 64 | #define ISUP_EVENT_CGU 20 /*!< Circuit group unblocking */ 65 | #define ISUP_EVENT_RSC 21 /*!< Reset circuit */ 66 | #define ISUP_EVENT_CPG 22 /*!< Call progress */ 67 | #define ISUP_EVENT_UCIC 23 /*!< Unequipped CIC (national use) */ 68 | #define ISUP_EVENT_LPA 24 /*!< Loop back acknowledgement (national use) */ 69 | #define ISUP_EVENT_CQM 25 /*!< Circuit group query (national use) */ 70 | #define ISUP_EVENT_FAR 26 /*!< Facility request */ 71 | #define ISUP_EVENT_FAA 27 /*!< Facility accepted */ 72 | #define ISUP_EVENT_CVT 28 /*!< ???Used??? */ 73 | #define ISUP_EVENT_CVR 29 /*!< Not used */ 74 | #define ISUP_EVENT_SUS 30 /*!< Suspend */ 75 | #define ISUP_EVENT_RES 31 /*!< Resume */ 76 | #define ISUP_EVENT_CGBA 32 /*!< Circuit group blocking acknowledgement */ 77 | #define ISUP_EVENT_CGUA 33 /*!< Circuit group unblocking acknowledgement */ 78 | #define ISUP_EVENT_SAM 34 /*!< Subsequent address */ 79 | #define ISUP_EVENT_DIGITTIMEOUT 35 /*!< ISUP T10 expired */ 80 | #define ISUP_EVENT_FRJ 36 /*!< Facility rejected */ 81 | 82 | /* ISUP MSG Flags */ 83 | #define ISUP_SENT_GRS (1 << 0) 84 | #define ISUP_SENT_CGB (1 << 1) 85 | #define ISUP_SENT_CGU (1 << 2) 86 | #define ISUP_SENT_RSC (1 << 3) 87 | #define ISUP_SENT_REL (1 << 4) 88 | #define ISUP_SENT_BLO (1 << 5) 89 | #define ISUP_SENT_UBL (1 << 6) 90 | #define ISUP_SENT_IAM (1 << 7) 91 | #define ISUP_SENT_FAR (1 << 8) 92 | #define ISUP_GOT_CCR (1 << 9) 93 | #define ISUP_GOT_IAM (1 << 10) 94 | #define ISUP_GOT_ACM (1 << 11) 95 | #define ISUP_GOT_CON (1 << 12) 96 | #define ISUP_GOT_ANM (1 << 13) 97 | #define ISUP_SENT_ACM (1 << 14) 98 | #define ISUP_GOT_CGB (1 << 15) 99 | #define ISUP_GOT_CGU (1 << 16) 100 | #define ISUP_SENT_CON (1 << 17) 101 | #define ISUP_SENT_ANM (1 << 18) 102 | #define ISUP_SENT_INR (1 << 19) 103 | #define ISUP_SENT_GRS2 (1 << 20) 104 | #define ISUP_PENDING_IAM (1 << 21) 105 | 106 | #define ISUP_CALL_CONNECTED (ISUP_GOT_ACM | ISUP_GOT_ANM | ISUP_GOT_CON | ISUP_SENT_CON | ISUP_SENT_ACM | ISUP_SENT_ANM) 107 | #define ISUP_CALL_PENDING (ISUP_GOT_IAM | ISUP_SENT_IAM | ISUP_PENDING_IAM | ISUP_GOT_CCR | ISUP_SENT_INR | ISUP_SENT_FAR) 108 | 109 | /* Different SS7 types */ 110 | #define SS7_ITU (1 << 0) 111 | #define SS7_ANSI (1 << 1) 112 | 113 | /* Debug levels */ 114 | #define SS7_DEBUG_MTP2 (1 << 0) 115 | #define SS7_DEBUG_MTP3 (1 << 1) 116 | #define SS7_DEBUG_ISUP (1 << 2) 117 | 118 | /* Network indicator */ 119 | #define SS7_NI_INT 0x00 120 | #define SS7_NI_INT_SPARE 0x01 121 | #define SS7_NI_NAT 0x02 122 | #define SS7_NI_NAT_SPARE 0x03 123 | 124 | /* Nature of Address Indicator */ 125 | #define SS7_NAI_SUBSCRIBER 0x01 126 | #define SS7_NAI_UNKNOWN 0x02 127 | #define SS7_NAI_NATIONAL 0x03 128 | #define SS7_NAI_INTERNATIONAL 0x04 129 | #define SS7_NAI_NETWORKROUTED 0x08 130 | 131 | /* Charge Number Nature of Address Indicator ANSI */ 132 | #define SS7_ANI_CALLING_PARTY_SUB_NUMBER 0x01 /* ANI of the calling party; subscriber number */ 133 | #define SS7_ANI_NOTAVAIL_OR_NOTPROVIDED 0x02 /* ANI not available or not provided */ 134 | #define SS7_ANI_CALLING_PARTY_NATIONAL_NUMBER 0x03 /* ANI of the calling party; national number */ 135 | #define SS7_ANI_CALLED_PARTY_SUB_NUMBER 0x05 /* ANI of the called party; subscriber number */ 136 | #define SS7_ANI_CALLED_PARTY_NOT_PRESENT 0x06 /* ANI of the called party; no number present */ 137 | #define SS7_ANI_CALLED_PARTY_NATIONAL_NUMBER 0x07 /* ANT of the called patty; national number */ 138 | 139 | /* Address Presentation */ 140 | #define SS7_PRESENTATION_ALLOWED 0x00 141 | #define SS7_PRESENTATION_RESTRICTED 0x01 142 | #define SS7_PRESENTATION_ADDR_NOT_AVAILABLE 0x02 143 | 144 | /* Screening */ 145 | #define SS7_SCREENING_USER_PROVIDED_NOT_VERIFIED 0x00 146 | #define SS7_SCREENING_USER_PROVIDED 0x01 147 | #define SS7_SCREENING_NETWORK_PROVIDED_FAILED 0x02 148 | #define SS7_SCREENING_NETWORK_PROVIDED 0x03 149 | 150 | /* Transmission Medium Requirement */ 151 | #define SS7_TMR_SPEECH 0x00 152 | #define SS7_TMR_SPARE 0x01 153 | #define SS7_TMR_64K_UNRESTRICTED 0x02 154 | #define SS7_TMR_3K1_AUDIO 0x03 155 | #define SS7_TMR_N64K_OR_SPARE 0x04 156 | 157 | /* CPG parameter types */ 158 | #define CPG_EVENT_ALERTING 0x01 159 | #define CPG_EVENT_PROGRESS 0x02 160 | #define CPG_EVENT_INBANDINFO 0x03 161 | #define CPG_EVENT_CFB 0x04 162 | #define CPG_EVENT_CFNR 0x05 163 | #define CPG_EVENT_CFU 0x06 164 | 165 | /* SS7 transport types */ 166 | #define SS7_TRANSPORT_DAHDIDCHAN 0 167 | #define SS7_TRANSPORT_DAHDIMTP2 1 168 | #define SS7_TRANSPORT_TCP 2 169 | 170 | /* What have to do after the hangup */ 171 | #define SS7_HANGUP_DO_NOTHING 0 172 | #define SS7_HANGUP_SEND_REL 1 173 | #define SS7_HANGUP_SEND_RSC 2 174 | #define SS7_HANGUP_SEND_RLC 3 175 | #define SS7_HANGUP_FREE_CALL 4 176 | #define SS7_HANGUP_REEVENT_IAM 5 177 | 178 | /* Special SS7 Hangupcause */ 179 | #define SS7_CAUSE_TRY_AGAIN 256 180 | 181 | /* return values from ss7_hangup */ 182 | #define SS7_CIC_NOT_EXISTS 0 183 | #define SS7_CIC_USED 1 184 | #define SS7_CIC_IDLE 2 185 | 186 | /* Closed user group indicator */ 187 | #define ISUP_CUG_NON 0 188 | #define ISUP_CUG_OUTGOING_ALLOWED 2 189 | #define ISUP_CUG_OUTGOING_NOT_ALLOWED 3 190 | 191 | /* FLAGS */ 192 | #define SS7_INR_IF_NO_CALLING (1 << 0) /* request calling num, if the remote party didn't send */ 193 | #define SS7_ISDN_ACCESS_INDICATOR (1 << 1) /* originating/access indicator */ 194 | 195 | struct ss7; 196 | struct isup_call; 197 | 198 | typedef struct { 199 | int e; 200 | int cic; 201 | int transcap; 202 | int cot_check_required; 203 | int cot_performed_on_previous_cic; 204 | char called_party_num[50]; 205 | unsigned char called_nai; 206 | char calling_party_num[50]; 207 | unsigned char calling_party_cat; 208 | unsigned char calling_nai; 209 | unsigned char presentation_ind; 210 | unsigned char screening_ind; 211 | char charge_number[50]; 212 | unsigned char charge_nai; 213 | unsigned char charge_num_plan; 214 | unsigned char gen_add_num_plan; 215 | unsigned char gen_add_nai; 216 | char gen_add_number[50]; 217 | unsigned char gen_add_pres_ind; 218 | unsigned char gen_add_type; 219 | char gen_dig_number[50]; 220 | unsigned char gen_dig_type; 221 | unsigned char gen_dig_scheme; 222 | char jip_number[50]; 223 | unsigned char lspi_type; 224 | unsigned char lspi_scheme; 225 | unsigned char lspi_context; 226 | unsigned char lspi_spare; 227 | char lspi_ident[50]; 228 | /* If orig_called_num contains a valid number, consider the other orig_called* values valid */ 229 | char orig_called_num[50]; 230 | unsigned char orig_called_nai; 231 | unsigned char orig_called_pres_ind; 232 | unsigned char orig_called_screening_ind; 233 | char redirecting_num[50]; 234 | unsigned char redirecting_num_nai; 235 | unsigned char redirecting_num_presentation_ind; 236 | unsigned char redirecting_num_screening_ind; 237 | unsigned char redirect_counter; 238 | unsigned char redirect_info; 239 | unsigned char redirect_info_ind; 240 | unsigned char redirect_info_orig_reas; 241 | unsigned char redirect_info_reas; 242 | unsigned char redirect_info_counter; 243 | unsigned char generic_name_typeofname; 244 | unsigned char generic_name_avail; 245 | unsigned char generic_name_presentation; 246 | unsigned char echocontrol_ind; 247 | char generic_name[50]; 248 | int oli_ani2; 249 | unsigned char cug_indicator; 250 | char cug_interlock_ni[5]; 251 | unsigned short cug_interlock_code; 252 | unsigned int opc; 253 | unsigned long got_sent_msg; 254 | struct isup_call *call; 255 | } ss7_event_iam; 256 | 257 | typedef struct { 258 | int e; 259 | int cic; 260 | int cause; 261 | unsigned int opc; 262 | unsigned long got_sent_msg; 263 | struct isup_call *call; 264 | } ss7_event_rel; 265 | 266 | typedef struct { 267 | int e; 268 | int cic; 269 | unsigned int opc; 270 | unsigned long got_sent_msg; 271 | struct isup_call *call; 272 | } ss7_event_cic; 273 | 274 | typedef struct { 275 | int e; 276 | int cic; 277 | unsigned int opc; 278 | unsigned long got_sent_msg; 279 | struct isup_call *call; 280 | char connected_num[50]; 281 | unsigned char connected_nai; 282 | unsigned char connected_presentation_ind; 283 | unsigned char connected_screening_ind; 284 | unsigned char echocontrol_ind; 285 | } ss7_event_con; 286 | 287 | typedef struct { 288 | int e; 289 | int cic; 290 | unsigned int opc; 291 | unsigned long got_sent_msg; 292 | struct isup_call *call; 293 | } ss7_event_rsc; 294 | 295 | typedef struct { 296 | int e; 297 | int cic; 298 | unsigned int opc; 299 | char connected_num[50]; 300 | unsigned char connected_nai; 301 | unsigned char connected_presentation_ind; 302 | unsigned char connected_screening_ind; 303 | unsigned long got_sent_msg; 304 | unsigned char echocontrol_ind; 305 | struct isup_call *call; 306 | } ss7_event_anm; 307 | 308 | typedef struct { 309 | int e; 310 | int cic; 311 | unsigned int call_ref_ident; 312 | unsigned int call_ref_pc; 313 | unsigned int opc; 314 | unsigned long got_sent_msg; 315 | struct isup_call *call; 316 | /* Backward call indicator */ 317 | unsigned char called_party_status_ind; 318 | unsigned char echocontrol_ind; 319 | } ss7_event_acm; 320 | 321 | typedef struct { 322 | int e; 323 | int startcic; 324 | int endcic; 325 | int sent_endcic; 326 | int type; 327 | int sent_type; 328 | unsigned int opc; 329 | unsigned char status[255]; 330 | unsigned int sent_status[255]; 331 | unsigned long got_sent_msg; 332 | struct isup_call *call; 333 | } ss7_event_cicrange; 334 | 335 | typedef struct { 336 | int e; 337 | int cic; 338 | int passed; 339 | int cot_performed_on_previous_cic; 340 | unsigned int opc; 341 | unsigned long got_sent_msg; 342 | struct isup_call *call; 343 | } ss7_event_cot; 344 | 345 | typedef struct { 346 | int e; 347 | int data; 348 | } ss7_event_generic; 349 | 350 | typedef struct { 351 | int e; 352 | struct mtp2 *link; 353 | } ss7_event_link; 354 | 355 | typedef struct { 356 | int e; 357 | int cic; 358 | unsigned int opc; 359 | unsigned char event; 360 | unsigned long got_sent_msg; 361 | unsigned char echocontrol_ind; 362 | unsigned char connected_nai; 363 | unsigned char connected_presentation_ind; 364 | unsigned char connected_screening_ind; 365 | char connected_num[50]; 366 | struct isup_call *call; 367 | } ss7_event_cpg; 368 | 369 | typedef struct { 370 | int e; 371 | int cic; 372 | unsigned int call_ref_ident; 373 | unsigned int call_ref_pc; 374 | unsigned int opc; 375 | struct isup_call *call; 376 | } ss7_event_frj; 377 | 378 | typedef struct { 379 | int e; 380 | int cic; 381 | unsigned int call_ref_ident; 382 | unsigned int call_ref_pc; 383 | unsigned int opc; 384 | struct isup_call *call; 385 | } ss7_event_faa; 386 | 387 | typedef struct { 388 | int e; 389 | int cic; 390 | unsigned int call_ref_ident; 391 | unsigned int call_ref_pc; 392 | unsigned int opc; 393 | struct isup_call *call; 394 | } ss7_event_far; 395 | 396 | typedef struct { 397 | int e; 398 | int cic; 399 | int network_isdn_indicator; 400 | unsigned int opc; 401 | unsigned long got_sent_msg; 402 | struct isup_call *call; 403 | } ss7_event_sus_res; 404 | 405 | typedef struct { 406 | int e; 407 | int cic; 408 | unsigned int opc; 409 | char called_party_num[50]; 410 | unsigned char called_nai; 411 | int cot_check_required; 412 | int cot_check_passed; 413 | int cot_performed_on_previous_cic; 414 | unsigned long got_sent_msg; 415 | struct isup_call *call; 416 | } ss7_event_sam; 417 | 418 | typedef struct { 419 | int e; 420 | int cic; 421 | unsigned int opc; 422 | int cot_check_required; 423 | int cot_check_passed; 424 | int cot_performed_on_previous_cic; 425 | struct isup_call *call; 426 | } ss7_event_digittimeout; 427 | 428 | 429 | typedef union { 430 | int e; 431 | ss7_event_generic gen; 432 | ss7_event_link link; 433 | ss7_event_iam iam; 434 | ss7_event_cicrange grs; 435 | ss7_event_cicrange cqm; 436 | ss7_event_cicrange gra; 437 | ss7_event_cicrange cgb; 438 | ss7_event_cicrange cgu; 439 | ss7_event_cicrange cgba; 440 | ss7_event_cicrange cgua; 441 | ss7_event_rel rel; 442 | ss7_event_cic rlc; 443 | ss7_event_anm anm; 444 | ss7_event_acm acm; 445 | ss7_event_frj frj; 446 | ss7_event_faa faa; 447 | ss7_event_far far; 448 | ss7_event_con con; 449 | ss7_event_cot cot; 450 | ss7_event_cic ccr; 451 | ss7_event_cic cvt; 452 | ss7_event_cic blo; 453 | ss7_event_cic ubl; 454 | ss7_event_cic bla; 455 | ss7_event_cic uba; 456 | ss7_event_cic ucic; 457 | ss7_event_rsc rsc; 458 | ss7_event_cpg cpg; 459 | ss7_event_sus_res sus; 460 | ss7_event_sus_res res; 461 | ss7_event_cic lpa; 462 | ss7_event_sam sam; 463 | ss7_event_digittimeout digittimeout; 464 | } ss7_event; 465 | 466 | void ss7_set_message(void (*func)(struct ss7 *ss7, char *message)); 467 | 468 | void ss7_set_error(void (*func)(struct ss7 *ss7, char *message)); 469 | 470 | void ss7_set_debug(struct ss7 *ss7, unsigned int flags); 471 | 472 | void ss7_set_notinservice(void (*func)(struct ss7 *ss7, int cic, unsigned int dpc)); 473 | 474 | void ss7_set_hangup(int (*func)(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)); 475 | 476 | void ss7_set_call_null(void (*func)(struct ss7 *ss7, struct isup_call *c, int lock)); 477 | 478 | /* SS7 Link control related functions */ 479 | int ss7_schedule_run(struct ss7 *ss7); 480 | 481 | struct timeval *ss7_schedule_next(struct ss7 *ss7); 482 | 483 | int ss7_add_link(struct ss7 *ss7, int transport, int fd, int slc, unsigned int adjpc); 484 | 485 | int ss7_set_network_ind(struct ss7 *ss7, int ni); 486 | 487 | int ss7_set_pc(struct ss7 *ss7, unsigned int pc); 488 | 489 | int ss7_set_default_dpc(struct ss7 *ss7, unsigned int pc); 490 | 491 | struct ss7 *ss7_new(int switchtype); 492 | 493 | void ss7_destroy(struct ss7 *ss7); 494 | 495 | void ss7_set_cause_location(struct ss7 *ss7, unsigned char location); 496 | 497 | void ss7_set_sls_shift(struct ss7 *ss7, unsigned char shift); 498 | 499 | void ss7_set_flags(struct ss7 *ss7, unsigned int flags); 500 | 501 | void ss7_clear_flags(struct ss7 *ss7, unsigned int flags); 502 | 503 | ss7_event *ss7_check_event(struct ss7 *ss7); 504 | 505 | int ss7_start(struct ss7 *ss7); 506 | 507 | int ss7_read(struct ss7 *ss7, int fd); 508 | 509 | int ss7_write(struct ss7 *ss7, int fd); 510 | 511 | void ss7_link_alarm(struct ss7 *ss7, int fd); 512 | 513 | void ss7_link_noalarm(struct ss7 *ss7, int fd); 514 | 515 | char * ss7_event2str(int event); 516 | 517 | const char *ss7_get_version(void); 518 | 519 | int ss7_pollflags(struct ss7 *ss7, int fd); 520 | 521 | int ss7_set_mtp3_timer(struct ss7 *ss7, char *name, int ms); 522 | 523 | /* ISUP call related message functions */ 524 | int ss7_set_isup_timer(struct ss7 *ss7, char *name, int ms); 525 | 526 | struct isup_call * isup_free_call_if_clear(struct ss7 *ss7, struct isup_call *c); 527 | 528 | int isup_start_digittimeout(struct ss7 *ss7, struct isup_call *c); 529 | 530 | /* Send an IAM */ 531 | int isup_iam(struct ss7 *ss7, struct isup_call *c); 532 | 533 | int isup_inr(struct ss7 *ss7, struct isup_call *c, unsigned char ind0, unsigned char ind1); 534 | 535 | int isup_inf(struct ss7 *ss7, struct isup_call *c, unsigned char ind0, unsigned char ind1); 536 | 537 | int isup_anm(struct ss7 *ss7, struct isup_call *c); 538 | 539 | int isup_con(struct ss7 *ss7, struct isup_call *c); 540 | 541 | struct isup_call * isup_new_call(struct ss7 *ss7, int cic, unsigned int dpc, int outgoing); 542 | 543 | int isup_acm(struct ss7 *ss7, struct isup_call *c); 544 | 545 | int isup_frj(struct ss7 *ss7, struct isup_call *c); 546 | 547 | int isup_faa(struct ss7 *ss7, struct isup_call *c); 548 | 549 | int isup_far(struct ss7 *ss7, struct isup_call *c); 550 | 551 | int isup_rel(struct ss7 *ss7, struct isup_call *c, int cause); 552 | 553 | int isup_rlc(struct ss7 *ss7, struct isup_call *c); 554 | 555 | int isup_sus(struct ss7 *ss7, struct isup_call *c, unsigned char indicator); 556 | 557 | int isup_res(struct ss7 *ss7, struct isup_call *c, unsigned char indicator); 558 | 559 | int isup_cpg(struct ss7 *ss7, struct isup_call *c, int event); 560 | 561 | int isup_lpa(struct ss7 *ss7, int cic, unsigned int dpc); 562 | 563 | int isup_gra(struct ss7 *ss7, struct isup_call *c, int endcic, unsigned char state[]); 564 | 565 | int isup_grs(struct ss7 *ss7, struct isup_call *c, int endcic); 566 | 567 | int isup_cgb(struct ss7 *ss7, struct isup_call *c, int endcic, unsigned char state[], int type); 568 | 569 | int isup_cgu(struct ss7 *ss7, struct isup_call *c, int endcic, unsigned char state[], int type); 570 | 571 | int isup_cgba(struct ss7 *ss7, struct isup_call *c, int endcic, unsigned char state[]); 572 | 573 | int isup_cgua(struct ss7 *ss7, struct isup_call *c, int endcic, unsigned char state[]); 574 | 575 | int isup_blo(struct ss7 *ss7, struct isup_call *c); 576 | 577 | int isup_ubl(struct ss7 *ss7, struct isup_call *c); 578 | 579 | /* int isup_ccr(struct ss7 *ss7, int cic, unsigned int dpc); FIXME Not Implemented ! */ 580 | 581 | int isup_bla(struct ss7 *ss7, struct isup_call *c); 582 | 583 | int isup_ucic(struct ss7 *ss7, int cic, unsigned int dpc); 584 | 585 | int isup_uba(struct ss7 *ss7, struct isup_call *c); 586 | 587 | int isup_rsc(struct ss7 *ss7, struct isup_call *c); 588 | 589 | int isup_cvr(struct ss7 *ss7, int cic, unsigned int dpc); 590 | 591 | int isup_cqr(struct ss7 *ss7, int begincic, int endcic, unsigned int dpc, unsigned char status[]); 592 | 593 | int isup_event_iam(struct ss7 *ss7, struct isup_call *c, int opc); 594 | 595 | void isup_clear_callflags(struct ss7 *ss7, struct isup_call *c, unsigned long flags); 596 | 597 | /* Various call related sets */ 598 | void isup_free_call(struct ss7 *ss7, struct isup_call *c); 599 | 600 | void isup_set_call_dpc(struct isup_call *c, unsigned int dpc); 601 | 602 | void isup_set_called(struct isup_call *c, const char *called, unsigned char called_nai, const struct ss7 *ss7); 603 | 604 | void isup_set_calling(struct isup_call *c, const char *calling, unsigned char calling_nai, unsigned char presentation_ind, unsigned char screening_ind); 605 | 606 | void isup_set_connected(struct isup_call *c, const char *connected, unsigned char connected_nai, unsigned char connected_presentation_ind, unsigned char connected_screening_ind); 607 | 608 | void isup_set_redirecting_number(struct isup_call *c, const char *redirecting_number, unsigned char redirecting_num_nai, unsigned char redirecting_num_presentation_ind, unsigned char redirecting_num_screening_ind); 609 | 610 | void isup_set_redirection_info(struct isup_call *c, unsigned char redirect_info_ind, unsigned char redirect_info_orig_reas, unsigned char redirect_info_counter, unsigned char redirect_info_reas); 611 | 612 | void isup_set_redirect_counter(struct isup_call *c, unsigned char redirect_counter); 613 | 614 | void isup_set_orig_called_num(struct isup_call *c, const char *orig_called_num, unsigned char orig_called_nai, unsigned char orig_called_pres_ind, unsigned char orig_called_screening_ind); 615 | 616 | void isup_set_tmr(struct isup_call *c, int tmr); 617 | 618 | void isup_set_charge(struct isup_call *c, const char *charge, unsigned char charge_nai, unsigned char charge_num_plan); 619 | 620 | void isup_set_oli(struct isup_call *c, int oli_ani2); 621 | 622 | void isup_set_gen_address(struct isup_call *c, const char *gen_number, unsigned char gen_add_nai, unsigned char gen_pres_ind, unsigned char gen_num_plan, unsigned char gen_add_type); 623 | 624 | void isup_set_gen_digits(struct isup_call *c, const char *gen_number, unsigned char gen_dig_type, unsigned char gen_dig_scheme); 625 | 626 | void isup_set_col_req(struct isup_call *c); 627 | 628 | void isup_set_cug(struct isup_call *c, unsigned char cug_indicator, const char *cug_interlock_ni, unsigned short cug_interlock_code); 629 | 630 | void isup_set_interworking_indicator(struct isup_call *c, unsigned char interworking_indicator); 631 | 632 | void isup_set_forward_indicator_pmbits(struct isup_call *c, unsigned char pmbits); 633 | 634 | void isup_set_echocontrol(struct isup_call *c, unsigned char ec); 635 | 636 | enum { 637 | GEN_NAME_PRES_ALLOWED = 0, 638 | GEN_NAME_PRES_RESTRICTED = 1, 639 | GEN_NAME_PRES_BLOCKING_TOGGLE = 2, 640 | GEN_NAME_PRES_NO_INDICATION = 3, 641 | }; 642 | 643 | enum { 644 | GEN_NAME_AVAIL_AVAILABLE = 0, 645 | GEN_NAME_AVAIL_NOT_AVAILABLE = 1 646 | }; 647 | 648 | enum { 649 | GEN_NAME_TYPE_CALLING_NAME = 1, 650 | GEN_NAME_TYPE_ORIG_CALLED_NAME = 2, 651 | GEN_NAME_TYPE_REDIRECTING_NAME = 3, 652 | GEN_NAME_TYPE_CONNECTED_NAME = 4, 653 | }; 654 | 655 | void isup_set_generic_name(struct isup_call *c, const char *generic_name, unsigned int typeofname, unsigned int availability, unsigned int presentation); 656 | 657 | void isup_set_jip_digits(struct isup_call *c, const char *jip_number); 658 | 659 | void isup_set_lspi(struct isup_call *c, const char *lspi_ident, unsigned char lspi_type, unsigned char lspi_scheme, unsigned char lspi_context); 660 | 661 | void isup_set_callref(struct isup_call *c, unsigned int call_ref_ident, unsigned int call_ref_pc); 662 | 663 | void isup_set_calling_party_category(struct isup_call *c, unsigned int category); 664 | 665 | /* End of call related sets */ 666 | 667 | typedef void (*ss7_printf_cb)(int fd, const char *fmt, ...) __attribute__((format(printf, 2, 3))); 668 | 669 | void isup_show_calls(struct ss7 *ss7, ss7_printf_cb cust_printf, int fd); 670 | 671 | void ss7_show_linkset(struct ss7 *ss7, ss7_printf_cb cust_printf, int fd); 672 | 673 | /* net mng */ 674 | const char * mtp3_net_mng(struct ss7 *ss7, unsigned int slc, const char *cmd, unsigned int param); 675 | 676 | void mtp3_init_restart(struct ss7 *ss7, int slc); 677 | 678 | int ss7_set_mtp3_timer(struct ss7 *ss7, char *name, int ms); 679 | 680 | void ss7_pc_to_str(int ss7type, unsigned int pc, char *str); 681 | 682 | #endif /* _LIBSS7_H */ 683 | -------------------------------------------------------------------------------- /mtp2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #include "ss7_internal.h" 33 | #include "mtp3.h" 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "mtp2.h" 40 | 41 | #define mtp_error ss7_error 42 | #define mtp_message ss7_message 43 | 44 | int len_buf(struct ss7_msg *buf) 45 | { 46 | int res = 0; 47 | struct ss7_msg *cur = buf; 48 | 49 | while (cur) { 50 | res++; 51 | cur = cur->next; 52 | } 53 | return res; 54 | } 55 | 56 | static inline char * linkstate2str(int linkstate) 57 | { 58 | char *statestr = NULL; 59 | 60 | switch (linkstate) { 61 | case MTP_IDLE: 62 | statestr = "IDLE"; 63 | break; 64 | case MTP_NOTALIGNED: 65 | statestr = "NOTALIGNED"; 66 | break; 67 | case MTP_ALIGNED: 68 | statestr = "ALIGNED"; 69 | break; 70 | case MTP_PROVING: 71 | statestr = "PROVING"; 72 | break; 73 | case MTP_ALIGNEDREADY: 74 | statestr = "ALIGNEDREADY"; 75 | break; 76 | case MTP_INSERVICE: 77 | statestr = "INSERVICE"; 78 | break; 79 | case MTP_ALARM: 80 | statestr = "ALARM"; 81 | break; 82 | default: 83 | statestr = "UNKNOWN"; 84 | } 85 | 86 | return statestr; 87 | } 88 | 89 | char *linkstate2strext(int linkstate) 90 | { 91 | return linkstate2str(linkstate); 92 | } 93 | 94 | static inline void init_mtp2_header(struct mtp2 *link, struct mtp_su_head *h, int new, int nack) 95 | { 96 | if (new) { 97 | link->curfsn += 1; 98 | link->flags |= MTP2_FLAG_WRITE; 99 | } 100 | 101 | h->fib = link->curfib; 102 | h->fsn = link->curfsn; 103 | 104 | if (nack) { 105 | link->curbib = !link->curbib; 106 | link->flags |= MTP2_FLAG_WRITE; 107 | } 108 | 109 | h->bib = link->curbib; 110 | h->bsn = link->lastfsnacked; 111 | } 112 | 113 | static inline int lssu_type(struct mtp_su_head *h) 114 | { 115 | return h->data[0]; 116 | } 117 | 118 | void flush_bufs(struct mtp2 *link) 119 | { 120 | struct ss7_msg *list, *cur; 121 | 122 | list = link->tx_buf; 123 | 124 | link->tx_buf = NULL; 125 | 126 | while (list) { 127 | cur = list; 128 | list = list->next; 129 | free(cur); 130 | } 131 | 132 | list = link->tx_q; 133 | 134 | link->tx_q = NULL; 135 | 136 | while (list) { 137 | cur = list; 138 | list = list->next; 139 | free(cur); 140 | } 141 | 142 | link->retransmit_pos = NULL; 143 | } 144 | 145 | static void reset_mtp(struct mtp2 *link) 146 | { 147 | link->curfsn = 127; 148 | link->curfib = 1; 149 | link->curbib = 1; 150 | #if 0 151 | ss7_message(link->master, "Lastfsn: %i txbuflen: %i SLC: %i ADJPC: %i\n", link->lastfsnacked, len_buf(link->tx_buf), link->slc, link->dpc); 152 | #endif 153 | link->lastfsnacked = 127; 154 | link->retransmissioncount = 0; 155 | link->flags |= MTP2_FLAG_WRITE; 156 | 157 | flush_bufs(link); 158 | } 159 | 160 | 161 | static void mtp2_request_retransmission(struct mtp2 *link) 162 | { 163 | link->retransmissioncount++; 164 | link->curbib = !link->curbib; 165 | link->flags |= MTP2_FLAG_WRITE; 166 | } 167 | 168 | static int mtp2_queue_su(struct mtp2 *link, struct ss7_msg *m) 169 | { 170 | struct ss7_msg *cur; 171 | 172 | if (!link->tx_q) { 173 | link->tx_q = m; 174 | m->next = NULL; 175 | return 0; 176 | } 177 | 178 | for (cur = link->tx_q; cur->next; cur = cur->next); 179 | 180 | cur->next = m; 181 | m->next = NULL; 182 | 183 | return 0; 184 | } 185 | 186 | static void make_lssu(struct mtp2 *link, unsigned char *buf, unsigned int *size, int lssu_status) 187 | { 188 | struct mtp_su_head *head; 189 | 190 | *size = LSSU_SIZE; 191 | 192 | memset(buf, 0, LSSU_SIZE); 193 | 194 | head = (struct mtp_su_head *)buf; 195 | head->li = 1; 196 | switch (lssu_status) { 197 | case LSSU_SIOS: 198 | case LSSU_SIO: 199 | reset_mtp(link); 200 | case LSSU_SIN: 201 | case LSSU_SIE: 202 | case LSSU_SIPO: 203 | case LSSU_SIB: 204 | head->bib = link->curbib; 205 | head->bsn = link->lastfsnacked; 206 | head->fib = link->curfib; 207 | head->fsn = link->curfsn; 208 | break; 209 | } 210 | 211 | head->data[0] = lssu_status; 212 | } 213 | 214 | static void make_fisu(struct mtp2 *link, unsigned char *buf, unsigned int *size, int nack) 215 | { 216 | struct mtp_su_head *h; 217 | 218 | *size = FISU_SIZE; 219 | 220 | h = (struct mtp_su_head *)buf; 221 | 222 | memset(buf, 0, *size); 223 | 224 | init_mtp2_header(link, h, 0, nack); 225 | 226 | h->li = 0; 227 | } 228 | 229 | static void add_txbuf(struct mtp2 *link, struct ss7_msg *m) 230 | { 231 | m->next = link->tx_buf; 232 | link->tx_buf = m; 233 | #if 0 234 | mtp_message(link->master, "Txbuf contains %d items\n", len_buf(link->tx_buf)); 235 | #endif 236 | } 237 | 238 | static void update_retransmit_pos(struct mtp2 *link) 239 | { 240 | struct ss7_msg *cur, *prev = NULL; 241 | /* Our txbuf is in reversed order from the order we need to retransmit in */ 242 | 243 | cur = link->tx_buf; 244 | 245 | while (cur) { 246 | if (cur == link->retransmit_pos) 247 | break; 248 | prev = cur; 249 | cur = cur->next; 250 | } 251 | 252 | link->retransmit_pos = prev; 253 | 254 | } 255 | 256 | static void mtp2_retransmit(struct mtp2 *link) 257 | { 258 | struct ss7_msg *m; 259 | 260 | link->flags |= MTP2_FLAG_WRITE; 261 | /* Have to invert the current fib */ 262 | link->curfib = !link->curfib; 263 | 264 | m = link->tx_buf; 265 | if (!m) { 266 | ss7_error(link->master, "Huh!? Asked to retransmit but we don't have anything in the tx buffer\n"); 267 | return; 268 | } 269 | 270 | while (m->next) 271 | m = m->next; 272 | 273 | link->retransmit_pos = m; 274 | } 275 | 276 | static void t7_expiry(void *data) 277 | { 278 | struct mtp2 *link = data; 279 | 280 | ss7_error(link->master, "T7 expired on link SLC: %i ADJPC: %i\n", link->slc, link->dpc); 281 | link->t7 = -1; 282 | mtp2_setstate(link, MTP_IDLE); 283 | } 284 | 285 | int mtp2_transmit(struct mtp2 *link) 286 | { 287 | int res = 0; 288 | unsigned char *h; 289 | unsigned char buf[64]; 290 | unsigned int size; 291 | struct ss7_msg *m = NULL; 292 | int retransmit = 0; 293 | 294 | if (link->retransmit_pos) { 295 | struct mtp_su_head *h1; 296 | m = link->retransmit_pos; 297 | retransmit = 1; 298 | 299 | if (!m) { 300 | ss7_error(link->master, "Huh, requested to retransmit, but nothing in retransmit buffer?!!\n"); 301 | return -1; 302 | } 303 | 304 | h = m->buf; 305 | size = m->size; 306 | 307 | h1 = (struct mtp_su_head *)h; 308 | /* Update the FIB and BSN since they aren't the same */ 309 | h1->fib = link->curfib; 310 | h1->bsn = link->lastfsnacked; 311 | 312 | } else { 313 | if (link->tx_q) { 314 | m = link->tx_q; 315 | } 316 | 317 | if (m) { 318 | h = m->buf; 319 | init_mtp2_header(link, (struct mtp_su_head *) h, 1, 0); /* in changeover we may manipulate the buffers!!! */ 320 | size = m->size; 321 | 322 | /* Advance to next MSU to be transmitted */ 323 | link->tx_q = m->next; 324 | /* Add it to the tx'd message queue (MSUs that haven't been acknowledged) */ 325 | add_txbuf(link, m); 326 | if (link->t7 == -1) { 327 | link->t7 = ss7_schedule_event(link->master, link->timers.t7, t7_expiry, link); 328 | } 329 | } else { 330 | size = sizeof(buf); 331 | if (link->autotxsutype == FISU) { 332 | make_fisu(link, buf, &size, 0); 333 | } else { 334 | make_lssu(link, buf, &size, link->autotxsutype); 335 | } 336 | h = buf; 337 | } 338 | } 339 | 340 | res = write(link->fd, h, size); /* Add 2 for FCS */ 341 | 342 | if (res > 0) { 343 | mtp2_dump(link, '>', h, size - 2); 344 | if (retransmit) { 345 | /* Update our retransmit positon since it transmitted */ 346 | update_retransmit_pos(link); 347 | } 348 | 349 | if (h == buf) { /* We just sent a non MSU */ 350 | link->flags &= ~MTP2_FLAG_WRITE; 351 | } 352 | } else { 353 | ss7_error(link->master, "mtp2_transmit: write returned %d, errno=%d\n", res, errno); 354 | if (!retransmit && m) { /* We need to retransmit, but on retransmit, we'll just try again later */ 355 | link->retransmit_pos = link->tx_buf; 356 | } 357 | } 358 | 359 | return res; 360 | } 361 | 362 | int mtp2_msu(struct mtp2 *link, struct ss7_msg *m) 363 | { 364 | int len = m->size - MTP2_SIZE; 365 | struct mtp_su_head *h = (struct mtp_su_head *) m->buf; 366 | 367 | link->flags |= MTP2_FLAG_WRITE; 368 | 369 | /* init_mtp2_header(link, h, 1, 0); */ 370 | 371 | if (len > MTP2_LI_MAX) { 372 | h->li = MTP2_LI_MAX; 373 | } else { 374 | h->li = len; 375 | } 376 | 377 | m->size += 2; /* For CRC */ 378 | mtp2_queue_su(link, m); 379 | /* Just in case */ 380 | m->next = NULL; 381 | 382 | return 0; 383 | } 384 | 385 | static int mtp2_lssu(struct mtp2 *link, int lssu_status) 386 | { 387 | link->flags |= MTP2_FLAG_WRITE; 388 | link->autotxsutype = lssu_status; 389 | return 0; 390 | } 391 | 392 | static int mtp2_fisu(struct mtp2 *link, int nack) 393 | { 394 | link->flags |= MTP2_FLAG_WRITE; 395 | link->autotxsutype = FISU; 396 | return 0; 397 | } 398 | 399 | void update_txbuf(struct mtp2 *link, struct ss7_msg **buf, unsigned char upto) 400 | { 401 | struct mtp_su_head *h; 402 | struct ss7_msg *prev = NULL, *cur; 403 | struct ss7_msg *frlist = NULL; 404 | /* Make a list, frlist that will be the SUs to free */ 405 | 406 | /* Empty list */ 407 | if (!*buf) { 408 | return; 409 | } 410 | 411 | cur = *buf; 412 | 413 | while (cur) { 414 | h = (struct mtp_su_head *)cur->buf; 415 | if (h->fsn == upto) { 416 | frlist = cur; 417 | if (!prev) { /* Head of list */ 418 | *buf = NULL; 419 | } else { 420 | prev->next = NULL; 421 | } 422 | frlist = cur; 423 | break; 424 | } 425 | prev = cur; 426 | cur = cur->next; 427 | } 428 | 429 | if (link && frlist && link->t7 > -1) { 430 | ss7_schedule_del(link->master, &link->t7); 431 | if (link->tx_buf) { 432 | link->t7 = ss7_schedule_event(link->master, link->timers.t7, &t7_expiry, link); 433 | } 434 | } 435 | 436 | while (frlist) { 437 | cur = frlist; 438 | frlist = frlist->next; 439 | free(cur); 440 | } 441 | 442 | return; 443 | } 444 | 445 | static int fisu_rx(struct mtp2 *link, struct mtp_su_head *h, int len) 446 | { 447 | if ((link->state == MTP_INSERVICE) && (h->fsn != link->lastfsnacked) && (h->fib == link->curbib)) { 448 | mtp_message(link->master, "Received out of sequence FISU w/ fsn of %d, lastfsnacked = %d, requesting retransmission\n", h->fsn, link->lastfsnacked); 449 | mtp2_request_retransmission(link); 450 | } 451 | 452 | if (link->lastsurxd == FISU) 453 | return 0; 454 | else 455 | link->lastsurxd = FISU; 456 | 457 | switch (link->state) { 458 | case MTP_PROVING: 459 | return mtp2_setstate(link, MTP_ALIGNEDREADY); 460 | /* Just in case our timers are a little off */ 461 | case MTP_ALIGNEDREADY: 462 | mtp2_setstate(link, MTP_INSERVICE); 463 | case MTP_INSERVICE: 464 | break; 465 | default: 466 | mtp_message(link->master, "Huh?! Got FISU in link state %d\n", link->state); 467 | return -1; 468 | } 469 | 470 | return 0; 471 | } 472 | 473 | static void t1_expiry(void *data) 474 | { 475 | struct mtp2 *link = data; 476 | 477 | mtp2_setstate(link, MTP_IDLE); 478 | 479 | return; 480 | } 481 | 482 | static void t2_expiry(void * data) 483 | { 484 | struct mtp2 *link = data; 485 | 486 | mtp2_setstate(link, MTP_IDLE); 487 | 488 | return; 489 | } 490 | 491 | static void t3_expiry(void * data) 492 | { 493 | struct mtp2 *link = data; 494 | 495 | mtp2_setstate(link, MTP_IDLE); 496 | 497 | return; 498 | } 499 | 500 | static void t4_expiry(void * data) 501 | { 502 | struct mtp2 *link = data; 503 | 504 | ss7_debug_msg(link->master, SS7_DEBUG_MTP2, "MTP2 T4 expired!\n"); 505 | mtp2_setstate(link, MTP_ALIGNEDREADY); 506 | 507 | return; 508 | } 509 | 510 | static int to_idle(struct mtp2 *link) 511 | { 512 | link->state = MTP_IDLE; 513 | if (mtp2_lssu(link, LSSU_SIOS)) { 514 | mtp_error(link->master, "Could not transmit LSSU\n"); 515 | return -1; 516 | } 517 | 518 | mtp2_setstate(link, MTP_NOTALIGNED); 519 | 520 | return 0; 521 | } 522 | 523 | int mtp2_setstate(struct mtp2 *link, int newstate) 524 | { 525 | ss7_event *e; 526 | 527 | ss7_debug_msg(link->master, SS7_DEBUG_MTP2, "Link state change: %s -> %s\n", linkstate2str(link->state), linkstate2str(newstate)); 528 | 529 | switch (link->state) { 530 | case MTP_ALARM: 531 | return 0; 532 | case MTP_IDLE: 533 | link->t2 = ss7_schedule_event(link->master, link->timers.t2, t2_expiry, link); 534 | if (mtp2_lssu(link, LSSU_SIO)) { 535 | mtp_error(link->master, "Unable to transmit initial LSSU\n"); 536 | return -1; 537 | } 538 | link->state = MTP_NOTALIGNED; 539 | return 0; 540 | case MTP_NOTALIGNED: 541 | ss7_schedule_del(link->master, &link->t2); 542 | switch (newstate) { 543 | case MTP_IDLE: 544 | return to_idle(link); 545 | case MTP_ALIGNED: 546 | case MTP_PROVING: 547 | if (newstate == MTP_ALIGNED) 548 | link->t3 = ss7_schedule_event(link->master, link->timers.t3, t3_expiry, link); 549 | else 550 | link->t4 = ss7_schedule_event(link->master, link->provingperiod, t4_expiry, link); 551 | if (link->emergency) { 552 | if (mtp2_lssu(link, LSSU_SIE)) { 553 | mtp_error(link->master, "Couldn't tx LSSU_SIE\n"); 554 | return -1; 555 | } 556 | } else { 557 | if (mtp2_lssu(link, LSSU_SIN)) { 558 | mtp_error(link->master, "Couldn't tx LSSU_SIE\n"); 559 | return -1; 560 | } 561 | } 562 | break; 563 | } 564 | link->state = newstate; 565 | return 0; 566 | case MTP_ALIGNED: 567 | ss7_schedule_del(link->master, &link->t3); 568 | 569 | switch (newstate) { 570 | case MTP_IDLE: 571 | return to_idle(link); 572 | case MTP_PROVING: 573 | link->t4 = ss7_schedule_event(link->master, link->provingperiod, t4_expiry, link); 574 | } 575 | link->state = newstate; 576 | return 0; 577 | case MTP_PROVING: 578 | ss7_schedule_del(link->master, &link->t4); 579 | 580 | switch (newstate) { 581 | case MTP_IDLE: 582 | return to_idle(link); 583 | case MTP_PROVING: 584 | link->t4 = ss7_schedule_event(link->master, link->provingperiod, t4_expiry, link); 585 | break; 586 | case MTP_ALIGNED: 587 | if (link->emergency) { 588 | if (mtp2_lssu(link, LSSU_SIE)) { 589 | mtp_error(link->master, "Could not transmit LSSU\n"); 590 | return -1; 591 | } 592 | } else { 593 | if (mtp2_lssu(link, LSSU_SIN)) { 594 | mtp_error(link->master, "Could not transmit LSSU\n"); 595 | return -1; 596 | } 597 | } 598 | break; 599 | case MTP_ALIGNEDREADY: 600 | link->t1 = ss7_schedule_event(link->master, link->timers.t1, t1_expiry, link); 601 | if (mtp2_fisu(link, 0)) { 602 | mtp_error(link->master, "Could not transmit FISU\n"); 603 | return -1; 604 | } 605 | break; 606 | } 607 | link->state = newstate; 608 | return 0; 609 | case MTP_ALIGNEDREADY: 610 | ss7_schedule_del(link->master, &link->t1); 611 | /* Our timer expired, it should be cleaned up already */ 612 | switch (newstate) { 613 | case MTP_IDLE: 614 | return to_idle(link); 615 | case MTP_ALIGNEDREADY: 616 | link->t1 = ss7_schedule_event(link->master, link->timers.t1, t1_expiry, link); 617 | if (mtp2_fisu(link, 0)) { 618 | mtp_error(link->master, "Could not transmit FISU\n"); 619 | return -1; 620 | } 621 | break; 622 | case MTP_INSERVICE: 623 | ss7_schedule_del(link->master, &link->t1); 624 | e = ss7_next_empty_event(link->master); 625 | if (!e) { 626 | return -1; 627 | } 628 | e->link.e = MTP2_LINK_UP; 629 | e->link.link = link; 630 | break; 631 | default: 632 | mtp_error(link->master, "Don't know how to handle state change from %d to %d\n", link->state, newstate); 633 | break; 634 | } 635 | link->state = newstate; 636 | return 0; 637 | case MTP_INSERVICE: 638 | if (newstate != MTP_INSERVICE) { 639 | e = ss7_next_empty_event(link->master); 640 | if (!e) { 641 | return -1; 642 | } 643 | e->link.e = MTP2_LINK_DOWN; 644 | e->link.link = link; 645 | return to_idle(link); 646 | } 647 | break; 648 | } 649 | return 0; 650 | } 651 | 652 | static int lssu_rx(struct mtp2 *link, struct mtp_su_head *h, int len) 653 | { 654 | unsigned char lssutype = lssu_type(h); 655 | 656 | /* Q.703 11.1.2 LSSU can be one or two bytes. Only one is used for now and the second should be ignored for compatibility reasons */ 657 | if (len > (LSSU_SIZE + 1)) { 658 | mtp_error(link->master, "Received LSSU with length %d longer than expected\n", len); 659 | } 660 | 661 | if (link->lastsurxd == lssutype) { 662 | return 0; 663 | } else { 664 | link->lastsurxd = lssutype; 665 | } 666 | 667 | if (lssutype == LSSU_SIE) { 668 | link->emergency = 1; 669 | } 670 | 671 | switch (link->state) { 672 | case MTP_IDLE: 673 | case MTP_NOTALIGNED: 674 | if ((lssutype != LSSU_SIE) && (lssutype != LSSU_SIN) && (lssutype != LSSU_SIO)) { 675 | return mtp2_setstate(link, MTP_NOTALIGNED); 676 | } 677 | 678 | if ((link->emergency) || (lssutype == LSSU_SIE)) { 679 | link->provingperiod = link->timers.t4e; 680 | } else { 681 | link->provingperiod = link->timers.t4; 682 | } 683 | 684 | if ((lssutype == LSSU_SIE) || (lssutype == LSSU_SIN)) { 685 | return mtp2_setstate(link, MTP_PROVING); 686 | } else { 687 | return mtp2_setstate(link, MTP_ALIGNED); 688 | } 689 | case MTP_ALIGNED: 690 | if (lssutype == LSSU_SIOS) { 691 | return mtp2_setstate(link, MTP_IDLE); 692 | } 693 | 694 | if ((link->emergency) || (lssutype == LSSU_SIE)) { 695 | link->provingperiod = link->timers.t4e; 696 | } else { 697 | link->provingperiod = link->timers.t4; 698 | } 699 | 700 | if ((link->provingperiod == link->timers.t4) && ((link->emergency) || (lssutype == LSSU_SIE))) { 701 | link->provingperiod = link->timers.t4e; 702 | } 703 | 704 | return mtp2_setstate(link, MTP_PROVING); 705 | case MTP_PROVING: 706 | if (lssutype == LSSU_SIOS) { 707 | return mtp2_setstate(link, MTP_IDLE); 708 | } 709 | 710 | if (lssutype == LSSU_SIO) { 711 | return mtp2_setstate(link, MTP_ALIGNED); 712 | } 713 | 714 | mtp_message(link->master, "Don't handle any other conditions in state %d\n", link->state); 715 | break; 716 | case MTP_ALIGNEDREADY: 717 | case MTP_INSERVICE: 718 | if ((lssutype != LSSU_SIOS) && (lssutype != LSSU_SIO)) { 719 | mtp_message(link->master, "Got LSSU of type %d while link is in state %d. Re-Aligning\n", lssutype, link->state); 720 | } 721 | return mtp2_setstate(link, MTP_IDLE); 722 | } 723 | 724 | return 0; 725 | } 726 | 727 | static int msu_rx(struct mtp2 *link, struct mtp_su_head *h, int len) 728 | { 729 | int res = 0; 730 | 731 | switch (link->state) { 732 | case MTP_ALIGNEDREADY: 733 | mtp2_setstate(link, MTP_INSERVICE); 734 | break; 735 | case MTP_INSERVICE: 736 | break; 737 | default: 738 | mtp_error(link->master, "Received MSU in invalid state %d\n", link->state); 739 | return -1; 740 | } 741 | 742 | /* If we're still waiting for our retranmission acknownledgement, we'll just ignore subsequent MSUs until it starts */ 743 | if (h->fib != link->curbib) { 744 | mtp_message(link->master, "MSU received, though still waiting for retransmission start. Dropping.\n"); 745 | return 0; 746 | } 747 | 748 | if (h->fsn == link->lastfsnacked) { 749 | /* Discard */ 750 | mtp_message(link->master, "Received double MSU, dropping\n"); 751 | return 0; 752 | } 753 | 754 | if (h->fsn != ((link->lastfsnacked+1) % 128)) { 755 | mtp_message(link->master, "Received out of sequence MSU w/ fsn of %d, lastfsnacked = %d, requesting retransmission\n", h->fsn, link->lastfsnacked); 756 | mtp2_request_retransmission(link); 757 | return 0; 758 | } 759 | 760 | /* Ok, it's a valid MSU now and we can accept it */ 761 | link->lastfsnacked = h->fsn; 762 | /* Set write flag since we need to update the FISUs with our new BSN */ 763 | link->flags |= MTP2_FLAG_WRITE; 764 | /* The big function */ 765 | res = mtp3_receive(link->master, link, h->data, len - MTP2_SU_HEAD_SIZE); 766 | 767 | return res; 768 | } 769 | 770 | int mtp2_start(struct mtp2 *link, int emergency) 771 | { 772 | reset_mtp(link); 773 | link->emergency = emergency; 774 | if (link->state == MTP_IDLE) { 775 | return mtp2_setstate(link, MTP_NOTALIGNED); 776 | } 777 | 778 | return 0; 779 | } 780 | 781 | int mtp2_stop(struct mtp2 *link) 782 | { 783 | return mtp2_setstate(link, MTP_IDLE); 784 | } 785 | 786 | int mtp2_alarm(struct mtp2 *link) 787 | { 788 | link->state = MTP_ALARM; 789 | return 0; 790 | } 791 | 792 | int mtp2_noalarm(struct mtp2 *link) 793 | { 794 | link->state = MTP_IDLE; 795 | return 0; 796 | } 797 | 798 | struct mtp2 * mtp2_new(int fd, unsigned int switchtype) 799 | { 800 | struct mtp2 * new = calloc(1, sizeof(struct mtp2)); 801 | int x; 802 | 803 | if (!new) { 804 | return NULL; 805 | } 806 | 807 | reset_mtp(new); 808 | 809 | new->fd = fd; 810 | new->autotxsutype = LSSU_SIOS; 811 | new->lastsurxd = -1; 812 | new->lastsutxd = -1; 813 | 814 | if (switchtype == SS7_ITU) { 815 | new->timers.t1 = ITU_TIMER_T1; 816 | new->timers.t2 = ITU_TIMER_T2; 817 | new->timers.t3 = ITU_TIMER_T3; 818 | new->timers.t4 = ITU_TIMER_T4_NORMAL; 819 | new->timers.t4e = ITU_TIMER_T4_EMERGENCY; 820 | new->timers.t7 = ITU_TIMER_T7; 821 | } else if (switchtype == SS7_ANSI) { 822 | new->timers.t1 = ANSI_TIMER_T1; 823 | new->timers.t2 = ANSI_TIMER_T2; 824 | new->timers.t3 = ANSI_TIMER_T3; 825 | new->timers.t4 = ANSI_TIMER_T4_NORMAL; 826 | new->timers.t4e = ANSI_TIMER_T4_EMERGENCY; 827 | new->timers.t7 = ANSI_TIMER_T7; 828 | } 829 | 830 | for (x = 0; x < MTP3_MAX_TIMERS; x++) { 831 | new->mtp3_timer[x] = -1; 832 | } 833 | 834 | return new; 835 | } 836 | 837 | 838 | void mtp2_dump(struct mtp2 *link, char prefix, unsigned char *buf, int len) 839 | { 840 | struct mtp_su_head *h = (struct mtp_su_head *)buf; 841 | unsigned char mtype; 842 | char *mtypech = NULL; 843 | char pc_str[64]; 844 | 845 | if (!(link->master->debug & SS7_DEBUG_MTP2)) { 846 | return; 847 | } 848 | 849 | ss7_pc_to_str(link->master->switchtype, link->adj_sp->adjpc, pc_str); 850 | 851 | switch (h->li) { 852 | case 0: 853 | mtype = 0; 854 | break; 855 | case 1: 856 | case 2: 857 | mtype = 1; 858 | break; 859 | default: 860 | mtype = 2; 861 | break; 862 | } 863 | 864 | 865 | switch (mtype) { 866 | case 0: 867 | if (prefix == '<' && link->lastsurxd == FISU) 868 | return; 869 | if (prefix == '>' && link->lastsutxd == FISU) 870 | return; 871 | else 872 | link->lastsutxd = FISU; 873 | ss7_dump_msg(link->master, buf, len); 874 | ss7_message(link->master, "FSN: %d FIB %d\n", h->fsn, h->fib); 875 | ss7_message(link->master, "BSN: %d BIB %d\n", h->bsn, h->bib); 876 | 877 | ss7_message(link->master, "%c[%s:%d] FISU\n", prefix, pc_str, link->slc); 878 | break; 879 | case 1: 880 | if (prefix == '<' && link->lastsurxd == h->data[0]) 881 | return; 882 | if (prefix == '>' && link->lastsutxd == h->data[0]) 883 | return; 884 | else 885 | link->lastsutxd = h->data[0]; 886 | switch (h->data[0]) { 887 | case LSSU_SIOS: 888 | mtypech = "SIOS"; 889 | break; 890 | case LSSU_SIO: 891 | mtypech = "SIO"; 892 | break; 893 | case LSSU_SIN: 894 | mtypech = "SIN"; 895 | break; 896 | case LSSU_SIE: 897 | mtypech = "SIE"; 898 | break; 899 | case LSSU_SIPO: 900 | mtypech = "SIPO"; 901 | break; 902 | case LSSU_SIB: 903 | mtypech = "SIB"; 904 | break; 905 | } 906 | ss7_dump_msg(link->master, buf, len); 907 | ss7_message(link->master, "FSN: %d FIB %d\n", h->fsn, h->fib); 908 | ss7_message(link->master, "BSN: %d BIB %d\n", h->bsn, h->bib); 909 | ss7_message(link->master, "%c[%s:%d] LSSU %s\n", prefix, pc_str, link->slc, mtypech); 910 | break; 911 | case 2: 912 | ss7_dump_msg(link->master, buf, len); 913 | ss7_message(link->master, "FSN: %d FIB %d\n", h->fsn, h->fib); 914 | ss7_message(link->master, "BSN: %d BIB %d\n", h->bsn, h->bib); 915 | ss7_message(link->master, "%c[%s:%d] MSU\n", prefix, pc_str, link->slc); 916 | ss7_dump_buf(link->master, 0, buf, 3); 917 | mtp3_dump(link->master, link, h->data, len - MTP2_SU_HEAD_SIZE); 918 | break; 919 | } 920 | 921 | ss7_message(link->master, "\n"); 922 | } 923 | 924 | /* returns an event */ 925 | int mtp2_receive(struct mtp2 *link, unsigned char *buf, int len) 926 | { 927 | struct mtp_su_head *h = (struct mtp_su_head *)buf; 928 | 929 | len -= 2; /* Strip the CRC off */ 930 | if (len < MTP2_SIZE) { 931 | ss7_message(link->master, "Got message smaller than the minimum SS7 SU length. Dropping\n"); 932 | return 0; 933 | } 934 | 935 | mtp2_dump(link, '<', buf, len); 936 | 937 | update_txbuf(link, &link->tx_buf, h->bsn); 938 | 939 | /* Check for retransmission request */ 940 | if ((link->state == MTP_INSERVICE) && (h->bib != link->curfib)) { 941 | /* Negative ack */ 942 | ss7_message(link->master, "Got retransmission request sequence numbers greater than %d. Retransmitting %d message(s).\n", h->bsn, len_buf(link->tx_buf)); 943 | mtp2_retransmit(link); 944 | } 945 | 946 | switch (h->li) { 947 | case 0: 948 | /* FISU */ 949 | return fisu_rx(link, h, len); 950 | case 1: 951 | case 2: 952 | /* LSSU */ 953 | return lssu_rx(link, h, len); 954 | default: 955 | /* MSU */ 956 | return msu_rx(link, h, len); 957 | } 958 | 959 | return 0; 960 | } 961 | -------------------------------------------------------------------------------- /mtp2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #ifndef _SS7_MTP_H 33 | #define _SS7_MTP_H 34 | 35 | #include "ss7_internal.h" 36 | 37 | /* Code for extended length of message, i.e. greater than 62 octects */ 38 | #define MTP2_LI_MAX 63 39 | 40 | #define SIF_MAX_SIZE 272 41 | 42 | #define MTP2_SU_HEAD_SIZE 3 43 | #define MTP2_SIZE MTP2_SU_HEAD_SIZE 44 | 45 | /* MTP2 Timers */ 46 | /* For ITU 64kbps links */ 47 | #define ITU_TIMER_T1 45000 48 | #define ITU_TIMER_T2 50000 49 | #define ITU_TIMER_T3 1500 50 | #define ITU_TIMER_T4_NORMAL 8500 51 | #define ITU_TIMER_T4_EMERGENCY 500 52 | #define ITU_TIMER_T7 1250 53 | 54 | /* For ANSI links */ 55 | #define ANSI_TIMER_T1 16000 56 | #define ANSI_TIMER_T2 11500 57 | #define ANSI_TIMER_T3 11500 58 | #define ANSI_TIMER_T4_NORMAL 2300 59 | #define ANSI_TIMER_T4_EMERGENCY 600 60 | #define ANSI_TIMER_T7 1250 61 | 62 | /* Bottom 3 bits in LSSU status field */ 63 | #define LSSU_SIO 0 /* Out of alignment */ 64 | #define LSSU_SIN 1 /* Normal alignament */ 65 | #define LSSU_SIE 2 /* Emergency alignment */ 66 | #define LSSU_SIOS 3 /* Out of Service */ 67 | #define LSSU_SIPO 4 /* MTP2 cannot reach MTP3, useless for us */ 68 | #define LSSU_SIB 5 /* MTP2 congestion */ 69 | 70 | #define FISU 6 71 | 72 | /* More MTP2 definitions */ 73 | /* Various sizes */ 74 | #define MTP_MAX_SIZE 277 /* 276 + 1 for RSIS */ 75 | #define LSSU_SIZE 6 76 | #define FISU_SIZE 5 77 | 78 | /* MTP2 Link states */ 79 | #define MTP_IDLE 0 80 | #define MTP_NOTALIGNED 1 81 | #define MTP_ALIGNED 2 82 | #define MTP_PROVING 3 83 | #define MTP_ALIGNEDREADY 4 84 | #define MTP_INSERVICE 5 85 | #define MTP_ALARM 6 86 | 87 | struct mtp_su_head { 88 | /* Common header for all signaling units */ 89 | unsigned char bsn:7; 90 | unsigned char bib:1; 91 | unsigned char fsn:7; 92 | unsigned char fib:1; 93 | unsigned char li:6; 94 | unsigned char spare:2; 95 | unsigned char data[0]; 96 | } __attribute__((packed)); 97 | 98 | struct ss7; 99 | 100 | struct mtp2_timers { 101 | int t1; 102 | int t2; 103 | int t3; 104 | int t4; 105 | int t4e; 106 | int t7; 107 | }; 108 | 109 | struct mtp2 { 110 | int state; 111 | int std_test_passed; 112 | int inhibit; 113 | int changeover; 114 | unsigned int got_sent_netmsg; 115 | 116 | struct ss7_msg *co_buf; 117 | struct ss7_msg *cb_buf; 118 | 119 | unsigned char curfsn:7; 120 | unsigned char curfib:1; 121 | unsigned char lastfsnacked:7; 122 | unsigned char co_lastfsnacked:7; /* store here before reset_mtp clear */ 123 | 124 | unsigned char curbib:1; 125 | int fd; 126 | int flags; 127 | 128 | int mtp3_timer[MTP3_MAX_TIMERS]; 129 | int q707_t1_failed; 130 | 131 | /* Timers */ 132 | int t1; 133 | int t2; 134 | int t3; 135 | int t4; 136 | int t7; 137 | struct mtp2_timers timers; 138 | 139 | int slc; 140 | int net_mng_sls; 141 | 142 | int emergency; 143 | int provingperiod; 144 | unsigned int dpc; 145 | 146 | int autotxsutype; 147 | int lastsurxd; 148 | int lastsutxd; 149 | 150 | /* Line related stats */ 151 | unsigned int retransmissioncount; 152 | 153 | struct ss7_msg *tx_buf; 154 | struct ss7_msg *tx_q; 155 | struct ss7_msg *retransmit_pos; 156 | struct ss7_msg *co_tx_buf; /* store here before reset_mtp flush it */ 157 | struct ss7_msg *co_tx_q; 158 | struct adjacent_sp *adj_sp; 159 | unsigned char cb_seq; 160 | struct ss7 *master; 161 | }; 162 | 163 | /* Flags for the struct mtp2 flags parameter */ 164 | #define MTP2_FLAG_DAHDIMTP2 (1 << 0) 165 | #define MTP2_FLAG_WRITE (1 << 1) 166 | 167 | /* Initialize MTP link */ 168 | int mtp2_start(struct mtp2 *link, int emergency); 169 | int mtp2_stop(struct mtp2 *link); 170 | int mtp2_alarm(struct mtp2 *link); 171 | int mtp2_noalarm(struct mtp2 *link); 172 | int mtp2_setstate(struct mtp2 *link, int state); 173 | struct mtp2 * mtp2_new(int fd, unsigned int switchtype); 174 | int mtp2_transmit(struct mtp2 *link); 175 | int mtp2_receive(struct mtp2 *link, unsigned char *buf, int len); 176 | int mtp2_msu(struct mtp2 *link, struct ss7_msg *m); 177 | void mtp2_dump(struct mtp2 *link, char prefix, unsigned char *buf, int len); 178 | char *linkstate2strext(int linkstate); 179 | void update_txbuf(struct mtp2 *link, struct ss7_msg **buf, unsigned char upto); 180 | int len_buf(struct ss7_msg *buf); 181 | void flush_bufs(struct mtp2 *link); 182 | 183 | #endif /* _SS7_MTP_H */ 184 | -------------------------------------------------------------------------------- /mtp3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #ifndef _MTP3_H 33 | #define _MTP3_H 34 | 35 | #include "ss7_internal.h" 36 | 37 | /* Service Indicator bits for Service Information Octet */ 38 | /* Bits 4-1 */ 39 | #define SIG_NET_MNG 0x00 40 | #define SIG_STD_TEST 0x01 41 | #define SIG_SPEC_TEST 0x02 42 | #define SIG_SCCP 0x03 43 | #define SIG_ISUP 0x05 44 | /* Bits 6-5 -- ANSI networks only */ 45 | #define PRIORITY_0 0x00 46 | #define PRIORITY_1 0x01 47 | #define PRIORITY_2 0x02 48 | #define PRIORITY_3 0x03 49 | 50 | #define SIO_SIZE 1 51 | 52 | #define MTP2_LINKSTATE_DOWN 0 53 | #define MTP2_LINKSTATE_INALARM 1 54 | #define MTP2_LINKSTATE_ALIGNING 2 55 | #define MTP2_LINKSTATE_UP 3 56 | 57 | #define MTP3_DOWN 0 58 | #define MTP3_UP 1 59 | 60 | #define GOT (1 << 0) 61 | #define SENT (1 << 1) 62 | 63 | /* Prohibited, restricted states */ 64 | #define TFP 1 65 | #define TFA 2 66 | #define TFR_NON_ACTIVE 3 67 | #define TFR_ACTIVE 4 68 | 69 | /* Net mngs h0 h1 */ 70 | #define NET_MNG_COO (0x01 | 0x10) 71 | #define NET_MNG_COA (0x01 | 0x20) 72 | #define NET_MNG_CBD (0x01 | 0x50) 73 | #define NET_MNG_CBA (0x01 | 0x60) 74 | 75 | #define NET_MNG_ECO (0x02 | 0x10) 76 | #define NET_MNG_ECA (0x02 | 0x20) 77 | 78 | #define NET_MNG_RCT (0x03 | 0x10) 79 | #define NET_MNG_TFC (0x03 | 0x20) 80 | 81 | #define NET_MNG_TFP (0x04 | 0x10) 82 | #define NET_MNG_TFR (0x04 | 0x30) 83 | #define NET_MNG_TFA (0x04 | 0x50) 84 | 85 | #define NET_MNG_RST (0x05 | 0x10) 86 | #define NET_MNG_RSR (0x05 | 0x20) 87 | 88 | #define NET_MNG_LIN (0x06 | 0x10) 89 | #define NET_MNG_LUN (0x06 | 0x20) 90 | #define NET_MNG_LIA (0x06 | 0x30) 91 | #define NET_MNG_LUA (0x06 | 0x40) 92 | #define NET_MNG_LID (0x06 | 0x50) 93 | #define NET_MNG_LFU (0x06 | 0x60) 94 | #define NET_MNG_LLT (0x06 | 0x70) 95 | #define NET_MNG_LRT (0x06 | 0x80) 96 | 97 | #define NET_MNG_TRA (0x07 | 0x10) 98 | 99 | #define NET_MNG_DLC (0x08 | 0x10) 100 | #define NET_MNG_CSS (0x08 | 0x20) 101 | #define NET_MNG_CNS (0x08 | 0x30) 102 | #define NET_MNG_CNP (0x08 | 0x40) 103 | 104 | #define NET_MNG_UPU (0x0a | 0x10) 105 | 106 | /* INHIBIT states */ 107 | #define INHIBITED_REMOTELY (1 << 0) 108 | #define INHIBITED_LOCALLY (1 << 1) 109 | 110 | /* Got, Sent netmsgs */ 111 | #define SENT_LUN (1 << 0) 112 | #define SENT_LIN (1 << 1) 113 | #define SENT_COO (1 << 2) 114 | #define SENT_ECO (1 << 3) 115 | #define SENT_CBD (1 << 4) 116 | #define SENT_LFU (1 << 5) 117 | 118 | /* Chaneover states */ 119 | #define NO_CHANGEOVER 0 120 | #define CHANGEOVER_INITIATED 1 121 | #define CHANGEOVER_IN_PROGRESS 2 122 | #define CHANGEOVER_COMPLETED 3 123 | #define CHANGEBACK_INITIATED 4 124 | #define CHANGEBACK 5 125 | 126 | /* MTP3 timers */ 127 | #define MTP3_TIMER_T1 1 128 | #define MTP3_TIMER_T2 2 129 | #define MTP3_TIMER_T3 3 130 | #define MTP3_TIMER_T4 4 131 | #define MTP3_TIMER_T5 5 132 | #define MTP3_TIMER_T6 6 133 | #define MTP3_TIMER_T7 7 134 | #define MTP3_TIMER_T8 8 135 | #define MTP3_TIMER_T10 9 136 | #define MTP3_TIMER_T12 10 137 | #define MTP3_TIMER_T13 11 138 | #define MTP3_TIMER_T14 12 139 | #define MTP3_TIMER_T19 13 140 | #define MTP3_TIMER_T21 14 141 | #define MTP3_TIMER_T22 15 142 | #define MTP3_TIMER_T23 16 143 | 144 | #define MTP3_TIMER_Q707_T1 17 145 | #define MTP3_TIMER_Q707_T2 18 146 | 147 | #define AUTORL(rl, link) \ 148 | struct routing_label rl; \ 149 | rl.sls = link->net_mng_sls; \ 150 | rl.dpc = link->dpc; \ 151 | rl.opc = link->master->pc 152 | 153 | 154 | struct net_mng_message { 155 | int h0; 156 | int h1; 157 | char *name; 158 | }; 159 | 160 | struct mtp3_route { 161 | int state; 162 | unsigned int dpc; 163 | int t6; 164 | int t10; 165 | struct ss7_msg *q; 166 | struct adjacent_sp *owner; 167 | struct mtp3_route *next; 168 | }; 169 | 170 | struct adjacent_sp { 171 | int state; 172 | unsigned int adjpc; 173 | struct mtp2 *links[SS7_MAX_LINKS]; 174 | unsigned int numlinks; 175 | int timer_t19; 176 | int timer_t21; 177 | unsigned int tra; 178 | struct ss7 *master; 179 | struct mtp3_route *routes; 180 | }; 181 | 182 | int net_mng_send(struct mtp2 *link, unsigned char h0h1, struct routing_label rl, unsigned int param); 183 | 184 | /* Process any MTP2 events that occur */ 185 | ss7_event* mtp3_process_event(struct ss7 *ss7, ss7_event *e); 186 | 187 | /* The main receive function for MTP3 */ 188 | int mtp3_receive(struct ss7 *ss7, struct mtp2 *link, void *msg, int len); 189 | 190 | int mtp3_dump(struct ss7 *ss7, struct mtp2 *link, void *msg, int len); 191 | 192 | /* Transmit */ 193 | int mtp3_transmit(struct ss7 *ss7, unsigned char userpart, struct routing_label rl, int priority, struct ss7_msg *m, struct mtp2 *link); 194 | 195 | void mtp3_alarm(struct ss7 *ss7, int fd); 196 | 197 | void mtp3_noalarm(struct ss7 *ss7, int fd); 198 | 199 | void mtp3_start(struct ss7 *ss7); 200 | 201 | unsigned char ansi_sls_next(struct ss7 *ss7); 202 | 203 | int set_routinglabel(unsigned char *sif, struct routing_label *rl); 204 | 205 | unsigned char sls_next(struct ss7 *ss7); 206 | 207 | char * mtp3_timer2str(int mtp3_timer); 208 | 209 | void mtp3_add_adj_sp(struct mtp2 *link); 210 | 211 | void mtp3_free_co(struct mtp2 *link); 212 | 213 | void mtp3_destroy_all_routes(struct adjacent_sp *adj_sp); 214 | 215 | #endif /* _MTP3_H */ 216 | -------------------------------------------------------------------------------- /parser_debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #include 33 | #include 34 | #include "libss7.h" 35 | #include "ss7_internal.h" 36 | #include "mtp2.h" 37 | #include "isup.h" 38 | #include "mtp3.h" 39 | 40 | int main(int argc, char **argv) 41 | { 42 | FILE *fp; 43 | struct ss7 *ss7; 44 | unsigned char mybuf[512]; 45 | unsigned int tmp; 46 | int ss7type; 47 | int res = 0, i = 0, size; 48 | ss7_event *e; 49 | 50 | if (argc != 3) { 51 | return -1; 52 | } 53 | 54 | if (!strcasecmp(argv[1], "ansi")) { 55 | ss7type = SS7_ANSI; 56 | } else if (!strcasecmp(argv[1], "itu")) { 57 | ss7type = SS7_ITU; 58 | } else { 59 | return -1; 60 | } 61 | 62 | ss7 = ss7_new(ss7type); 63 | 64 | fp = fopen(argv[2], "r"); 65 | 66 | while (res != EOF) { 67 | res = fscanf(fp, "%x ", &tmp); 68 | mybuf[i++] = (unsigned char) tmp; 69 | } 70 | 71 | size = i + 1; 72 | 73 | for (i = 0; i < size; i++) { 74 | printf("%.2x ", mybuf[i]); 75 | } 76 | 77 | printf("\n"); 78 | 79 | ss7_add_link(ss7, SS7_TRANSPORT_DAHDIDCHAN, 10, -1, 0); 80 | 81 | ss7->debug = SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP; 82 | ss7->links[0]->state = MTP_INSERVICE; 83 | 84 | mtp2_receive(ss7->links[0], mybuf, size); 85 | 86 | if ((e = ss7_check_event(ss7))) { 87 | printf("Got event: %s\n", ss7_event2str(e->e)); 88 | } 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /ss7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "libss7.h" 41 | #include "ss7_internal.h" 42 | #include "mtp2.h" 43 | #include "isup.h" 44 | #include "mtp3.h" 45 | 46 | 47 | static void (*__ss7_message)(struct ss7 *ss7, char *message); 48 | static void (*__ss7_error)(struct ss7 *ss7, char *message); 49 | void (*ss7_notinservice)(struct ss7 *ss7, int cic, unsigned int dpc); 50 | int (*ss7_hangup)(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup); 51 | void (*ss7_call_null)(struct ss7 *ss7, struct isup_call *c, int lock); 52 | 53 | void ss7_set_message(void (*func)(struct ss7 *ss7, char *message)) 54 | { 55 | __ss7_message = func; 56 | } 57 | 58 | void ss7_set_error(void (*func)(struct ss7 *ss7, char *message)) 59 | { 60 | __ss7_error = func; 61 | } 62 | 63 | void ss7_set_notinservice(void (*func)(struct ss7 *ss7, int cic, unsigned int dpc)) 64 | { 65 | ss7_notinservice = func; 66 | } 67 | 68 | void ss7_set_hangup(int (*func)(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)) 69 | { 70 | ss7_hangup = func; 71 | } 72 | 73 | /* not called in normal operation */ 74 | void ss7_set_call_null(void (*func)(struct ss7 *ss7, struct isup_call *c, int lock)) 75 | { 76 | ss7_call_null = func; 77 | } 78 | 79 | void ss7_message(struct ss7 *ss7, const char *fmt, ...) 80 | { 81 | char tmp[1024]; 82 | va_list ap; 83 | 84 | va_start(ap, fmt); 85 | vsnprintf(tmp, sizeof(tmp), fmt, ap); 86 | va_end(ap); 87 | if (__ss7_message) { 88 | __ss7_message(ss7, tmp); 89 | } else { 90 | fputs(tmp, stdout); 91 | } 92 | } 93 | 94 | void ss7_error(struct ss7 *ss7, const char *fmt, ...) 95 | { 96 | char tmp[1024]; 97 | va_list ap; 98 | 99 | va_start(ap, fmt); 100 | vsnprintf(tmp, sizeof(tmp), fmt, ap); 101 | va_end(ap); 102 | if (__ss7_error) { 103 | __ss7_error(ss7, tmp); 104 | } else { 105 | fputs(tmp, stdout); 106 | } 107 | } 108 | 109 | void ss7_set_debug(struct ss7 *ss7, unsigned int flags) 110 | { 111 | ss7->debug = flags; 112 | } 113 | 114 | void ss7_dump_buf(struct ss7 *ss7, int tabs, unsigned char *buf, int len) 115 | { 116 | int i, j = 0; 117 | char tmp[1024]; 118 | 119 | for (i = 0; i < tabs; i++) { 120 | snprintf(&tmp[i], sizeof(tmp)-i, "\t"); 121 | } 122 | snprintf(&tmp[i], sizeof(tmp)-i, "[ "); 123 | j = i + 2; /* some TAB + "[ " */ 124 | for (i = 0; i < len; i++) { 125 | snprintf(&tmp[3*i]+j, sizeof(tmp)-3*i-j, "%02x ", buf[i]); /* &tmp[3*i]+j - for speed optimization, don't change format! */ 126 | } 127 | ss7_message(ss7, "%s]\n", tmp); 128 | } 129 | 130 | void ss7_dump_msg(struct ss7 *ss7, unsigned char *buf, int len) 131 | { 132 | int i; 133 | char tmp[1024]; 134 | 135 | for (i = 0; i < len; i++) { 136 | snprintf(&tmp[3*i], sizeof(tmp)-3*i, "%02x ", buf[i]); /* &tmp[3*i] - for speed optimization, don't change format! */ 137 | } 138 | ss7_message(ss7, "Len = %d [ %s]\n", len, tmp); 139 | } 140 | 141 | void ss7_msg_free(struct ss7_msg *m) 142 | { 143 | free(m); 144 | } 145 | 146 | struct ss7_msg * ss7_msg_new(void) 147 | { 148 | return calloc(1, sizeof(struct ss7_msg)); 149 | } 150 | 151 | unsigned char * ss7_msg_userpart(struct ss7_msg *msg) 152 | { 153 | return msg->buf + MTP2_SIZE + SIO_SIZE; 154 | } 155 | 156 | void ss7_msg_userpart_len(struct ss7_msg *msg, int len) 157 | { 158 | msg->size = MTP2_SIZE + SIO_SIZE + len; 159 | return; 160 | } 161 | 162 | ss7_event * ss7_next_empty_event(struct ss7 *ss7) 163 | { 164 | ss7_event *e; 165 | 166 | if (ss7->ev_len == MAX_EVENTS) { 167 | /* Should never happen. If it does, very bad things can happen to the call. */ 168 | ss7_error(ss7, "Event queue full! Very bad!\n"); 169 | return NULL; 170 | } 171 | 172 | e = &ss7->ev_q[(ss7->ev_h + ss7->ev_len) % MAX_EVENTS]; 173 | ss7->ev_len += 1; 174 | 175 | return e; 176 | } 177 | 178 | ss7_event * ss7_check_event(struct ss7 *ss7) 179 | { 180 | ss7_event *e; 181 | 182 | if (!ss7->ev_len) { 183 | return NULL; 184 | } else { 185 | e = &ss7->ev_q[ss7->ev_h]; 186 | } 187 | ss7->ev_h += 1; 188 | ss7->ev_h %= MAX_EVENTS; 189 | ss7->ev_len -= 1; 190 | 191 | return mtp3_process_event(ss7, e); 192 | } 193 | 194 | int ss7_start(struct ss7 *ss7) 195 | { 196 | mtp3_start(ss7); 197 | return 0; 198 | } 199 | 200 | void ss7_link_alarm(struct ss7 *ss7, int fd) 201 | { 202 | mtp3_alarm(ss7, fd); 203 | } 204 | 205 | void ss7_link_noalarm(struct ss7 *ss7, int fd) 206 | { 207 | mtp3_noalarm(ss7, fd); 208 | } 209 | 210 | /* TODO: Add entry to routing table instead */ 211 | static int ss7_set_adjpc(struct mtp2 *mtp2, unsigned int pc) 212 | { 213 | mtp2->dpc = pc; 214 | mtp3_add_adj_sp(mtp2); 215 | return 0; 216 | } 217 | 218 | int ss7_add_link(struct ss7 *ss7, int transport, int fd, int slc, unsigned int adjpc) 219 | { 220 | if (ss7->numlinks >= SS7_MAX_LINKS) { 221 | return -1; 222 | } 223 | 224 | if ((transport == SS7_TRANSPORT_DAHDIDCHAN) || (transport == SS7_TRANSPORT_DAHDIMTP2)) { 225 | struct mtp2 *m; 226 | 227 | m = mtp2_new(fd, ss7->switchtype); 228 | if (!m) { 229 | return -1; 230 | } 231 | 232 | m->master = ss7; 233 | 234 | if (transport == SS7_TRANSPORT_DAHDIMTP2) { 235 | m->flags |= MTP2_FLAG_DAHDIMTP2; 236 | } 237 | 238 | m->slc = (slc > -1) ? slc : ss7->numlinks; 239 | ss7->numlinks++; 240 | 241 | ss7->links[ss7->numlinks - 1] = m; 242 | ss7_set_adjpc(ss7->links[ss7->numlinks-1], adjpc); 243 | 244 | return 0; 245 | } 246 | 247 | return -1; 248 | } 249 | 250 | int ss7_find_link_index(struct ss7 *ss7, int fd) 251 | { 252 | int i; 253 | 254 | for (i = 0; i < ss7->numlinks && ss7->links[i]->fd != fd; i++); 255 | 256 | return ((i != ss7->numlinks) ? i : -1); 257 | } 258 | 259 | struct mtp2 * ss7_find_link(struct ss7 *ss7, int fd) 260 | { 261 | int i = ss7_find_link_index(ss7, fd); 262 | 263 | return ((i != -1) ? ss7->links[i] : NULL); 264 | } 265 | 266 | int ss7_pollflags(struct ss7 *ss7, int fd) 267 | { 268 | int flags = POLLPRI | POLLIN; 269 | int winner = ss7_find_link_index(ss7, fd); 270 | 271 | if (winner < 0) { 272 | return -1; 273 | } 274 | 275 | if (ss7->links[winner]->flags & MTP2_FLAG_DAHDIMTP2) { 276 | if (ss7->links[winner]->flags & MTP2_FLAG_WRITE) { 277 | flags |= POLLOUT; 278 | } 279 | } else { 280 | flags |= POLLOUT; 281 | } 282 | 283 | return flags; 284 | } 285 | 286 | int ss7_set_pc(struct ss7 *ss7, unsigned int pc) 287 | { 288 | ss7->pc = pc; 289 | return 0; 290 | } 291 | 292 | int ss7_set_network_ind(struct ss7 *ss7, int ni) 293 | { 294 | ss7->ni = ni; 295 | return 0; 296 | } 297 | 298 | char * ss7_event2str(int event) 299 | { 300 | switch (event) { 301 | case SS7_EVENT_UP: 302 | return "SS7_EVENT_UP"; 303 | case SS7_EVENT_DOWN: 304 | return "SS7_EVENT_DOWN"; 305 | case MTP2_LINK_UP: 306 | return "MTP2_LINK_UP"; 307 | case MTP2_LINK_DOWN: 308 | return "MTP2_LINK_DOWN"; 309 | case ISUP_EVENT_IAM: 310 | return "ISUP_EVENT_IAM"; 311 | case ISUP_EVENT_ACM: 312 | return "ISUP_EVENT_ACM"; 313 | case ISUP_EVENT_ANM: 314 | return "ISUP_EVENT_ANM"; 315 | case ISUP_EVENT_REL: 316 | return "ISUP_EVENT_REL"; 317 | case ISUP_EVENT_RLC: 318 | return "ISUP_EVENT_RLC"; 319 | case ISUP_EVENT_GRS: 320 | return "ISUP_EVENT_GRS"; 321 | case ISUP_EVENT_GRA: 322 | return "ISUP_EVENT_GRA"; 323 | case ISUP_EVENT_CON: 324 | return "ISUP_EVENT_CON"; 325 | case ISUP_EVENT_COT: 326 | return "ISUP_EVENT_COT"; 327 | case ISUP_EVENT_CCR: 328 | return "ISUP_EVENT_CCR"; 329 | case ISUP_EVENT_BLO: 330 | return "ISUP_EVENT_BLO"; 331 | case ISUP_EVENT_UBL: 332 | return "ISUP_EVENT_UBL"; 333 | case ISUP_EVENT_BLA: 334 | return "ISUP_EVENT_BLA"; 335 | case ISUP_EVENT_UBA: 336 | return "ISUP_EVENT_UBA"; 337 | case ISUP_EVENT_CGB: 338 | return "ISUP_EVENT_CGB"; 339 | case ISUP_EVENT_CGU: 340 | return "ISUP_EVENT_CGU"; 341 | case ISUP_EVENT_RSC: 342 | return "ISUP_EVENT_RSC"; 343 | case ISUP_EVENT_CPG: 344 | return "ISUP_EVENT_CPG"; 345 | case ISUP_EVENT_UCIC: 346 | return "ISUP_EVENT_UCIC"; 347 | case ISUP_EVENT_LPA: 348 | return "ISUP_EVENT_LPA"; 349 | case ISUP_EVENT_CQM: 350 | return "ISUP_EVENT_CQM"; 351 | case ISUP_EVENT_FAR: 352 | return "ISUP_EVENT_FAR"; 353 | case ISUP_EVENT_FAA: 354 | return "ISUP_EVENT_FAA"; 355 | case ISUP_EVENT_CVT: 356 | return "ISUP_EVENT_CVT"; 357 | case ISUP_EVENT_CVR: 358 | return "ISUP_EVENT_CVR"; 359 | case ISUP_EVENT_SUS: 360 | return "ISUP_EVENT_SUS"; 361 | case ISUP_EVENT_RES: 362 | return "ISUP_EVENT_RES"; 363 | case ISUP_EVENT_CGBA: 364 | return "ISUP_EVENT_CGBA"; 365 | case ISUP_EVENT_CGUA: 366 | return "ISUP_EVENT_CGUA"; 367 | case ISUP_EVENT_SAM: 368 | return "ISUP_EVENT_SAM"; 369 | case ISUP_EVENT_DIGITTIMEOUT: 370 | return "ISUP_EVENT_DIGITTIMEOUT"; 371 | default: 372 | return "Unknown Event"; 373 | } 374 | } 375 | 376 | struct ss7 *ss7_new(int switchtype) 377 | { 378 | struct ss7 *s; 379 | int x; 380 | 381 | if (((switchtype != SS7_ITU) && (switchtype != SS7_ANSI)) || !(s = calloc(1, sizeof(struct ss7)))) { 382 | return NULL; 383 | } 384 | 385 | /* Initialize the event queue */ 386 | s->ev_h = 0; 387 | s->ev_len = 0; 388 | s->state = SS7_STATE_DOWN; 389 | s->switchtype = switchtype; 390 | 391 | for (x = 0; x < ISUP_MAX_TIMERS; x++) { 392 | s->isup_timers[x] = 0; 393 | } 394 | 395 | s->linkset_up_timer = -1; 396 | 397 | s->flags = SS7_ISDN_ACCESS_INDICATOR; 398 | s->sls_shift = 0; 399 | s->cause_location = LOC_PRIV_NET_LOCAL_USER; 400 | 401 | return s; 402 | } 403 | 404 | void ss7_destroy(struct ss7 *ss7) 405 | { 406 | int i; 407 | 408 | if (!ss7) { 409 | return; 410 | } 411 | 412 | /* ISUP */ 413 | isup_free_all_calls(ss7); 414 | 415 | /* MTP3 */ 416 | for (i = 0; i > ss7->numsps; i++) { 417 | mtp3_destroy_all_routes(ss7->adj_sps[i]); 418 | free(ss7->adj_sps[i]); 419 | } 420 | 421 | for (i = 0; i > ss7->numlinks; i++) { 422 | flush_bufs(ss7->links[i]); 423 | mtp3_free_co(ss7->links[i]); 424 | free(ss7->links[i]); 425 | } 426 | 427 | free(ss7); 428 | } 429 | 430 | void ss7_set_sls_shift(struct ss7 *ss7, unsigned char shift) 431 | { 432 | if (!ss7) { 433 | return; 434 | } 435 | 436 | ss7->sls_shift = shift; 437 | } 438 | 439 | void ss7_set_flags(struct ss7 *ss7, unsigned int flags) 440 | { 441 | if (!ss7) { 442 | return; 443 | } 444 | 445 | ss7->flags |= flags; 446 | } 447 | 448 | void ss7_clear_flags(struct ss7 *ss7, unsigned int flags) 449 | { 450 | if (!ss7) { 451 | return; 452 | } 453 | 454 | ss7->flags &= ~flags; 455 | } 456 | 457 | void ss7_set_cause_location(struct ss7 *ss7, unsigned char location) 458 | { 459 | if (!ss7) { 460 | return; 461 | } 462 | 463 | ss7->cause_location = 0x0f & location; 464 | } 465 | 466 | int ss7_write(struct ss7 *ss7, int fd) 467 | { 468 | int res; 469 | int winner = ss7_find_link_index(ss7, fd); 470 | 471 | if (winner < 0) { 472 | return -1; 473 | } 474 | 475 | res = mtp2_transmit(ss7->links[winner]); 476 | 477 | return res; 478 | } 479 | 480 | int ss7_read(struct ss7 *ss7, int fd) 481 | { 482 | int res; 483 | int winner = ss7_find_link_index(ss7, fd); 484 | unsigned char buf[1024]; 485 | 486 | if (winner < 0) { 487 | return -1; 488 | } 489 | 490 | res = read(ss7->links[winner]->fd, buf, sizeof(buf)); 491 | if (res <= 0) { 492 | return res; 493 | } 494 | 495 | res = mtp2_receive(ss7->links[winner], buf, res); 496 | 497 | return res; 498 | } 499 | 500 | static inline char * changeover2str(int state) 501 | { 502 | switch(state) { 503 | case NO_CHANGEOVER: 504 | return "NO"; 505 | case CHANGEOVER_COMPLETED: 506 | return "COMPLETED"; 507 | case CHANGEOVER_IN_PROGRESS: 508 | return "IN PROGRESS"; 509 | case CHANGEOVER_INITIATED: 510 | return "CHANGEOVER INITIATED"; 511 | case CHANGEBACK_INITIATED: 512 | return "CHANGEBACK INITIATED"; 513 | case CHANGEBACK: 514 | return "IN CHANGEBACK"; 515 | default: 516 | return "UNKNOWN"; 517 | } 518 | } 519 | 520 | static inline char * got_sent2str(char * buf, unsigned int got_sent) 521 | { 522 | buf[0] = '\0'; 523 | 524 | if (got_sent & SENT_LIN) { 525 | strcat(buf, " sentLIN"); 526 | } 527 | if (got_sent & SENT_LUN) { 528 | strcat(buf, " sentLUN"); 529 | } 530 | if (got_sent & SENT_COO) { 531 | strcat(buf, " sentCOO"); 532 | } 533 | if (got_sent & SENT_ECO) { 534 | strcat(buf, " sentECO"); 535 | } 536 | if (got_sent & SENT_CBD) { 537 | strcat(buf, " sentCBD"); 538 | } 539 | if (got_sent & SENT_LFU) { 540 | strcat(buf, " sentLFU"); 541 | } 542 | 543 | return buf; 544 | } 545 | 546 | static inline char * mtp2state2str(struct ss7 *ss7, struct mtp2 *link) 547 | { 548 | int i; 549 | 550 | for (i = 0; i < ss7->numlinks; i++) { 551 | if (ss7->links[i] == link) { 552 | break; 553 | } 554 | } 555 | 556 | if (i == ss7->numlinks) { 557 | return "UNKNOWN"; 558 | } 559 | 560 | switch (ss7->mtp2_linkstate[i]) { 561 | case MTP2_LINKSTATE_DOWN: 562 | return "DOWN"; 563 | case MTP2_LINKSTATE_INALARM: 564 | return "INALARM"; 565 | case MTP2_LINKSTATE_ALIGNING: 566 | return "ALIGNING"; 567 | case MTP2_LINKSTATE_UP: 568 | return "UP"; 569 | default: 570 | return "UNKNOWN"; 571 | } 572 | } 573 | 574 | static inline char * mtp3_state(int state) 575 | { 576 | switch (state) { 577 | case MTP3_DOWN: 578 | return "DOWN"; 579 | case MTP3_UP: 580 | return "UP"; 581 | default: 582 | return "UNKNOWN"; 583 | } 584 | } 585 | 586 | static inline char * route_state(int state) 587 | { 588 | switch (state) { 589 | case TFP: 590 | return "TFP"; 591 | case TFA: 592 | return "TFA"; 593 | case TFR_NON_ACTIVE: 594 | return "TFR NON ACTIVE"; 595 | case TFR_ACTIVE: 596 | return "TFR ACTIVE"; 597 | default: 598 | return "Unknown"; 599 | } 600 | } 601 | 602 | void ss7_pc_to_str(int ss7type, unsigned int pc, char *str) 603 | { 604 | if (ss7type == SS7_ITU) { 605 | sprintf(str, "%d", pc); 606 | } else { 607 | sprintf(str, "%d-%d-%d", (pc >> 16) & 0xff, (pc >> 8) & 0xff, pc & 0xff); 608 | } 609 | } 610 | 611 | void ss7_show_linkset(struct ss7 *ss7, ss7_printf_cb cust_printf, int fd) 612 | { 613 | int j, i, x; 614 | char *p; 615 | char got_sent_buf[256], timers[512]; 616 | struct adjacent_sp *adj_sp; 617 | struct mtp2 *link; 618 | struct mtp3_route *cur; 619 | char pc_str[64]; 620 | 621 | ss7_pc_to_str(ss7->switchtype, ss7->pc, pc_str); 622 | 623 | cust_printf(fd, "Switch type: %s\n", (ss7->switchtype == SS7_ITU) ? "ITU" : "ANSI"); 624 | cust_printf(fd, "Our point code: %s\n", pc_str); 625 | cust_printf(fd, "SLS shift: %i\n", ss7->sls_shift); 626 | cust_printf(fd, "numlinks: %i\n", ss7->numlinks); 627 | cust_printf(fd, "numsps: %i\n", ss7->numsps); 628 | 629 | 630 | for (j = 0; j < ss7->numsps; j++) { 631 | adj_sp = ss7->adj_sps[j]; 632 | ss7_pc_to_str(ss7->switchtype, adj_sp->adjpc, pc_str); 633 | cust_printf(fd, " ---------------------------------\n Adjacent SP PC: %s STATE: %s\n", pc_str, mtp3_state(adj_sp->state)); 634 | cust_printf(fd, " TRA: %s%s T19: %s T21: %s\n", (adj_sp->tra & GOT) ? "GOT " : "", (adj_sp->tra & SENT) ? "SENT" : "", 635 | (adj_sp->timer_t19 > -1) ? "running" : "not running", (adj_sp->timer_t21 > -1) ? "running" : "not running"); 636 | 637 | cust_printf(fd, " Routes:\n"); 638 | cust_printf(fd, " DPC State T6 T10\n"); 639 | cur = adj_sp->routes; 640 | while (cur) { 641 | ss7_pc_to_str(ss7->switchtype, cur->dpc, pc_str); 642 | cust_printf(fd, "%s %12s%10s%10s\n", pc_str, route_state(cur->state), (cur->t6 > -1) ? "running" : "-", 643 | (cur->t10 > -1) ? "running" : "-"); 644 | cur = cur->next; 645 | } 646 | for (i = 0; i < adj_sp->numlinks; i++) { 647 | link = adj_sp->links[i]; 648 | timers[0] = '\0'; 649 | p = timers; 650 | for (x = 0; x < MTP3_MAX_TIMERS; x++) { 651 | if (link->mtp3_timer[x] > -1) { 652 | strcpy(p, mtp3_timer2str(x)); 653 | p += strlen(p); 654 | sprintf(p, "(%lis)%c", ss7->ss7_sched[ss7->links[i]->mtp3_timer[x]].when.tv_sec - time(NULL), 655 | ss7->ss7_sched[ss7->links[i]->mtp3_timer[x]].callback ? ' ' : '!'); 656 | p += strlen(p); 657 | } 658 | } 659 | 660 | ss7_pc_to_str(ss7->switchtype, link->adj_sp->adjpc, pc_str); 661 | cust_printf(fd, " Link ADJ_PC:SLC: %s:%i NetMngSLS: %i\n", pc_str, link->slc, link->net_mng_sls); 662 | cust_printf(fd, " State: %s, %s\n", linkstate2strext(link->state), mtp2state2str(ss7, link)); 663 | cust_printf(fd, " STD Test: %s\n", link->std_test_passed ? "passed" : "failed"); 664 | cust_printf(fd, " Got, sent :%s\n", got_sent2str(got_sent_buf, link->got_sent_netmsg)); 665 | cust_printf(fd, " Inhibit: %s%s\n", (link->inhibit & INHIBITED_LOCALLY) ? "Locally " : " ", 666 | (ss7->links[i]->inhibit & INHIBITED_REMOTELY) ? "Remotely" : ""); 667 | cust_printf(fd, " Changeover: %s\n", changeover2str(link->changeover)); 668 | cust_printf(fd, " Tx buffer: %i\n", len_buf(link->tx_buf)); 669 | cust_printf(fd, " Tx queue: %i\n", len_buf(link->tx_q)); 670 | cust_printf(fd, " Retrans pos %i\n", len_buf(link->retransmit_pos)); 671 | cust_printf(fd, " CO buffer: %i\n", len_buf(link->co_buf)); 672 | cust_printf(fd, " CB buffer: %i\n", len_buf(link->cb_buf)); 673 | cust_printf(fd, " Last FSN: %i\n", link->lastfsnacked); 674 | cust_printf(fd, " MTP3timers: %s\n", timers); 675 | } /* links */ 676 | } /* sps */ 677 | } 678 | -------------------------------------------------------------------------------- /ss7_internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #ifndef _SS7_H 33 | #define _SS7_H 34 | 35 | #include 36 | #include 37 | #include "libss7.h" 38 | /* #include "mtp2.h" */ 39 | /* #include "mtp3.h" */ 40 | 41 | /* ISUP parameters */ 42 | 43 | /* ISUP Timers */ 44 | #define ISUP_MAX_TIMERS 64 45 | 46 | /* Information Transfer Capability */ 47 | #define ISUP_TRANSCAP_SPEECH 0x00 48 | #define ISUP_TRANSCAP_UNRESTRICTED_DIGITAL 0x08 49 | #define ISUP_TRANSCAP_RESTRICTED_DIGITAL 0x09 50 | #define ISUP_TRANSCAP_31KHZ_AUDIO 0x10 51 | #define ISUP_TRANSCAP_7KHZ_AUDIO 0x11 52 | 53 | /* User Information layer 1 protocol types */ 54 | #define ISUP_L1PROT_G711ULAW 0x02 55 | 56 | #define MAX_EVENTS 16 57 | #define MAX_SCHED 512 /* need a lot cause of isup timers... */ 58 | #define SS7_MAX_LINKS 8 59 | #define SS7_MAX_ADJSPS 8 60 | 61 | #define SS7_STATE_DOWN 0 62 | #define SS7_STATE_UP 1 63 | 64 | /* delay to starting sending GRS when linkset came up */ 65 | #define LINKSET_UP_DELAY 500 66 | 67 | /* MTP3 timers */ 68 | #define MTP3_MAX_TIMERS 32 69 | 70 | #define LOC_PRIV_NET_LOCAL_USER 0x1 71 | 72 | typedef unsigned int point_code; 73 | 74 | struct routing_label { 75 | unsigned int type; 76 | point_code dpc; 77 | point_code opc; 78 | unsigned char sls; 79 | }; 80 | 81 | struct ss7_msg { 82 | unsigned char buf[512]; 83 | unsigned int size; 84 | struct ss7_msg *next; 85 | }; 86 | 87 | struct ss7_sched { 88 | struct timeval when; 89 | void (*callback)(void *data); 90 | void *data; 91 | }; 92 | 93 | struct ss7 { 94 | unsigned int switchtype; 95 | unsigned int numsps; 96 | unsigned int numlinks; 97 | 98 | /* Our point code */ 99 | point_code pc; 100 | 101 | unsigned char ni; 102 | unsigned char sls; 103 | int state; 104 | 105 | unsigned int debug; 106 | /* event queue */ 107 | int ev_h; 108 | int ev_t; 109 | int ev_len; 110 | ss7_event ev_q[MAX_EVENTS]; 111 | 112 | struct ss7_sched ss7_sched[MAX_SCHED]; 113 | struct isup_call *calls; 114 | 115 | unsigned int mtp2_linkstate[SS7_MAX_LINKS]; 116 | struct mtp2 *links[SS7_MAX_LINKS]; 117 | struct adjacent_sp *adj_sps[SS7_MAX_ADJSPS]; 118 | int isup_timers[ISUP_MAX_TIMERS]; 119 | int mtp3_timers[MTP3_MAX_TIMERS]; 120 | unsigned char sls_shift; 121 | unsigned int flags; 122 | unsigned char cb_seq; 123 | int linkset_up_timer; 124 | unsigned char cause_location; 125 | }; 126 | 127 | /* Getto hacks for developmental purposes */ 128 | struct ss7_msg * ss7_msg_new(void); 129 | 130 | void ss7_msg_free(struct ss7_msg *m); 131 | 132 | /* Scheduler functions */ 133 | int ss7_schedule_event(struct ss7 *ss7, int ms, void (*function)(void *data), void *data); 134 | 135 | ss7_event * ss7_next_empty_event(struct ss7 * ss7); 136 | 137 | void ss7_schedule_del(struct ss7 *ss7,int *id); 138 | 139 | int ss7_find_link_index(struct ss7 *ss7, int fd); 140 | 141 | struct mtp2 * ss7_find_link(struct ss7 *ss7, int fd); 142 | 143 | unsigned char *ss7_msg_userpart(struct ss7_msg *m); 144 | 145 | void ss7_msg_userpart_len(struct ss7_msg *m, int len); 146 | 147 | void ss7_message(struct ss7 *ss7, const char *fmt, ...) __attribute__((format(printf, 2, 3))); 148 | void ss7_error(struct ss7 *ss7, const char *fmt, ...) __attribute__((format(printf, 2, 3))); 149 | 150 | #define ss7_debug_msg(ctrl, flags, ...) \ 151 | do { \ 152 | if ((ctrl)->debug & (flags)) { \ 153 | ss7_message(ctrl, __VA_ARGS__); \ 154 | } \ 155 | } while (0) 156 | 157 | void ss7_dump_buf(struct ss7 *ss7, int tabs, unsigned char *buf, int len); 158 | 159 | void ss7_dump_msg(struct ss7 *ss7, unsigned char *buf, int len); 160 | 161 | extern void (*ss7_notinservice)(struct ss7 *ss7, int cic, unsigned int dpc); 162 | 163 | extern int (*ss7_hangup)(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup); 164 | 165 | extern void (*ss7_call_null)(struct ss7 *ss7, struct isup_call *c, int lock); 166 | 167 | #endif /* _SS7_H */ 168 | -------------------------------------------------------------------------------- /ss7_sched.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #include "libss7.h" 33 | #include "ss7_internal.h" 34 | #include "mtp3.h" 35 | #include 36 | 37 | 38 | /* Scheduler routines */ 39 | int ss7_schedule_event(struct ss7 *ss7, int ms, void (*function)(void *data), void *data) 40 | { 41 | int x; 42 | struct timeval tv; 43 | for (x=1;xss7_sched[x].callback) 45 | break; 46 | if (x == MAX_SCHED) { 47 | ss7_error(ss7, "No more room in scheduler\n"); 48 | return -1; 49 | } 50 | gettimeofday(&tv, NULL); 51 | tv.tv_sec += ms / 1000; 52 | tv.tv_usec += (ms % 1000) * 1000; 53 | if (tv.tv_usec > 1000000) { 54 | tv.tv_usec -= 1000000; 55 | tv.tv_sec += 1; 56 | } 57 | ss7->ss7_sched[x].when = tv; 58 | ss7->ss7_sched[x].callback = function; 59 | ss7->ss7_sched[x].data = data; 60 | return x; 61 | } 62 | 63 | struct timeval *ss7_schedule_next(struct ss7 *ss7) 64 | { 65 | struct timeval *closest = NULL; 66 | int x; 67 | /* Check subchannels */ 68 | for (x=1;xss7_sched[x].callback && 70 | (!closest || (closest->tv_sec > ss7->ss7_sched[x].when.tv_sec) || 71 | ((closest->tv_sec == ss7->ss7_sched[x].when.tv_sec) && 72 | (closest->tv_usec > ss7->ss7_sched[x].when.tv_usec)))) 73 | closest = &ss7->ss7_sched[x].when; 74 | } 75 | return closest; 76 | } 77 | 78 | static int __ss7_schedule_run(struct ss7 *ss7, struct timeval *tv) 79 | { 80 | int x; 81 | void (*callback)(void *); 82 | void *data; 83 | for (x=1;xss7_sched[x].callback && 85 | ((ss7->ss7_sched[x].when.tv_sec < tv->tv_sec) || 86 | ((ss7->ss7_sched[x].when.tv_sec == tv->tv_sec) && 87 | (ss7->ss7_sched[x].when.tv_usec <= tv->tv_usec)))) { 88 | callback = ss7->ss7_sched[x].callback; 89 | data = ss7->ss7_sched[x].data; 90 | ss7->ss7_sched[x].callback = NULL; 91 | ss7->ss7_sched[x].data = NULL; 92 | callback(data); 93 | } 94 | } 95 | return 0; 96 | } 97 | 98 | int ss7_schedule_run(struct ss7 *ss7) 99 | { 100 | int res; 101 | 102 | struct timeval tv; 103 | gettimeofday(&tv, NULL); 104 | 105 | res = __ss7_schedule_run(ss7, &tv); 106 | 107 | return res; 108 | } 109 | 110 | void ss7_schedule_del(struct ss7 *ss7, int *id) 111 | { 112 | if ((*id >= MAX_SCHED)) 113 | ss7_error(ss7, "Asked to delete sched id %d???\n", *id); 114 | 115 | if (*id < 0) /* Item already deleted */ 116 | return; 117 | 118 | ss7->ss7_sched[*id].callback = NULL; 119 | *id = -1; /* "Delete" the event */ 120 | } 121 | -------------------------------------------------------------------------------- /ss7linktest.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include "libss7.h" 46 | 47 | struct linkset { 48 | struct ss7 *ss7; 49 | int linkno; 50 | int fd; 51 | } linkset[2]; 52 | 53 | int linknum = 1; 54 | int callcount = 0; 55 | unsigned int opc; 56 | unsigned int dpc; 57 | 58 | #define NUM_BUFS 32 59 | 60 | static void ss7_call(struct ss7 *ss7) 61 | { 62 | struct isup_call *c; 63 | 64 | c = isup_new_call(ss7, (callcount % 12) + 1, dpc, 0); 65 | 66 | if (c) { 67 | isup_set_called(c, "12345", SS7_NAI_NATIONAL, ss7); 68 | isup_set_calling(c, "7654321", SS7_NAI_NATIONAL, SS7_PRESENTATION_ALLOWED, SS7_SCREENING_USER_PROVIDED); 69 | isup_iam(ss7, c); 70 | printf("Callcount = %d\n ", ++callcount); 71 | } 72 | } 73 | 74 | static void *ss7_run(void *data) 75 | { 76 | int res = 0; 77 | struct timeval *next = NULL, tv; 78 | struct linkset *linkset = (struct linkset *) data; 79 | struct ss7 *ss7 = linkset->ss7; 80 | ss7_event *e = NULL; 81 | struct pollfd poller; 82 | int nextms; 83 | int x; 84 | struct isup_call *c; 85 | unsigned char state[255]; 86 | int i; 87 | 88 | for (i = 0; i < 255; i++) { 89 | state[i] = 0; 90 | } 91 | 92 | printf("Starting link %d\n", linknum++); 93 | ss7_start(ss7); 94 | 95 | while (1) { 96 | if ((next = ss7_schedule_next(ss7))) { 97 | gettimeofday(&tv, NULL); 98 | tv.tv_sec = next->tv_sec - tv.tv_sec; 99 | tv.tv_usec = next->tv_usec - tv.tv_usec; 100 | if (tv.tv_usec < 0) { 101 | tv.tv_usec += 1000000; 102 | tv.tv_sec -= 1; 103 | } 104 | if (tv.tv_sec < 0) { 105 | tv.tv_sec = 0; 106 | tv.tv_usec = 0; 107 | } 108 | nextms = tv.tv_sec * 1000; 109 | nextms += tv.tv_usec / 1000; 110 | } else { 111 | nextms = -1; 112 | } 113 | poller.fd = linkset->fd; 114 | poller.events = ss7_pollflags(ss7, linkset->fd); 115 | poller.revents = 0; 116 | 117 | res = poll(&poller, 1, nextms); 118 | if (res < 0) { 119 | #if 0 120 | printf("next->tv_sec = %d\n", (int) next->tv_sec); 121 | printf("next->tv_usec = %d\n", (int) next->tv_usec); 122 | printf("tv->tv_sec = %d\n", (int) tv.tv_sec); 123 | printf("tv->tv_usec = %d\n", (int) tv.tv_usec); 124 | #endif 125 | perror("select"); 126 | } else if (!res) { 127 | ss7_schedule_run(ss7); 128 | continue; 129 | } 130 | 131 | if (poller.revents & POLLPRI) { 132 | if (ioctl(linkset->fd, DAHDI_GETEVENT, &x)) { 133 | perror("Error in exception retrieval!\n"); 134 | } 135 | switch (x) { 136 | case DAHDI_EVENT_OVERRUN: 137 | printf("Overrun detected!\n"); 138 | break; 139 | case DAHDI_EVENT_BADFCS: 140 | printf("Bad FCS!\n"); 141 | break; 142 | case DAHDI_EVENT_ABORT: 143 | printf("HDLC Abort!\n"); 144 | break; 145 | default: 146 | printf("Got exception %d!\n", x); 147 | break; 148 | } 149 | } 150 | 151 | if (poller.revents & POLLIN) 152 | res = ss7_read(ss7, linkset->fd); 153 | if (poller.revents & POLLOUT) { 154 | res = ss7_write(ss7, linkset->fd); 155 | if (res < 0) { 156 | printf("Error in write %s", strerror(errno)); 157 | } 158 | } 159 | 160 | #if 0 161 | if (res < 0) 162 | exit(-1); 163 | #endif 164 | 165 | while ((e = ss7_check_event(ss7))) { 166 | if (e) { 167 | switch (e->e) { 168 | case SS7_EVENT_UP: 169 | printf("[%d] --- SS7 Up ---\n", linkset->linkno); 170 | c = isup_new_call(ss7, 1, dpc, 0); 171 | isup_grs(ss7, c, 24); 172 | break; 173 | case MTP2_LINK_UP: 174 | printf("[%d] MTP2 link up\n", linkset->linkno); 175 | break; 176 | case ISUP_EVENT_GRS: 177 | printf("Got GRS from cic %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic); 178 | isup_gra(ss7, e->grs.call, e->grs.endcic, state); 179 | break; 180 | case ISUP_EVENT_RSC: 181 | isup_rlc(ss7, e->rsc.call); 182 | break; 183 | case ISUP_EVENT_GRA: 184 | printf("Got GRA from cic %d to %d.\n", e->gra.startcic, e->gra.endcic); 185 | ss7_call(ss7); 186 | break; 187 | case ISUP_EVENT_BLO: 188 | isup_bla(ss7, e->blo.call); 189 | break; 190 | case ISUP_EVENT_CGB: 191 | isup_cgba(ss7, e->cgb.call, e->cgb.endcic, e->cgb.status); 192 | break; 193 | case ISUP_EVENT_CGU: 194 | isup_cgua(ss7, e->cgu.call, e->cgu.endcic, e->cgu.status); 195 | break; 196 | case ISUP_EVENT_IAM: 197 | printf("Got IAM for cic %d and number %s\n", e->iam.cic, e->iam.called_party_num); 198 | printf("CallerID is %s\n", e->iam.calling_party_num); 199 | printf("Sending ACM\n"); 200 | isup_acm(ss7, e->iam.call); 201 | printf("Sending ANM\n"); 202 | isup_anm(ss7, e->iam.call); 203 | break; 204 | case ISUP_EVENT_REL: 205 | printf("Got REL for cic %d\n", e->rel.cic); 206 | isup_rlc(ss7, e->rel.call); 207 | //ss7_call(ss7); 208 | break; 209 | case ISUP_EVENT_ACM: 210 | printf("Got ACM for cic %d\n", e->acm.cic); 211 | break; 212 | case ISUP_EVENT_ANM: 213 | printf("Got ANM for cic %d\n", e->anm.cic); 214 | isup_rel(ss7, e->anm.call, 16); 215 | break; 216 | case ISUP_EVENT_RLC: 217 | printf("Got RLC for cic %d\n", e->rlc.cic); 218 | //ss7_call(ss7); 219 | break; 220 | default: 221 | printf("Unknown event %d\n", e->e); 222 | break; 223 | } 224 | } 225 | } 226 | } 227 | 228 | return NULL; 229 | } 230 | 231 | static void myprintf(struct ss7 *ss7, char *fmt) 232 | { 233 | printf("%s", fmt); 234 | } 235 | 236 | static int dahdi_open(int devnum, int *ismtp2) 237 | { 238 | int fd; 239 | struct dahdi_bufferinfo bi; 240 | struct dahdi_params z; 241 | fd = open("/dev/dahdi/channel", O_RDWR|O_NONBLOCK, 0600); 242 | if ((fd < 0) || (ioctl(fd, DAHDI_SPECIFY, &devnum) == -1)) { 243 | printf("Could not open device %d: %s\n", devnum, strerror(errno)); 244 | return -1; 245 | } 246 | bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 247 | bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 248 | bi.numbufs = NUM_BUFS; 249 | bi.bufsize = 512; 250 | if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 251 | close(fd); 252 | return -1; 253 | } 254 | 255 | if (ioctl(fd, DAHDI_GET_PARAMS, &z)) { 256 | close(fd); 257 | return -1; 258 | } 259 | 260 | if (z.sigtype == DAHDI_SIG_MTP2) 261 | *ismtp2 = 1; 262 | else 263 | *ismtp2 = 0; 264 | return fd; 265 | } 266 | 267 | static void print_args(void) 268 | { 269 | printf("Incorrect arguments. Should be:\n"); 270 | printf("ss7linktest [sigchan number] [ss7 style - itu or ansi] [OPC - in decimal] [DPC - in decimal]\n"); 271 | printf("Example:\n"); 272 | printf("ss7linktest 16 itu 1 2\n"); 273 | printf("This would run the linktest program on dahdi/16 with ITU style signalling, with an OPC of 1 and a DPC of 2\n"); 274 | } 275 | 276 | int main(int argc, char *argv[]) 277 | { 278 | int fd; 279 | struct ss7 *ss7; 280 | pthread_t tmp; 281 | int channum; 282 | int ismtp2; 283 | unsigned int type; 284 | 285 | if (argc < 5) { 286 | print_args(); 287 | return -1; 288 | } 289 | channum = atoi(argv[1]); 290 | 291 | if (!strcasecmp(argv[2], "ansi")) { 292 | type = SS7_ANSI; 293 | } else if (!strcasecmp(argv[2], "itu")) { 294 | type = SS7_ITU; 295 | } else { 296 | print_args(); 297 | return -1; 298 | } 299 | 300 | opc = atoi(argv[3]); 301 | dpc = atoi(argv[4]); 302 | 303 | fd = dahdi_open(channum, &ismtp2); 304 | 305 | if (fd == -1) { 306 | return -1; 307 | } 308 | 309 | if (!(ss7 = ss7_new(type))) { 310 | perror("ss7_new"); 311 | exit(1); 312 | } 313 | linkset[0].ss7 = ss7; 314 | linkset[0].fd = fd; 315 | linkset[0].linkno = 0; 316 | 317 | ss7_set_message(myprintf); 318 | ss7_set_error(myprintf); 319 | ss7_set_network_ind(ss7, SS7_NI_NAT); 320 | 321 | ss7_set_debug(ss7, 0xffffffff); 322 | if ((ss7_add_link(ss7, ismtp2 ? SS7_TRANSPORT_DAHDIMTP2 : SS7_TRANSPORT_DAHDIDCHAN, fd, -1, dpc))) { 323 | perror("ss7_add_link"); 324 | exit(1); 325 | } 326 | 327 | ss7_set_pc(ss7, opc); 328 | 329 | if (pthread_create(&tmp, NULL, ss7_run, &linkset[0])) { 330 | perror("thread(0)"); 331 | exit(1); 332 | } 333 | 334 | pthread_join(tmp, NULL); 335 | 336 | return 0; 337 | } 338 | -------------------------------------------------------------------------------- /ss7test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libss7: An implementation of Signalling System 7 3 | * 4 | * Written by Matthew Fredrickson 5 | * 6 | * scheduling routines taken from libpri by Mark Spencer 7 | * 8 | * Copyright (C) 2006-2008, Digium, Inc 9 | * All Rights Reserved. 10 | */ 11 | 12 | /* 13 | * See http://www.asterisk.org for more information about 14 | * the Asterisk project. Please do not directly contact 15 | * any of the maintainers of this project for assistance; 16 | * the project provides a web site, mailing lists and IRC 17 | * channels for your use. 18 | * 19 | * This program is free software, distributed under the terms of 20 | * the GNU General Public License Version 2 as published by the 21 | * Free Software Foundation. See the LICENSE file included with 22 | * this program for more details. 23 | * 24 | * In addition, when this program is distributed with Asterisk in 25 | * any form that would qualify as a 'combined work' or as a 26 | * 'derivative work' (but not mere aggregation), you can redistribute 27 | * and/or modify the combination under the terms of the license 28 | * provided with that copy of Asterisk, instead of the license 29 | * terms granted here. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include "libss7.h" 44 | 45 | struct linkset { 46 | struct ss7 *ss7; 47 | int linkno; 48 | int fd; 49 | } linkset[2]; 50 | 51 | int linknum = 1; 52 | 53 | #define NUM_BUFS 32 54 | 55 | static void *ss7_run(void *data) 56 | { 57 | int res = 0; 58 | struct timeval *next = NULL, tv; 59 | struct linkset *linkset = (struct linkset *) data; 60 | struct ss7 *ss7 = linkset->ss7; 61 | int ourlink = linknum; 62 | ss7_event *e = NULL; 63 | fd_set rfds; 64 | fd_set wfds; 65 | fd_set efds; 66 | 67 | printf("Starting link %d\n", linknum++); 68 | ss7_start(ss7); 69 | 70 | while(1) { 71 | if ((next = ss7_schedule_next(ss7))) { 72 | gettimeofday(&tv, NULL); 73 | tv.tv_sec = next->tv_sec - tv.tv_sec; 74 | tv.tv_usec = next->tv_usec - tv.tv_usec; 75 | if (tv.tv_usec < 0) { 76 | tv.tv_usec += 1000000; 77 | tv.tv_sec -= 1; 78 | } 79 | if (tv.tv_sec < 0) { 80 | tv.tv_sec = 0; 81 | tv.tv_usec = 0; 82 | } 83 | } 84 | FD_ZERO(&rfds); 85 | FD_SET(linkset->fd, &rfds); 86 | FD_ZERO(&wfds); 87 | FD_SET(linkset->fd, &wfds); 88 | FD_ZERO(&efds); 89 | FD_SET(linkset->fd, &efds); 90 | res = select(linkset->fd + 1, &rfds, &wfds, &efds, next ? &tv : NULL); 91 | if (res < 0) { 92 | printf("next->tv_sec = %d\n", (int) next->tv_sec); 93 | printf("next->tv_usec = %d\n", (int) next->tv_usec); 94 | printf("tv->tv_sec = %d\n", (int) tv.tv_sec); 95 | printf("tv->tv_usec = %d\n", (int) tv.tv_usec); 96 | perror("select"); 97 | } 98 | else if (!res) 99 | ss7_schedule_run(ss7); 100 | 101 | #if LINUX 102 | if (FD_ISSET(linkset->fd, &efds)) { 103 | int x; 104 | if (ioctl(linkset->fd, DAHDI_GETEVENT, &x)) { 105 | perror("Error in exception retrieval!\n"); 106 | exit(-1); 107 | } 108 | printf("Got exception %d!\n", x); 109 | } 110 | #endif 111 | 112 | if (FD_ISSET(linkset->fd, &rfds)) 113 | res = ss7_read(ss7, linkset->fd); 114 | if (FD_ISSET(linkset->fd, &wfds)) { 115 | res = ss7_write(ss7, linkset->fd); 116 | if (res < 0) { 117 | perror("Error in write"); 118 | } 119 | } 120 | 121 | if (res < 0) 122 | exit(-1); 123 | 124 | while ((e = ss7_check_event(ss7))) { 125 | if (e) { 126 | switch (e->e) { 127 | case SS7_EVENT_UP: 128 | printf("[%d] --- SS7 Up ---\n", linkset->linkno); 129 | break; 130 | case MTP2_LINK_UP: 131 | printf("[%d] MTP2 link up\n", linkset->linkno); 132 | break; 133 | default: 134 | printf("Unknown event %d\n", e->e); 135 | break; 136 | } 137 | } 138 | } 139 | 140 | if (ourlink == 1) { 141 | /* Our demo call */ 142 | } 143 | } 144 | } 145 | 146 | static void myprintf(struct ss7 *ss7, char *fmt) 147 | { 148 | int i = 0; 149 | for (i = 0; i < 2; i++) { 150 | if (linkset[i].ss7 == ss7) 151 | break; 152 | } 153 | if (i == 0) 154 | printf("SS7[%d] %s", i, fmt); 155 | else 156 | printf("\t\t\t\t\tSS7[%d] %s", i, fmt); 157 | } 158 | 159 | #ifdef LINUX 160 | static int dahdi_open(int devnum) 161 | { 162 | int fd; 163 | struct dahdi_bufferinfo bi; 164 | fd = open("/dev/dahdi/channel", O_RDWR|O_NONBLOCK, 0600); 165 | if ((fd < 0) || (ioctl(fd, DAHDI_SPECIFY, &devnum) == -1)) { 166 | printf("Could not open device %d: %s\n", strerror(errno)); 167 | return -1; 168 | } 169 | bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE; 170 | bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE; 171 | bi.numbufs = NUM_BUFS; 172 | bi.bufsize = 512; 173 | if (ioctl(fd, DAHDI_SET_BUFINFO, &bi)) { 174 | close(fd); 175 | return -1; 176 | } 177 | return fd; 178 | } 179 | #endif 180 | 181 | int main(int argc, char *argv[]) 182 | { 183 | int fds[2]; 184 | struct ss7 *ss7; 185 | pthread_t tmp, tmp2; 186 | 187 | if (argc == 2) { 188 | if (!strcasecmp(argv[1], "socketpair")) { 189 | if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, fds)) { 190 | perror("socketpair"); 191 | exit(1); 192 | } 193 | #ifdef LINUX 194 | } else if (!strcasecmp(argv[1], "live")) { 195 | fds[0] = dahdi_open(24); 196 | if (fds[0] < 0) { 197 | return -1; 198 | } 199 | 200 | fds[1] = dahdi_open(48); 201 | if (fds[1] < 0) { 202 | return -1; 203 | } 204 | #endif 205 | } else { 206 | return -1; 207 | } 208 | } else { 209 | return -1; 210 | } 211 | 212 | if (!(ss7 = ss7_new(SS7_ITU))) { 213 | perror("ss7_new"); 214 | exit(1); 215 | } 216 | linkset[0].ss7 = ss7; 217 | linkset[0].fd = fds[0]; 218 | linkset[0].linkno = 0; 219 | 220 | ss7_set_message(myprintf); 221 | ss7_set_error(myprintf); 222 | 223 | ss7_set_debug(ss7, 0xffffffff); 224 | if ((ss7_add_link(ss7, SS7_TRANSPORT_DAHDIDCHAN, fds[0], -1, 0))) { 225 | perror("ss7_add_link"); 226 | exit(1); 227 | } 228 | 229 | if (pthread_create(&tmp, NULL, ss7_run, &linkset[0])) { 230 | perror("thread(0)"); 231 | exit(1); 232 | } 233 | 234 | if (!(ss7 = ss7_new(SS7_ITU))) { 235 | perror("ss7_new"); 236 | exit(1); 237 | } 238 | ss7_set_debug(ss7, 0xffffffff); 239 | linkset[1].linkno = 1; 240 | 241 | if ((ss7_add_link(ss7, SS7_TRANSPORT_DAHDIDCHAN, fds[1], -1, 1))) { 242 | perror("ss7_add_link"); 243 | exit(1); 244 | } 245 | 246 | linkset[1].ss7 = ss7; 247 | linkset[1].fd = fds[1]; 248 | 249 | if (pthread_create(&tmp2, NULL, ss7_run, &linkset[1])) { 250 | perror("thread(0)"); 251 | exit(1); 252 | } 253 | 254 | 255 | pthread_join(tmp, NULL); 256 | pthread_join(tmp2, NULL); 257 | 258 | return 0; 259 | } 260 | --------------------------------------------------------------------------------