From 86d1df86c7da9a35004e6a9a326f10b8167c9179 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 9 Jul 2010 20:55:33 +0200 Subject: [PATCH] import sualibrary-0.1.0 from 2002-02-15 --- AUTHORS | 1 + COPYING | 280 ++ ChangeLog | 0 INSTALL | 167 + Makefile.am | 8 + README | 1 + TODO | 1 + configure.in | 383 +++ stamp-h.in | 1 + sualibrary.kdevprj | 290 ++ sualibrary.lsm | 14 + sualibrary/Makefile.am | 9 + sualibrary/docs/Makefile.am | 5 + sualibrary/docs/en/Makefile.am | 6 + sualibrary/docs/en/index-1.html | 100 + sualibrary/docs/en/index-2.html | 63 + sualibrary/docs/en/index-3.html | 138 + sualibrary/docs/en/index-4.html | 1067 ++++++ sualibrary/docs/en/index-5.html | 54 + sualibrary/docs/en/index-6.html | 37 + sualibrary/docs/en/index.html | 73 + sualibrary/sua/Makefile.am | 30 + sualibrary/sua/sua.h | 388 +++ sualibrary/sua/sua_adapt.cpp | 222 ++ sualibrary/sua/sua_adapt.h | 79 + sualibrary/sua/sua_asp_mgnt.cpp | 1030 ++++++ sualibrary/sua/sua_asp_mgnt.h | 190 ++ sualibrary/sua/sua_cl.cpp | 550 ++++ sualibrary/sua/sua_cl.h | 88 + sualibrary/sua/sua_co.cpp | 1768 ++++++++++ sualibrary/sua/sua_co.h | 170 + sualibrary/sua/sua_database.cpp | 642 ++++ sualibrary/sua/sua_database.h | 397 +++ sualibrary/sua/sua_dataname.cpp | 174 + sualibrary/sua/sua_datassoc.cpp | 1000 ++++++ sualibrary/sua/sua_debug.h | 79 + sualibrary/sua/sua_distribution.cpp | 1167 +++++++ sualibrary/sua/sua_distribution.h | 170 + sualibrary/sua/sua_file.cpp | 401 +++ sualibrary/sua/sua_file.h | 74 + sualibrary/sua/sua_logging.cpp | 268 ++ sualibrary/sua/sua_logging.h | 72 + sualibrary/sua/sua_sual.cpp | 686 ++++ sualibrary/sua/sua_sual.h | 459 +++ sualibrary/sua/sua_syntax.cpp | 4733 +++++++++++++++++++++++++++ sualibrary/sua/sua_syntax.h | 447 +++ sualibrary/sua/sua_tcb.cpp | 218 ++ sualibrary/sua/sua_tcb.h | 153 + sualibrary/testup/Makefile.am | 20 + sualibrary/testup/main.cpp | 321 ++ sualibrary/testup/testuser.cpp | 887 +++++ sualibrary/testup/testuser.h | 128 + 52 files changed, 19709 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 README create mode 100644 TODO create mode 100644 configure.in create mode 100644 stamp-h.in create mode 100644 sualibrary.kdevprj create mode 100644 sualibrary.lsm create mode 100644 sualibrary/Makefile.am create mode 100644 sualibrary/docs/Makefile.am create mode 100644 sualibrary/docs/en/Makefile.am create mode 100644 sualibrary/docs/en/index-1.html create mode 100644 sualibrary/docs/en/index-2.html create mode 100644 sualibrary/docs/en/index-3.html create mode 100644 sualibrary/docs/en/index-4.html create mode 100644 sualibrary/docs/en/index-5.html create mode 100644 sualibrary/docs/en/index-6.html create mode 100644 sualibrary/docs/en/index.html create mode 100644 sualibrary/sua/Makefile.am create mode 100644 sualibrary/sua/sua.h create mode 100644 sualibrary/sua/sua_adapt.cpp create mode 100644 sualibrary/sua/sua_adapt.h create mode 100644 sualibrary/sua/sua_asp_mgnt.cpp create mode 100644 sualibrary/sua/sua_asp_mgnt.h create mode 100644 sualibrary/sua/sua_cl.cpp create mode 100644 sualibrary/sua/sua_cl.h create mode 100644 sualibrary/sua/sua_co.cpp create mode 100644 sualibrary/sua/sua_co.h create mode 100644 sualibrary/sua/sua_database.cpp create mode 100644 sualibrary/sua/sua_database.h create mode 100644 sualibrary/sua/sua_dataname.cpp create mode 100644 sualibrary/sua/sua_datassoc.cpp create mode 100644 sualibrary/sua/sua_debug.h create mode 100644 sualibrary/sua/sua_distribution.cpp create mode 100644 sualibrary/sua/sua_distribution.h create mode 100644 sualibrary/sua/sua_file.cpp create mode 100644 sualibrary/sua/sua_file.h create mode 100644 sualibrary/sua/sua_logging.cpp create mode 100644 sualibrary/sua/sua_logging.h create mode 100644 sualibrary/sua/sua_sual.cpp create mode 100644 sualibrary/sua/sua_sual.h create mode 100644 sualibrary/sua/sua_syntax.cpp create mode 100644 sualibrary/sua/sua_syntax.h create mode 100644 sualibrary/sua/sua_tcb.cpp create mode 100644 sualibrary/sua/sua_tcb.h create mode 100644 sualibrary/testup/Makefile.am create mode 100644 sualibrary/testup/main.cpp create mode 100644 sualibrary/testup/testuser.cpp create mode 100644 sualibrary/testup/testuser.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..d9d34b7 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Lode Coene diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c7aea18 --- /dev/null +++ b/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..02a4a07 --- /dev/null +++ b/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..474c97d --- /dev/null +++ b/Makefile.am @@ -0,0 +1,8 @@ +####### kdevelop will overwrite this part!!! (begin)########## + +SUBDIRS = sualibrary + +EXTRA_DIST = sualibrary.kdevprj AUTHORS COPYING ChangeLog INSTALL README TODO sualibrary.lsm + +####### kdevelop will overwrite this part!!! (end)############ +AUTOMAKE_OPTIONS = foreign 1.4 diff --git a/README b/README new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/README @@ -0,0 +1 @@ + diff --git a/TODO b/TODO new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/TODO @@ -0,0 +1 @@ + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..37405e5 --- /dev/null +++ b/configure.in @@ -0,0 +1,383 @@ +AC_PREREQ(2.12) +AC_COPYRIGHT(test) + +rm -f config.cache + +AC_INIT(acconfig.h) + +AC_CANONICAL_SYSTEM +AC_ARG_PROGRAM + +AM_INIT_AUTOMAKE(sualibrary,0.1.0) + +AC_PREFIX_DEFAULT(/usr/local) +if test "x$prefix" = "xNONE"; then + prefix=$ac_default_prefix + ac_configure_args="$ac_configure_args --prefix $prefix" +fi + +dnl keep this order because automake gets confused apart from the authors +AM_CONFIG_HEADER(config.h:config.h.in) + +dnl Checks for programs. +AC_PROG_AWK +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_CXX +AC_PROG_RANLIB + + +dnl Checks for libraries. +dnl create only shared libtool-libraries (add --enable-shared) +AC_ENABLE_SHARED(no) +dnl AM_DISABLE_SHARED + +dnl set the following to yes, if you want to create static +dnl libtool-libraries, else no +AC_ENABLE_STATIC(yes) + +dnl create a working libtool-script +if test -z "$LIBTOOL"; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_LIBTOOL_DLOPEN + AM_PROG_LIBTOOL + dnl LIBTOOL="$LIBTOOL --silent" + dnl AC_SUBST(LIBTOOL) + AC_LANG_RESTORE + LIBTOOL_SHELL='/bin/sh ./libtool' +else + LIBTOOL_SHELL=$LIBTOOL +fi + + +dnl activate the following for some additional tests +dnl (compat, crypt, socket, nsl, ...) + +all_libraries="$USER_LDFLAGS $all_libraries" +all_includes="$all_includes $USER_INCLUDES" +AC_SUBST(all_includes) +AC_SUBST(all_libraries) +AC_SUBST(AUTODIRS) + +dnl Checks for header files. + +AC_HEADER_STDC +AC_HEADER_TIME +AC_CHECK_HEADERS(strings.h sys/file.h sys/time.h unistd.h netinet/in.h netdb.h \ +sys/socket.h netinet/icmp6.h) +AC_CHECK_HEADERS(sys/poll.h, AC_DEFINE(HAVE_SYS_POLL_H)) + + +dnl Checks for typedefs, structures, and compiler characteristics. + +dnl ---------------------- +dnl Packages configuration - Blatantly stolen from zebra ! +dnl ---------------------- +AC_ARG_ENABLE(ipv6, +[ --disable-ipv6 turn off IPv6 support ]) + +dnl ---------- +dnl IPv6 check +dnl ---------- +AC_MSG_CHECKING(whether this OS does have IPv6 stack) +if test "${enable_ipv6}" = "no"; then + AC_MSG_RESULT(disabled) +else +dnl ---------- +dnl INRIA IPv6 +dnl ---------- +if grep IPV6_INRIA_VERSION /usr/include/netinet/in.h >/dev/null 2>&1; then + cv_ipv6=yes + AC_DEFINE(HAVE_IPV6) + AC_DEFINE(INRIA_IPV6) + LIB_IPV6="" + AC_MSG_RESULT(INRIA IPv6) +fi +dnl --------- +dnl KAME IPv6 +dnl --------- +if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then + cv_ipv6=yes + AC_DEFINE(HAVE_IPV6) + AC_DEFINE(KAME) + if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then + LIB_IPV6="-L/usr/local/v6/lib -linet6" + fi + AC_MSG_RESULT(KAME) +fi +dnl --------- +dnl NRL check +dnl --------- +if grep NRL /usr/include/netinet6/in6.h >/dev/null 2>&1; then + cv_ipv6=yes + AC_DEFINE(HAVE_IPV6) + AC_DEFINE(NRL) + if test x"$opsys" = x"bsdi";then + AC_DEFINE(BSDI_NRL) + AC_MSG_RESULT(BSDI_NRL) + else + AC_MSG_RESULT(NRL) + fi +fi +dnl ---------- +dnl Linux IPv6 +dnl ---------- +if test "${enable_ipv6}" = "yes"; then + AC_EGREP_CPP(yes, [dnl + #include + /* 2.1.128 or later */ + #if LINUX_VERSION_CODE >= 0x020180 + yes + #endif], + [cv_ipv6=yes; cv_linux_ipv6=yes;AC_MSG_RESULT(Linux IPv6)]) +else +if test x`ls /proc/net/ipv6_route 2>/dev/null` = x"/proc/net/ipv6_route" + then + cv_ipv6=yes + cv_linux_ipv6=yes + AC_MSG_RESULT(Linux IPv6) + fi +fi +if test "$cv_linux_ipv6" = "yes";then + AC_DEFINE(HAVE_IPV6) + AC_MSG_CHECKING(for GNU libc 2.1) + AC_EGREP_CPP(yes, [ +#include +#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 + yes +#endif], [glibc=yes; AC_MSG_RESULT(yes)], AC_MSG_RESULT(no)) + AC_DEFINE(LINUX_IPV6) + if test "$glibc" != "yes"; then + INCLUDES="-I/usr/inet6/include" + if test x`ls /usr/inet6/lib/libinet6.a 2>/dev/null` != x;then + LIB_IPV6="-L/usr/inet6/lib -linet6" + fi + fi +fi + +fi + +dnl ----------------------- +dnl Set IPv6 related values +dnl ----------------------- +LIBS="$LIB_IPV6 $LIBS" +AC_SUBST(LIB_IPV6) + +dnl ----------------------------------- +dnl check sin6_scope_id of sockaddr_in6 +dnl ----------------------------------- +if test "$cv_ipv6" = yes; then + AC_MSG_CHECKING(whether struct sockaddr_in6 has a sin6_scope_id field) + AC_TRY_COMPILE([#include +#include +],[static struct sockaddr_in6 ac_i;int ac_j = sizeof(ac_i.sin6_scope_id);], +[AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SIN6_SCOPE_ID)], + AC_MSG_RESULT(no)) +fi + +dnl ----------------------------------- +dnl Check for New Socket API (RFC2292BIS) +dnl ----------------------------------- +AC_MSG_CHECKING(for rfc2292bis support) +AC_TRY_COMPILE([#include +#include ], + [int x = IPV6_RECVPKTINFO;], + [AC_DEFINE(USE_RFC2292BIS) + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)]) + + +AC_MSG_CHECKING(for struct in_pktinfo) +AC_TRY_COMPILE([#include +#include ], + [struct in_pktinfo x; x.ipi_ifindex = 0;], + [AC_DEFINE(HAVE_PKTINFO) + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)]) + +dnl This is taken from the ethereal configuration scripts. +dnl We check whether user wants to build gtk-based programs +dnl These need to be enabled explicitly +GTK_OK=yes + +# GTK checks +# We don't add $GLIB_LIBS to LIBS, because we don't want to force all +# programs to be built with GTK+. +# + +AM_PATH_GTK(1.2.0, CFLAGS="$CFLAGS $GTK_CFLAGS", GTK_OK=no) +if test "x$GTK_OK" = "xno" ; then + AC_MSG_RESULT(GTK distribution not found - disabling sctpd compilation.) + AC_MSG_RESULT(On FreeBSD, you might want to do: ln -s gtk12-config gtk-config) +fi + +# GLib checks +# This doesn't add GLIB_CFLAGS to CFLAGS, because AM_PATH_GTK will add +# GTK_CFLAGS to CFLAGS, and GTK_CFLAGS is a superset of CFLAGS. +# However, this means that both @GLIB_LIBS@ and @GTK_LIBS@ will be +# set when generating the Makefile, so we can make programs that require +# only GLib link with @GLIB_LIBS@ and make programs that require GTK+ +# link with @GTK_LIBS@ (which includes @GLIB_LIBS@). +# We don't add $GLIB_LIBS to LIBS, because we don't want to force all +# programs to be built with GLib. +# + +enable_sctpd="no" +# gtkprogs_bin="" +sctpd_SUBDIRS="" +# Honor GLIB_CFLAGS +AM_PATH_GLIB(1.2.0, CFLAGS="$CFLAGS $GLIB_CFLAGS", AC_MSG_ERROR(GLib distribution not found. On FreeBSD do: ln -s glib12-config glib-config), gmodule) + + +#AC_SUBST(gtkprogs_bin) +AC_SUBST(sctp_SUBDIRS) + + +dnl Checks for library functions. +AC_CHECK_LIB(socket, socket) +AC_CHECK_LIB(nsl, gethostbyname) +AC_CHECK_LIB(sctp, sctp_eventloop) + +dnl removed libefence....this should be used though, when we REALLY debug :-) +AC_CHECK_LIB(efence, malloc) +AC_CHECK_LIB(glib, g_main_add_poll) + + +AC_CHECK_HEADERS(ncurses.h, AC_DEFINE(HAVE_NCURSES_H)) +# AC_CHECK_HEADERS(curses.h, AC_DEFINE(HAVE_CURSES_H)) +AC_CHECK_LIB(ncurses, initscr, found_ncurses_lib=yes,found_ncurses_lib=no) + +if test "x$found_ncurses_lib" = "xyes" -a "x$ac_cv_header_ncurses_h" = "xyes" ; then + curses_LIBS="-lncurses" + # CPPFLAGS="$CPPFLAGS -I/usr/include/ncurses.h" + cursesprogs_BIN="monitor chat echo_monitor" +else +# AC_CHECK_LIB(curses, initscr, found_curses_lib=yes,found_curses_lib=no) +# if test "x$found_curses_lib" = "xyes" -a "x$ac_cv_header_curses_h" = "xyes" ; then +# curses_LIBS="-lcurses" + # CPPFLAGS="$CPPFLAGS -I/usr/include/curses.h" +# cursesprogs_BIN="monitor chat echo_monitor" +# else + cursesprogs_BIN="" + curses_LIBS="" + AC_MSG_WARN(nCurses libraries seem to be missing. Not compiling Curses-Programs! Please contact ajung@exp-math.uni-essen.de in case this test should not have failed!) +# fi +fi +AC_SUBST(cursesprogs_BIN) +AC_SUBST(curses_LIBS) + +if test "$GTK_OK" = "yes" ; then + sctp_LIBS="-L/usr/local/lib/ -lsctp" + gtk_LIBS="$GTK_LIBS" + glib_LIBS="$GLIB_LIBS" +else + sctp_LIBS="-L/usr/local/lib/ -lsctp" + gtk_LIBS="" + glib_LIBS="$GLIB_LIBS" +fi + +AC_SUBST(sctp_LIBS) +AC_SUBST(gtk_LIBS) +AC_SUBST(glib_LIBS) + +AC_CHECK_LIB(c, inet_ntop, [AC_DEFINE(HAVE_INET_NTOP)]) +AC_CHECK_LIB(c, inet_pton, [AC_DEFINE(HAVE_INET_PTON)]) +AC_CHECK_LIB(c, inet_aton, [AC_DEFINE(HAVE_INET_ATON)]) + +dnl Checks for library functions. +AC_FUNC_VPRINTF +AC_FUNC_MEMCMP +AC_CHECK_FUNCS(gettimeofday socket strerror poll getuid setuid geteuid random) +AC_CHECK_FUNCS(getaddrinfo, [have_getaddrinfo=yes], [have_getaddrinfo=no]) + + +dnl checks for host/build/target system type +AC_CANONICAL_HOST +case $host_os in +bsdi*) + CFLAGS="$CFLAGS -DBSDI" + thread_LIBS="-lpthread" + # CFLAGS="$CFLAGS `glib-config --cflags`" + #LDFLAGS="$LDFLAGS `glib-config --libs`" + ;; +freebsd*) + CFLAGS="$CFLAGS -DFreeBSD -Wall -pthread" + CXXFLAGS="$CXXFLAGS -DFreeBSD -Wall -pthread" + thread_LIBS="" + # CFLAGS="$CFLAGS `glib12-config --cflags`" + #LDFLAGS="$LDFLAGS `glib12-config --libs`" + ;; +hpux*) + CFLAGS="$CFLAGS -DSNAKE" + test -z "$GCC" && TRY_CFLAGS="$TRY_CFLAGS -Wp,-H600000" + thread_LIBS="-lpthread" + # CFLAGS="$CFLAGS `glib-config --cflags`" + #LDFLAGS="$LDFLAGS `glib-config --libs`" + ;; +linux*) + CFLAGS="$CFLAGS -Wall -DLINUX " + CXXFLAGS="$CXXFLAGS -Wall -DLINUX " + thread_LIBS="-lpthread" + # CFLAGS="$CFLAGS `glib-config --cflags`" + #LDFLAGS="`glib-config --libs` $LDFLAGS" + ;; +openbsd*) + LIBS="$LIBS -lcompat" + thread_LIBS="-lpthread" + # CFLAGS="$CFLAGS `glib-config --cflags`" + #LDFLAGS="$LDFLAGS `glib-config --libs`" + ;; +solaris*) + CFLAGS="$CFLAGS -Wall -DSOLARIS -D__sun -DSUN -DSUNOS_5" + CXXFLAGS="$CXXFLAGS -Wall -DSOLARIS -D__sun -DSUN -DSUNOS_5" + thread_LIBS="-lpthread" + LDFLAGS="$LDFLAGS -lsocket -lnsl -lrt -lresolv" + # CFLAGS="$CFLAGS `glib-config --cflags`" + # LDFLAGS="$LDFLAGS `glib-config --libs`" + ;; +sunos4*) + CFLAGS="$CFLAGS -DSUN -DSUN4" + thread_LIBS="-lpthread" + # CFLAGS="$CFLAGS `glib-config --cflags`" + # LDFLAGS="$LDFLAGS `glib-config --libs`" + ;; +darwin*) + CFLAGS="$CFLAGS -DDARWIN" + CXXFLAGS="$CXXFLAGS -DDARWIN" + thread_LIBS="-lpthread" + # CFLAGS="$CFLAGS `glib-config --cflags`" + # LDFLAGS="$LDFLAGS `glib-config --libs`" + ;; +esac +AC_SUBST(thread_LIBS) + + + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T +AC_STRUCT_TM +AC_CHECK_SIZEOF(char, 1) +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(long long, 8) + +AC_MSG_CHECKING(for type socklen_t) +AC_TRY_COMPILE([#include +#include +#include +#include ], +[socklen_t x; x = 0;], +[AC_DEFINE(HAVE_SOCKLEN_T) + AC_MSG_RESULT(yes)], +[AC_MSG_RESULT(no)]) + + + + +dnl add here all your Makefiles. These will be created by configure +AC_OUTPUT(Makefile sualibrary/Makefile sualibrary/docs/Makefile sualibrary/docs/en/Makefile sualibrary/sua/Makefile sualibrary/testup/Makefile ) diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/sualibrary.kdevprj b/sualibrary.kdevprj new file mode 100644 index 0000000..7f82109 --- /dev/null +++ b/sualibrary.kdevprj @@ -0,0 +1,290 @@ +# KDE Config File +[Workspace_1] +openfiles=Untitled.h,Untitled.cpp,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index.html,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index-1.html,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index-4.html,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index-2.html,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index-3.html,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index-5.html,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index-6.html,/home/p82609/siemens/sualibrary/sualibrary/docs/en/Makefile.in,/home/p82609/siemens/sualibrary/sualibrary/docs/en/index.sgml, +show_outputview=true +show_treeview=true +header_file=/home/p82609/siemens/sualibrary/sualibrary/docs/en/index-4.html +cpp_file=Untitled.cpp +browser_file=file:/opt/kde/share/doc/HTML/default/kdevelop/reference/C/LIBRARIES/libraries.html +[sualibrary/docs/en/index-6.html] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/sua_logging.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua_logging.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_adapt.cpp] +install_location= +dist=true +install=false +type=SOURCE +[COPYING] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/sua_database.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua_tcb.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua.h] +install_location= +dist=true +install=false +type=HEADER +[Config for BinMakefileAm] +ldflags= +addcxxflags= +ldadd= +bin_program=sualibrary +cxxflags=-O0 -g3 -Wall +[sualibrary/testup/main.cpp] +install_location= +dist=true +install=false +type=SOURCE +[README] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/sua_file.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua_asp_mgnt.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary.kdevprj] +install_location= +dist=true +install=false +type=DATA +[sualibrary/docs/en/index-1.html] +install_location= +dist=true +install=false +type=DATA +[LFV Groups] +GNU=AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,NEWS, +Others=*, +groups=Headers,Sources,GNU,Others, +Sources=*.cpp,*.c,*.cc,*.C,*.cxx,*.ec,*.ecpp,*.lxx,*.l++,*.ll,*.l, +Headers=*.h,*.hh,*.hxx,*.hpp,*.H, +[sualibrary/docs/en/index-2.html] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/sua_sual.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/docs/en/Makefile.am] +files=sualibrary/docs/en/index.html,sualibrary/docs/en/index-1.html,sualibrary/docs/en/index-2.html,sualibrary/docs/en/index-3.html,sualibrary/docs/en/index-4.html,sualibrary/docs/en/index-5.html,sualibrary/docs/en/index-6.html, +type=normal +sub_dirs= +[sualibrary/docs/en/index.html] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/sua_file.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_dataname.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_asp_mgnt.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/docs/en/index-3.html] +install_location= +dist=true +install=false +type=DATA +[sualibrary/docs/Makefile.am] +type=normal +sub_dirs=en, +[sualibrary/testup/assoc.sua] +install_location= +dist=false +install=false +type=DATA +[sualibrary/sua/sua_distribution.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/docs/en/index-4.html] +install_location= +dist=true +install=false +type=DATA +[sualibrary/testup/testuser.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua_syntax.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_tcb.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/Makefile.am] +files= +type=prog_main +sub_dirs=docs,sua,testup, +[sualibrary.lsm] +install_location= +dist=true +install=false +type=DATA +[sualibrary/docs/en/index-5.html] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/sua_datassoc.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_cl.cpp] +install_location= +dist=true +install=false +type=SOURCE +[ChangeLog] +install_location= +dist=true +install=false +type=DATA +[General] +make_options=-j1 +makefiles=Makefile.am,sualibrary/Makefile.am,sualibrary/docs/Makefile.am,sualibrary/docs/en/Makefile.am,sualibrary/sua/Makefile.am,sualibrary/testup/Makefile.am, +version_control=None +project_type=normal_cpp +author=Lode Coene +sub_dir=sualibrary/ +lfv_open_groups= +workspace=1 +project_name=Sualibrary +version=0.1 +AMChanged=true +sgml_file=/home/p82609/sualibrary/sualibrary/docs/en/index.sgml +short_info=, +email=lode.coene@siemens.atea.be +kdevprj_version=1.2 +configure_args= +modifyMakefiles=true +[INSTALL] +install_location= +dist=true +install=false +type=DATA +[TODO] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/Makefile.am] +files=sualibrary/sua/sua.h,sualibrary/sua/sua_adapt.cpp,sualibrary/sua/sua_adapt.h,sualibrary/sua/sua_asp_mgnt.cpp,sualibrary/sua/sua_asp_mgnt.h,sualibrary/sua/sua_cl.cpp,sualibrary/sua/sua_cl.h,sualibrary/sua/sua_datassoc.cpp,sualibrary/sua/sua_co.cpp,sualibrary/sua/sua_co.h,sualibrary/sua/sua_database.cpp,sualibrary/sua/sua_database.h,sualibrary/sua/sua_dataname.cpp,sualibrary/sua/sua_debug.h,sualibrary/sua/sua_distribution.cpp,sualibrary/sua/sua_distribution.h,sualibrary/sua/sua_file.cpp,sualibrary/sua/sua_file.h,sualibrary/sua/sua_logging.cpp,sualibrary/sua/sua_logging.h,sualibrary/sua/sua_sual.cpp,sualibrary/sua/sua_sual.h,sualibrary/sua/sua_syntax.cpp,sualibrary/sua/sua_syntax.h,sualibrary/sua/sua_tcb.cpp,sualibrary/sua/sua_tcb.h, +type=static_library +[sualibrary/sua/sua_syntax.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua_co.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/testup/local.sua] +install_location=local.sua +dist=false +install=false +type=DATA +[sualibrary/testup/testuser.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_database.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_co.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_adapt.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua_sual.h] +install_location= +dist=true +install=false +type=HEADER +[sualibrary/sua/sua_distribution.cpp] +install_location= +dist=true +install=false +type=SOURCE +[sualibrary/sua/sua_cl.h] +install_location= +dist=true +install=false +type=HEADER +[Makefile.am] +files=sualibrary.kdevprj,AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,sualibrary.lsm, +type=normal +sub_dirs=sualibrary, +[sualibrary/testup/Makefile.am] +files=sualibrary/testup/main.cpp,sualibrary/testup/testuser.cpp,sualibrary/testup/testuser.h,sualibrary/testup/local.sua,sualibrary/testup/assoc.sua, +sub_dirs= +type=static_library +[AUTHORS] +install_location= +dist=true +install=false +type=DATA +[sualibrary/sua/sua_debug.h] +install_location= +dist=true +install=false +type=HEADER diff --git a/sualibrary.lsm b/sualibrary.lsm new file mode 100644 index 0000000..a3639f5 --- /dev/null +++ b/sualibrary.lsm @@ -0,0 +1,14 @@ +Begin3 +Title: Sualibrary +Version: 0.1 +Entered-date: +Description: +Keywords: +Author: Lode Coene +Maintained-by: Lode Coene +Primary-site: +Home-page: http://www.sctp.be/sua +Original-site: +Platforms: Linux and other Unices +Copying-policy: GNU Public License +End diff --git a/sualibrary/Makefile.am b/sualibrary/Makefile.am new file mode 100644 index 0000000..e778ee2 --- /dev/null +++ b/sualibrary/Makefile.am @@ -0,0 +1,9 @@ +####### kdevelop will overwrite this part!!! (begin)########## + + +####### kdevelop will overwrite this part!!! (end)############ + +SUBDIRS = docs sua testup + + + diff --git a/sualibrary/docs/Makefile.am b/sualibrary/docs/Makefile.am new file mode 100644 index 0000000..550ae51 --- /dev/null +++ b/sualibrary/docs/Makefile.am @@ -0,0 +1,5 @@ +####### kdevelop will overwrite this part!!! (begin)########## + +SUBDIRS = en + +####### kdevelop will overwrite this part!!! (end)############ diff --git a/sualibrary/docs/en/Makefile.am b/sualibrary/docs/en/Makefile.am new file mode 100644 index 0000000..3515e66 --- /dev/null +++ b/sualibrary/docs/en/Makefile.am @@ -0,0 +1,6 @@ +####### kdevelop will overwrite this part!!! (begin)########## + + +EXTRA_DIST = index.html index-1.html index-2.html index-3.html index-4.html index-5.html index-6.html + +####### kdevelop will overwrite this part!!! (end)############ diff --git a/sualibrary/docs/en/index-1.html b/sualibrary/docs/en/index-1.html new file mode 100644 index 0000000..22a6aa7 --- /dev/null +++ b/sualibrary/docs/en/index-1.html @@ -0,0 +1,100 @@ + + + + + The Sualibrary Handbook: Introduction + + + + + +Next +Previous +Contents +
+

1. Introduction

+ + +

1.1 General concept

+

+ +The sualib-0.1.0 library release is the product of a cooperation between Siemens AG (ICM), Munich, Germany and Siemens Atea, Herentals Belgium. + +It has been developed since late 2000 and has been planned to become a fairly complete prototype implementation of the SCCP User Adaptation + +(SUA) protocol as described in [1]. +

+ +The API of the function library was modeled after the API of the SCTPLIB[2], and most parameters + +an functions should be self-explanatory to the user familiar with this document. In addition to the interface + +functions between an Upper Layer Protocol (ULP) and an SUA instance, the library also provides a + +number of helper functions that can be used to manage callback function routines to make them execute at + +a certain point of time (i.e. timer-based), which may then be used for an asynchronous interprocess communication. + +

+ +All of these functions may be made use of by simply linking the static libsua-library to an application, + +and including the file sua.h . As SUA runs on top of SCTP which operates on top of IP, SCTP chose to open a raw socket to catch all incoming packets with the IP protocol id byte set to 132 (=SCTP). For this, it is necessary that an application using the library functions have privileges to do so. On most Unix machines that means this application has to be run by root (i.e. be made setuid 0). + +An application making use of the libsua-library can expect to be able to manage a large number of + +associations (e.g. as a server, all bound to one port) as well as handle several so-called SCTP instances, + +which may work on several different ports. Ports of incoming packets are checked whether they belong to + +an already existing association or may start a new one. + +

+ +The concept of the library is the following: After registration of a first SUA instance, sockets are opened + +and an application may register timer events, or file descriptors, that asynchronously trigger execution of + +callback functions. The function callbacks for these routines are passed in the registration functions, and + +callbacks for SUA events are passed in a SUA_ulpCallbacks(described more closely in sections 6.2.1 + +and 6.5). + +Then the application either calls the possibly blocking function sua_eventLoop(). While calling the former, it will react to a previously scheduled timer or any file descriptor event (by executing the registered callback functions). In case a timer is scheduled at a very late point in time, and no events happen on registered file descriptors (e.g. sockets), the program will sleep (because the system call poll() is used. In this case, the control flow is handled by the library, and the user must register appropriate callbacks for events and timers before handing control over to the sua_eventLoop() function. The proper use of the sua_eventLoop() is explained in some simple example programs in section 7. + + +

+

1.2 Changes +

+ +Changes in comparison with sualibrary 0.0.5: +

+- portable to different UNIX versions

+- tested on both Linux and FreeBSD vs 4.4

+- tested with both IPv4 and IPv6 networks

+- msg syntax updated to (example: DNS names)

+

+ +

1.3 Nomenclature

+ +Throughout this document, +

+_ function names are written as func_name(),

+_ function parameters as parameter,

+_ data types as typename, and

+_ file names as name_of_file.

+_ constants as CONSTANT

+ +

+

+


+Next +Previous +Contents + + diff --git a/sualibrary/docs/en/index-2.html b/sualibrary/docs/en/index-2.html new file mode 100644 index 0000000..86b026b --- /dev/null +++ b/sualibrary/docs/en/index-2.html @@ -0,0 +1,63 @@ + + + + + The Sualibrary Handbook: Installation + + + + + +Next +Previous +Contents +
+

2. Installation

+ +

+

2.1 How to obtain Sualibrary +

+You can find SUA library at http://www.sctp.be/sua +

+

+

2.2 Requirements +

+ +The libsua-library depends on a software packet (glib-1.2) for portable definition of types, + +list functions etc and on the presence of the libsctp-library .(www.sctp.de) + +

+

+

2.3 Compilation and installation +

+ +

+

In order to compile and install Sualibrary on your system, type the following in +the base directory of the Sualibrary distribution: +

+

+
+% ./configure
+% make
+% make install
+
+
+

+

Since Sualibrary uses +

+autoconf
+
+ you should have not trouble +compiling it. +Should you run into problems please report them to the the author at +Lode Coene

+

+ +

+


+Next +Previous +Contents + + diff --git a/sualibrary/docs/en/index-3.html b/sualibrary/docs/en/index-3.html new file mode 100644 index 0000000..17dc4f7 --- /dev/null +++ b/sualibrary/docs/en/index-3.html @@ -0,0 +1,138 @@ + + + + + The Sualibrary Handbook: Usage + + + + + +Next +Previous +Contents +
+

3. Usage

+ +

+

3.1 General usage of the SUA library +

+ +

+ +If you compile the entire project, and install the files sua.h in the directory /usr/local/includeand libsua.ain /usr/local/lib(by simply copying these from the libsua/sua/ subdirectory to their repective destinations: this is done automatically by the the make during installation), it is trivial to compile an application. + +Let’s assume, your application is named app and consists of the file app.c. If you use gccas compiler, + +it is sufficient to issue the command + +host:˜> gcc -o app app.c -lsctp –lglib -lsua + + + +in order to compile your application. Note though, that FreeBSD calls the glib-library by default + +libglib12, since it exists both in several versions (i.e. glib version 1.0 would be called libglib10 + +under FreeBSD (and possibly other BSD unixes). So under this platform, you would use + +BSDhost:˜> gcc -o app app.c -lsctp -lglib12 –lsua + + + +Some features are selectable, see sua_debug.h for a overview of the switches. + +Switches include the displaying debug msg on the screen, + +Dumping SUA msg and debug info into a file, optional use of SUA ASP management, etc… + +

+

+

+

3.2 Features of the implementation +

+

+

+The implementation is able to do the following: +

+Statically and dynamically setup of SCTP association for the transport of the SUA messages +

+Connectionless : CLDT message transfer +

+Connectionoriented: CORE, COAK, RELRE, RELCO, COREF & CODT message transfer +

+Adressing options: use of Ipv4 and Ipv6 addresses, SS7 pointcodes, hostname +

+SUA ASP management(optional) +

+It has been tested with implementations of 4 companies in the first SUA bakeoff. +

+The following flags are recognized when reading a configuration file for SUA: +

+-s : source address

+ +-l: source portnumber (optional, default is set at 14001)

+ +-d : destination address(optional)

+ +-r : destination portnumber(optional, default is set at 14001)

+ +-n : subsystem number to be used

+ +-a : Application server number(optional)

+ +-t : number of streams in & out(optional, default is set at 1)

+ +-7d : SS7 destination pointcode(optional)

+ +-7s : SS7 source pointcode(optional)

+ +-sn: Source hostname

+ +-dn: Destination hostname

+ +

+ +example of a association

+ +-s 10.0.1.1 -7s 1 -d 10.0.3.1 -7d 66051 -r 14001 -n 255 -a 1 -t 16

+ +example of a local listener

+ +-s be.atea.sua01 –n 255 –a 1 –t 2

+ + +

+

+

+

3.3 What is missing. +

+

+

+ +Features to be included in future version: +

+- Relaying functionality

+ +- SUA management: ASP , AS management, etc

+

+Features not to be included: +

+- NIF/interworking with classical SS7 SCCP

+ +- Routing keys

+ +- Registration of Applications

+

+Probably there is some more. Additions, comments, bug-reports and bug-fixes as welll as patches, + +patches, and patches are always welcome ! +

+

+

+


+Next +Previous +Contents + + diff --git a/sualibrary/docs/en/index-4.html b/sualibrary/docs/en/index-4.html new file mode 100644 index 0000000..79d3626 --- /dev/null +++ b/sualibrary/docs/en/index-4.html @@ -0,0 +1,1067 @@ + + + + + The Sualibrary Handbook: SUA Application Program Interface (SUA API) + + + + + +Next +Previous +Contents +
+

4. SUA Application Program Interface (SUA API)

+ +

4.1 General API issues. +

+

+

4.1.1 Constants +

+

+ +The maximum size of an IPv4/IPv6 address string is limited to SCTP_MAX_IP_LEN. An endpoint may + +(for now) have a maximum number of addresses, which is limited to SCTP_MAX_NUM_ADDRESSES. The + +maximum size of a datagram that may be passed to the sctp_send() function is SCTP_MAXIMUM_DATA_ + +LENGTH. Since we do NOT do proper MTU path discovery in this release, we cannot guarantee that IP + +fragmentation occurs, but for Ethernet hardware type and most packets, these settings will ensure that there + +is no fragmentation. +

+#define SCTP_MAX_IP_LEN 46 +

+#define SCTP_MAX_NUM_ADDRESSES 20 +

+#define SCTP_MAXIMUM_DATA_LENGTH 1400 +

+ +

+

4.1.2 Type definitions +

+

+ +The main include file of sua.h defines a number of types that are used throughout the library as well as in + +some of the interface functions. They will be explained in the subsequent sections. + + +

+

4.1.3 SUA_ulpCallbacks +

+

+ + + +This is a structure containing pointers to functions (used as callbacks for SUA events that may occur + +and that the ULP needs to be notified of), which are all explained in detail in section 6.5. This structure + +is usually initialized early in the program, and then passed to the function sua_registerInstance() (see + +section 4.2.2.3), which in turn registers the appropriate functions from this structure for the corresponding + +events. +

+ +Definition: +

+Struct{

+ void (*ulp_ClDataIndNotif) ( unsigned int local_sua_Id,

+ unsigned int primitive,

+ unsigned int datalen

+ );

+ + void (*ulp_ConnIndNotif) ( unsigned int local_sua_id,

+ unsigned int local_sua_ref,

+ + unsigned int datalen

+ + );

+ + void (*ulp_ConnConfIndNotif) ( unsigned int local_sua_id,

+ + unsigned int local_sua_ref,

+ + unsigned int datalen

+ + );

+ + void (*ulp_ConnDataIndNotif) ( unsigned int local_sua_id,

+ + unsigned int local_sua_ref,

+ + unsigned int datalen

+ + );

+ + void (*ulp_DisConnIndNotif) ( unsigned int local_sua_id,

+ + unsigned int local_sua_ref,

+ + unsigned int reason,

+ + unsigned int datalen

+ + );

+ +} Sua_ULP_CallBacks;

+ +

+parameters:

+ +Local_sua_Id : identifies the local SUA instance

+ +Primitive: identifies the CLDT or CLDR in case of a Connectionless Data Notification

+ +Local_sua_ref : reference to the SUA connection used for data transfer

+ +Reason: reason for the release of the SUA connection

+ + +

+

4.1.4 SCTP Helper Functions +

+

+ + + +The libsctp-library contains a few functions that influence the general control flow of a program using + +them, and are needed to create an application that works as expected. The important functions needed in + +any program using the libsctp-library are the functions sctp_eventLoop() + + + +

+

4.1.4.1 sctp_timerCallback +

+

+ + +Definition: see also [3].

+ +typedef void (*sctp_timerCallback) (unsigned int, void *, void *);

+ +Defines the callback function that is called when a timer expires. Parameters:

+ +unsigned int ID of timer

+ +void* pointer to param1

+ +void* pointer to param2

+ +param1 and param2 are pointers to data that are returned to the callback function, when the timer expires. + +These must still exist at that time and point to valid data !

+ + + + + +

+

4.1.4.2 sctp_eventLoop() +

+

+ +Basically this is a wrapper to a poll() or select()-system call. The function waits until either of one events + +occurrs:

+ +1. the time for which a timer event was scheduled has passed by, so the callback function belonging to + +that (previously registered) event is executed.

+ +2. one of the sockets that had previously been registered with the function sua_registerCallback() + +or the raw socket that waits for incoming SCTP packets has encountered a read event, so there is data + +available. The appropriate function callback is then called to treat that event. + +The control flow of the program is given to the callback function which may in turn register new timer + +events. The function returns -1 if an error ocurrs, 0 if a timeout has ocurred, or else the number of file + +descriptor events that have been treated.

+ +Definition:

+ +int sctp_eventLoop();

+ + +

+

4.1.4.3 sctp_registerStdinCallback() +

+

+6.3.4 + + + +This function is supposed to register a callback function for catching input from the Unix STDIN file + +descriptor. We expect this to be useful in test programs mainly, so it is provided here for convenience. + +Events on this file descriptor are dispatched differently, as applications may read directly from STDIN (i.e. + +the callback function buffer does not contain the data from STDIN, and the registered callback function + +may retrieve this data with functions as fgets()).

+ +scf callback funtion that is called when data has arrived

+ +It returns 0, or -1 if an error ocurred.

+ +Definition:

+ +int sctp_registerStdinCallback(sctp_socketCallback scf);

+ + +

+

4.1.4.4 sctp_startTimer() +

+

+ + +This function adds a callback that is to be called some time from now. It realizes the timer (in an ordered + +list). The function takes the following parameters:

+ +milliseconds action is to be started in milliseconds ms from now

+ +timer_cb pointer to a function to be executed, when timer expires

+ +param1 pointer to be returned to the caller when timer expires

+ +param2 pointer to be returned to the caller when timer expires

+ +The function returns a timer ID value, that can be used to cancel or restart this timer. NOTE: the pointers + +param1 and param2 exist to point to data useful for the function callback. They need to point to data + +that is still valid at the time the callback is activated. Do not pass pointers to temporary objects !

+ +Definition:

+ +unsigned int sctp_startTimer(unsigned int milliseconds, + +sctp_timerCallback timer_cb, void *param1, void *param2);

+ + +

+

4.1.4.5 sctp_stopTimer() +

+

+ +This function stops a previously started timer. The function takes the following parameter:

+ +tid timer-id of timer to be removed

+ +The function returns 0 on success, 1 if tid not in the list, -1 on error.

+ +Definition:

+ +int sctp_stopTimer(unsigned int tid);

+ + +

+

4.1.4.6 sctp_restartTimer() +

+

+ + +Restarts a timer that is currently running. The function takes the following parameters:

+ +timer_id the timer id returned by start_timer

+ +milliseconds action is to be taken in milliseconds ms from now

+ +The function returns a new timer ID, zero when there is an error (i.e. the timer was not running). The + +function basically stops the old timer, and sets a new timer. So it is there for convenience. The timer ID + +will be different after calling this function !

+ +Definition:

+ +unsigned int sctp_restartTimer(unsigned int timer_id, unsigned int milliseconds);

+ + +

+

4.1.4.7 sctp_getTime() +

+

+ +This helper function returns a 32 bit value representing the current time in milliseconds. Beware, this + +counter wraps about once per 20 days. Keep that in mind when calculating time differences ! This function + +may be useful, or may not be useful.

+ +Definition:

+ +unsigned int sctp_getTime(void);

+ + +

4.2 standard SUA API +

+ +

+

4.2.1 ULP-to-SUA +

+

+ + +

+

4.2.1.1 sua_read_config_file() +

+

+ +sua_read_config_file() is called to fill in the internal SUA database.

+ +The file can contain:

+ +- only IP source address(es) and portnumber(s) of local SUA instance(s) or

+ +- IP source and destination address togethers with the portnumbers for setting up SCTP associations between the specified endpoints.

+ +If the port is not specified then the default SUA port 14001 will be used.

+ +Definition:

+ +unsigned int sua_read_config_file

+ +( char *pConfFile );

+ +Parameters:

+ +*pConfFile: pointer to a char array. Containing the filename Filename has to be terminated with ‘\0’ character.

+ + +

+

4.2.1.2 sua_registerInstance() +

+

+ + +sua_registerInstance() is called to initialize one SUA instance. On the very first call, it will open raw + +sockets for capturing SCTP packets (IPv4 and if possible, IPv6, too) from the network. An application may + +register several instances with different sets of callback functions, but there should not be several instances + +with the same subsystemnumber(local SSN).

+ +Definition:

+ +unsigned int sua_registerInstance

+ + ( short local_ssn,

+ + Sua_ULP_CallBacks ulp_callback

+ + );

+ +The function returns the instance name of this new SUA instance.

+ +Parameters:

+ +short local_ssn: SSN used for registering the callback function

+ +Sua_ULP_CallBacks ulp_callback : callbackfunction to be used for that SSN

+ + +

+

4.2.1.3 sua_unregisterInstance() +

+

+ + +??? + + +

+

4.2.1.4 sua_associate() +

+

+ + +This function is called to set up one or more SCTP associations. It uses the info provided with the configuration file which was entered in the SUA database.

+ +Definition:

+ +unsigned int sua_associate ( );

+ + +

+

4.2.1.5 sua_shutdown() +

+

+ +??? + + +

+

4.2.1.6 sua_send() +

+

+ +sua_send() is used by the ULP to send data as SUA messages. There are quite a few parameters that can be + +or must be passed along:

+ +Definition:

+ +unsigned int Send_sua_primitive( unsigned int primitive,

+ + unsigned int &sua_ConnId,

+ + sccp_QOS_str &QOS,

+ + sccp_addr_str &called_pty_address,

+ + sccp_addr_str &calling_pty_address,

+ + char *buffer,

+ + unsigned int len

+ + );

+ + + +The function returns an error code: -1 for send error, 1 for association error, 0 if successful.

+ +Parameters:

+ +Primitive: the primitive indicating to do CLDT, CODT, CORE, CORE, RELRE,RELCO processing.

+ +sua_ConnID: identifies the connection to be used in case of connection oriented transfer. The field is ignored as input in case of Connectionless CLDT and CORE. +it returns the specific connection identifier in case of the CORE primitive as output.

+ +QOS : specifies the QOS parameters needed with the primitive.

+ +Called_pty_address: provide destination/remote address for connectionless CLDT and connection oriented CORE. Ignored for other primitives

+ +Calling_pty_address: provide source/local address for connectionless CLDT and connection oriented CORE. Ignored for other primitives.

+ +*buffer: application data(memory space MUST be assigned by the application)

+ +Len : length of the application data.

+ + + + +

+

4.2.1.7 sua_receive() +

+

+ +sua_receive() is called in response to the DataArrive-Notification to get the received data.

+ +Definition:

+ +unsigned int Receive_sua_primitive( unsigned int &primitive,

+ + unsigned int &sua_ConnId,

+ + sccp_QOS_str &QOS,

+ + sccp_addr_str &called_pty_address,

+ + sccp_addr_str &calling_pty_address,

+ + char *buffer,

+ + unsigned int len

+ + );

+ +It returns 1 if association does not exist, 0 if okay

+ +parameters:

+ +Primitive: the primitive indicating which msg type was received(ex. CLDT, CODT, CORE, CORE, RELRE,RELCO …)

+ +sua_ConnID: identifies the connection on which the data is received in case of connection oriented transfer. The field is ignored as input in case of Connectionless CLDT.

+ +QOS : returns the QOS parameters used with the primitive.

+ +Called_pty_address: returns destination/remote address for connectionless CLDT, CLDA and connection oriented CORE. Ignored for other primitives

+ +Calling_pty_address: returns source/local address for connectionless CLDT, CLDA and connection oriented CORE. Ignored for other primitives.

+ +*buffer: application data(memory space MUST be assigned by the application)

+ +Len : length of the application data.

+ + +

+

4.2.2 SUA-to-ULP +

+

+ +

+

4.2.2.1 Sua address structure +

+

+ + +Defines the structure of the source/calling party and the destination/called party address.

+ + +The sockaddr, sockaddr_in and sockaddr_in6 address structure can be found in [4].

+ +union sockunion

+ +{ struct sockaddr sa;

+ + struct sockaddr_in sin;

+ + struct sockaddr_in6 sin6;

+ + unsigned char ch[SCTP_MAX_IP_LEN];

+ +};

+ + + +typedef enum { ITU14bit,

+ + ITU24bit,

+ + ANSI24bit

+ +} SS7pc_set;

+ + + +typedef struct {

+ + SS7pc_set family;

+ + uint32_t pc;

+ +} SS7_ITU14_str;

+ + + +/* define structure of SS7 MTP pointcode (ITU/ANSI/other...) */

+ +union SS7union

+ +{

+ + SS7_ITU14_str ITU14;

+ + SS7_ITU14_str ITU24;

+ + SS7_ITU14_str ANSI24;

+ +};

+ + + +typedef enum { no_pc_present,

+ + ipvx_pc_present, // IPvx(4 or 6) present in pc field

+ + ss7_pc_present // SS7 pointcode present in pc field

+ +} pointcode_set;

+ + + +typedef enum { no_name_present,

+ + hostname_present,

+ + GT_present

+ +} name_gt_set;

+ + + +typedef enum { no_sap_present,

+ + ssn_present,

+ + portnumber_present

+ +} application_SAP_set;

+ + + +typedef enum { include_nothing,

+ + include_pc_in_header,

+ + include_ssn_port_in_header

+ +} sua_header_set;

+ + + +typedef struct {

+ + pointcode_set pc;

+ + name_gt_set name_gt;

+ + application_SAP_set ssn_port;

+ + sua_header_set field_in_header;

+ +} addr_elements_str;

+ + + +typedef struct {

+ + SS7union ss7;

+ + sockunion ipvx;

+ +} pointcode_str;

+ + + +typedef char hostname_str[255];

+ + + +typedef char global_title_str[255]

; + + + +typedef union {

+ + global_title_str GT;

+ + hostname_str HostName;

+ +}name_str;

+ + + +typedef short application_sap_str;

+ + + +typedef enum { route_on_ssn, // use pointcode for routing

+ + route_on_name_gt, // use gt/name for routing

+ + route_on_name_gt_next_office, // perform GTT in next node

+ + no_address_present // no routing requested

+ +} routing_type_set;

+ + + +typedef struct {

+ + addr_elements_str address_fields_present; // which fields are present?

+ + pointcode_str pc; // pointcode field

+ + name_str name; //global title/hostname field

+ + application_sap_str ssn; // application ssn/port

+ + routing_type_set routing_ind; // how must msg be routed

+ + short network_apperance;

+ +} sccp_addr_str;

+ + + + +

+

4.2.2.2 sua Quality Of Service(QOS) structure +

+

+ + +typedef enum { class0, // connectionless transport, non-sequenced + + class1, // connectionless transport, sequenced + + class2, // connectionoriented + + class3 // connectionoriented with flow control + +} protocol_class_set; + + + +typedef struct { + + protocol_class_set prot_class; // class 0, 1 or 2 + + bool in_sequence; // msg delivevered in sequence + + short sequence_number; // = stream number + + bool return_msg_on_error; // return a CLDR msg on err + + short importance; // importance of msg(0..7) + + short hopcounter; // hopcounter + +} sccp_QOS_str; + + + + +

+

4.2.2.3 sua ULPcallbackFunctions +

+

+ + + +typedef struct { + + void (*ulp_ClDataIndNotif) ( unsigned int local_sua_Id, + + unsigned int primitive, + + unsigned int datalen + + ); + + void (*ulp_ConnIndNotif) ( unsigned int local_sua_id, + + unsigned int local_sua_ref, + + unsigned int datalen + + ); + + void (*ulp_ConnConfIndNotif) ( unsigned int local_sua_id, + + unsigned int local_sua_ref, + + unsigned int datalen + + ); + + void (*ulp_ConnDataIndNotif) ( unsigned int local_sua_id, + + unsigned int local_sua_ref, + + unsigned int datalen + + ); + + void (*ulp_DisConnIndNotif) ( unsigned int local_sua_id, + + unsigned int local_sua_ref, + + unsigned int reason, + + unsigned int datalen + + ); + +} Sua_ULP_CallBacks; + + + +

4.3 SUA light API +

+ + +This is a Siemens specific interface. + +WARNING: The SUA and the SUAL structures, callbackfunctions, config files and functions cannot be mixed with each other. + +

+

4.3.1 SUAL address structure +

+

+ + +typedef struct sual_PeerAddr { + + int AddrType; /* predefined values for AddrType to indicate which + + type is used in uPeerAddr: SUAL_ADDRTYPE_IPV4, + + SUAL_ADDRTYPE_IPV6 */ + + union uPeerAddr { + + struct in_addr ip4; + + struct in6_addr ip6; + + } uPeerAddr; + +} sual_PeerAddr_t; + + + +typedef enum { + + SUAL_ADDRTYPE_IPV4, + + SUAL_ADDRTYPE_IPV6 + +} sual_IpAddrType_t; + + + + + +

+

4.3.2 SUAL ULPcallbackFunctions +

+

+ + +/* SUAL_ULP_CallBacks definitions */ + +typedef struct sual_ULPcallbackFunctions { + + + + void (*ConnIndNotif)( sual_id_t sual_ConnId, + + sual_PeerAddr_t *pPeerAddr, + + uint UserDataLen + + ); + + void (*ConnConfNotif)( sual_id_t sual_ConnId, + + uint UserDataLen + + ); + +void (*CoDataIndNotif)( sual_id_t sual_ConnId, + + uint UserDataLen + + ); + + void (*DisconnIndNotif)( sual_id_t sual_ConnId, + + reason_t reason, + + uint UserDataLen + + ); + + void (*ClDataIndNotif)( sual_id_t sual_DataId, + + uint ControlNumer, + + sual_PeerAddr_t *pPeerAddr, + + uint UserDataLen + + ); + +} sual_ULPcallbackFunctions_t; + + + + + +

+

4.3.3 SUAL sual_init () +

+

+ +extern int sual_init( + + unsigned char *pConfFile + +); + + + +

+

4.3.4 SUAL sual_RegisterSUAL_Instance () +

+

+ +extern sual_InstId_t sual_RegisterSUAL_Instance( + + sual_port_t LocalPort, + + sual_ULPcallbackFunctions_t *pULPcallbackFunctions + +); + + + + + +

+

4.3.5 SUAL sual_ConnReq () +

+

+ +sual_id_t + +sual_ConnReq( + + sual_id_t InstId, + + sual_PeerAddr_t *pPeerAddr, + + unsigned char *pUserData, + + uint UserDataLen + +); + + + +

+

4.3.6 SUAL sual _ConnResp () +

+

+6.6.6 + +int + +sual_ConnResp( + + sual_id_t InstId, + + sual_id_t sual_ConnId, + + unsigned char *pUserData, + + uint UserDataLen + +); + + + +

+

4.3.7 SUAL sual_DisconnReq () +

+

+ +int + +sual_DisconnReq( + + sual_id_t InstId, + + sual_id_t sual_ConnId, + + unsigned char *pUserData, + + uint UserDataLen + +); + + + +

+

4.3.8 SUAL sual_CoDataRead () +

+

+ +int + +sual_CoDataRead( + + sual_id_t InstId, + + sual_id_t sual_ConnId, + + unsigned char *pBuff, + + uint BuffLen + +); + + + +

+

4.3.9 SUAL sual_ClDataRead () +

+

+ +int + +sual_ClDataRead( + + sual_id_t InstId, + + sual_DataId_t DataId, + + unsigned char *pBuff, + + uint BuffLen + +); + + + +

+

4.3.10 SUAL sual_CoDataReq () +

+

+ +int + +sual_CoDataReq( + + sual_id_t InstId, + + sual_id_t sual_ConnId, + + unsigned char *pUserData, + + uint UserDataLen + +); + + + +

+

4.3.11 SUAL sual_ClDataReq () +

+

+ +int + +sual_ClDataReq( + + sual_id_t InstId, + + sual_PeerAddr_t *pPeerAddr, + + uint ControlNumber, + + unsigned char *pUserData, + + uint UserDataLen + +); + + + +

+

+


+Next +Previous +Contents + + diff --git a/sualibrary/docs/en/index-5.html b/sualibrary/docs/en/index-5.html new file mode 100644 index 0000000..55ed5bb --- /dev/null +++ b/sualibrary/docs/en/index-5.html @@ -0,0 +1,54 @@ + + + + + The Sualibrary Handbook: References, Questions and Answers & Examples + + + + + +Next +Previous +Contents +
+

5. References, Questions and Answers & Examples

+ +

5.1 References

+

+

+[1] Stewart, R.R. and Xie, Q. and others: RFC 2960 - Stream Control Transmission Protocol, IETF, + +SIGTRAN Working Group, October 2000 +

+ +[2] Loughney, J. and others: RFC xxxx - SCCP User Adaptation Layer Protocol, IETF, + +SIGTRAN Working Group, March 2002 +

+ +[3] Manual SCTP implementation on http://www.sctp.de/ + + +

5.2 Examples

+ +Text based application program + + +A sample program for sending text from one node to another. See source code for more details. Adapted from the SCTPLIB ULP[3]. + +And no, this has nothing to do with SMS text messages(yet). + + +

5.3 Questions and Answers

+ +None (at his moment). + +

+

+


+Next +Previous +Contents + + diff --git a/sualibrary/docs/en/index-6.html b/sualibrary/docs/en/index-6.html new file mode 100644 index 0000000..9306197 --- /dev/null +++ b/sualibrary/docs/en/index-6.html @@ -0,0 +1,37 @@ + + + + + The Sualibrary Handbook: Copyright + + + + +Next +Previous +Contents +
+

6. Copyright

+ +

+

Sualibrary Copyright 2002 Lode Coene , lode.coene@siemens.atea.be +

+

This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +

This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +

You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +

+

+


+Next +Previous +Contents + + diff --git a/sualibrary/docs/en/index.html b/sualibrary/docs/en/index.html new file mode 100644 index 0000000..61609e1 --- /dev/null +++ b/sualibrary/docs/en/index.html @@ -0,0 +1,73 @@ + + + + + The Sualibrary Handbook + + + + + +Next +Previous +Contents +
+

The Sualibrary Handbook

+ +

Lode Coene lode.coene@siemens.atea.be

+

Gery Verwimp gery.verwimp@siemens.atea.be

+Version 0.1.0 , Friday Feb 15 12:01:21 CET 2002 +


+This Handbook describes Sualibrary Version 0.1.0 +
+

+

1. Introduction

+ + +

+

2. Installation

+ + +

+

3. Usage

+ + +

+

4. SUA Application Program Interface (SUA API)

+ + +

+

+

5. References, Questions and Answers & Examples

+ + +

+

+

6. Copyright

+ +
+Next +Previous +Contents + + diff --git a/sualibrary/sua/Makefile.am b/sualibrary/sua/Makefile.am new file mode 100644 index 0000000..b7fa555 --- /dev/null +++ b/sualibrary/sua/Makefile.am @@ -0,0 +1,30 @@ +####### kdevelop will overwrite this part!!! (begin)########## +noinst_LIBRARIES = libsua.a + +libsua_a_SOURCES = sua_tcb.cpp sua_syntax.cpp sua_sual.cpp sua_logging.cpp sua_file.cpp sua_distribution.cpp sua_dataname.cpp sua_database.cpp sua_co.cpp sua_datassoc.cpp sua_cl.cpp sua_asp_mgnt.cpp sua_adapt.cpp + + +EXTRA_DIST = sua.h sua_adapt.cpp sua_adapt.h sua_asp_mgnt.cpp sua_asp_mgnt.h sua_cl.cpp sua_cl.h sua_datassoc.cpp sua_co.cpp sua_co.h sua_database.cpp sua_database.h sua_dataname.cpp sua_debug.h sua_distribution.cpp sua_distribution.h sua_file.cpp sua_file.h sua_logging.cpp sua_logging.h sua_sual.cpp sua_sual.h sua_syntax.cpp sua_syntax.h sua_tcb.cpp sua_tcb.h + +####### kdevelop will overwrite this part!!! (end)############ +SOMAJOR = 1 +SOMINOR = 0 +SOSUBMINOR = 0 + +libsua_la_LIBADD = @glib_LIBS@ @sctp_LIBS@ + +# here you should add all header files, which contains the functionality +# of your shared lib (published for the users) +include_HEADERS = sua.h + +INCLUDES = -I/usr/local/include + +#build a libtool library for installation in libdir +lib_LTLIBRARIES = libsua.la +libsua_la_SOURCES = sua_tcb.cpp sua_syntax.cpp sua_sual.cpp sua_logging.cpp sua_file.cpp sua_distribution.cpp sua_dataname.cpp sua_database.cpp sua_co.cpp sua_datassoc.cpp sua_cl.cpp sua_asp_mgnt.cpp sua_adapt.cpp + + +libsua_la_LDFLAGS = -no-undefined -version-info $(SOMAJOR):$(SOMINOR):$(SOSUBMINOR) $(LDFLAGS) + + + diff --git a/sualibrary/sua/sua.h b/sualibrary/sua/sua.h new file mode 100644 index 0000000..d0e5e02 --- /dev/null +++ b/sualibrary/sua/sua.h @@ -0,0 +1,388 @@ +/*************************************************************************** + sua.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua.h,v 1.3 2002/02/15 16:19:46 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Marleen + * "El Loco was here." + * "He drinks boiling motor oil and likes his meat alive in the cantina." + * + * Purpose: This header-file defines the SUA interface used by the + * SUA application for: + * - SUA address information structure + * - SUA Quality-Of-Service(QOS) structure + * - SUA callback function structure + * and adaptation functions used by the SUA application for: + * - initialising the SUA layer + * - reading the SUA configuration file + * - registering a local SUA instance + * - Setting up the association with a remote SUA node + * - get info on a certain (SUA) association + * - terminate a association + * - Send a SUA primtive to SUA + * - Receive a SUA primitive from SUA + * - convert Hostname(string) to SUAname(Character array) + * - convert SUAname(Character array) to Hostname(Character array) + */ + +#define __EXTENSIONS__ +#ifndef SUA_GLOBAL_H +#define SUA_GLOBAL_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#ifdef STDC_HEADERS + #ifdef HAVE_SYS_TIME_H + #include + #ifdef TIME_WITH_SYS_TIME + #include + #endif + #endif + #ifdef HAVE_UNISTD_H + #include + #endif +#endif + +#ifdef FreeBSD +#include +#include +#endif + +#ifdef SOLARIS +#include +#include +#endif + +#include + + +/* turn on Posix 1g for compatible cmsg structure */ +#ifdef USE_RFC2292BIS + #define _XPG4_2 +#endif + +#include + +/* turn off Posix 1g for compatible cmsg structure */ +#ifdef USE_RFC2292BIS + #undef _XPG4_2 +#endif + +#include +#include + +#include "sctp.h" /* SCTP library */ + +#define SUA_PORT 14001 +#define SUA_PPI 4 +#define IPPROTO_SCTP 132 + +#define SUA_MAX_MSG_LEN 2000 + +/*#define HAVE_UNISTD_H TRUE */ + +#define N_UNITDATA 1 +#define N_NOTICE 2 +#define N_CONNECT_REQ 10 +#define N_CONNECT_IND 11 +#define N_CONNECT_REFUSED 12 +#define N_CONNECT_RESP 13 +#define N_CONNECT_CONF 14 +#define N_DATA_REQ 20 +#define N_DATA_IND 21 +#define N_RELEASE_REQ 30 +#define N_RELEASE_CONF 31 + +typedef unsigned char boolean; + +#define FALSE (0) +#define TRUE (!FALSE) + + +#define OK 0 +#define PROTOCOL_CLASS_NOT_SPECIFIED -10 +#define INVALID_CLG_ADDRESS -20 +#define INVALID_CLD_ADDRESS -30 +#define MSG_ENCODING_FAILED -40 + +/* shortcut macro to specify address field of struct sockaddr */ +#define sockunion_family(X) (X)->sa.sa_family +#define sock2ip(X) (((struct sockaddr_in *)(X))->sin_addr.s_addr) +#define sock2ip6(X) (((struct sockaddr_in6 *)(X))->sin6_addr.s6_addr) + +#define SUPPORT_ADDRESS_TYPE_IPV4 0x00000001 +#define SUPPORT_ADDRESS_TYPE_IPV6 0x00000002 +#define SUPPORT_ADDRESS_TYPE_DNS 0x00000004 + + +/* union for handling either type of addresses: ipv4 and ipv6 */ +/*#ifndef SOCKUNION_DEFINE*/ +#define SOCKUNION_DEFINE 1 +/* define structure of IPv4/6 address */ +union sockunion +{ + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + unsigned char ch[SCTP_MAX_IP_LEN]; +}; +/*#endif SOCKUNION_DEFINE */ + +#define ipvxunion sockunion + +/*union ipvxunion +{ + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + unsigned char ch[SCTP_MAX_IP_LEN]; +};*/ + +typedef enum { ITU14bit, + ITU24bit, + ANSI24bit +} SS7pc_set; + +typedef struct { + SS7pc_set family; + uint32_t pc; +} SS7_ITU14_str; + +/* define structure of SS7 MTP pointcode (ITU/ANSI/other...) */ +union SS7union +{ + SS7_ITU14_str ITU14; + SS7_ITU14_str ITU24; + SS7_ITU14_str ANSI24; +}; + +typedef enum { no_pc_present, + ipvx_pc_present, // IPvx(4 or 6) present in pc field + ss7_pc_present // SS7 pointcode present in pc field +} pointcode_set; + +typedef enum { no_name_present, + hostname_present, + GT_present +} name_gt_set; + +typedef enum { no_sap_present, + ssn_present, + portnumber_presentr +} application_SAP_set; + +typedef enum { include_nothing, + include_pc_in_header, + include_ssn_port_in_header +} sua_header_set; + +typedef struct { + pointcode_set pc; + name_gt_set name_gt; + application_SAP_set ssn_port; + sua_header_set field_in_header; +} addr_elements_str; + +typedef struct { + SS7union ss7; + sockunion ipvx; + /*ipvxunion ipvx;*/ +} pointcode_str; + +typedef char hostname_str[255]; + +typedef char global_title_str[255]; + +typedef union { + global_title_str GT; + hostname_str HostName; +}name_str; + +typedef short application_sap_str; + +typedef enum { route_on_ssn, // use pointcode for routing + route_on_name_gt, // use gt/name for routing + route_on_name_gt_next_office, // perform GTT in next node + no_address_present // no routing requested +} routing_type_set; + +typedef struct { + addr_elements_str address_fields_present; // which fields are present? + pointcode_str pc; // pointcode field + name_str name; //global title/hostname field + application_sap_str ssn; // application ssn/port + routing_type_set routing_ind; // how must msg be routed + short network_apperance; +} sccp_addr_str; + +typedef enum { class0, // connectionless transport, non-sequenced + class1, // connectionless transport, sequenced + class2, // connectionoriented + class3 // connectionoriented with flow control +} protocol_class_set; + +typedef struct { + protocol_class_set prot_class; // class 0, 1 or 2 + bool in_sequence; // msg delivevered in sequence + short sequence_number; // = stream number + bool return_msg_on_error; // return a UDT service on err + short importance; // importance of msg(0..7) + short hopcounter; // hopcounter +} sccp_QOS_str; + +typedef struct { + void (*ulp_ClDataIndNotif) ( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int datalen + ); + void (*ulp_ConnIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ); + void (*ulp_ConnConfIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ); + void (*ulp_ConnDataIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ); + void (*ulp_DisConnIndNotif) ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int reason, + unsigned int datalen + ); +} Sua_ULP_CallBacks; + + +void sua_initialisation(); + +#define SUA_CFG_NO_ERROR 0 +#define SUA_CFG_FILE_UNKNOWN 1 +#define SUA_CFG_NO_SOURCE_ADDR 2 +#define SUA_CFG_NO_SOURCE_SSN 3 +#define SUA_CFG_NO_SOURCE_PORT 4 + +unsigned int sua_read_config_file + ( char *pConfFile + ); + +#define SUA_REG_NO_ERROR 0 + +unsigned int sua_registerInstance + ( short local_ssn, + Sua_ULP_CallBacks ulp_callback + ); + + +#define SUA_ASS_NO_ERROR 0 + +unsigned int sua_associate ( ); + +typedef struct { + sccp_addr_str remote_addr; + sccp_addr_str local_addr; + int blabla; + unsigned int ASP_status; +} sua_Path_str; + +#define SUA_PATH_NO_ERROR 0 +#define SUA_PATH_NO_DEST_ADDR_PRESENT 1 + +unsigned int sua_getPath( unsigned int assoc_id, + sua_Path_str &pathinfo + ); + +#define SUA_TERM_NO_ERROR 0 +#define SUA_TERM_NO_DEST_ADDR_PRESENT 1 + +unsigned int sua_terminate(); + + +#define SUA_SEND_NO_ERROR 0 +#define SUA_SEND_PRIM_NOT_SENT 1 + +unsigned int Send_sua_primitive( unsigned int primitive, + unsigned int &sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ); + +#define SUA_REC_NO_ERROR 0 +#define SUA_REC_NO_DATA_PRESENT 1 + +unsigned int Receive_sua_primitive( unsigned int &primitive, + unsigned int &sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ); + + + +#endif // SUA_GLOBAL_H + +// end of module sua.h + + + + + + + + + + + diff --git a/sualibrary/sua/sua_adapt.cpp b/sualibrary/sua/sua_adapt.cpp new file mode 100644 index 0000000..5dcb396 --- /dev/null +++ b/sualibrary/sua/sua_adapt.cpp @@ -0,0 +1,222 @@ +/*************************************************************************** + sua_adapt.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_adapt.cpp,v 1.2 2002/02/15 16:19:46 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Katrien + * "Come on barbie, let's go party" + * + * Purpose: This code-file defines the SUA adaptation functions used by + * the SUA application for: + * - initialising the SUA layer + * - reading the SUA configuration file + * - registering a local SUA instance + * - Setting up the association with a remote SUA node + * - get info on a certain (SUA) association + * - terminate a association + * - convert Hostname(string) to SUAname(Character array) + * - convert SUAname(Character array) to Hostname(Character array) + */ + +// sua_adapt.c++ +// SCCP user adaptation program + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_file.h" +#include "sua_distribution.h" +#include "sua_logging.h" + +#ifdef LINUX + #include +#endif + +#include + +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include + +using namespace std; +/* definition of SUA local object and of remote object */ +db_Sua_LocalList local_sua; +db_Sua_RemoteList remote_sua; +db_Sua_AssociationList Assoc_sua; +db_Sua_NameList NameDB_sua; +db_Sua_ASList ApplicServ_sua; + +/***********************************************************************/ +/* sua_initialisation */ +/***********************************************************************/ +void sua_initialisation() +{ + int res; + cout << "Initialising SCTP & SUA\n "; + res = sctp_initLibrary(); + init_logging_file(); + local_sua.initialize(); + remote_sua.initialize(); + Assoc_sua.initialize(); + cout << "Finished initialising SUA data\n "; + +} /* end of sua_initialisation */ + +/***********************************************************************/ +/* sua_read_configuration file */ +/***********************************************************************/ +unsigned int sua_read_config_file( char *pConfFile) +{ + unsigned int result = SUA_CFG_NO_ERROR; + string sua_filename; + sua_filename = pConfFile; + result = read_sua_file( sua_filename, + local_sua, + remote_sua, + Assoc_sua, + NameDB_sua, + ApplicServ_sua + ); + return(result); +} + +/***********************************************************************/ +/* sua_registerInstance */ +/***********************************************************************/ +unsigned int sua_registerInstance ( short local_ssn, + Sua_ULP_CallBacks ulp_callback + ) +{ + unsigned int result = SUA_REG_NO_ERROR; + SCTP_ulp_Callbacks SCTPCallbackFunctions; + + SCTPCallbackFunctions.dataArriveNotif = &sctp_DataArriveNotif; + SCTPCallbackFunctions.networkStatusChangeNotif = &sctp_NetworkStatusChangeNotif; + SCTPCallbackFunctions.sendFailureNotif = &sctp_SentFailureNotif; + SCTPCallbackFunctions.communicationLostNotif = &sctp_CommunicationLostNotif; + SCTPCallbackFunctions.communicationUpNotif = &sctp_CommunicationUpNotif; + SCTPCallbackFunctions.communicationErrorNotif = &sctp_CommunicationErrorNotif; + SCTPCallbackFunctions.restartNotif = &sctp_RestartNotif; + SCTPCallbackFunctions.shutdownCompleteNotif = &sctp_ShutDownCompleteNotif; + + result = Assoc_sua.register_instance ( SCTPCallbackFunctions, + ulp_callback, + local_sua + ); + + return(result); +} + + +/***********************************************************************/ +/* sua_associate */ +/***********************************************************************/ +unsigned int sua_associate ( ) +{ + unsigned int result = SUA_ASS_NO_ERROR; + result = Assoc_sua.associate_instance( local_sua, + remote_sua + ); + return(result); + +} + + +/***********************************************************************/ +/* sua_getPath */ +/***********************************************************************/ +unsigned int sua_getPath( unsigned int assoc_id, + sua_Path_str &pathinfo + ) +{ + unsigned int result = SUA_PATH_NO_ERROR; + + if ( Assoc_sua.instance[assoc_id].Dest.nr_of_addrs > 0) + { + /*pathinfo.remote_addr.*/ + pathinfo.remote_addr.pc.ipvx = Assoc_sua.instance[assoc_id].Dest.addrs[0]; + /*pathinfo.remote_addr.pc.ss7 = Assoc_sua.instance[assoc_id].Dest.pc;*/ + pathinfo.remote_addr.ssn = remote_sua.instance[Assoc_sua.instance[assoc_id].remote_sua_id].ssn.ssn; + + pathinfo.ASP_status = Assoc_sua.instance[assoc_id].asp.status; + +#ifdef DEBUG + //cout << "remote ssn = " << pathinfo.remote_addr.ssn << "\n"; + //cout << "remote sua_id = " << Assoc_sua.instance[assoc_id].remote_sua_id << "\n"; +#endif + } + else + result = SUA_PATH_NO_DEST_ADDR_PRESENT; + pathinfo.local_addr.pc.ipvx = Assoc_sua.instance[assoc_id].Source.addrs[0]; + pathinfo.local_addr.pc.ss7 = Assoc_sua.instance[assoc_id].Source.pc; + pathinfo.local_addr.ssn = local_sua.instance[Assoc_sua.instance[assoc_id].local_sua_id].ssn.ssn; + + return (result); + +} + +/***********************************************************************/ +/* sua_terminate */ +/***********************************************************************/ +unsigned int sua_terminate( ) +{ + unsigned int result = SUA_TERM_NO_ERROR; + + Assoc_sua.shutdown(); + close_logging_file(); + + return (result); + +} + + + +// end of module sua_adapt.c++ diff --git a/sualibrary/sua/sua_adapt.h b/sualibrary/sua/sua_adapt.h new file mode 100644 index 0000000..190c425 --- /dev/null +++ b/sualibrary/sua/sua_adapt.h @@ -0,0 +1,79 @@ +/*************************************************************************** + sua_adapt.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_adapt.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * Purpose: This header-file defines the SUA adaptation functions used by + * the SUA application for: + * - Nope + */ + +#include "sua_database.h" + +#ifdef LINUX + #include +#endif + + +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include + + +using namespace std; + + + + + +// end of module sua_adapt.h + + diff --git a/sualibrary/sua/sua_asp_mgnt.cpp b/sualibrary/sua/sua_asp_mgnt.cpp new file mode 100644 index 0000000..93f0b9e --- /dev/null +++ b/sualibrary/sua/sua_asp_mgnt.cpp @@ -0,0 +1,1030 @@ +/*************************************************************************** + sua_asp_mgnt.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_asp_mgnt.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Sabine + * "Due to small parts(Booleans), this code is not suitable for" + * "childeren under 3 years." + * + * Purpose: This code-file defines the SUA management handling functions for + * sending and receiving Application Server Process(ASP) messages: + * - send a ASP-UP msg to remote node + * - send a ASP-UP ACKnowledge msg to remote node + * - send a ASP-DOWN ACKnowledge msg to remote node + * - send a Hearbeat msg to remote node + * - send a Heartbeat ACKnowledge msg to remote node + * - send a ASP-ACTIVE msg to remote node + * - send a ASP-ACTIVE ACKnowledge msg to remote node + * - send a ASP-INactive Acknowledge msg to remote node + * - Receive/process ASP UP msg + * - Receive/process ASP UP ACKnowladge msg + * - Receive/process ASP DOWN msg + * - Receive/process ASP DOWN ACKnowledge msg + * - Receive/process Heartbeat msg + * - Receive/process Heartbeat ACKnowledge msg + * - Receive/process ASP ACTIVE msg + * - Receive/process ASP ACTIVE ACKnowladge msg + * - Receive/process ASP INactive msg + * - Receive/process ASP INactive ACKnowledge msg + */ + +#include "sua_debug.h" +#include "sua_asp_mgnt.h" +#include "sua_database.h" +#include "sua_syntax.h" +#include "sua_logging.h" +#include "sua_tcb.h" + +#include +#include + +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; +extern db_Sua_ASList ApplicServ_sua; +extern tcb_Sua_msgqueue_pool msg_store; + +/***********************************************************************/ +/* Sending SUA Management msg */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_send_ASPUP */ +/***********************************************************************/ +int sua_send_ASPUP( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_up; + msg.sua_prim.ASP_id_pres = TRUE; + msg.sua_prim.ASP_id = 1; + msg.sua_prim.asp_cap_pres = FALSE; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPUP sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPUP_ACK */ +/***********************************************************************/ +int sua_send_ASPUP_ACK( unsigned int Sua_assoc_id, + boolean ASP_id_pres, + uint32_t ASP_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_up_ack; + /* rest is optional */ + msg.sua_prim.ASP_id_pres = ASP_id_pres; + if ( ASP_id_pres) + msg.sua_prim.ASP_id = ASP_id; + + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPUP_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPDOWN_ACK */ +/***********************************************************************/ +int sua_send_ASPDOWN_ACK( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_down_ack; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPDOWN_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_BEAT */ +/***********************************************************************/ +int sua_send_BEAT( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_beat; + msg.sua_prim.hb_data_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result BEAT sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_BEAT_ACK */ +/***********************************************************************/ +int sua_send_BEAT_ACK( unsigned int Sua_assoc_id, + bool HB_data_present, + string HB_data + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_aspsm; + msg.sua_prim.hdr_msg_type.aspsm = aspsm_beat_ack; + msg.sua_prim.hb_data_pres = HB_data_present; + if (HB_data_present) + msg.sua_prim.hb_data = HB_data; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result BEAT_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPAC */ +/***********************************************************************/ +int sua_send_ASPAC( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_asptm; + msg.sua_prim.hdr_msg_type.asptm = asptm_act; + /* traffic mode is optional mandatory */ + msg.sua_prim.traf_mode_pres = TRUE; + msg.sua_prim.traf_mode = tmt_loadshare; + /* rest is optional */ + msg.sua_prim.rout_con_pres = FALSE; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPAC sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_ASPAC_ACK */ +/***********************************************************************/ +int sua_send_ASPAC_ACK( unsigned int Sua_assoc_id, + boolean traffic_mode_present, + Sua_traffic_mode_type traffic_mode, + boolean routing_context_present, + uint32_t routing_context + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_asptm; + msg.sua_prim.hdr_msg_type.asptm = asptm_act_ack; + + /* rest is optional */ + msg.sua_prim.traf_mode_pres = traffic_mode_present; + if ( traffic_mode_present) + msg.sua_prim.traf_mode = traffic_mode; + + msg.sua_prim.rout_con_pres = routing_context_present; + if (routing_context_present) + msg.sua_prim.rout_con = routing_context; + + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPAC_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + + +/***********************************************************************/ +/* sua_send_ASPINAC_ACK */ +/***********************************************************************/ +int sua_send_ASPINAC_ACK( unsigned int Sua_assoc_id + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value = 0; + int string_size, datalen; + signed int sctp_assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_asptm; + msg.sua_prim.hdr_msg_type.asptm = asptm_inact_ack; + msg.sua_prim.rout_con_pres = FALSE; + msg.sua_prim.info_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + delivery_type = SCTP_UNORDERED_DELIVERY; + + sctp_assoc_id = Assoc_sua.instance[Sua_assoc_id].SCTP_assoc_id; + + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_asp_mgnt.c",logstring); + log_byte_array("sua_asp_mgnt.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPINAC_ACK sctp send = "<< result << "\n"; +#endif + } + + return(error_value); +} + +/***********************************************************************/ +/* Receiving SUA Management msg */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_process_ASPUP_msg */ +/***********************************************************************/ +int process_ASPUP_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + + int error_value; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPUP received, send back a ASPUP_ACK and set state to ASP-INACTIVE.\n"; +#endif + + Assoc_sua.up(sua_assoc_id,0); + + error_value = sua_send_ASPUP_ACK( sua_assoc_id , + sua_asp_msg.sua_prim.ASP_id_pres, + sua_asp_msg.sua_prim.ASP_id + ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send ASPUP_ACK = "<< error_value << "\n"; + cout << "sua_asp_mgnt.c:ASPUP processing state = "<< Assoc_sua.instance[sua_assoc_id].asp.status << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPUP_ACK_msg */ +/***********************************************************************/ +int process_ASPUP_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPUP_ACK received, looks like remote is inactive.\n"; +#endif + + Assoc_sua.up(sua_assoc_id,0); + + /* send activation to remote */ + error_value = sua_send_ASPAC( sua_assoc_id ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send ASPAC = "<< error_value << "\n"; + cout << "sua_asp_mgnt.c:ASPUP_ACK processing state = "<< Assoc_sua.instance[sua_assoc_id].asp.status << "\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPDOWN_msg */ +/***********************************************************************/ +int process_ASPDOWN_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + + int error_value; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPDOWN received, send back a ASPDOWN_ACK and set state to ASP-DOWN.\n"; +#endif + + Assoc_sua.down(sua_assoc_id,0); + + + error_value = sua_send_ASPDOWN_ACK( sua_assoc_id ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send ASPDOWN_ACK = "<< error_value << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPDOWN_ACK_msg */ +/***********************************************************************/ +int process_ASPDOWN_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPDOWN_ACK received, remote looks down.\n"; +#endif + + Assoc_sua.down(sua_assoc_id,0); + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_BEAT_msg */ +/***********************************************************************/ +int process_BEAT_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + + int error_value; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:HEARTBEAT received, send back a HEARTBEAT_ACK.\n"; +#endif + + error_value = sua_send_BEAT_ACK( sua_assoc_id, + sua_asp_msg.sua_prim.hb_data_pres, + sua_asp_msg.sua_prim.hb_data + ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result send HEARTBEAT_ACK = "<< error_value << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_BEAT_ACK_msg */ +/***********************************************************************/ +int process_BEAT_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:HEARTBEAT_ACK received, nothing further to do.\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPAC_msg */ +/***********************************************************************/ +int process_ASPAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + bool holdtraffic_pres = FALSE; + int error_value; + tcb_Sua_msg_elem sua_msg; + int datalen; + signed int sctp_assoc_id; + int result; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPAC received, send back a ASPAC_ACK and set state to ASP-ACTIVE.\n"; +#endif + + if (sua_asp_msg.sua_prim.traf_mode_pres) + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id, + sua_asp_msg.sua_prim.traf_mode); + else + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id,0); + + error_value = sua_send_ASPAC_ACK( sua_assoc_id, + sua_asp_msg.sua_prim.traf_mode_pres, + sua_asp_msg.sua_prim.traf_mode, + sua_asp_msg.sua_prim.rout_con_pres, + sua_asp_msg.sua_prim.rout_con + ); + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPAC_ACK send = "<< error_value << "\n"; + cout << "sua_asp_mgnt.c:ASPAC processing state = "<< Assoc_sua.instance[sua_assoc_id].asp.status << "\n"; +#endif + + if (holdtraffic_pres) + { + /* send all stored msg for this association to remote side */ + /* should be looping to get all waiting messages */ + /* - get the saved msg ansd send it on the association that is setup */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + while ( sua_msg.valid) + { + char* databuf = new char[sua_msg.byte.length()]; + sua_msg.byte.copy(databuf, sua_msg.byte.length()); + datalen = sua_msg.byte.length(); + + /* msg retrieved and copied, may now remove it from queue */ + msg_store.delete_msg ( sua_assoc_id ); + + sctp_assoc_id = Assoc_sua.instance[sua_assoc_id].SCTP_assoc_id; + +#ifdef DEBUG + display_byte_array(databuf , sua_msg.byte.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_distribution.c",logstring); + log_byte_array("sua_distribution.c", databuf,sua_msg.byte.length()); + + result = sctp_send ( sctp_assoc_id, + sua_msg.stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + sua_msg.delivery_type, + SCTP_BUNDLING_DISABLED + ); + + delete databuf; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result sctp send = "<< result << "\n"; +#endif + /* get the next saved msg ansd send if any ? */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + } + + } + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPAC_ACK_msg */ +/***********************************************************************/ +int process_ASPAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; + bool holdtraffic_pres = FALSE; + +#ifdef SG_ASP_MODE + if (sua_asp_msg.sua_prim.traf_mode_pres) + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id, + sua_asp_msg.sua_prim.traf_mode); + else + holdtraffic_pres = Assoc_sua.activate(sua_assoc_id,0); + +#endif + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPAC_ACK received, nothing further to do.\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPINAC_msg */ +/***********************************************************************/ +int process_ASPINAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value; + tcb_Sua_msg_elem sua_msg; + +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPINAC received, send back a ASPINAC_ACK and set state to ASP-INACTIVE.\n"; +#endif + Assoc_sua.deactivate(sua_assoc_id,0); + + error_value = sua_send_ASPINAC_ACK( sua_assoc_id ); +#ifdef DEBUG + cout << "sua_asp_mgnt.c:result ASPINAC_ACK send = "<< error_value << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_process_ASPINAC_ACK_msg */ +/***********************************************************************/ +int process_ASPINAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ) +{ + int error_value = 0; +#ifdef DEBUG + cout << "sua_asp_mgnt.c:ASPINAC_ACK received, nothing further to do.\n"; +#endif + return(error_value); +} + +/***********************************************************************/ +/* Asp_mngt_standby */ +/***********************************************************************/ +void Asp_mngt_standby ( unsigned int sua_AS_id, + unsigned int sua_asp_id, + short mode + ) +{ + ApplicServ_sua.override_ASP( sua_asp_id, + sua_AS_id, + mode + ); +} + +void asp_activate_override ( unsigned int asp_sua_assoc_id ) +{ + Assoc_sua.activate(asp_sua_assoc_id,0); +} + +void asp_deactivate ( unsigned int asp_sua_assoc_id) +{ + Assoc_sua.deactivate(asp_sua_assoc_id,0); +} + + +//end of module sua_asp_mgnt.c++ + + + + + + + + + + + + + diff --git a/sualibrary/sua/sua_asp_mgnt.h b/sualibrary/sua/sua_asp_mgnt.h new file mode 100644 index 0000000..6531d17 --- /dev/null +++ b/sualibrary/sua/sua_asp_mgnt.h @@ -0,0 +1,190 @@ +/*************************************************************************** + sua_asp_mgnt.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_asp_mgnt.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * Purpose: This header-file defines the SUA management handling functions for + * sending and receiving Application Server Process(ASP) messages: + * - send a ASP-UP msg to remote node + * - send a ASP-ACTIVE msg to remote node + * - Receive/process ASP UP msg + * - Receive/process ASP UP ACKnowladge msg + * - Receive/process ASP DOWN msg + * - Receive/process ASP DOWN ACKnowledge msg + * - Receive/process Heartbeat msg + * - Receive/process Heartbeat ACKnowledge msg + * - Receive/process ASP ACTIVE msg + * - Receive/process ASP ACTIVE ACKnowladge msg + * - Receive/process ASP INactive msg + * - Receive/process ASP INactive ACKnowledge msg + * Contains also the ASP management states set + */ + +#ifndef SUA_ASP_MGNT_H +#define SUA_ASP_MGNT_H + +#include "sua.h" +#include "sua_syntax.h" + +#include + + + +typedef enum {asp_idle, // 0 + asp_down, // 1 + asp_down_traf_hold, // 2 + asp_inactive, // 3 + asp_inactive_traf_hold, // 4 + asp_active // 5 +} asp_Sua_asp_state_set; + + +typedef enum {as_idle, // 0 + as_down, // 1 + as_pending, // 2 + as_inactive, // 3 + as_active // 4 +} asp_Sua_as_state_set; + +typedef enum { lm_override, // 0: standard loadshare: only 1 ASP + lm_share_RR, // 1: Round robin load sharing + lm_share_XX, // 2: unknown load sharing + lm_share_BC // 3: Broadcasting +}asp_Sua_loadmode_set; + +int sua_send_ASPUP( unsigned int Sua_assoc_id + ); + +int sua_send_ASPAC( unsigned int Sua_assoc_id + ); + + +int process_ASPUP_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPUP_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPDOWN_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPDOWN_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_BEAT_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_BEAT_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPINAC_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +int process_ASPINAC_ACK_msg ( unsigned int sua_assoc_id, + int local_sua_id, + int remote_sua_id, + Sua_container sua_asp_msg + ); + +void Asp_mngt_standby ( unsigned int sua_AS_id, + unsigned int sua_asp_id, + short mode + ); + +void asp_activate_override ( unsigned int asp_sua_assoc_id ); + +void asp_deactivate ( unsigned int asp_sua_assoc_id); + + + + +#endif // SUA_ASP_MGNT_H + +//end of module sua_asp_mgnt.h + + + + + + + + + + + + + diff --git a/sualibrary/sua/sua_cl.cpp b/sualibrary/sua/sua_cl.cpp new file mode 100644 index 0000000..4ec0bb7 --- /dev/null +++ b/sualibrary/sua/sua_cl.cpp @@ -0,0 +1,550 @@ +/*************************************************************************** + sua_cl.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_cl.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Dorothee + * "Always admire the local beauties in their natural enviroment." + * + * Purpose: This code-file defines the SUA connectionless message handling: + * - send a Unitdata msg to remote node + * (- send a Unitdata Service msg to remote node) + * - Process a Unitdata msg + * (- Process a Unitdata Service msg) + */ + + +#include "sua_debug.h" +#include "sua_syntax.h" +#include "sua_database.h" +#include "sua_logging.h" +#include "sua_distribution.h" +#include "sua_tcb.h" + +#ifdef LINUX + #include +#endif + + +#include +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include + +using namespace std; + +// import the dataobjects of SUA +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; + +extern tcb_Sua_msgqueue_pool msg_store; + +// import the received msg pool +extern vector rec_msg_pool; + +/***********************************************************************/ +/* sua_send_Unitdata */ +/***********************************************************************/ +int sua_send_Unitdata(sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + signed int sctp_assoc_id; + unsigned int sua_assoc_id; + short stream_id = 0; + int delivery_type, result; + tcb_Sua_msg_elem sua_msg; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_cl; + msg.sua_prim.hdr_msg_type.cl = cl_data_transfer; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class0): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_0; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = QOS.sequence_number; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class1): + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_1; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = QOS.sequence_number; + delivery_type = SCTP_ORDERED_DELIVERY; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + // fill in the source address (=local sua address/CLG) + switch (calling_pty_address.routing_ind) + { + case (route_on_ssn): + + if (calling_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.source_addr.ip_addr_pres = TRUE; + msg.sua_prim.source_addr.pc_pres = FALSE; + if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v4; + msg.sua_prim.source_addr.ip_addr.ipv4 = calling_pty_address.pc.ipvx.sin; + } + else if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v6; + msg.sua_prim.source_addr.ip_addr.ipv6 = calling_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLG IP address \n"; + + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + } + else if (calling_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = TRUE; + msg.sua_prim.source_addr.pc = calling_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.source_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = TRUE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + cout << "SS7 PC in CLG address \n"; + } + else + cout << "unsupported CLG address option\n"; + break; + case(route_on_name_gt): + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = FALSE; + msg.sua_prim.source_addr.hostname_pres = TRUE; + msg.sua_prim.source_addr.hostname = calling_pty_address.name.HostName; + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_hostname; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = TRUE; + msg.sua_prim.source_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLG_ADDRESS); + break; + } + + + // fill in the destination address(=remote sua address/CLD) + switch (called_pty_address.routing_ind) + { + case (route_on_ssn): + + if (called_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.dest_addr.ip_addr_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v4; + msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin; + } + else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v6; + msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLD IP address \n"; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + } + else if (called_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.pc_pres = TRUE; + msg.sua_prim.dest_addr.pc = called_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.dest_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = TRUE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + cout << "SS7 PC in CLD address \n"; + } + else + cout << "unsupported CLD address option\n"; + + break; + case(route_on_name_gt): + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.hostname_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + msg.sua_prim.dest_addr.hostname = called_pty_address.name.HostName; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_hostname; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = TRUE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLD_ADDRESS); + break; + } + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + // call routing to figure out which association to take for sending + // out the message +#ifdef DEBUG + cout << "call routing function\n"; +#endif + sctp_assoc_id = Assoc_sua.route_msg( called_pty_address, + calling_pty_address + ); +#ifdef DEBUG + cout << "routed to SCTP assoc " << sctp_assoc_id << "\n"; +#endif + /* does association exist? */ + if (sctp_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_cl.c",logstring); + log_byte_array("sua_cl.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_cl.c:result sctp send = "<< result << "\n"; +#endif + } + else if (sctp_assoc_id < 0) + { +#ifdef DEBUG + cout << "sua_cl.c:sending msg prohibited \n"; +#endif + error_value = -1; + } + else + { + /* NO it does NOT exist. */ + /* - Try to set up the association */ + sua_assoc_id = Assoc_sua.Dynamic_Associate ( local_sua, + remote_sua, + called_pty_address, + calling_pty_address, + 1, + 1, + 1 + ); + + /* - save the msg till the association is setup or */ + /* association setup fails -> drop saved msg */ + sua_msg.byte = msg.sua_msg; + sua_msg.delivery_type = delivery_type; + sua_msg.stream_id = stream_id; + sua_msg.valid = true; + msg_store.add_msg ( sua_assoc_id, + sua_msg + ); + + error_value = -1; + } + return(error_value); +} + + +/***********************************************************************/ +/* SUA receive a connectionless message */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_process_unitdata */ +/***********************************************************************/ +short process_unitdata_msg ( int local_sua_id, + unsigned int sua_assoc_id, + Sua_container &msg + ) +{ + + sua_save_str temp; + + temp.primitive = N_UNITDATA; + temp.user_ref = 0; + + if (msg.sua_prim.prot_class_pres) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_0): // connectionless transport, non-sequenced + temp.QOS.prot_class = class0; + temp.QOS.in_sequence = false; + break; + case(prot_class_1): + temp.QOS.prot_class = class1; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + // which types are present in the address(ip pc, SS7 pc, GT, hostname) + if (msg.sua_prim.source_addr.ip_addr_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ipvx_pc_present; + if (msg.sua_prim.source_addr.ip_addr_type == ip_v4) { + temp.calling_pty_address.pc.ipvx.sin = msg.sua_prim.source_addr.ip_addr.ipv4; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET; + temp.calling_pty_address.pc.ipvx.sin.sin_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port; + } + else if (msg.sua_prim.source_addr.ip_addr_type == ip_v6) { + temp.calling_pty_address.pc.ipvx.sin6 = msg.sua_prim.source_addr.ip_addr.ipv6; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET6; + temp.calling_pty_address.pc.ipvx.sin6.sin6_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port; + } + else + cout << "Unknown IP address format\n"; + } + if (msg.sua_prim.source_addr.pc_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ss7_pc_present; + temp.calling_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.calling_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + if (msg.sua_prim.source_addr.gt_pres == TRUE) + { + cout << "Global Title : unsupported address format\n"; + } + if (msg.sua_prim.source_addr.hostname_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.source_addr.hostname.copy( temp.calling_pty_address.name.HostName, + (msg.sua_prim.source_addr.hostname.length()+1 ) + ); + temp.calling_pty_address.name.HostName[msg.sua_prim.source_addr.hostname.length()] = '\0'; + } + if ((msg.sua_prim.source_addr.ip_addr_pres /= TRUE) && + (msg.sua_prim.source_addr.pc_pres /= TRUE) && + (msg.sua_prim.source_addr.gt_pres /= TRUE) && + (msg.sua_prim.source_addr.hostname_pres /= TRUE)) + { + cout << "No valid address format found in msg\n"; + } + + // routing indicator + switch (msg.sua_prim.source_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case(ri_route_IP_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + temp.calling_pty_address.address_fields_present.ssn_port = ssn_present; + temp.calling_pty_address.ssn = msg.sua_prim.source_addr.ssn; + + + // retrieve the called(=destination) address(=should be our own local addr) + // not completely done yet + if (msg.sua_prim.dest_addr.pc_pres == TRUE) + { + temp.called_pty_address.address_fields_present.pc = ss7_pc_present; + temp.called_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.called_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + + if (msg.sua_prim.dest_addr.hostname_pres == TRUE) + { + temp.called_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.dest_addr.hostname.copy( temp.called_pty_address.name.HostName, + (msg.sua_prim.dest_addr.hostname.length()+1 ) + ); + temp.called_pty_address.name.HostName[msg.sua_prim.dest_addr.hostname.length()] = '\0'; + } + // routing indicator + switch (msg.sua_prim.dest_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.called_pty_address.routing_ind = route_on_ssn; + break; + case(ri_route_IP_SSN): + temp.called_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + temp.called_pty_address.address_fields_present.ssn_port = ssn_present; + temp.called_pty_address.ssn = msg.sua_prim.dest_addr.ssn; + + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_cl.c: no sua user data in unitdata msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ClDataIndNotif + ( local_sua_id, + N_UNITDATA, + temp.userdata.length() + ); + + return(0); +} + + +// end of module sua_cl.c + + + + + diff --git a/sualibrary/sua/sua_cl.h b/sualibrary/sua/sua_cl.h new file mode 100644 index 0000000..6c32df3 --- /dev/null +++ b/sualibrary/sua/sua_cl.h @@ -0,0 +1,88 @@ +/*************************************************************************** + sua_cl.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_cl.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * Purpose: This header-file defines the SUA connectionless message handling: + * - send a Unitdata msg to remote node + * (- send a Unitdata Service msg to remote node) + * - Process a Unitdata msg + * (- Process a Unitdata Service msg) + */ + +#ifndef SUA_CL_H +#define SUA_CL_H + +#include "sua_database.h" + +#ifdef LINUX + #include +#endif + + +#include +#include +#include +#include + + +using namespace std; + +int sua_send_Unitdata(sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ); + +short process_unitdata_msg ( int local_sua_id, + unsigned int sua_assoc_id, + Sua_container &sua_msg + ); + +#endif // SUA_CL_H + +// end of module sua_cl.h + + diff --git a/sualibrary/sua/sua_co.cpp b/sualibrary/sua/sua_co.cpp new file mode 100644 index 0000000..0b08a1f --- /dev/null +++ b/sualibrary/sua/sua_co.cpp @@ -0,0 +1,1768 @@ +/*************************************************************************** + sua_co.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_co.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Virginie + * "This code was written using the KISS methodology. (Yes, we kissed a " + * "lot of beautifull girls) We always use this method." + * + * Purpose: This code-file defines the SUA connection-oriented message + * handling: + * - send a COnnect REquest msg to remote node + * - send a COnnect RESPonse msg to remote node + * - send a CO DATA msg to remote node + * - send a CO RELease REQuest msg to remote node + * - send a CO RELease COnfirm msg to remote node + * - Process a COnnect REquest msg + * - Process a COnnect RESPonse msg + * - Process a CO DATA msg + * - Process a CO RELease REQuest msg + * - Process a CO RELease COnfirm msg + * - Process a COnnect REFuse msg + */ + +#include "sua_debug.h" +#include "sua_syntax.h" +#include "sua_database.h" +#include "sua_distribution.h" +#include "sua_logging.h" +#include "sua_tcb.h" + + +#ifdef LINUX + #include +#endif + +#include +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include + +using namespace std; + +// import the dataobjects of SUA +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; + +// import the TCB pool of SUA +extern tcb_Sua_TCB_arr tcb_pool; +extern tcb_Sua_msgqueue_pool msg_store; + +// import the received msg pool +extern vector rec_msg_pool; + +/***********************************************************************/ +/* Send sua connection-oriented request primitive to remote side */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_send_CORE */ +/***********************************************************************/ +int sua_send_CORE( sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + signed int SCTP_assoc_id; + unsigned int sua_assoc_id; + short stream_id = 0; + int delivery_type, result; + tcb_Sua_msg_elem sua_msg; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_core; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = 1; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + // fill in the source address (=local sua address/CLG) + switch (calling_pty_address.routing_ind) + { + case (route_on_ssn): + + if (calling_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.source_addr.ip_addr_pres = TRUE; + msg.sua_prim.source_addr.pc_pres = FALSE; + if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v4; + msg.sua_prim.source_addr.ip_addr.ipv4 = calling_pty_address.pc.ipvx.sin; + } + else if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.source_addr.ip_addr_type = ip_v6; + msg.sua_prim.source_addr.ip_addr.ipv6 = calling_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLG IP address \n"; + + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + } + else if (calling_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = TRUE; + msg.sua_prim.source_addr.pc = calling_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.source_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = TRUE; + msg.sua_prim.source_addr.gt_incl = FALSE; + msg.sua_prim.source_addr.ssn = calling_pty_address.ssn; + cout << "SS7 PC in CLG address \n"; + } + else + cout << "unsupported CLG address option\n"; + + break; + case(route_on_name_gt): + msg.sua_prim.source_addr.ip_addr_pres = FALSE; + msg.sua_prim.source_addr.pc_pres = FALSE; + msg.sua_prim.source_addr.hostname_pres = TRUE; + msg.sua_prim.source_addr.hostname = calling_pty_address.name.HostName; + msg.sua_prim.source_addr_pres = TRUE; + msg.sua_prim.source_addr.rout_ind = ri_route_hostname; + msg.sua_prim.source_addr.ssn_incl = TRUE; + msg.sua_prim.source_addr.pc_incl = FALSE; + msg.sua_prim.source_addr.gt_incl = TRUE; + msg.sua_prim.source_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLG_ADDRESS); + break; + } + + + // fill in the destination address(=remote sua address/CLD) + switch (called_pty_address.routing_ind) + { + case (route_on_ssn): + + if (called_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.dest_addr.ip_addr_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v4; + msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin; + } + else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v6; + msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLD IP address \n"; + + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + } + else if (called_pty_address.address_fields_present.pc == ss7_pc_present) + { + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.pc_pres = TRUE; + msg.sua_prim.dest_addr.pc = called_pty_address.pc.ss7.ITU24.pc; + msg.sua_prim.dest_addr.rout_ind = ri_route_PC_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = TRUE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + cout << "SS7 PC in CLD address \n"; + } + else + cout << "unsupported CLD address option\n"; + + break; + case(route_on_name_gt): + msg.sua_prim.dest_addr.ip_addr_pres = FALSE; + msg.sua_prim.dest_addr.hostname_pres = TRUE; + msg.sua_prim.dest_addr.pc_pres = FALSE; + msg.sua_prim.dest_addr.hostname = called_pty_address.name.HostName; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_hostname; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = TRUE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLD_ADDRESS); + break; + } + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = Sua_ConnId; + msg.sua_prim.dest_ref = FALSE; + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + +#ifdef DEBUG + cout << "Data = " << stemp << "\n"; + cout << "Source LR = " << Sua_ConnId << "\n"; +#endif + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + // call routing to figure out which association to take for sending + // out the message +#ifdef DEBUG + cout << "call routing function\n"; +#endif + SCTP_assoc_id = Assoc_sua.route_msg( called_pty_address, + calling_pty_address + ); +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif + + // fill in the TCB + tcb_ptr->Source_LR = Sua_ConnId; + tcb_ptr->User_ref_id = 1; + tcb_ptr->sctp_Association_id = SCTP_assoc_id; + tcb_ptr->state = scoc_outgoing; + tcb_ptr->remote_address = called_pty_address; + tcb_ptr->seq_number = Sua_ConnId % 256 ; + + /* does association exist? */ + if (SCTP_assoc_id > 0) + { + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + + /* yes it does, continue, no problem, send the msg */ +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + } + else if (SCTP_assoc_id < 0) + { +#ifdef DEBUG + cout << "sua_co.c:sending msg prohibited \n"; +#endif + error_value = -1; + } + else + { + /* NO it does NOT exist. */ + /* - Try to set up the association */ + sua_assoc_id = Assoc_sua.Dynamic_Associate ( local_sua, + remote_sua, + called_pty_address, + calling_pty_address, + 1, + 1, + 1 + ); + /* save newly assigned SCTP association id in SCOC TCB */ + tcb_ptr->sctp_Association_id = Assoc_sua.instance[sua_assoc_id].SCTP_assoc_id; + + /* - save the msg till the association is setup or */ + /* association setup fails -> drop saved msg */ + sua_msg.byte = msg.sua_msg; + sua_msg.delivery_type = delivery_type; + sua_msg.stream_id = stream_id; + sua_msg.valid = true; + msg_store.add_msg ( sua_assoc_id, + sua_msg + ); + + error_value = -1; + } + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CORESP */ +/***********************************************************************/ +int sua_send_CORESP( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_coak; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + + tcb_ptr->state = scoc_active; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + // fill in the user data + if (len > 0) + { + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + } + else + msg.sua_prim.data_pres = FALSE; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CODATA */ +/***********************************************************************/ +int sua_send_CODATA( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_data; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = FALSE; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.seq_nr_pres = TRUE; + msg.sua_prim.seq_nr.more_data = FALSE; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CO Release request */ +/***********************************************************************/ +int sua_send_CORELRQ( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_relre; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = TRUE; + msg.sua_prim.SCCP_cause.cause_type = ctp_release_cause; + msg.sua_prim.SCCP_cause.cause_value = 3; + + tcb_ptr->state = scoc_disconnect; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CO Release Confirm */ +/***********************************************************************/ +int sua_send_CORELCO( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_relco; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 7; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = TRUE; + msg.sua_prim.SCCP_cause.cause_type = ctp_release_cause; + msg.sua_prim.SCCP_cause.cause_value = 3; + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + // release the TCB of this connection + tcb_pool.release_TCB(Sua_ConnId); + + return(error_value); +} + +/***********************************************************************/ +/* sua_send_CO Connection Refused */ +/***********************************************************************/ +int sua_send_COREF( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ) +{ + Sua_container msg; + Sua_syntax_error_struct error; + int error_value; + int string_size, datalen; + unsigned int SCTP_assoc_id; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + short stream_id = 0; + int delivery_type, result = 0; + sccp_addr_str called_pty_address; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_coref; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = 1; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 5; + msg.sua_prim.hop_count_pres = TRUE; + msg.sua_prim.hop_count = 15; + + // QOS choice + switch (QOS.prot_class) + { + case(class2): // connectionless transport, non-sequenced + msg.sua_prim.prot_class_pres = TRUE; + msg.sua_prim.prot_class.pcl = prot_class_2; + msg.sua_prim.seq_control_pres = TRUE; + msg.sua_prim.seq_control = tcb_ptr->seq_number ; + delivery_type = SCTP_UNORDERED_DELIVERY; + break; + case(class3): + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + if (QOS.return_msg_on_error) + msg.sua_prim.prot_class.return_option = TRUE; + else + msg.sua_prim.prot_class.return_option = FALSE; + + called_pty_address = tcb_ptr->remote_address; + + // fill in the destination address(=remote sua address/CLD) + switch (called_pty_address.routing_ind) + { + case (route_on_ssn): + + if (called_pty_address.address_fields_present.pc == ipvx_pc_present) + { + msg.sua_prim.dest_addr.ip_addr_pres = TRUE; + if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v4; + msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin; + } + else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6) + { + msg.sua_prim.dest_addr.ip_addr_type = ip_v6; + msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6; + } + else + cout << "error filling in CLD IP address \n"; + } + else + cout << "unsupported CLD address option\n"; + msg.sua_prim.dest_addr_pres = TRUE; + msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN; + msg.sua_prim.dest_addr.ssn_incl = TRUE; + msg.sua_prim.dest_addr.pc_incl = FALSE; + msg.sua_prim.dest_addr.gt_incl = FALSE; + msg.sua_prim.dest_addr.ssn = called_pty_address.ssn; + break; + case(route_on_name_gt): + break; + case(route_on_name_gt_next_office): + break; + default: + return(INVALID_CLD_ADDRESS); + break; + } + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = FALSE; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = TRUE; + msg.sua_prim.SCCP_cause.cause_type = ctp_refusal_cause; + msg.sua_prim.SCCP_cause.cause_value = 3; + + // fill in the user data + msg.sua_prim.data_pres = TRUE; + string stemp(buffer,len); + msg.sua_prim.data_string = stemp; + + // encode the SUA unitdata message + error = msg.sua_encode(); + string_size = msg.sua_msg.size(); + + SCTP_assoc_id = tcb_ptr->sctp_Association_id; + + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + sua_assoc_id = Assoc_sua.Find_association( SCTP_assoc_id, + local_sua_id, + remote_sua_id + ); + + if (Assoc_sua.instance[sua_assoc_id].asp.status == asp_active) + { +#endif + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", SCTP_assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( SCTP_assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + error_value = result; + delete databuf; +#ifdef SUA_MANAGEMENT + } + else + { +#ifdef DEBUG + cout << "sua_co.c:message sending prohibited\n"; +#endif + error_value = -1; + } +#endif + +#ifdef DEBUG + cout << "sua_co.c:result sctp send = "<< result << "\n"; +#endif + + // release the TCB of this connection + tcb_pool.release_TCB(Sua_ConnId); + + return(error_value); +} + +/***********************************************************************/ +/* Receive a sua connection-oriented message from the remote side */ +/***********************************************************************/ +/***********************************************************************/ +/* sua_process_CORE */ +/***********************************************************************/ +short process_CORE_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + sua_save_str temp; + + temp.primitive = N_CONNECT_IND; + temp.user_ref = Sua_ConnId; + + if ( msg.sua_prim.prot_class_pres ) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_2): // connectionoriented transport, non-sequenced + temp.QOS.prot_class = class2; + temp.QOS.in_sequence = true; + break; + case(prot_class_3): + temp.QOS.prot_class = class3; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + // which types are present in the address(ip pc, SS7 pc, GT, hostname) + if (msg.sua_prim.source_addr.ip_addr_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ipvx_pc_present; + if (msg.sua_prim.source_addr.ip_addr_type == ip_v4) { + temp.calling_pty_address.pc.ipvx.sin = msg.sua_prim.source_addr.ip_addr.ipv4; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET; + temp.calling_pty_address.pc.ipvx.sin.sin_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port; + } + else if (msg.sua_prim.source_addr.ip_addr_type == ip_v6) { + temp.calling_pty_address.pc.ipvx.sin6 = msg.sua_prim.source_addr.ip_addr.ipv6; + temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET6; + temp.calling_pty_address.pc.ipvx.sin6.sin6_port = Assoc_sua.instance[sua_assoc_id].Dest.addrs[0].sin6.sin6_port; + } + else + cout << "Unknown IP address format\n"; + } + if (msg.sua_prim.source_addr.pc_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.pc = ss7_pc_present; + temp.calling_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.calling_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + if (msg.sua_prim.source_addr.gt_pres == TRUE) + { + cout << "Global Title : unsupported address format\n"; + } + if (msg.sua_prim.source_addr.hostname_pres == TRUE) + { + temp.calling_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.source_addr.hostname.copy( temp.calling_pty_address.name.HostName, + (msg.sua_prim.source_addr.hostname.length()+1 ) + ); + temp.calling_pty_address.name.HostName[msg.sua_prim.source_addr.hostname.length()] = '\0'; + } + if ((msg.sua_prim.source_addr.ip_addr_pres /= TRUE) && + (msg.sua_prim.source_addr.pc_pres /= TRUE) && + (msg.sua_prim.source_addr.gt_pres /= TRUE) && + (msg.sua_prim.source_addr.hostname_pres /= TRUE)) + { + cout << "No valid address format found in msg\n"; + } + + // routing indicator + switch (msg.sua_prim.source_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case(ri_route_IP_SSN): + temp.calling_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.calling_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + if (msg.sua_prim.source_addr.ssn_incl == TRUE) { + temp.calling_pty_address.address_fields_present.ssn_port = ssn_present; + temp.calling_pty_address.ssn = msg.sua_prim.source_addr.ssn; + } + else + temp.calling_pty_address.address_fields_present.ssn_port = no_sap_present; + + + // retrieve the called(=destination) address(=should be our own local addr) + // not completely done yet + if (msg.sua_prim.dest_addr.pc_pres == TRUE) + { + temp.called_pty_address.address_fields_present.pc = ss7_pc_present; + temp.called_pty_address.pc.ss7.ITU24.family = ITU24bit; + temp.called_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc; + } + + if (msg.sua_prim.dest_addr.hostname_pres == TRUE) + { + temp.called_pty_address.address_fields_present.name_gt = hostname_present; + msg.sua_prim.dest_addr.hostname.copy( temp.called_pty_address.name.HostName, + (msg.sua_prim.dest_addr.hostname.length()+1 ) + ); + temp.called_pty_address.name.HostName[msg.sua_prim.dest_addr.hostname.length()] = '\0'; + } + // routing indicator + switch (msg.sua_prim.dest_addr.rout_ind) + { + case(ri_route_PC_SSN): + temp.called_pty_address.routing_ind = route_on_ssn; + break; + case (ri_route_GT): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + case (ri_route_hostname): + temp.called_pty_address.routing_ind = route_on_name_gt; + break; + default: + break; + } + + temp.called_pty_address.address_fields_present.ssn_port = ssn_present; + temp.called_pty_address.ssn = msg.sua_prim.dest_addr.ssn; + + // fill in the allocated TCB + tcb_ptr->Source_LR = Sua_ConnId; + tcb_ptr->Dest_LR = msg.sua_prim.source_ref; + tcb_ptr->User_ref_id = 1; + tcb_ptr->sctp_Association_id = Assoc_sua.instance[sua_assoc_id].SCTP_assoc_id; + tcb_ptr->state = scoc_incoming; + tcb_ptr->remote_address = temp.calling_pty_address; + tcb_ptr->seq_number = Sua_ConnId % 255; + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CORE msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + +#ifdef DEBUG + cout << "primitive stored , local_sua_id = " << local_sua_id << "\n"; +#endif + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnIndNotif + ( local_sua_id, + Sua_ConnId, + temp.userdata.length() + ); + + return(0); +} + +/***********************************************************************/ +/* sua_process_COAK */ +/***********************************************************************/ +short process_COAK_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + sua_save_str temp; + + temp.primitive = N_CONNECT_CONF; + temp.user_ref = sua_ConnId; + + if (msg.sua_prim.prot_class_pres) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_2): // connectionoriented transport, non-sequenced + temp.QOS.prot_class = class2; + temp.QOS.in_sequence = true; + break; + case(prot_class_3): + temp.QOS.prot_class = class3; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + + // fill in the allocated TCB + tcb_ptr->Dest_LR = msg.sua_prim.source_ref; + tcb_ptr->User_ref_id = 1; + tcb_ptr->state = scoc_active; + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnConfIndNotif + ( local_sua_id, + sua_ConnId, + temp.userdata.length() + ); + + return(0); + +} +/***********************************************************************/ +/* sua_process_CODATA */ +/***********************************************************************/ +short process_CODATA_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + sua_save_str temp; + + //temp.primitive = N_CODATA; + temp.user_ref = sua_ConnId; + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + // not needed -> to be found in TCB + // retrieve the called(=destination) address(=should be our own local addr) + // not needed -> to be found in TCB + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnDataIndNotif + ( local_sua_id, + sua_ConnId, + temp.userdata.length() + ); + + return(0); + +} + +/***********************************************************************/ +/* sua_process_CORELRQ */ +/***********************************************************************/ +short process_CORELRQ_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + unsigned int release_cause = 0; + unsigned int routing_Contex = 0; + sua_save_str temp; + + temp.primitive = N_RELEASE_REQ; + temp.user_ref = sua_ConnId; + routing_Contex = msg.sua_prim.rout_con; + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + tcb_ptr->state = scoc_disconnect; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + // send a CORELCONF back to the remote node + Sua_syntax_error_struct error; + int datalen; + unsigned int assoc_id; + short stream_id = 0; + int delivery_type, result; + + // init the message + msg.sua_init(); + + // fill in the main sua header + msg.sua_prim.hdr_msg_class = sua_co; + msg.sua_prim.hdr_msg_type.co = co_relco; + + msg.sua_prim.rout_con_pres = TRUE; + msg.sua_prim.rout_con = routing_Contex; + msg.sua_prim.importance_pres = TRUE; + msg.sua_prim.importance = 7; + + // QOS choice + delivery_type = SCTP_UNORDERED_DELIVERY; + + // fill in the connection-oriented specific data of the msg + msg.sua_prim.source_ref_pres = TRUE; + msg.sua_prim.source_ref = tcb_ptr->Source_LR ; + msg.sua_prim.dest_ref_pres = TRUE; + msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ; + msg.sua_prim.SCCP_cause_pres = FALSE; + + // fill in the user data + msg.sua_prim.data_pres = FALSE; + + // encode the SUA Release complete message + error = msg.sua_encode(); + //string_size = msg.sua_msg.size(); + + assoc_id = tcb_ptr->sctp_Association_id; + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + +#ifdef DEBUG + cout << "routed to SCTP assoc " << assoc_id << "\n"; +#endif + + tcb_ptr->state = scoc_idle; + + // send data to SCTP + char* databuf = new char[msg.sua_msg.length()]; + msg.sua_msg.copy(databuf, msg.sua_msg.length()); + datalen = msg.sua_msg.length(); + +#ifdef DEBUG + // display byte array + display_byte_array(databuf , msg.sua_msg.length()); +#endif + + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", assoc_id); + event_log("sua_co.c",logstring); + log_byte_array("sua_co.c", databuf,msg.sua_msg.length()); + + result = sctp_send ( assoc_id, + stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + delivery_type, + SCTP_BUNDLING_DISABLED + ); + + delete databuf; + + // release the TCB of this connection + tcb_pool.release_TCB(sua_ConnId); + +#ifdef DEBUG + cout << "local_sua_id = " << local_sua_id << "\n"; +#endif + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif + ( local_sua_id, + sua_ConnId, + release_cause, + temp.userdata.length() + ); + + return(0); + +} + +/***********************************************************************/ +/* sua_process_CORELCO */ +/***********************************************************************/ +short process_CORELCO_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + unsigned int release_cause = 0; + sua_save_str temp; + + temp.primitive = N_RELEASE_CONF; + temp.user_ref = sua_ConnId; + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + local_sua_id = Assoc_sua.instance[sua_assoc_id].local_sua_id; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + // release the TCB of this connection + tcb_pool.release_TCB(sua_ConnId); + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif + ( local_sua_id, + sua_ConnId, + release_cause, + temp.userdata.length() + ); + + return(0); +} + + +/***********************************************************************/ +/* sua_process_COREF */ +/***********************************************************************/ +short process_COREF_msg ( unsigned int sua_assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &sua_ConnId, + Sua_container &msg + ) +{ + unsigned int local_sua_id = 0; + unsigned int release_cause = 0; + sua_save_str temp; + + temp.primitive = N_CONNECT_REFUSED; + temp.user_ref = sua_ConnId; + + if ( msg.sua_prim.prot_class_pres ) + { + // QOS choice + switch ( msg.sua_prim.prot_class.pcl) + { + case(prot_class_2): // connectionoriented transport, non-sequenced + temp.QOS.prot_class = class2; + temp.QOS.in_sequence = true; + break; + case(prot_class_3): + temp.QOS.prot_class = class3; + temp.QOS.in_sequence = true; + break; + default: + return(PROTOCOL_CLASS_NOT_SPECIFIED); + break; + } + + temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE); + } + temp.QOS.sequence_number = 0; + temp.QOS.importance = msg.sua_prim.importance; + + // retrieve the clg(=source) address (=remote sua address) + + // retrieve the called(=destination) address(=should be our own local addr) + tcb_ptr->state = scoc_idle; + +#ifdef DEBUG + cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n"; + cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n"; + cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n"; + cout << "TCB state = " << tcb_ptr->state << "\n"; +#endif + + if (msg.sua_prim.data_pres == TRUE) + temp.userdata = msg.sua_prim.data_string; + else + cout << "sua_co.c: no sua user data in CODATA msg \n"; + + // store primitive in a list(is retrieve via sua_receive_msg) + rec_msg_pool.push_back(temp); + + // release the TCB of this connection + tcb_pool.release_TCB(sua_ConnId); + +#ifdef DEBUG + cout << "local_sua_id = " << local_sua_id << "\n"; +#endif + + /* call the application/user callBack function */ + local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif + ( local_sua_id, + sua_ConnId, + release_cause, + temp.userdata.length() + ); + + return(0); + +} +// end of module sua_co.c + + + + + + diff --git a/sualibrary/sua/sua_co.h b/sualibrary/sua/sua_co.h new file mode 100644 index 0000000..8f4fd11 --- /dev/null +++ b/sualibrary/sua/sua_co.h @@ -0,0 +1,170 @@ +/*************************************************************************** + sua_co.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_co.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * Purpose: This header-file defines the SUA connection-oriented message + * handling: + * - send a COnnect REquest msg to remote node + * - send a COnnect RESPonse msg to remote node + * - send a CO DATA msg to remote node + * - send a CO RELease REQuest msg to remote node + * - send a CO RELease COnfirm msg to remote node + * - Process a COnnect REquest msg + * - Process a COnnect RESPonse msg + * - Process a CO DATA msg + * - Process a CO RELease REQuest msg + * - Process a CO RELease COnfirm msg + * - Process a COnnect REFuse msg + */ + +#ifndef SUA_CO_H +#define SUA_CO_H + +#include "sua_database.h" + +#ifdef LINUX + #include +#endif + + +#include +#include +#include +#include + + +using namespace std; + + +/***********************************************************************/ +/* Send sua connection-oriented request primitive to remote side */ +/***********************************************************************/ +int sua_send_CORE( sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CORESP( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CODATA( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CORELRQ( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_CORELCO( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +int sua_send_COREF( sccp_QOS_str &QOS, + char *buffer, + unsigned int len, + unsigned int &Sua_ConnId, + tcb_Sua_TCB_str *tcb_ptr + ); + +/***********************************************************************/ +/* Receive a sua connection-oriented message from the remote side */ +/***********************************************************************/ +short process_CORE_msg( unsigned int sua_Assoc_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_COAK_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_CODATA_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_CORELRQ_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_CORELCO_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); + +short process_COREF_msg( unsigned int local_sua_id, + tcb_Sua_TCB_str *tcb_ptr, + unsigned int &Sua_ConnId, + Sua_container &sua_msg + ); +#endif // SUA_CO_H + +// end of module sua_co.h + + diff --git a/sualibrary/sua/sua_database.cpp b/sualibrary/sua/sua_database.cpp new file mode 100644 index 0000000..ce953e1 --- /dev/null +++ b/sualibrary/sua/sua_database.cpp @@ -0,0 +1,642 @@ +/*************************************************************************** + sua_database.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_database.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Ann V. + * "What does reuse of code mean if the code is NOT even used yet." + * + * Purpose: This code-file defines the SUA database access functions for: + * - dummy Indication Notifications + * - dummy DISxx indciation Notifications + * Sybsystem Number(SSN) Object: + * - read SSN + * Address Object: + * - read IP address parameter + * - read IP portnumber + * Local SUA Object: + * - initialise Local SUA Object + * Local SUA List: + * - initialise Local SUA List + * - read SSN + * - increase instance + * - unregister instance + * - register instance + * Remote SUA object: + * - initialise Remote SUA Object + * Remote SUA List + * - initialise Remote SUA list + * - read SSN + * - increase instance + * SUA Application Server list + * - initialise AS List + * + */ + +#include "sctp.h" + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_logging.h" + +#include +#include +#include +#include + +#include "unistd.h" + + + +using namespace std; + + +/***********************************************************************/ +/*Initialisation dummy functions for the object class SUA List & Object*/ +/***********************************************************************/ +void db_dummy_xxxxIndNotif ( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int datalen + ) +{ + cout << "You've just called the dummy_xxxxIndNotif function ! \n"; + cout << "Better check youre initialisation and registration !! \n"; +} + +void db_dummy_DisxIndNotif ( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int cause, + unsigned int datalen + ) +{ + cout << "You've just called the dummy_DisxIndNotif function ! \n"; + cout << "Better check youre initialisation and registration !! \n"; +} +/***********************************************************************/ +/* functions of the object class SUA SSN Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_SSNObject::read_ssn */ +/***********************************************************************/ +void db_Sua_SSNObject::read_ssn(string ssn_str){ + + char *tokstr = new char[ssn_str.length()+1]; + short sua_ssn; + + + ssn_str.copy(tokstr,ssn_str.length()); + tokstr[ssn_str.length()] = '\0'; + sua_ssn = atoi(tokstr); + + ssn = sua_ssn; + +#ifdef DEBUG + //cout << "SSN value = " << sua_ssn << "\n"; +#endif +}; + +/***********************************************************************/ +/* functions of the object class SUA Address Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_AddressObject::read_addr_param */ +/***********************************************************************/ +void db_Sua_AddressObject::read_addr_param(string address_str){ + int b=0,len=0,count_punct=0, count_colon=0; + unsigned int i=0; + int tokstr_len = 0; + char *tokstr; + int result; + +#ifdef DEBUG + cout << "address = " << address_str << " len = " <= 2) + { // IPv6 address parameters + addrs[nr_of_addrs].sa.sa_family = AF_INET6; + addrs[nr_of_addrs].sin6.sin6_port = SUA_PORT; + result = inet_pton(AF_INET6, tokstr,&addrs[nr_of_addrs].sin6.sin6_addr); + if (result != 1) + cout << "IPvx address conversion returned "<< result << " \n"; +#ifdef DEBUG + cout << "IPv6 = " << &addrs[nr_of_addrs].sin6.sin6_addr << " \n"; +#endif + } + + nr_of_addrs++; + b = i + 1; + count_punct = 0; + count_colon = 0; + + } + + i++; + + } +#ifdef DEBUG + cout << "number of address = " << nr_of_addrs << " \n"; +#endif +} + +/***********************************************************************/ +/* Sua_AddressObject::read_pointcode */ +/***********************************************************************/ +void db_Sua_AddressObject::read_pointcode_param(string pointcode_str) { + int b=0,len=0; + unsigned int i=0; + int tokstr_len = 0; + char *tokstr; + +#ifdef DEBUG + cout << "Pointcode string = " << pointcode_str << " len = " << pointcode_str.length() << "\n"; +#endif + + while ((i <= pointcode_str.length())) + { + if (i == pointcode_str.length()) + { + len = i - b; + string dest(pointcode_str,b,len); + + tokstr_len = dest.length()+1; + tokstr = new char[tokstr_len]; + + dest.copy(tokstr,dest.length()); + // we are dealing with char arrays, so.... + tokstr[dest.length()] = '\0'; + + pc.ITU24.family = ITU24bit; + pc.ITU24.pc = atoi(tokstr); + +#ifdef DEBUG + cout << "Pointcode value = " << pc.ITU24.pc << " \n"; +#endif + b = i + 1; + } + i++; + } + +#ifdef DEBUG + cout << "Only 1 pointcode per association allowed \n"; +#endif +} + +/***********************************************************************/ +/* Sua_AddressObject::read_port_num */ +/***********************************************************************/ +void db_Sua_AddressObject::read_port_num(string port_str){ + int i=0; + char *tokstr = new char[port_str.length()+1]; + int sua_port_number; + + + port_str.copy(tokstr,port_str.length()); + tokstr[port_str.length()] = '\0'; + sua_port_number = atoi(tokstr); + + for(i = 0; i < nr_of_addrs ; i++) + addrs[i].sin6.sin6_port = sua_port_number; + +#ifdef DEBUG + //cout << "Portnumber = " << sua_port_number << " * " << nr_of_addrs << " times \n"; +#endif +} + +/***********************************************************************/ +/* functions of the object class SUA Local Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_LocalObject::initalize */ +/***********************************************************************/ +void db_Sua_LocalObject::initialize(){ + + + SUA_APLCallBack.ulp_ClDataIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_ConnIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_ConnConfIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_ConnDataIndNotif = &db_dummy_xxxxIndNotif; + SUA_APLCallBack.ulp_DisConnIndNotif = &db_dummy_DisxIndNotif; + +} + +/***********************************************************************/ +/* functions of the object class SUA LocalList */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_LocalList::initialize */ +/***********************************************************************/ +void db_Sua_LocalList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_LOCAL_SUA; i++) + { + instance[i].initialize(); + } +} + +/***********************************************************************/ +/* Sua_LocalList::read_ssn */ +/***********************************************************************/ +void db_Sua_LocalList:: read_ssn(string ssn_str){ + + instance[num_of_instance].ssn.read_ssn(ssn_str); +}; + +/***********************************************************************/ +/* Sua_LocalList::increase_instance */ +/***********************************************************************/ +void db_Sua_LocalList:: increase_instance(){ + + num_of_instance++; +#ifdef DEBUG + cout << "New instance nr " << (num_of_instance - 1) << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "New instance nr %d", num_of_instance - 1); + event_log("sua_database.c",logstring); + +}; + + +/***********************************************************************/ +/* Sua_LocalList::unregister_instance */ +/***********************************************************************/ +short db_Sua_LocalList:: unregister_instance(){ + + int i; + + for(i=0; i < num_of_instance; i++) + { +#ifdef DEBUG + cout << "UnRegister SUA(& SCTP) local instance nr " << i << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Unregister SUA(& SCTP) local instance nr %d", i); + event_log("sua_database.c",logstring); + /* result = sctp_unregisterSCTP_instance ( instance[i].assoc_id ); + */ + } + return(0); +}; + +/***********************************************************************/ +/* Sua_LocalList::register_instance */ +/***********************************************************************/ +short db_Sua_LocalList:: +register_instance( unsigned int local_sua_id, + Sua_ULP_CallBacks SUACallbackFunctions, + unsigned int init_association + ){ + + + instance[local_sua_id].SUA_APLCallBack.ulp_ClDataIndNotif = SUACallbackFunctions.ulp_ClDataIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_ConnIndNotif = SUACallbackFunctions.ulp_ConnIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_ConnConfIndNotif = SUACallbackFunctions.ulp_ConnConfIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_ConnDataIndNotif = SUACallbackFunctions.ulp_ConnDataIndNotif; + instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif = SUACallbackFunctions.ulp_DisConnIndNotif; + + instance[local_sua_id].init_assoc_id = init_association; + + return(0); +} + +/***********************************************************************/ +/* functions of the object class SUA Remote Object */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_RemoteObject::initalize */ +/***********************************************************************/ +void db_Sua_RemoteObject::initialize(){ + + ; +} + +/***********************************************************************/ +/* functions of the object class SUA RemoteList */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_RemoteList::initialize */ +/***********************************************************************/ +void db_Sua_RemoteList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_REMOTE_SUA; i++) + { + instance[i].initialize(); + } +} + +/***********************************************************************/ +/* Sua_RemoteList::read_ssn */ +/***********************************************************************/ +void db_Sua_RemoteList:: read_ssn(string ssn_str){ + + instance[num_of_instance].ssn.read_ssn(ssn_str); +}; + +/***********************************************************************/ +/* Sua_RemoteList::increase_instance */ +/***********************************************************************/ +void db_Sua_RemoteList:: increase_instance(){ + + num_of_instance++; +#ifdef DEBUG + cout << "New instance nr " << (num_of_instance - 1) << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "New instance nr %d", num_of_instance - 1); + event_log("sua_database.c",logstring); + +}; +/***********************************************************************/ +/* functions of the object class SUA Application Server Process (ASP) */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_ASPObject::initalize */ +/***********************************************************************/ +void db_Sua_ASPObject::initialize(){ + short j; + + status = asp_idle; + for (j=0; j < db_MAX_1ASP_IN_AS ; j++) + linked_to_AS[j] = 0; +} + +/***********************************************************************/ +/* Sua_ASPObject::Activate ASP */ +/***********************************************************************/ +bool db_Sua_ASPObject::activate(unsigned int sua_assoc_id, + short mode + ) +{ + bool traf_hold=FALSE; + short i; + + + switch ( status) + { + case (asp_inactive): + { + switch (mode) + { + case (tmt_override ): + { + cout << "ASP in override mode\n"; + /* this node becomes the override node for processing */ + /* all other ASP of this AS must be put in standby */ + i = 0; + /*while (i <= db_MAX_1ASP_IN_AS) + { + if ((linked_to_AS[i] > 0) && + (linked_to_AS[i] <= db_MAX_SUA_AS)) + Asp_mngt_standby ( linked_to_AS[i], + sua_assoc_id, + mode + ); + }*/ + } + case (tmt_loadshare): + { + cout << "ASP in loadshare mode\n"; + } + case (tmt_max/*broadcast*/): + { + cout << "ASP in broadcast -> very dangerous\n"; + } + default: + { + cout << "default mode in activation\n"; + } + } + status = asp_active; + } + case (asp_inactive_traf_hold): + { + status = asp_active; + traf_hold = TRUE; + } + default: + { + /* remain in same state */ + /* depdending on the mode of the ASPAC */ + ; + } + } + return(traf_hold); +} + +/***********************************************************************/ +/* Sua_ASPObject::inactivate ASP */ +/***********************************************************************/ +void db_Sua_ASPObject::deactivate( unsigned int sua_assoc_id, + short mode + ) +{ + if( status == asp_active) + status = asp_inactive; +} + +/***********************************************************************/ +/* Sua_ASPObject::put ASP up = inactive */ +/***********************************************************************/ +void db_Sua_ASPObject::up( unsigned int sua_assoc_id, + short mode + ) +{ + switch(status) + { + case( asp_down): + { + status = asp_inactive; + } + case (asp_down_traf_hold): + { + status = asp_inactive_traf_hold; + } + default: + { + // do nothing , state is not changed + } + } +} + +/***********************************************************************/ +/* Sua_ASPObject::put ASP in down mode */ +/***********************************************************************/ +void db_Sua_ASPObject::down( unsigned int sua_assoc_id, + short mode + ) +{ + status = asp_down; +} + +/***********************************************************************/ +/* functions of the object class SUA Application Server List */ +/***********************************************************************/ +/***********************************************************************/ +/* Sua_ASList::initalize */ +/***********************************************************************/ +void db_Sua_ASList::initialize(){ + + short i,j; + num_of_instance = 0; + for (i=0; i < db_MAX_SUA_AS; i++) + { + instance[i].status = as_idle; + for (j=0; j < db_MAX_ASP_IN_1AS; j++) + instance[i].ASP_linked_to_this_AS[j] = 0; + } +} + +/***********************************************************************/ +/* Sua_ASList::read_AS string */ +/***********************************************************************/ +short db_Sua_ASList::read_AS( string as_str, + unsigned int sua_id + ){ + int i=0; + char *tokstr = new char[as_str.length()+1]; + int as_number; + bool cont_loop; + + + as_str.copy(tokstr,as_str.length()); + tokstr[as_str.length()] = '\0'; + as_number = atoi(tokstr); + + if ( instance[as_number].status == as_idle) + instance[as_number].status = as_down; + + i= 0; + cont_loop = (i < db_MAX_ASP_IN_1AS); + while (cont_loop) + { + if (instance[as_number].ASP_linked_to_this_AS[i] == 0) + { + instance[as_number].ASP_linked_to_this_AS[i] = sua_id; + cont_loop = false; + } + } +#ifdef DEBUG + cout << "Application Server number used " << as_number << " for ASP " << sua_id << "\n"; +#endif + + return(as_number); + +} + +/***********************************************************************/ +/* AS_override_ASP */ +/***********************************************************************/ +void db_Sua_ASList::override_ASP( unsigned int asp_sua_assoc_id, + unsigned int AS_id, + short mode + ) +{ + short i; + short asp_present_nr = 0; + unsigned short processed_ASP = 0; + + for (i=0; i <= db_MAX_ASP_IN_1AS; i++){ + processed_ASP = instance[AS_id].ASP_linked_to_this_AS[i]; + if (processed_ASP == asp_sua_assoc_id ) + { + asp_present_nr++; + asp_activate_override(asp_sua_assoc_id); + } + else if ((processed_ASP > 0) && + (processed_ASP <= db_MAX_REMOTE_SUA)) + { + asp_present_nr++; + asp_deactivate(asp_sua_assoc_id); + } + /*else nothing to do */ + + } + //if (asp_present_nr = 0) + // instance(AS_id).status = as_ +} + +// end of module sua_database.c + + + + + + diff --git a/sualibrary/sua/sua_database.h b/sualibrary/sua/sua_database.h new file mode 100644 index 0000000..9b2005a --- /dev/null +++ b/sualibrary/sua/sua_database.h @@ -0,0 +1,397 @@ +/*************************************************************************** + sua_database.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_database.h,v 1.2 2002/02/07 16:34:27 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 8. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Ann S. + * "Don't mention the war." + * + * Purpose: This code-file defines the SUA database objects for: + * - Sybsystem Number(SSN) Object + * - Address Object + * - Local SUA Object + * - Local SUA List + * - Remote SUA object + * - Remote SUA List + * - SUA Name Object(host names/Global Titles) + * - SUA Name List + * - SUA Association Object + * - SUA Association List + * - SUA Application Server Process (ASP) Object + * - SUA Application Server (AS) Object + * - SUA Application Server (AS) List + */ + +#ifndef SUA_DATABASE_H +#define SUA_DATABASE_H + +#include "sua.h" +#include "sua_asp_mgnt.h" + +#include + + + +typedef enum {nc_empty, nc_ipv4, nc_ipv6} db_net_class; + +const int db_MAX_MULTIHOME_ADDR = 10; +const int db_MAX_LOCAL_SUA = 10; +const int db_MAX_REMOTE_SUA = 1000; +const int db_MAX_SSN_SUA = 256; +const int db_MAX_SUA_AS = 100; +const int db_MAX_ASP_IN_1AS = 8; /* maximal 8 ASP's can be covered by a single AS */ +const int db_MAX_1ASP_IN_AS = 4; /* 1 ASP can appear in maximal up till 4 different AS's */ + +/***********************************************************************/ +/* Sua_SSNObject */ +/***********************************************************************/ +class db_Sua_SSNObject { + public: + short ssn; + public: + void read_ssn(string ssn); +}; ///:~ + +/***********************************************************************/ +/* Sua_LocalObject */ +/***********************************************************************/ +class db_Sua_LocalObject{ + public: + db_Sua_SSNObject ssn; + /* contains the initial SUA association */ + unsigned int init_assoc_id; + /* the local sua id with which it is linked. */ + unsigned int sua_id; + Sua_ULP_CallBacks SUA_APLCallBack; + public: + // functions of the Class + void initialize(); +}; ///:~ + +/***********************************************************************/ +/* Sua_LocalList */ +/***********************************************************************/ +class db_Sua_LocalList{ + public: + int num_of_instance; + db_Sua_LocalObject instance[db_MAX_LOCAL_SUA]; + void initialize(); + void read_ssn(string ssn); + short register_instance( unsigned int local_sua_id, + Sua_ULP_CallBacks SUACallbackFunctions, + unsigned int init_assoc_id + ); + short unregister_instance(); + void increase_instance(); +}; ///:~ + +/***********************************************************************/ +/* Sua_RemoteObject */ +/***********************************************************************/ +class db_Sua_RemoteObject{ + public: + db_Sua_SSNObject ssn; + /* contains the SCTP assoc id */ + unsigned int SCTP_assoc_id; + /* contains the local sua id with which it is linked. */ + unsigned int sua_id; + public: + // functions of the Class + void initialize(); +}; ///:~ + +/***********************************************************************/ +/* Sua_RemoteList */ +/***********************************************************************/ +class db_Sua_RemoteList{ + public: + int num_of_instance; + public: + db_Sua_RemoteObject instance[db_MAX_REMOTE_SUA]; + void initialize(); + void read_ssn(string ssn); + void increase_instance(); + +}; ///:~ + + +/***********************************************************************/ +/* Sua_AddressObject */ +/***********************************************************************/ +class db_Sua_AddressObject { + public: + int nr_of_addrs; // number of ip addresses used(multihoming) + unsigned char address_string[db_MAX_MULTIHOME_ADDR][SCTP_MAX_IP_LEN]; + ipvxunion addrs[db_MAX_MULTIHOME_ADDR]; + SS7union pc; + public: + void read_addr_param(string address); + void read_pointcode_param(string point_code); + void read_port_num(string port); +}; ///:~ + +/***********************************************************************/ +/* Sua_ApplicationServerProcessObject (ASP) */ +/***********************************************************************/ +class db_Sua_ASPObject { + public: + asp_Sua_asp_state_set status; /* status of the ASP */ + short linked_to_AS[db_MAX_1ASP_IN_AS]; /* this ASP may belong to different Application Servers(AS) */ + public: + void initialize(); + bool activate( unsigned int sua_assoc_id, short mode ); + void deactivate( unsigned int sua_assoc_id, short mode ); + void down( unsigned sua_assoc_id, short mode ); + void up( unsigned sua_assoc_id, short mode ); +}; ///:~ + +/***********************************************************************/ +/* Sua_LS_OverRideObject (LS_OverRide) */ +/***********************************************************************/ +class db_Sua_LS_OverRideObject { + private: + short ASP_to_use; /* ASP presently being the workhorse)*/ + public: + void assign_ASP(short ASP_num); + short ASP_used(); +}; ///:~ + +/***********************************************************************/ +/* Sua_LS_RoundRobinObject (LS_RoundRobin) */ +/***********************************************************************/ +class db_Sua_LS_RoundRobinObject { + private: + short ASP_to_use; /* ASP presently being the workhorse)*/ + public: + short ASP_used(); +}; + +/***********************************************************************/ +/* Sua_LoadShareObject (LS_AS) */ +/***********************************************************************/ +class db_Sua_LoadShareObject { + public: + asp_Sua_loadmode_set load_mode; /* mode of loadsharing)*/ + db_Sua_LS_OverRideObject override; /* AS has a ASP in override */ + db_Sua_LS_RoundRobinObject RRobin; /* AS is RR all active ASP's */ +}; ///:~ + + +/***********************************************************************/ +/* Sua_ApplicationServerObject (AS) */ +/***********************************************************************/ +class db_Sua_ASObject { + public: + asp_Sua_as_state_set status; /* status of the AS */ + short ASP_linked_to_this_AS[db_MAX_ASP_IN_1AS];/* AS may contain a couple of ASP's */ + db_Sua_LoadShareObject loadshare; + public: + void initialize(); +}; ///:~ + +/***********************************************************************/ +/* Sua_ApplicationServerList (AS list) */ +/***********************************************************************/ +class db_Sua_ASList{ + public: + int num_of_instance; + db_Sua_ASObject instance[db_MAX_SUA_AS]; + public: + void initialize(); + short read_AS( string address_str, + unsigned int sua_id + ); + void override_ASP( unsigned int asp_sua_assoc_id, + unsigned int AS_id, + short mode + ); +}; ///:~ + +/***********************************************************************/ +/* Sua_AssociationsObject */ +/***********************************************************************/ +class db_Sua_AssociationObject { + public: + unsigned int SCTP_assoc_id; + unsigned int SCTP_instance_name; + unsigned int remote_sua_id; + unsigned int local_sua_id; + short nr_of_inbound_streams; + short nr_of_outbound_streams; + db_Sua_ASPObject asp; + db_net_class netw; // sort of network(v4/v6) to be used + // ip source/destination addresses , should be the same network type + db_Sua_AddressObject Source; + db_Sua_AddressObject Dest; + public: + void initialize(); + short shutdown(); +}; ///:~ + +/***********************************************************************/ +/* Sua_AssociationList */ +/***********************************************************************/ +class db_Sua_AssociationList{ + public: + int num_of_instance; + db_Sua_AssociationObject instance[db_MAX_REMOTE_SUA]; + public: + void initialize(); + void read_Source_addr(string address); + void read_Dest_addr(string address); + void read_Source_pointcode(string address); + void read_Dest_pointcode(string address); + void read_Source_port(string port); + void read_Dest_port(string port); + void read_stream_number(string stream_num); + short register_instance(SCTP_ulp_Callbacks APLCallbackFunctions, + Sua_ULP_CallBacks SUACallbackFunctions, + db_Sua_LocalList& local_sua + ); + short unregister_instance(); + unsigned int Find_association( unsigned int sctp_assoc_id, + unsigned int &Local_sua_id, + unsigned int &Remote_sua_id + ); + unsigned int Find_local_sua( sccp_addr_str& local_address + ); + short associate_instance( db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua + ); + unsigned int passive_associate( unsigned int assoc_id, + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ); + unsigned int Dynamic_Associate( db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + sccp_addr_str& cld, + sccp_addr_str& clg, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ); + short Terminate_remote_assoc_instance(); + short shutdown(); + signed int route_msg(sccp_addr_str& cld, + sccp_addr_str& clg + ); + signed int route_on_IPpc ( ipvxunion& dest_pc, + ipvxunion& org_pc, + int& sua_assoc_id + ); + signed int route_on_SS7pc ( SS7union& dest_pc, + SS7union& org_pc, + int& sua_assoc_id + ); + signed int route_on_GTname ( hostname_str& dest_name, + hostname_str& org_name, + int& sua_assoc_id, + pointcode_str& dest_pc, + pointcode_str& org_pc + ); + void increase_instance(); + bool activate( unsigned int sua_id, + short mode + ); + void deactivate( unsigned int sua_id, + short mode + ); + void down( unsigned int sua_id, + short mode + ); + void up( unsigned int sua_id, + short mode + ); +}; ///:~ + +/***********************************************************************/ +/* Sua_NameObject */ +/***********************************************************************/ +class db_Sua_NameObject { + public: + unsigned int SUA_assoc_id; + public: + void initialize(); + +}; ///:~ + +/***********************************************************************/ +/* Sua_NameList */ +/***********************************************************************/ +class db_Sua_NameList{ + public: + int num_of_instance; + db_Sua_NameObject instance[db_MAX_REMOTE_SUA]; + public: + void initialize(); + string read_host_name(string name); + string read_Global_Title(string name); + unsigned int perform_GTT( sccp_addr_str& cld_in, + sccp_addr_str& clg_in, + sccp_addr_str& cld_out, + sccp_addr_str& clg_out + ); + void increase_instance(); +}; ///:~ + +#endif // SUA_DATABASE_H + +//end of module sua_database.h + + + + + + + + + + + + + diff --git a/sualibrary/sua/sua_dataname.cpp b/sualibrary/sua/sua_dataname.cpp new file mode 100644 index 0000000..b1e6914 --- /dev/null +++ b/sualibrary/sua/sua_dataname.cpp @@ -0,0 +1,174 @@ +/*************************************************************************** + sua_dataname.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_dataname.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Vicky + * "This module reuse some code, thus it will mostly reuse trouble." + * + * Purpose: This code-file defines the SUA database access functions for: + * SUA Name Object (host names/Global Titles): + * - initialise Name + * SUA Name List: + * - initialise Name List + * - read hostname + */ + +#include "sctp.h" + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_asp_mgnt.h" +#include "sua_logging.h" + +#include +#include +#include +#include + +#include "unistd.h" + + + +using namespace std; + +/***********************************************************************/ +/* functions of the object class SUA name Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_NameObject::initalize */ +/***********************************************************************/ +void db_Sua_NameObject::initialize(){ + + // initialise to point to a invalid SUA association + SUA_assoc_id = 0; +} + + + +/***********************************************************************/ +/* functions of the object class SUA NameList */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_NameList::initalize */ +/***********************************************************************/ +void db_Sua_NameList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_REMOTE_SUA; i++) { + instance[i].initialize(); + } +} + +string db_Sua_NameList::read_host_name(string name){ + + char *hostname; + const char *ip_addr_ptr; + struct hostent *hptr; + char str[INET6_ADDRSTRLEN]; + char **pptr; + string addr_str; + + hostname = new char[name.length()+1]; + name.copy(hostname,name.length()); + // we are dealing with char arrays, so.... + hostname[name.length()] = '\0'; + + if ((hptr = gethostbyname(hostname)) == NULL){ + cout << "Determination of hostname failed\n"; + return("127.0.0.1"); + } + +#ifdef DEBUG + cout << "Hostname " << hptr->h_name << " has the following IP address(es)\n"; +#endif + + pptr = hptr->h_addr_list; + for ( ; *pptr != NULL;pptr++) + { + ip_addr_ptr = inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str)); + addr_str = addr_str + ip_addr_ptr; + if ((*(pptr+1)) != NULL) + /* another ip address is comming after the present one */ + addr_str = addr_str + ","; + /*else this is the last ip address */ +#ifdef DEBUG + cout << ip_addr_ptr << "\n"; +#endif + } + +#ifdef DEBUG + cout << "output IP list = " << addr_str << "\n"; +#endif + + string name_str; + int last= name.size(); + unsigned int current = name.rfind('.'); + while(current != string::npos){ + name_str = name_str + name.substr(current+1,(last-current)) + "."; + last= current - 1; + current = name.rfind('.', last); + } + name_str = name_str + name.substr(0,last+1); + +#ifdef DEBUG + cout << "Ready for storing SUA dest hostname = " << name_str << " in NameDB\n"; +#endif + + + return(addr_str); + +} + + +// end of module sua_dataname.c + + + + + + diff --git a/sualibrary/sua/sua_datassoc.cpp b/sualibrary/sua/sua_datassoc.cpp new file mode 100644 index 0000000..c3bcc5f --- /dev/null +++ b/sualibrary/sua/sua_datassoc.cpp @@ -0,0 +1,1000 @@ +/*************************************************************************** + sua_datassoc.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_datassoc.cpp,v 1.3 2002/02/15 16:19:46 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Vera + * "You ain't seen nothing yet" + * "said Garfield the Ripper while putting on his binbag" + * + * Purpose: This code-file defines the SUA database access functions for + * SUA Association Object: + * - initialise association object + * - shutdown association + * - Dynamic association + * SUA Association List: + * - initialise association list + * - read source address + * - read Destination address + * - read source port + * - read destination port + * - read stream number + * - register instance + * - associate instance(initiating) + * - Find a association + * - Find a local SUA instance + * - Passive association instantiation(terminating) + * - shutdown a association + * - route on IP pointcode address + * - route on Global Title/Hostname + * - route message to a association + * - increase instance + * - Dynamic association setup(initiating) + */ + +#include "sctp.h" + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_asp_mgnt.h" +#include "sua_logging.h" + +#include +#include +#include +#include +#include + +#include "unistd.h" + + + +using namespace std; + +struct ulp_data_str { + int maximumStreamID; + unsigned int chunkCount; +}; + +static ulp_data_str ULPData[db_MAX_MULTIHOME_ADDR]; + + +/***********************************************************************/ +/* functions of the object class SUA Association Object */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_AssociationObject::initalize */ +/***********************************************************************/ +void db_Sua_AssociationObject::initialize(){ + short i; + Source.nr_of_addrs = 0; + Dest.nr_of_addrs = 0; + netw = nc_empty; + nr_of_inbound_streams = 0; + nr_of_outbound_streams = 0; + asp.status = asp_down; + for (i=0; i < db_MAX_MULTIHOME_ADDR; i++) { + Source.addrs[i].sa.sa_family = AF_INET; + Dest.addrs[i].sa.sa_family = AF_INET; + } + Source.pc.ITU24.pc = 0; + Dest.pc.ITU24.pc = 0; + for (i=0; i < db_MAX_1ASP_IN_AS; i++) + asp.linked_to_AS[i] = 0; +} + +/***********************************************************************/ +/* Sua_RemoteObject::shutdown_instance */ +/***********************************************************************/ +short db_Sua_AssociationObject:: shutdown(){ + + int result; + result = sctp_shutdown( SCTP_assoc_id ); + + return(result); + +}; + +/***********************************************************************/ +/* Sua_AssociationL::Dynamic_Associate */ +/***********************************************************************/ +unsigned int Dynamic_Associate( sccp_addr_str& cld, + sccp_addr_str& clg + ) +{ + return(0); +} + +/***********************************************************************/ +/* functions of the object class SUA AssociationList */ +/***********************************************************************/ + +/***********************************************************************/ +/* Sua_AssociationList::initalize */ +/***********************************************************************/ +void db_Sua_AssociationList::initialize(){ + short i; + num_of_instance = 0; + for (i=0; i < db_MAX_REMOTE_SUA; i++) { + instance[i].initialize(); + } +} + + +/***********************************************************************/ +/* Sua_AssociationList::read_Source_addr */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Source_addr(string address){ + + instance[num_of_instance].Source.read_addr_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Dest_addr */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Dest_pointcode(string address){ + + instance[num_of_instance].Dest.read_pointcode_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Source_pointcode */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Source_pointcode(string address){ + + instance[num_of_instance].Source.read_pointcode_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Dest_addr */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Dest_addr(string address){ + + instance[num_of_instance].Dest.read_addr_param(address); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Source_port */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Source_port(string port){ + + instance[num_of_instance].Source.read_port_num(port); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_Dest_port */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_Dest_port(string port){ + + instance[num_of_instance].Dest.read_port_num(port); + +} + +/***********************************************************************/ +/* Sua_AssociationList::read_stream_number */ +/***********************************************************************/ +void db_Sua_AssociationList:: read_stream_number(string stream_num){ + + + int i=0; + char *tokstr = new char[stream_num.length()+1]; + int sua_stream_nr; + + + stream_num.copy(tokstr,stream_num.length()); + tokstr[stream_num.length()] = '\0'; + sua_stream_nr = atoi(tokstr); + + for(i = 1; i <= num_of_instance ; i++) { + instance[i].nr_of_inbound_streams = sua_stream_nr; + instance[i].nr_of_outbound_streams = sua_stream_nr; + } +} + +/***********************************************************************/ +/* Sua_AssociationList::register_instance */ +/***********************************************************************/ +short db_Sua_AssociationList:: +register_instance( SCTP_ulp_Callbacks APLCallbackFunctions, + Sua_ULP_CallBacks SUACallbackFunctions, + db_Sua_LocalList& local_sua + ){ + + int i; + unsigned int local_sua_idx; + short sua_portnumber = SUA_PORT; + + for(i=1; i <= num_of_instance; i++) + { + local_sua_idx = instance[i].local_sua_id; +#ifdef DEBUG + cout << "Register SUA(& SCTP) local instance nr " << local_sua_idx << " with association " << i << " ,SSN = "<< local_sua.instance[local_sua_idx].ssn.ssn <<" \n"; +#endif + char logstring[100]; + sprintf(logstring, "Register SUA(& SCTP) local instance nr %d with association %d, SSN = %d", local_sua_idx,i,local_sua.instance[local_sua_idx].ssn.ssn ); + event_log("sua_database.c",logstring); + local_sua.register_instance( instance[i].local_sua_id, + SUACallbackFunctions, + i + ); + if (instance[i].Source.addrs[0].sa.sa_family == AF_INET) + sua_portnumber = instance[i].Source.addrs[0].sin.sin_port; + else if (instance[i].Source.addrs[0].sa.sa_family == AF_INET6) + sua_portnumber = instance[i].Source.addrs[0].sin6.sin6_port; + + instance[i].SCTP_instance_name = + sctp_registerInstance( sua_portnumber, + instance[i].nr_of_inbound_streams, + instance[i].nr_of_outbound_streams, + instance[i].Source.nr_of_addrs, + instance[i].Source.address_string, + APLCallbackFunctions + ); + +#ifdef DEBUG + cout << "SCTP instance name = " << instance[i].SCTP_instance_name << " \n"; +#endif + sprintf(logstring, "Local SCTP instance nr %d name = %d", i, instance[i].SCTP_instance_name); + event_log("sua_database.c",logstring); + + } +return(0); +}; + +/***********************************************************************/ +/* Sua_AssociationList::associate_instance */ +/***********************************************************************/ +short db_Sua_AssociationList:: +associate_instance( db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua + ){ + + int i; + SCTP_InstanceParameters SCTP_assoc_parms; + SCTP_InstanceParameters *SCTP_assoc_status = &SCTP_assoc_parms; + short sua_portnumber = SUA_PORT; + int res=0; + + // get default values of association + res = sctp_getAssocDefaults( instance[1].SCTP_instance_name, + SCTP_assoc_status + ); + + // fill in the TOS field needed for DIFFSERV + SCTP_assoc_status->ipTos = 'a'; + + // set the new value for all associations + res = sctp_setAssocDefaults( instance[1].SCTP_assoc_id, + SCTP_assoc_status + ); + + for(i=1; i <= num_of_instance; i++) + { + if (instance[i].Dest.nr_of_addrs != 0) { +#ifdef DEBUG + cout << "Associate remote SUA(& SCTP) instance nr " << i << " with local SUA(& SCTP) instance nr " << instance[i].local_sua_id <<" \n"; +#endif + char logstring[100]; + sprintf(logstring, "Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", i, instance[i].local_sua_id ); + event_log("sua_database.c",logstring); + + if (instance[i].Dest.addrs[0].sa.sa_family == AF_INET) + sua_portnumber = instance[i].Dest.addrs[0].sin.sin_port; + else if (instance[i].Dest.addrs[0].sa.sa_family == AF_INET6) + sua_portnumber = instance[i].Dest.addrs[0].sin6.sin6_port; + + ULPData[0].maximumStreamID = -1; + + short unsigned instance_name = instance[i].SCTP_instance_name ; + instance[i].SCTP_assoc_id = + sctp_associate( instance_name, + instance[i].nr_of_outbound_streams, + instance[i].Dest.address_string[0], + sua_portnumber, + NULL + ); + + /* no msg queued, mark assoc down(from sua management viewpoint)*/ + instance[i].asp.status = asp_down; + +#ifdef DEBUG + cout << "SCTP association result = " << instance[i].SCTP_assoc_id <<" \n"; +#endif + + } + } + return(0); +}; + + +/***********************************************************************/ +/* Sua_AssociationList::Find_association */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList:: +Find_association( unsigned int sctp_assoc_id, + unsigned int &Local_sua_id, + unsigned int &Remote_sua_id + ) +{ + short i = 0; + unsigned int sua_assoc_id = 0; + bool result = FALSE; + Local_sua_id = 0; + Remote_sua_id = 0; + + while ((i < db_MAX_REMOTE_SUA) && !(result)) + { + + result = (instance[i].SCTP_assoc_id == sctp_assoc_id); + if (result) { + Local_sua_id = instance[i].local_sua_id; + Remote_sua_id = instance[i].remote_sua_id; + sua_assoc_id = i; + } + i++; + } + + return(sua_assoc_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::Find_local_sua */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList:: +Find_local_sua( sccp_addr_str& local_address + ) +{ + short i = 1, j = 0; + unsigned int Local_sua_id = 0; + bool result = FALSE; + + while ((i < db_MAX_REMOTE_SUA) && !(result) && (instance[i].Source.nr_of_addrs != 0)) + { + j = 0; + while ((j < instance[i].Source.nr_of_addrs) && !(result)) + { + result = ((instance[i].Source.addrs[j].sin.sin_addr.s_addr == local_address.pc.ipvx.sin.sin_addr.s_addr) || + (instance[i].Source.addrs[j].sin6.sin6_addr.s6_addr == local_address.pc.ipvx.sin6.sin6_addr.s6_addr)); + if (result) + { + Local_sua_id = instance[i].local_sua_id; +#ifdef DEBUG + cout << "local_sua_id = " << Local_sua_id << " , instance "<< i << "\n"; +#endif + } + j++; + } + i++; + } + + return(Local_sua_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::passive_associate */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList:: +passive_associate( unsigned int assoc_id, + db_Sua_LocalList &local_sua, + db_Sua_RemoteList &remote_sua, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ){ + + SCTP_AssociationStatus status; + int result; + short k; + int bla; + short i = 1, assoc_instance_idx = 1; + bool cont, partial_assoc_found = FALSE; + + while ((i <= num_of_instance) && !(partial_assoc_found)){ + partial_assoc_found = (instance[i].Dest.nr_of_addrs == 0); + if (partial_assoc_found) + assoc_instance_idx = i; + + i++; + } + + if (!(partial_assoc_found)) + { + /* new association added */ + num_of_instance++; + assoc_instance_idx = num_of_instance; + instance[assoc_instance_idx].Source = instance[assoc_instance_idx-1].Source; + + instance[assoc_instance_idx].nr_of_inbound_streams = nr_of_input_streams ; + instance[assoc_instance_idx].nr_of_outbound_streams = nr_of_input_streams ; + } + + remote_sua.increase_instance(); + + instance[assoc_instance_idx].SCTP_assoc_id = assoc_id; + instance[assoc_instance_idx].remote_sua_id = remote_sua.num_of_instance; + remote_sua.instance[remote_sua.num_of_instance].ssn.ssn = local_sua.instance[local_sua.num_of_instance].ssn.ssn; + // should search for the correct sua local instance(future) + instance[assoc_instance_idx].local_sua_id = local_sua.num_of_instance; +#ifdef DEBUG + cout << "Associate remote SUA(& SCTP) instance nr " << assoc_id << " with local SUA(& SCTP) instance nr " << assoc_instance_idx << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", assoc_id, assoc_instance_idx ); + event_log("sua_database.c",logstring); + + + result = sctp_getAssocStatus(instance[assoc_instance_idx].SCTP_assoc_id, &status); + + /* conversion and fill in the destination address */ + instance[assoc_instance_idx].Dest.nr_of_addrs = nr_of_dest_addr; + instance[assoc_instance_idx].Dest.address_string[0] = status.primaryDestinationAddress; + instance[assoc_instance_idx].Dest.addrs[0].sin.sin_port = status.destPort; + + /* try to figure out ipv4 or v6 address family: get it from the source address */ + k = 0; + instance[assoc_instance_idx].Dest.addrs[0].sa.sa_family = AF_LOCAL; + cont = true; + while ((k < 24) && (cont)) + { + if (instance[assoc_instance_idx].Dest.address_string[0][k] == '.') + { + cont = false; + instance[assoc_instance_idx].Dest.addrs[0].sa.sa_family = AF_INET; + } + if (instance[assoc_instance_idx].Dest.address_string[0][k] == ':') + { + cont = false; + instance[assoc_instance_idx].Dest.addrs[0].sa.sa_family = AF_INET6; + } + k++; + } + + for(k=0; k < instance[assoc_instance_idx].Dest.nr_of_addrs ; k++) + { + if (instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET) + bla = inet_pton( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + &instance[assoc_instance_idx].Dest.addrs[k].sin.sin_addr + ); + else if (instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET6) + bla = inet_pton( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + &instance[assoc_instance_idx].Dest.addrs[k].sin6.sin6_addr + ); + else + cout << "Unsupported address family in passive associate\n"; + + } + + /* no msg queued, mark assoc down(from sua management viewpoint)*/ + instance[assoc_instance_idx].asp.status = asp_down; + + return(assoc_instance_idx); +} + +/***********************************************************************/ +/* Sua_AssociationList::shutdown_instance */ +/***********************************************************************/ +short db_Sua_AssociationList:: shutdown(){ + + int i; + short result; + + for(i=1; i <= num_of_instance; i++) + { +#ifdef DEBUG + cout << "shutdown remote SUA(& SCTP) instance nr " << i << " with local SUA(& SCTP) instance nr " << instance[i].local_sua_id <<" \n"; +#endif + char logstring[100]; + sprintf(logstring, "Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", i, instance[i].local_sua_id ); + event_log("sua_database.c",logstring); + + result = instance[i].shutdown(); + + } + + return(0); +}; + +/***********************************************************************/ +/* Sua_AssociationList::route_on_IPpc */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_on_IPpc ( ipvxunion& dest_pc, + ipvxunion& org_pc, + int& sua_assoc_id + ) +{ + int j=0,i=1,count, addr_start, addr_stop; + unsigned int sctp_assoc_id = 0; + + sua_assoc_id = 0; + bool cont = (i <= num_of_instance); + bool found_assoc = false; + + while (cont) + { + found_assoc = false; + j = 0; + while ((j < instance[i].Dest.nr_of_addrs) && (!found_assoc)) + { + found_assoc = (dest_pc.sa.sa_family == instance[i].Dest.addrs[j].sa.sa_family); + if (dest_pc.sa.sa_family == AF_INET) + { + addr_start = 4; + addr_stop = addr_start + 4; + } + else if (dest_pc.sa.sa_family == AF_INET6) + { + addr_start = 8; + addr_stop = addr_start + 16; + } + else + { + addr_start = 0; + addr_stop = 0; + found_assoc = false; + cout << "ERROR route_on_IPpc: Unknown addresstype\n"; + } + /* compare the address family field */ + found_assoc = found_assoc && (dest_pc.ch[1] == instance[i].Dest.addrs[j].ch[1]); + + /* compare the ipv4/ipv6 address field */ + for (count = addr_start; count < addr_stop; count++) + { + found_assoc = found_assoc + && (dest_pc.ch[count] == instance[i].Dest.addrs[j].ch[count]); + } + j++; + } + + if (found_assoc) + { + cont = false; + sctp_assoc_id = instance[i].SCTP_assoc_id; + sua_assoc_id = i; +#ifdef DEBUG + cout << "Found Sua association " << i << " with SCTP assoc " << sctp_assoc_id << "\n"; + + if (dest_pc.sa.sa_family == AF_INET) + { + cout << "CLD ip v4 = " << dest_pc.sin.sin_addr.s_addr << "\n"; + cout << "Remote IP = " << instance[i].Dest.addrs[0].sin.sin_addr.s_addr << "\n"; + } + else if (dest_pc.sa.sa_family == AF_INET6) + { + cout << "CLD ip v6 = " << dest_pc.sin6.sin6_addr.s6_addr << "\n"; + cout << "Remote IP = " << instance[i].Dest.addrs[0].sin6.sin6_addr.s6_addr << "\n"; + } + else + cout << "Unknown CLD IP address type format\n"; +#endif + } + else + { + i++; + cont = (i <= num_of_instance); + } + } + + return(sctp_assoc_id); +}; + + +/***********************************************************************/ +/* Sua_AssociationList::route_on_SS7pc */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_on_SS7pc ( SS7union& dest_pc, + SS7union& org_pc, + int& sua_assoc_id + ) +{ + int i=1; + unsigned int sctp_assoc_id = 0; + +#ifdef DEBUG + cout << "route on SS7 PC\n"; + cout << "PC family = " << dest_pc.ITU24.family << "\n"; + cout << "PC value = " << dest_pc.ITU24.pc << "\n"; +#endif + + sua_assoc_id = 0; + bool cont = (i <= num_of_instance); + bool found_assoc = false; + + while (cont) + { + + if (dest_pc.ITU14.family == ITU14bit) // standard ITU: 14 bits + found_assoc = ((dest_pc.ITU14.pc == instance[i].Dest.pc.ITU14.pc)); + else if (dest_pc.ITU24.family == ITU24bit) // chinese PC length: 24 bits + found_assoc = ((dest_pc.ITU24.pc == instance[i].Dest.pc.ITU24.pc)); + else if (dest_pc.ANSI24.family == ANSI24bit) // ANSI PC length: 24 bits + found_assoc = ((dest_pc.ANSI24.pc == instance[i].Dest.pc.ANSI24.pc)); + else + found_assoc = false; + + + if (found_assoc) + { + cont = false; + sctp_assoc_id = instance[i].SCTP_assoc_id; + sua_assoc_id = i; +#ifdef DEBUG + cout << "Found Sua association " << i << " with SCTP assoc " << sctp_assoc_id << "\n"; + + cout << "CLD SS7 PC = " << dest_pc.ITU24.pc << "\n"; + cout << "Remote PC = " << instance[i].Dest.pc.ITU24.pc << "\n"; + +#endif + } + else + { + i++; + cont = (i <= num_of_instance); + } + } + + return(sctp_assoc_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::route_on_GTname */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_on_GTname ( hostname_str& dest_name, + hostname_str& org_name, + int& sua_assoc_id, + pointcode_str& dest_pc, + pointcode_str& org_pc + ) +{ + struct hostent *hptr; + char **pptr; + unsigned int sctp_assoc_id = 0; + char str[INET6_ADDRSTRLEN]; + char *dest_carr; + + sua_assoc_id = 0; + + /* resolving can be done via: */ + /* - local global Titel database */ + /* - resolve hostname via DNS(simplest for single hop translations) */ + dest_carr = dest_name; + + if ((hptr = gethostbyname( dest_carr )) == NULL) + { + cout << "Hostname " << dest_name << " not known in DNS.\n"; + return(-1); + } + +#ifdef DEBUG + cout << "Hostname " << dest_name << " resolved to dest IP address(es)\n"; + cout << "IP address length = "<< hptr->h_length << "\n"; +#endif + + /* initialise the length field of the structure: */ + /* length field is NOT always present in every Unix like operating system */ + dest_pc.ipvx.ch[0] = 0; + org_pc.ipvx.ch[0] = 0; + + pptr = hptr->h_addr_list; + for ( ; (*pptr != NULL) ;pptr++) + { + inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str)); +#ifdef DEBUG + cout << str << "\n"; +#endif + /* got IP address, look if association already exists */ + dest_pc.ipvx.sa.sa_family = hptr->h_addrtype; + if (dest_pc.ipvx.sa.sa_family == AF_INET) + inet_pton( AF_INET, + str, + &dest_pc.ipvx.sin.sin_addr + ); + else if (dest_pc.ipvx.sa.sa_family == AF_INET6) + inet_pton( AF_INET6, + str, + &dest_pc.ipvx.sin6.sin6_addr + ); + else + cout << "ERROR route_on_GTname: Unknown IP addresstype\n"; + + sctp_assoc_id = route_on_IPpc( dest_pc.ipvx, + org_pc.ipvx, + sua_assoc_id + ); + + if (sctp_assoc_id != 0 ) + return(sctp_assoc_id); + + } + + return(sctp_assoc_id); +}; + +/***********************************************************************/ +/* Sua_AssociationList::route_msg */ +/***********************************************************************/ +signed int db_Sua_AssociationList:: +route_msg( sccp_addr_str& cld, + sccp_addr_str& clg + ){ + + unsigned int sctp_assoc_id = 0; + int sua_assoc_id = 0; + +#ifdef DEBUG + cout << "num_of_instance : "<< num_of_instance << "\n"; +#endif + + if ((cld.address_fields_present.pc == ipvx_pc_present) && + (cld.routing_ind == route_on_ssn)) + { + sctp_assoc_id = route_on_IPpc( cld.pc.ipvx, + clg.pc.ipvx, + sua_assoc_id + ); + } + else if ((cld.address_fields_present.name_gt == hostname_present) && + (cld.routing_ind == route_on_name_gt)) + { + sctp_assoc_id = route_on_GTname( cld.name.HostName, + clg.name.HostName, + sua_assoc_id, + cld.pc, + clg.pc + ); + } + else if ((cld.address_fields_present.name_gt == hostname_present) && + (cld.address_fields_present.pc == ipvx_pc_present) && + (cld.routing_ind == route_on_name_gt_next_office)) + { + sctp_assoc_id = route_on_IPpc( cld.pc.ipvx, + clg.pc.ipvx, + sua_assoc_id + ); + } + else if ((cld.address_fields_present.pc == ss7_pc_present) && + (cld.routing_ind == route_on_ssn)) + { + sctp_assoc_id = route_on_SS7pc( cld.pc.ss7, + clg.pc.ss7, + sua_assoc_id + ); + } + else + { + cout << "Unknown routing requested\n"; + } + +#ifdef SUA_MANAGEMENT + /* check if allowed to send msg over the association */ + if ((sua_assoc_id > 0) && + (sua_assoc_id <= num_of_instance) && + (instance[sua_assoc_id].asp.status != asp_active)) + { + sctp_assoc_id = (-sctp_assoc_id); + } +#endif + +#ifdef DEBUG + cout << "route msg towards remote SUA(& SCTP) association " << sctp_assoc_id << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Route msg towards Remote SUA(& SCTP) instance nr %d", sctp_assoc_id ); + event_log("sua_database.c",logstring); + + return(sctp_assoc_id); +}; + + +/***********************************************************************/ +/* Sua_AssociationList::increase_instance */ +/***********************************************************************/ +void db_Sua_AssociationList:: increase_instance(){ + + num_of_instance++; + +} + +/***********************************************************************/ +/* Sua_AssociationList::Dynamic_Associate */ +/***********************************************************************/ +unsigned int db_Sua_AssociationList::Dynamic_Associate( + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + sccp_addr_str& cld, + sccp_addr_str& clg, + unsigned short nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams + ) +{ + short sua_portnumber = SUA_PORT; + + short i = 1, assoc_instance_idx = 1, assoc_source_idx = 0; + bool partial_assoc_found = FALSE; + + while ((i <= num_of_instance) && !(partial_assoc_found)){ + partial_assoc_found = (instance[i].Dest.nr_of_addrs == 0); + if (partial_assoc_found) + assoc_instance_idx = i; + i++; + } + + if (!(partial_assoc_found)) + { + /* all assoc's are complete, allocate a new one */ + num_of_instance++; + assoc_instance_idx = num_of_instance; + + } + + assoc_source_idx = Find_local_sua ( clg); + +#ifdef DEBUG + cout << " assoc source idx = " << assoc_source_idx << ", assoc_instance_idx = " << assoc_instance_idx << "\n"; +#endif + + instance[assoc_instance_idx].Source = instance[assoc_source_idx].Source; + instance[assoc_instance_idx].SCTP_instance_name = instance[assoc_source_idx].SCTP_instance_name; + instance[assoc_instance_idx].local_sua_id = instance[assoc_source_idx].local_sua_id; + instance[assoc_instance_idx].nr_of_inbound_streams = nr_of_input_streams ; + instance[assoc_instance_idx].nr_of_outbound_streams = nr_of_input_streams ; + + /* conversion and fill in the destination address */ + instance[assoc_instance_idx].Dest.nr_of_addrs = 1; + instance[assoc_instance_idx].Dest.addrs[0] = cld.pc.ipvx; + + short k; + const char *ptr; + for(k=0; k < instance[assoc_instance_idx].Dest.nr_of_addrs ; k++) + { + if ( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET ) + ptr = inet_ntop( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + &instance[assoc_instance_idx].Dest.addrs[k].sin.sin_addr, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + SCTP_MAX_IP_LEN + ); + else if ( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family == AF_INET6 ) + ptr = inet_ntop( instance[assoc_instance_idx].Dest.addrs[k].sa.sa_family, + &instance[assoc_instance_idx].Dest.addrs[k].sin6.sin6_addr, + (char *)instance[assoc_instance_idx].Dest.address_string[k], + SCTP_MAX_IP_LEN + ); + else + cout << "Unsupported address family in dynamic associate\n"; + } + + remote_sua.increase_instance(); + + instance[assoc_instance_idx].SCTP_assoc_id = + sctp_associate( instance[assoc_instance_idx].SCTP_instance_name, + instance[assoc_instance_idx].nr_of_outbound_streams, + instance[assoc_instance_idx].Dest.address_string[0], + sua_portnumber, + NULL + ); + instance[assoc_instance_idx].remote_sua_id = remote_sua.num_of_instance; + remote_sua.instance[remote_sua.num_of_instance].ssn.ssn = local_sua.instance[instance[assoc_instance_idx].local_sua_id].ssn.ssn; + + /* a message is queued for this association -> send decision is taken */ + /* on receiving the communicationUp notification of SCTP AND whether */ + /* SUA management is going to be used */ + instance[assoc_instance_idx].asp.status = asp_down_traf_hold; + +#ifdef DEBUG + cout << "Dynamic Associate remote SUA(& SCTP) instance nr " << assoc_instance_idx << " with local SUA(& SCTP) instance nr " << instance[assoc_instance_idx].local_sua_id << " \n"; +#endif + char logstring[100]; + sprintf(logstring, "Dynamic Associate Remote SUA(& SCTP) instance nr %d with local SUA(& SCTP) instance nr %d", assoc_instance_idx, instance[assoc_instance_idx].local_sua_id ); + event_log("sua_datasoc.c",logstring); + + return(assoc_instance_idx); +} + +/***********************************************************************/ +/* Sua_AssociationList::Activate_Association */ +/***********************************************************************/ +bool db_Sua_AssociationList::activate( unsigned int sua_assoc_id, + short mode + ) +{ + return(instance[sua_assoc_id].asp.activate(mode, + sua_assoc_id + )); +} + +/***********************************************************************/ +/* Sua_AssociationList::DeActivate_Association */ +/***********************************************************************/ +void db_Sua_AssociationList::deactivate( unsigned int sua_assoc_id, + short mode + ) +{ + instance[sua_assoc_id].asp.deactivate(mode, + sua_assoc_id + ); +} + +/***********************************************************************/ +/* Sua_AssociationList::Down_Association */ +/***********************************************************************/ +void db_Sua_AssociationList::down( unsigned int sua_assoc_id, + short mode + ) +{ + instance[sua_assoc_id].asp.down(mode, + sua_assoc_id + ); +} + +/***********************************************************************/ +/* Sua_AssociationList::Up_Association */ +/***********************************************************************/ +void db_Sua_AssociationList::up( unsigned int sua_assoc_id, + short mode + ) +{ + instance[sua_assoc_id].asp.up(mode, + sua_assoc_id + ); +} + +// end of module sua_database.c + + + + + + diff --git a/sualibrary/sua/sua_debug.h b/sualibrary/sua/sua_debug.h new file mode 100644 index 0000000..a4e3d83 --- /dev/null +++ b/sualibrary/sua/sua_debug.h @@ -0,0 +1,79 @@ +/*************************************************************************** + sua_debug.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_debug.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * Gery Verwimp + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Michelle + * "The debugger with the cape rides again" + * "He will hunt bugs as long as they do not reside in dark memory lanes" + * + * Purpose: This header-file defines the SUA debugging constants used + * for dumping debug info to the screen, dump debug info to file, + * activate ASP management...etc.... + */ + +#ifndef SUA_DEBUG_H +#define SUA_DEBUG_H + +/*#define DEBUG activates debuging msg on screen */ +/*#define FILE_DEBUG activates debugging info to output file */ +#define SUA_MANAGEMENT /* activates SUA management */ +#define SG_ASP_MODE /* implementation acts as ASP towards a SG */ + + +#endif // SUA_DEBUG_H + +// end of module sua_debug.h + + + + + + + + + + + diff --git a/sualibrary/sua/sua_distribution.cpp b/sualibrary/sua/sua_distribution.cpp new file mode 100644 index 0000000..c588f49 --- /dev/null +++ b/sualibrary/sua/sua_distribution.cpp @@ -0,0 +1,1167 @@ +/*************************************************************************** + sua_distribution.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_distribution.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Pascale + * "We are continously looking for Ghostwriters." + * "When we find one, he will be terminated on the spot. Nobody writes (into) + * "my lifes variables without my permission." + * + * Purpose: This code-file defines the SUA distributor functions for: + * - Data arrive notification(from SCTP) -> receive the msg data + * from SCTP(use receive_sua_primitive function below), process it + * and call the aproriate SUA msg handling function + * - Network status change Notification(from SCTP) + * - Sent Failure Notification(from SCTP) + * - Communication Lost Notification(from SCTP) + * - Communication Up Notification(from SCTP) + * - Communication Error Notification(from SCTP) + * - Restart Notification(from SCTP) + * - Shutdown Notification(from SCTP) + * - Send a SUA primitive -> generate and send the msg to SCTP + * - Receive the sua "primitive"/msg data from SCTP + */ + +#include "sua_debug.h" +#include "sua_database.h" +#include "sua_tcb.h" +#include "sua_logging.h" +#include "sua_syntax.h" +#include "sua_cl.h" +#include "sua_co.h" +#include "sua_distribution.h" + + +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define BUFSIZE 2000 + +// syntax definitions of the sua message +Sua_container msg; + +// storage for received SUA messages +vector rec_msg_pool; + +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; +extern tcb_Sua_TCB_arr tcb_pool; +extern tcb_Sua_msgqueue_pool msg_store; + +/***********************************************************************/ +/* sctp_DataArriveNotif */ +/***********************************************************************/ +void sctp_DataArriveNotif( unsigned int sctp_assoc_id, + unsigned int stream_id, + unsigned int len, + unsigned int protocol_id, + unsigned int unordered_flag, + void * ulp_data_ptr + ) +{ + + unsigned short result; + unsigned int Sua_ConnId; + unsigned int sua_assoc_id; + unsigned int local_sua_id,remote_sua_id; + tcb_Sua_TCB_str *tcb_ptr; + Sua_syntax_error_struct error; + char databuf[BUFSIZE]; + unsigned int flags = SCTP_MSG_DEFAULT; + +#ifdef DEBUG + cout << "Received a Data notification from SCTP for association " << sctp_assoc_id << " : handle and distribute\n"; +#endif + + + + // receive data from SCTP + result = sctp_receive( sctp_assoc_id, + stream_id, + (unsigned char *) databuf, + &len, + flags + ); + + // display byte array +#ifdef DEBUG + display_byte_array(databuf ,len); +#endif + char logstring[100]; + sprintf(logstring, "SUA message, just received from SCTP"); + event_log("sua_distribution.c",logstring); + log_byte_array("sua_distribution.c", databuf,len); + + + // copy received data from databuf to msg object -> byte array + msg.sua_msg.insert(0, databuf, len); + // decode data to figure which SUA message we received + error = msg.sua_decode(); + + if (!error.no_error) + { + char logstring[100]; + sprintf(logstring, "Decoding error in received SUA message : index = %d,", error.msg_index); + event_log("sua_distribution.c",logstring); + char *spare = new char[error.error_text.length()]; + error.error_text.copy(spare, error.error_text.length()); + sprintf(logstring, "Error string = %s,", spare); + event_log("sua_distribution.c",logstring); + cout << "Decoding error in received SUA message : "<< error.error_text << ", index = " << error.msg_index << "\n"; + msg.sua_prim.hdr_msg_class = sua_max; + return; + } + + // distribute the message based on some parameters + // Connectionless or connection-oriented + switch (msg.sua_prim.hdr_msg_class) + { + case (sua_cl): + + // connectionless : strip of header and send to user + switch (msg.sua_prim.hdr_msg_type.cl) + { + case cl_data_transfer /*N_UNITDATA*/: + { +#ifdef DEBUG + cout << "CL: Unitdata message handling\n"; +#endif + unsigned int local_sua_id,remote_sua_id; + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + result = process_unitdata_msg ( local_sua_id, + sua_assoc_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received Unitdata msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case cl_data_response /*N_UNITDATA_SERVICE*/: + { +#ifdef DEBUG + cout << "CL: Unitdata Service message handling\n"; +#endif + char logstring[100]; + sprintf(logstring, "Received Unitdata Service msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown connectionless message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown connectionless message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + case (sua_co): + + // connectionoriented: get SCOC TCB, do state-event handling and send to use + switch (msg.sua_prim.hdr_msg_type.co) + { + case co_core /*N_CONNECT_IND */: + { +#ifdef DEBUG + cout << "CO: Connect indication message handling\n"; +#endif + char logstring[100]; + sprintf(logstring, "Received Connect Indication msg"); + event_log("sua_distribution.c",logstring); + + + unsigned int local_sua_id,remote_sua_id; + + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + tcb_ptr = tcb_pool.allocate_TCB(Sua_ConnId); + + result = process_CORE_msg ( sua_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + break; + } + case co_coak /*connect confirm */: + { +#ifdef DEBUG + cout << "CO: Connection request acknowledge message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Connect Confirm Indication msg"); + event_log("sua_distribution.c",logstring); + + // call connection request acknowledge message handling + result = process_COAK_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + } + case co_data /*data*/: + { +#ifdef DEBUG + cout << "CO: Data message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)/* && + ( tcb_ptr /= NULL)*/) + { + char logstring[100]; + sprintf(logstring, "Received Data Indication msg"); + event_log("sua_distribution.c",logstring); + + // call data message handling function + result = process_CODATA_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + break; + } + case co_relre /*release request*/: + { +#ifdef DEBUG + cout << "CO: Release Request message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Release Request Indication msg"); + event_log("sua_distribution.c",logstring); + + // call release request message handling function + result = process_CORELRQ_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + + break; + } + case co_relco /*release completed */: + { +#ifdef DEBUG + cout << "CO: Release Complete message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Release Confirm Indication msg"); + event_log("sua_distribution.c",logstring); + + // call release complete message handling function + result = process_CORELCO_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + + break; + } + case co_coref /*connection refused */: + { +#ifdef DEBUG + cout << "CO: Connection refused message handling\n"; +#endif + Sua_ConnId = msg.sua_prim.dest_ref; + tcb_ptr = tcb_pool.get_tcb(Sua_ConnId); + if (( msg.sua_prim.dest_ref_pres)) + { + char logstring[100]; + sprintf(logstring, "Received Connect Confirm Indication msg"); + event_log("sua_distribution.c",logstring); + + // call connection request acknowledge message handling + result = process_COREF_msg ( sctp_assoc_id, + tcb_ptr, + Sua_ConnId, + msg + ); + } + else + cout << "ERROR: TCB " << Sua_ConnId << " was not retrieved?!!\n"; + + } + default: + { + char logstring[100]; + sprintf(logstring, "Unknown connectionoriented message type"); + event_log("sua_distribution.c",logstring); + cout << "Unknown connectionoriented message type !!\n"; + break; + } + } + + break; + + case (sua_mngt): + // SUA management msg + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.mngt) + { + case mngt_error : + { +#ifdef DEBUG + cout << "SUA Management: ERROR message handling\n"; +#endif + + + char logstring[100]; + sprintf(logstring, "Received ERROR msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case mngt_notify : + { +#ifdef DEBUG + cout << "SUA Management: NOTIFY message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received NOTIFY msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown SUA managment message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown SUA Management message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + + + case (sua_ssnm): + // Signalling Network Management(SNM) msg + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.ssnm) + { + case ssnm_duna : + { +#ifdef DEBUG + cout << "SNM: Destination unavialable\n"; +#endif + + + char logstring[100]; + sprintf(logstring, "Received DUNA msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_dava : + { +#ifdef DEBUG + cout << "SNM: Destination avialable message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DAVA msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_daud : + { +#ifdef DEBUG + cout << "SNM: Destination state audit message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DAUD msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_scon : + { +#ifdef DEBUG + cout << "SNM: Network congestion message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received SCON msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_dupu : + { +#ifdef DEBUG + cout << "SNM: Destination User Part Unavialable message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DUPU msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case ssnm_drst : + { +#ifdef DEBUG + cout << "SNM: Destination restricted message handling\n"; +#endif + + char logstring[100]; + sprintf(logstring, "Received DRST msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown SUA managment message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown SUA Management message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + case (sua_aspsm): + // ASP State maintenance msg + + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.aspsm) + { + case aspsm_up : + { +#ifdef DEBUG + cout << "ASPSM: ASP_UP message handling\n"; +#endif + result = process_ASPUP_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPUP msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_up_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASP_UP_ACK message handling\n"; +#endif + result = process_ASPUP_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPUP ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_down : + { +#ifdef DEBUG + cout << "ASPSM: ASP_DOWN message handling\n"; +#endif + result = process_ASPDOWN_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPDO msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_down_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASP_DOWN_ACK message handling\n"; +#endif + result = process_ASPDOWN_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPDOWN ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_beat : + { +#ifdef DEBUG + cout << "ASPSM: HEARTBEAT message handling\n"; +#endif + result = process_BEAT_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received HEARTBEAT msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case aspsm_beat_ack : + { +#ifdef DEBUG + cout << "ASPSM: HEARTBEAT_ACK message handling\n"; +#endif + result = process_BEAT_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received HEARTBEAT ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown ASP State Maintenance message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown ASP State Maintenance message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + case (sua_asptm): + // ASP Traffic maintenance msg + + sua_assoc_id = Assoc_sua.Find_association( sctp_assoc_id, + local_sua_id, + remote_sua_id + ); + + switch (msg.sua_prim.hdr_msg_type.asptm) + { + case asptm_act : + { +#ifdef DEBUG + cout << "ASPTM: ASPAC message handling\n"; +#endif + result = process_ASPAC_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPAC msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case asptm_act_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASPAC_ACK message handling\n"; +#endif + result = process_ASPAC_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPAC ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case asptm_inact : + { +#ifdef DEBUG + cout << "ASPTM: ASPINAC message handling\n"; +#endif + result = process_ASPINAC_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPINAC msg"); + event_log("sua_distribution.c",logstring); + + break; + } + case asptm_inact_ack : + { +#ifdef DEBUG + cout << "ASPSM: ASPINAC_ACK message handling\n"; +#endif + result = process_ASPINAC_ACK_msg ( sua_assoc_id, + local_sua_id, + remote_sua_id, + msg + ); + + char logstring[100]; + sprintf(logstring, "Received ASPINAC ACK msg"); + event_log("sua_distribution.c",logstring); + + break; + } + default: + { + cout << "Unknown ASP Traffic Maintenance message type !!\n"; + char logstring[100]; + sprintf(logstring, "Unknown ASP Traffic Maintenance message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + + break; + + default: + { + char logstring[100]; + sprintf(logstring, "Unknown message type"); + event_log("sua_distribution.c",logstring); + break; + } + } + // return +#ifdef DEBUG + cout << "Received message processed\n"; +#endif +} + +/***********************************************************************/ +/* sctp_NetworkStatusChangeNotif */ +/***********************************************************************/ +void sctp_NetworkStatusChangeNotif( unsigned int assoc_id, + short dest_addr_index, + unsigned short new_path_state, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received a Network status change notification from SCTP for association " << assoc_id << "\n"; +#endif +} + +/***********************************************************************/ +/* sctp_SentFailureNotif */ +/***********************************************************************/ +void sctp_SentFailureNotif( unsigned int assoc_id, + unsigned char * unsent_data_sent_ptr, + unsigned int len, + unsigned int * sctp_send_context_ptr, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received a send failure notification from SCTP for association " << assoc_id << " Ignore it, not supported.\n"; +#endif +} + +/***********************************************************************/ +/* sctp_communicationLostNotif */ +/***********************************************************************/ +void sctp_CommunicationLostNotif( unsigned int sctp_assoc_id, + unsigned short status_event, + void * ulp_data_ptr + ) +{ + unsigned int sua_assoc_id,local_sua_id, remote_sua_id; + +#ifdef DEBUG + cout << "Received indication that communication with remote peer was lost for association " << sctp_assoc_id << "\n"; + cout << "Status CommunicationLostNotif = " << status_event << "\n"; +#endif + /* Put in debugging file */ + char logstring[100]; + sprintf(logstring, "CommunicationLostNotif received from SCTP"); + event_log("sua_distribution.c",logstring); + sprintf(logstring,"assoc_id = %d, status = %d ",sctp_assoc_id,status_event); + event_log("sua_distribution.c",logstring); + +#ifdef SUA_MANAGEMENT + if ((sua_assoc_id = Assoc_sua.Find_association(sctp_assoc_id, local_sua_id,remote_sua_id)) != 0) + { + /* if we found the sua assoc then the SUA ASP is marked down, */ + /* as the sctp association has failed */ + Assoc_sua.down(sua_assoc_id, 0); +#ifdef DEBUG + cout << "ASP down for SUA association " << sua_assoc_id << "\n"; +#endif + + } +#endif + +} + +/***********************************************************************/ +/* sctp_CommunicationUpNotif */ +/***********************************************************************/ +void *sctp_CommunicationUpNotif( unsigned int sctp_assoc_id, + unsigned short status_event, + int nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams, + void * ulp_data_ptr + ) +{ + + unsigned int sua_assoc_id,local_sua_id, remote_sua_id; + char logstring[100]; + int result; + tcb_Sua_msg_elem sua_msg; + +#ifdef DEBUG + cout << "Received Communication Up indication for association " << sctp_assoc_id <<"\n"; + cout << "Status CommunicationUpNotif = " << status_event << ", number of addresses used = " << nr_of_dest_addr << "\n"; + cout << "Number of input streams = " << nr_of_input_streams << ", number of output streams = " << nr_of_output_streams << "\n"; +#endif + + /* Put in debugging file */ + sprintf(logstring, "CommunicationUpNotif received from SCTP"); + event_log("sua_distribution.c",logstring); + sprintf(logstring,"assoc_id = %d, status = %d , number of dest addr = %d",sctp_assoc_id,status_event, nr_of_dest_addr); + event_log("sua_distribution.c",logstring); + sprintf(logstring,"Number of input streams = %d, number of output streams = %d", nr_of_input_streams,nr_of_output_streams); + event_log("sua_distribution.c",logstring); + + + + if ((sua_assoc_id = Assoc_sua.Find_association(sctp_assoc_id, local_sua_id,remote_sua_id)) == 0) { +#ifdef DEBUG + cout << "association " << sctp_assoc_id << " is not present\n"; +#endif + sua_assoc_id = Assoc_sua.passive_associate( sctp_assoc_id, + local_sua, + remote_sua, + nr_of_dest_addr, + nr_of_input_streams, + nr_of_output_streams + ); + } + + /* code include if SUA management is NOT used */ +#ifndef SUA_MANAGEMENT + if ( Assoc_sua.instance[sua_assoc_id].status == asp_down_traf_hold) + { + /* - get the saved msg ansd send it on the association that is setup */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + while ( sua_msg.valid) + { + char* databuf = new char[sua_msg.byte.length()]; + sua_msg.byte.copy(databuf, sua_msg.byte.length()); + datalen = sua_msg.byte.length(); + + /* msg retrieved and copied, may now remove it from queue */ + msg_store.delete_msg ( sua_assoc_id ); + +#ifdef DEBUG + display_byte_array(databuf , sua_msg.byte.length()); +#endif + char logstring[100]; + sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", sctp_assoc_id); + event_log("sua_distribution.c",logstring); + log_byte_array("sua_distribution.c", databuf,sua_msg.byte.length()); + + result = sctp_send ( sctp_assoc_id, + sua_msg.stream_id, + (unsigned char *) databuf, + datalen, + SUA_PPI, + SCTP_USE_PRIMARY, + SCTP_NO_CONTEXT, + SCTP_INFINITE_LIFETIME, + sua_msg.delivery_type, + SCTP_BUNDLING_DISABLED + ); + + delete databuf; +#ifdef DEBUG + cout << "sua_distribution.c:result sctp send = "<< result << "\n"; +#endif + /* get the next saved msg ansd send if any ? */ + sua_msg = msg_store.get_msg ( sua_assoc_id ); + + } + /* SUA ASP is marked down */ + Assoc_sua.down(sua_assoc_id,0); + } + +#endif + + /* code include if SUA management IS used */ +#ifdef SUA_MANAGEMENT +#ifdef DEBUG + cout << "sua_distribution.c:should send ASPUP\n"; +#endif + /* send ASP-UP to remote to start activating local & remote ASP */ + result = sua_send_ASPUP( sua_assoc_id + ); +#endif + + return NULL; +} + +/***********************************************************************/ +/* sctp_CommunicationErrorNotif */ +/***********************************************************************/ +void sctp_CommunicationErrorNotif( unsigned int assoc_id, + unsigned short error_status, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received Error indication for association " << assoc_id << " with error status " << error_status << "\n"; + cout << "Aborting association \n"; +#endif + sctp_deleteAssociation(assoc_id); +} + + +/***********************************************************************/ +/* sctp_RestartNotif */ +/***********************************************************************/ +void sctp_RestartNotif( unsigned int sctp_assoc_id, + void * ulp_data_ptr + ) +{ + unsigned int sua_assoc_id,local_sua_id, remote_sua_id; + int result; + +#ifdef DEBUG + cout << "Received Restart indication for association " << sctp_assoc_id << "\n"; +#endif + +#ifdef SUA_MANAGEMENT + if ((sua_assoc_id = Assoc_sua.Find_association(sctp_assoc_id, local_sua_id,remote_sua_id)) == 0) + { +#ifdef DEBUG + cout << "ASP status = " << Assoc_sua.instance[sua_assoc_id].asp.status <<" for SUA association " << sua_assoc_id << "\n"; +#endif + + /* restart association: ASP state should be set to down */ + Assoc_sua.down(sua_assoc_id,0); + + /* if we found the sua assoc then we restart the ASP bringup sequence */ + /* as the sctp association has come back online */ + /* send ASP-UP to remote to start activating local & remote ASP */ + result = sua_send_ASPUP( sua_assoc_id + ); + } +#endif + +} + +/***********************************************************************/ +/* sctp_ShutDownCompleteNotif */ +/***********************************************************************/ +void sctp_ShutDownCompleteNotif( unsigned int assoc_id, + void * ulp_data_ptr + ) +{ +#ifdef DEBUG + cout << "Received shutdown indication for association " << assoc_id << "\n"; +#endif +} + + + +/***********************************************************************/ +/* Send_sua_primitive */ +/***********************************************************************/ +unsigned int Send_sua_primitive( unsigned int primitive, + unsigned int &sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char *buffer, + unsigned int len + ) +{ + int error; + char logstring[100]; + tcb_Sua_TCB_str *tcb_ptr; +#ifdef DEBUG + cout << "Send SUA primitive to local SUA instance\n"; + cout << "ConnId = " << sua_ConnId << "\n"; +#endif + + // search for the required local_ref + if (sua_ConnId != 0) + { + //handle connection oriented primitves which have already a TCB + tcb_ptr = tcb_pool.get_tcb(sua_ConnId); + + switch (primitive) + { + case N_CONNECT_RESP: + //send back response on received CORE of connection + sprintf(logstring, "CO N-CONNECT RESPONSE primitive req"); + event_log("sua_distribution.c",logstring); + + error = sua_send_CORESP( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_DATA_REQ: + //send data on existing connection + sprintf(logstring, "CO N-DATA REQ primitive req"); + event_log("sua_distribution.c",logstring); + error = sua_send_CODATA( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_RELEASE_REQ: + //Disconnect request on existing connection + sprintf(logstring, "CO N-RELEASE REQ primitive req"); + event_log("sua_distribution.c",logstring); + error = sua_send_CORELRQ( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_RELEASE_CONF: + //Disconnect confirm request on existing connection + sprintf(logstring, "CO N-RELEASE CONFIRM primitive req"); + event_log("sua_distribution.c",logstring); + error = sua_send_CORELCO( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + case N_CONNECT_REFUSED: + //send a connect refused on connection + sprintf(logstring, "CO N-CONNECT REFUSED primitive req"); + event_log("sua_distribution.c",logstring); + + error = sua_send_COREF( QOS, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + + break; + default: + sua_ConnId = 0; + error = 1; + break; + } + } + else + { + //handle connectionless primitives + //handle connection oriented primitives for which no TCB was yet alllocated + // figured out connectionless/connection-oriented primitived + switch (primitive) + { + case N_UNITDATA: + sprintf(logstring, "Unitdata primitive req"); + event_log("sua_distribution.c",logstring); + sua_ConnId = 0; + error = sua_send_Unitdata(QOS, + called_pty_address, + calling_pty_address, + buffer, + len + ); + break; + case N_CONNECT_REQ: + sprintf(logstring, "CO N-CONNECT REQ primitive req"); + event_log("sua_distribution.c",logstring); + + tcb_ptr = tcb_pool.allocate_TCB(sua_ConnId); + + error = sua_send_CORE( QOS, + called_pty_address, + calling_pty_address, + buffer, + len, + sua_ConnId, + tcb_ptr + ); + break; + default: + sua_ConnId = 0; + error = 1; + break; + } + } + + return(error); + +} + +/***********************************************************************/ +/* receive_sua_primitive */ +/***********************************************************************/ +unsigned int Receive_sua_primitive( unsigned int &primitive, + unsigned int &Sua_ConnId, + sccp_QOS_str &QOS, + sccp_addr_str &called_pty_address, + sccp_addr_str &calling_pty_address, + char* buffer, + unsigned int len + ) +{ + + + // retrieve the stored user data from the received msg list + sua_save_str temp=rec_msg_pool.front(); + // delete the user data in the received msg list + rec_msg_pool.erase(rec_msg_pool.begin()); + + // primitive and address parameters + primitive = temp.primitive; + Sua_ConnId = temp.user_ref; + QOS = temp.QOS; + called_pty_address = temp.called_pty_address; + calling_pty_address = temp.calling_pty_address; + // put in supplied byte array(space is allocated beforehand by application) + temp.userdata.copy(buffer, temp.userdata.length()); + len = temp.userdata.length(); + + return(len); +} + +// end of module sua_distribution.c diff --git a/sualibrary/sua/sua_distribution.h b/sualibrary/sua/sua_distribution.h new file mode 100644 index 0000000..f384f29 --- /dev/null +++ b/sualibrary/sua/sua_distribution.h @@ -0,0 +1,170 @@ +/*************************************************************************** + sua_distribution.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_distribution.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Dorine + * "When B.B. releases one of his pearls of wisedom and " + * "starts one of his walks around the block, then this designer says:" + * "I am getting tired of running in circles even if it is " + * "a nice block in a nice neighbourhood(maybe his walks are recursive)" + * + * Purpose: This header-file defines the SUA distributor functions for: + * - Data arrive notification(from SCTP) -> receive the msg data + * from SCTP(use receive_sua_primitive function below), process it + * and call the aproriate SUA msg handling function + * - Network status change Notification(from SCTP) + * - Sent Failure Notification(from SCTP) + * - Communication Lost Notification(from SCTP) + * - Communication Up Notification(from SCTP) + * - Communication Error Notification(from SCTP) + * - Restart Notification(from SCTP) + * - Shutdown Notification(from SCTP) + * - Send a SUA primitive -> generate and send the msg to SCTP + * - Receive the sua "primitive"/msg data from SCTP + */ + + +#ifndef SUA_DISTRIBUTION_H +#define SUA_DISTRIBUTION_H + + +#include "sua.h" +#include + + +using namespace std; + +typedef struct { + unsigned int primitive; + unsigned int user_ref; + sccp_QOS_str QOS; + sccp_addr_str called_pty_address; + sccp_addr_str calling_pty_address; + string userdata; +} sua_save_str; + +/***********************************************************************/ +/* sctp_DataArriveNotif */ +/***********************************************************************/ +void sctp_DataArriveNotif( unsigned int assoc_id, + unsigned int stream_id, + unsigned int len, + unsigned int protocol_id, + unsigned int unordered_flag, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_NetworkStatusChangeNotif */ +/***********************************************************************/ +void sctp_NetworkStatusChangeNotif( unsigned int assoc_id, + short dest_addr_index, + unsigned short new_path_state, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_SentFailureNotif */ +/***********************************************************************/ +void sctp_SentFailureNotif( unsigned int assoc_id, + unsigned char * unsent_data_sent_ptr, + unsigned int len, + unsigned int * sctp_send_context_ptr, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_communicationLostNotif */ +/***********************************************************************/ +void sctp_CommunicationLostNotif( unsigned int assoc_id, + unsigned short status_event, + void * ulp_data_ptr + ); + +/***********************************************************************/ +/* sctp_CommunicationUpNotif */ +/***********************************************************************/ +void* sctp_CommunicationUpNotif( unsigned int assoc_id, + unsigned short status_event, + int nr_of_dest_addr, + unsigned short nr_of_input_streams, + unsigned short nr_of_output_streams, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_CommunicationErrorNotif */ +/***********************************************************************/ +void sctp_CommunicationErrorNotif( unsigned int assoc_id, + unsigned short error_status, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_RestartNotif */ +/***********************************************************************/ +void sctp_RestartNotif( unsigned int assoc_id, + void * ulp_data_ptr + ); + + +/***********************************************************************/ +/* sctp_ShutDownCompleteNotif */ +/***********************************************************************/ +void sctp_ShutDownCompleteNotif( unsigned int assoc_id, + void * ulp_data_ptr + ); + +#endif // SUA_DISTRIBUTION_H + +// end of module sua_distribution.h + + diff --git a/sualibrary/sua/sua_file.cpp b/sualibrary/sua/sua_file.cpp new file mode 100644 index 0000000..c5ad667 --- /dev/null +++ b/sualibrary/sua/sua_file.cpp @@ -0,0 +1,401 @@ +/*************************************************************************** + sua_file.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_file.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Martine + * "This is the module of the fallen function with the big files by + * "Von Craenendonck!" + * "This module contains some real schoftware" + * + * Purpose: This code-file defines the SUA file access functions for: + * - get a argument in the line(delimited by a space) + * - read the sua file(containing arguments for the SUA database) + */ + + +#ifdef LINUX + #include +#endif + +#include "sua_debug.h" +#include "sua_database.h" + +#include +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include + +#define SUA_PORT 14001 +#define SUA_PPI 4 + +using namespace std; + + +string get_argument(string line, + int& begin, + int& end, + unsigned int& num_of_char_in_line) +{ + int len = 0; + bool cont = true; + while ((num_of_char_in_line <= line.length()) && (cont)) + { + + if ((line[num_of_char_in_line] == ' ') || + (num_of_char_in_line >= line.length())) + { + end = num_of_char_in_line - 1; + len = num_of_char_in_line - begin; + cont = false; + } + num_of_char_in_line++; + + } + + char *temp = new char[len]; + + // convert to lowercase characters for easier processing + int i=0; + for(i = 0; i < len ; i++) + temp[i] = tolower(line[begin+i]); + string sua_arg(temp, len); + +#ifdef DEBUGFILE + cout << "indexes = "<< begin << " , " << end << " , " << len << "\n"; + cout << temp << "\n"; + cout << "got argument = " << sua_arg << " \n"; + char v; + cin >> v; +#endif + + begin = end + 2; + end = 0; + delete temp; + + return(sua_arg); +} + + +int read_sua_file(string filename, + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + db_Sua_AssociationList& Assoc_sua, + db_Sua_NameList& NameDB_sua, + db_Sua_ASList& ApplicServ_sua + ) +{ + string sua_filename; + string sua_arg; + string address_str,ip_addr_str; + char ch1, ch2; + string sua_line; + int num_of_char = 0; + int num_of_arg = 0; + int num_of_lines = 0; + int present_local_instance = 0; + int present_remote_instance = 0; + +#ifdef DEBUG + cout << "file to read = " << filename << " \n"; +#endif + cout << "SUA local sua instantation parameters(mandatory) \n"; + cout << "-s x.x.x.x -l yyy [-u] \n"; + cout << "-s : source address \n"; + cout << "-l : source local sua portnumber \n"; + cout << "-u : listen on local port number \n"; + cout << "SUA parameters of the sua tester (optional)\n"; + cout << "Not supported yet (-b 1000 -o -v) \n"; + cout << "SUA parameters of the SUA remote instantation(s) (optional)\n"; + cout << "-d x.x.x.x -r yyy [-g tt-nat-np-digits] [-a ASnumber] \n"; + cout << "-d : destination address \n"; + cout << "-r : destination sua portnumber \n"; + cout << "-g : global title(TTID-NAT-NUMPLAN-Digits) linked to destination address \n"; + cout << "-a : Application Server(AS) this address belongs to \n"; + + ifstream infile(filename.c_str()); + while (getline(infile, sua_line)) + { + num_of_lines++; + // analyse input line and split up in arguments according to + // the spaces in the line: each argument is then processed + unsigned int num_of_char_in_line = 0; + int b=0, e=0; + bool next_arg; + + sua_arg = get_argument(sua_line,b,e,num_of_char_in_line); + next_arg = false; + + // make selection on cmd argument + while (num_of_char_in_line < sua_line.length()) + { + ch2 = ' '; + if (sua_arg[0] == '-') + { + ch1 = sua_arg[1]; + ch2 = sua_arg[2]; + } + else if (sua_arg[0] == '/') + ch1 = sua_arg[0]; + else + { + cout << "weird option \n"; + ch1 = ' '; + } + + switch (ch1) + { + case 's': // read source addresses for sua + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + if (present_local_instance > 0) { + present_local_instance= 0; + } + local_sua.increase_instance(); + Assoc_sua.increase_instance(); + present_remote_instance = 0; + Assoc_sua.instance[Assoc_sua.num_of_instance].local_sua_id = local_sua.num_of_instance; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_inbound_streams = 1; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_outbound_streams = 1; + + if (ch2 == 'n') { + ip_addr_str = NameDB_sua.read_host_name(address_str); + Assoc_sua.read_Source_addr(ip_addr_str); + } + else { + Assoc_sua.read_Source_addr(address_str); + } + + present_local_instance++; + break; + } + case 'd': + { // read destination addresses for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + remote_sua.increase_instance(); + if (present_remote_instance > 0) { + Assoc_sua.increase_instance(); + Assoc_sua.instance[Assoc_sua.num_of_instance].Source = + Assoc_sua.instance[Assoc_sua.num_of_instance-1].Source; + Assoc_sua.instance[Assoc_sua.num_of_instance].local_sua_id = + Assoc_sua.instance[Assoc_sua.num_of_instance-1].local_sua_id; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_inbound_streams = 1; + Assoc_sua.instance[Assoc_sua.num_of_instance].nr_of_outbound_streams = 1; + present_remote_instance = 0; + } + if (ch2 == 'n') { + ip_addr_str = NameDB_sua.read_host_name(address_str); + Assoc_sua.read_Dest_addr(ip_addr_str); + } + else { + Assoc_sua.read_Dest_addr(address_str); + } + Assoc_sua.instance[Assoc_sua.num_of_instance].remote_sua_id = remote_sua.num_of_instance; + + present_remote_instance++; + + break; + } + case 'l': + { // read local portnumber for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + Assoc_sua.read_Source_port(address_str); + + break; + } + case 'r': + { // read remote portnumber for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + Assoc_sua.read_Dest_port(address_str); + + break; + } + case 'a': + { // read Application Server number this remote ASP belongs to + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + Assoc_sua.instance[Assoc_sua.num_of_instance].asp.linked_to_AS[0] = ApplicServ_sua.read_AS(address_str, Assoc_sua.num_of_instance ); + + break; + } + case 'b': + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); +#ifdef DEBUG + cout << "discard option b \n"; +#endif + + + } + case 'n': + { // read sybsytem number = SSN (valid for both local and remote) + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + remote_sua.read_ssn(address_str); + local_sua.read_ssn(address_str); + + break; + } + case 'q': // read QOS fields for sua + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + + break; + } + case 'u': + { // + break; + } + case 'm': + { // + break; + } + case 'o': + { // + break; + } + case 't': + { // number of streams incoming AND outgoing + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + Assoc_sua.read_stream_number(address_str); + break; + } + case 'v': + { // + break; + } + case 'f': + { // file option: we are in file mode could later be used for + // recursive filereading. Ignore for the moment + num_of_arg++; + break; + } + case 'i': + { + // ignore character, is not a error, go to next argument + break; + } + case '7': + { /* read SS7 pointcodes */ + switch (ch2) + { + case 's': // read source pointcode for sua + { + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + Assoc_sua.read_Source_pointcode(address_str); + + break; + } + case 'd': + { // read destination pointcode for sua + num_of_arg++; + address_str = get_argument(sua_line,b,e,num_of_char_in_line); + + Assoc_sua.read_Dest_pointcode(address_str); + + break; + } + default: + { + break; + } + } + break; + } + case '/': + { + // comment: skip this line + num_of_char_in_line = num_of_char_in_line + sua_line.length(); + b=0; + e=0; + break; + } + default: + { + break; + } + } + sua_arg = get_argument(sua_line,b,e,num_of_char_in_line); + num_of_arg++; + } + // finished reading the whole line + num_of_char = num_of_char + num_of_char_in_line; + cout << "Line " << num_of_lines << " : " << sua_line << "\n"; + } + +#ifdef DEBUG + cout << "End of file: statistics \n"; + cout << "Number of lines = " << num_of_lines <<"\n"; + cout << "Number of characters in file = " << num_of_char << "\n"; + +#endif + + return (0); + +} /* end of read_sua_file */ + + +// end of module sua_file.c + + + diff --git a/sualibrary/sua/sua_file.h b/sualibrary/sua/sua_file.h new file mode 100644 index 0000000..df7c3d5 --- /dev/null +++ b/sualibrary/sua/sua_file.h @@ -0,0 +1,74 @@ +/*************************************************************************** + sua_file.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_file.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Annemie + * "" + * + * Purpose: This header-file defines the SUA file access functions for: + * - get a argument in the line(delimited by a space) + * - read the sua file(containing arguments for the SUA database) + */ + +#ifndef SUA_FILE_H +#define SUA_FILE_H + + +#include + +using namespace std; + +int read_sua_file(string filename, + db_Sua_LocalList& local_sua, + db_Sua_RemoteList& remote_sua, + db_Sua_AssociationList& Assoc_sua, + db_Sua_NameList& NameDB_sua, + db_Sua_ASList& ApplicServ_sua + ); + +#endif // SUA_FILE_H + +// end of module sua_file.h diff --git a/sualibrary/sua/sua_logging.cpp b/sualibrary/sua/sua_logging.cpp new file mode 100644 index 0000000..8bc9757 --- /dev/null +++ b/sualibrary/sua/sua_logging.cpp @@ -0,0 +1,268 @@ +/*************************************************************************** + sua_logging.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_logging.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Cindy + * "KISS (ME * ) methodology applies" + * " * The extended KISS method only applies to beautifull girls." + * + * Purpose: This code-file defines the SUA logging(error or normal stuff) + * functions for: + * - initialise the logging file + * - log events to logging file + * - log byte arrya to logging file + * - Display byte array to screen + * - close logging file + */ + + +#include "sua_debug.h" +#include "sua.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + + +#define MAX_BYTES_IN_LINE 20 + +ofstream logfile; +char log_filename[100]; + +typedef enum { min = -127, + max = 128 +} sua_byte_str; + +/***********************************************************************/ +/* init_logging_file */ +/***********************************************************************/ +void init_logging_file() +{ + struct timeval tv; + struct timezone tz; + struct tm *the_time; + // random temporary logfile + //sprintf(log_filename, "./tmp%d.log",(int)getpid()); + sprintf(log_filename, "./tmp2603.log"); + cout << "Logging all errors and events to file " << log_filename <<"\n"; + // creation of random logfile: overwrite file if already exists + logfile.open(log_filename); + if (!logfile) + { + cout << "Logging file " << log_filename << " could not be created\n"; + exit(0); + } + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> Logfile " << log_filename << " created \n" << flush; + +} + + + +/* This function logs events. + Parameters: + @param event_log_level : INTERNAL_EVENT_0 INTERNAL_EVENT_1 EXTERNAL_EVENT_X EXTERNAL_EVENT + @param module_name : the name of the module that received the event. + @param log_info : the info that is printed with the modulename. + @param anyno : optional pointer to unsigned int, which is printed along with log_info. + The conversion specification must be contained in log_info. + @author Hölzlwimmer +*/ + +/***********************************************************************/ +/* event_log */ +/***********************************************************************/ +void event_log( char *module_name, char *log_info, ...) +{ + +#ifdef FILE_DEBUG + struct timeval tv; + struct timezone tz; + struct tm *the_time; + + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> " << module_name << " >> " << log_info << " \n" << flush; +#endif + + return; +} + +/***********************************************************************/ +/* event_log_byte_array */ +/***********************************************************************/ +void log_byte_array( char *module_name, char *log_info, int len) +{ +#ifdef FILE_DEBUG + int i,space; + int li; + int lines; + int index; + struct timeval tv; + struct timezone tz; + struct tm *the_time; + + + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> " << module_name << " >> " ; + logfile << "Display byte array(in Hex), length " << len << "(hex " << hex << len << ")\n"; + + lines = (len / MAX_BYTES_IN_LINE) + 1; + li = 0; + index = 0; + logfile.setf(ios::hex); + while ( li < lines){ + i = 0; + space = 0; + while (( i < MAX_BYTES_IN_LINE) && (index < len)) { + /* what is needed to display a single byte in hex */ + /* convert the char element to a unsigned character : weird??? */ + /* then convert the unsigned char to a unsigned short */ + /* do the display of the unsigned short */ + unsigned char usc = (log_info[index]); + unsigned short c = usc; + logfile << hex << setfill('0') << setw(2) << c; + space++; + if (space >= 4) { + logfile << " "; + space = 0; + } + index++; + i++; + } + logfile << "\n"; + li++; + } + logfile.setf(ios::dec); + logfile << flush; +#endif + + return; +} + + +/***********************************************************************/ +/* display_byte_array */ +/***********************************************************************/ +void display_byte_array( char *log_info, int len) +{ + int i,li, lines,index, space; + + lines = (len / MAX_BYTES_IN_LINE) + 1; + li = 0; + index = 0; + + + //cout << "lines = " << lines << " , len = " << len << "\n"; + cout.setf(ios::hex); + while ( li < lines){ + i = 0; + space = 0; + while (( i < MAX_BYTES_IN_LINE) && (index < len)) { + /* what is needed to display a single byte in hex */ + /* convert the char element to a unsigned character : weird??? */ + /* then convert the unsigned char to a unsigned short */ + /* do the display of the unsigned short */ + unsigned char usc = (log_info[index]); + unsigned short c = usc; + cout << hex << setfill('0') << setw(2) << c; + space++; + if (space >= 4) { + cout << " "; + space = 0; + } + index++; + i++; + } + cout << "\n"; + // cout << dec << "i = " << i << " , li = " << li << " , index = " << index << "\n"; + li++; + } + cout.setf(ios::dec); + cout << "SUA message size = " << len << "\n"; + +} + + +/***********************************************************************/ +/* close_logging_file */ +/***********************************************************************/ +void close_logging_file() +{ + struct timeval tv; + struct timezone tz; + struct tm *the_time; + + gettimeofday(&tv, &tz); + the_time = localtime((time_t *) & (tv.tv_sec)); + logfile << the_time->tm_hour << ":" << the_time->tm_min << ":" << the_time->tm_sec << ":" << (int) (tv.tv_usec / 1000) << " >> Logfile " << log_filename << " closed \n" << flush; + + // closing of random logfile + logfile.close(); + +} + + + + + + + + diff --git a/sualibrary/sua/sua_logging.h b/sualibrary/sua/sua_logging.h new file mode 100644 index 0000000..850be1e --- /dev/null +++ b/sualibrary/sua/sua_logging.h @@ -0,0 +1,72 @@ +/*************************************************************************** + sua_logging.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_logging.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Annick + * "" + * + * Purpose: This header-file defines the SUA logging(error or normal stuff) + * functions for: + * - initialise the logging file + * - log events to logging file + * - log byte arrya to logging file + * - Display byte array to screen + * - close logging file + */ + +#ifndef SUA_LOGGING_H +#define SUA_LOGGING_H + +void init_logging_file(); +void event_log( char *module_name, char *log_info, ...); +void log_byte_array( char *module_name, char *log_info, int len); +void display_byte_array( char *log_info, int len); +void close_logging_file(); + +#endif // SUA_LOGGING_H + + + diff --git a/sualibrary/sua/sua_sual.cpp b/sualibrary/sua/sua_sual.cpp new file mode 100644 index 0000000..1b23cc0 --- /dev/null +++ b/sualibrary/sua/sua_sual.cpp @@ -0,0 +1,686 @@ +/*************************************************************************** + sua_sual.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_sual.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Patricia + * "a straight line version of SUA, really " + * "without the handpainted perrywinkels according to Hyacinth Bucket" + * + * Purpose: This code-file defines the SUA light interface: + * - SUAL Callback function + * and SUA light functions for: + * - SUAL initialisation + * - SUAL Connectionless data Notification + * - SUAL CO Connect Notification + * - SUAL CO Connect Confirm Notification + * - SUAL CO Data Notification + * - SUAL CO DisConnect Notification + * - SUAL Register Instance + * - SUAL Connectionless Data Request to SUA + * - SUAL CO Connect Request to SUA + * - SUAL CO Connect Confirm Request to SUA + * - SUAL CO Data Request to SUA + * - SUAL CO DisConnect Request to SUA + * - SUAL CO Data read from SUA + * - SUAL Connectionless Data read from SUA + */ + +#include "sua_sual.h" +#include "sua_database.h" +#include "sua_file.h" +#include "sua_distribution.h" +#include "sua_logging.h" + +#ifdef LINUX + #include +#endif + + +#include +#include +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include + +#define MAX_DATA_LENGTH 2000 + +using namespace std; +/* definition of SUA local object and of remote object */ +extern db_Sua_LocalList local_sua; +extern db_Sua_RemoteList remote_sua; +extern db_Sua_AssociationList Assoc_sua; + +typedef struct { + unsigned int local_sua_id; + unsigned int user_ref; + string userdata; +} sual_save_str; + +vector sual_rec_msg; + +SUAL_ULP_CallBacks sual_callback; + +/***********************************************************************/ +/* SUA light clone interface functions and structs with SUA */ +/***********************************************************************/ +/***********************************************************************/ +/* sual_init */ +/***********************************************************************/ + +int sual_init(unsigned char *pConfFile) +{ + + cout << "Initialising SUA datastructures\n "; + init_logging_file(); + local_sua.initialize(); + remote_sua.initialize(); + Assoc_sua.initialize(); + cout << "Finished initialising SUAL data\n "; + return (0); +} /* end of sua_initialisation */ + +/***********************************************************************/ +/* SUAL_ClDataIndNotif */ +/***********************************************************************/ +void SUAL_ClDataIndNotif ( unsigned int local_sua_id, + unsigned int primitive, + unsigned int datalen + ) +{ + unsigned int ControlNumber; + unsigned int length = 0; + sual_PeerAddr PeerAddr; + sual_PeerAddr *pPeerAddr; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + // fill in the source address (=local sua address/CLG) + switch (clg.routing_ind) + { + case (route_on_ssn): + + if (clg.address_fields_present.pc == ipvx_pc_present) + { + if (clg.pc.ipvx.sa.sa_family == AF_INET) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV4; + PeerAddr.uPeerAddr.ip4 = clg.pc.ipvx.sin.sin_addr; + } + else if (clg.pc.ipvx.sa.sa_family == AF_INET6) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV6; + PeerAddr.uPeerAddr.ip6 = clg.pc.ipvx.sin6.sin6_addr; + } + else + cout << "error filling in CLG IP address \n"; + } + else + cout << "unsupported CLG address option\n"; + + break; + default: + cout << "Invalid CLG address option\n"; + break; + } + + ControlNumber = QOS.sequence_number; + pPeerAddr = &PeerAddr; + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.ClDataIndNotif ( local_sua_id, + ControlNumber, + pPeerAddr, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_ConnIndNotif */ +/***********************************************************************/ +void SUAL_ConnIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + sual_PeerAddr PeerAddr; + sual_PeerAddr *pPeerAddr; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + // fill in the source address (=local sua address/CLG) + switch (clg.routing_ind) + { + case (route_on_ssn): + + if (clg.address_fields_present.pc == ipvx_pc_present) + { + if (clg.pc.ipvx.sa.sa_family == AF_INET) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV4; + PeerAddr.uPeerAddr.ip4 = clg.pc.ipvx.sin.sin_addr; + } + else if (clg.pc.ipvx.sa.sa_family == AF_INET6) + { + PeerAddr.AddrType = SUAL_ADDRTYPE_IPV6; + PeerAddr.uPeerAddr.ip6 = clg.pc.ipvx.sin6.sin6_addr; + } + else + cout << "error filling in CLG IP address \n"; + } + else + cout << "unsupported CLG address option\n"; + + break; + default: + cout << "Invalid CLG address option\n"; + break; + } + + pPeerAddr = &PeerAddr; + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.ConnIndNotif ( Sua_ConnId, + pPeerAddr, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_ConnConfIndNotif */ +/***********************************************************************/ +void SUAL_ConnConfIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.ConnConfNotif ( Sua_ConnId, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_CoDataIndNotif */ +/***********************************************************************/ +void SUAL_CoDataIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.CoDataIndNotif ( Sua_ConnId, + datalen + ); + + +} + +/***********************************************************************/ +/* SUAL_DisConnIndNotif */ +/***********************************************************************/ +void SUAL_DisConnIndNotif ( unsigned int local_sua_id, + unsigned int local_sua_ref, + unsigned int reason, + unsigned int datalen + ) +{ + unsigned int primitive; + unsigned int length = 0; + unsigned int Sua_ConnId = 0; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + sual_save_str temp; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + + temp.user_ref = Sua_ConnId; + temp.local_sua_id = local_sua_id; + // copy character array to temp string + temp.userdata.insert(0,databuffer,length); + + sual_rec_msg.push_back(temp); + + sual_callback.DisconnIndNotif ( Sua_ConnId, + reason, + datalen + ); + + +} + +/***********************************************************************/ +/* sual_RegisterSUAL_instance */ +/***********************************************************************/ +extern sual_InstId_t sual_RegisterSUAL_instance ( sual_port_t local_ssn, + SUAL_ULP_CallBacks *callback + ) +{ + Sua_ULP_CallBacks ULP_CallbackFunctions; + int res; + + sual_callback.ClDataIndNotif = callback->ClDataIndNotif; + sual_callback.ConnIndNotif = callback->ConnIndNotif; + sual_callback.ConnConfNotif = callback->ConnConfNotif; + sual_callback.CoDataIndNotif = callback->CoDataIndNotif; + sual_callback.DisconnIndNotif = callback->DisconnIndNotif; + + + ULP_CallbackFunctions.ulp_ClDataIndNotif = &SUAL_ClDataIndNotif; + ULP_CallbackFunctions.ulp_ConnIndNotif = &SUAL_ConnIndNotif; + ULP_CallbackFunctions.ulp_ConnConfIndNotif = &SUAL_ConnConfIndNotif; + ULP_CallbackFunctions.ulp_ConnDataIndNotif = &SUAL_CoDataIndNotif; + ULP_CallbackFunctions.ulp_DisConnIndNotif = &SUAL_DisConnIndNotif; + + // register all the local SUA together with their SCTP instances + res = sua_registerInstance( local_ssn, + ULP_CallbackFunctions + ); + + return(0); +} + +/***********************************************************************/ +/* sual_ClDataReq : send Connectionless UnitData request to SUAL/SUA */ +/***********************************************************************/ +int sual_ClDataReq( sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + uint ControlNumber, + unsigned char *pUserData, + uint UserDataLen + ) +{ + + unsigned int Sua_ConnId = 0; + sccp_addr_str cl_clg, cl_cld; + sccp_QOS_str cl_QOS; + unsigned int xsxx; + + cl_QOS.prot_class = class0; + cl_QOS.in_sequence = false; + cl_QOS.sequence_number = ControlNumber; + cl_QOS.return_msg_on_error = 0; + cl_QOS.importance = 0; + + /* indicate to SUA to get own(=source) address from the sua database */ + cl_clg.address_fields_present.pc = no_pc_present; + cl_clg.address_fields_present.name_gt = no_name_present; + cl_clg.address_fields_present.ssn_port = no_sap_present; + cl_clg.address_fields_present.field_in_header = include_nothing; + + /* convert destination address (only pointcodes supported) */ + cl_cld.address_fields_present.pc = ipvx_pc_present; + cl_cld.address_fields_present.name_gt = no_name_present; + cl_cld.address_fields_present.ssn_port = no_sap_present; + cl_cld.address_fields_present.field_in_header = include_nothing; + cl_cld.routing_ind = route_on_ssn; + + if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV4) + { + cl_cld.pc.ipvx.sa.sa_family = AF_INET; + cl_cld.pc.ipvx.sin.sin_addr = pPeerAddr->uPeerAddr.ip4; + cl_cld.pc.ipvx.sin.sin_port = SUAL_DEF_PORTNUMBER; + } + else if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV6) + { + cl_cld.pc.ipvx.sa.sa_family = AF_INET6; + cl_cld.pc.ipvx.sin6.sin6_addr = pPeerAddr->uPeerAddr.ip6; + cl_cld.pc.ipvx.sin6.sin6_port = SUAL_DEF_PORTNUMBER; + } + else + { + cout << "Invalid Destination address option\n"; + } + + char *databuffer = (char *) pUserData; + + xsxx = Send_sua_primitive(N_UNITDATA, + Sua_ConnId, + cl_QOS, + cl_cld, + cl_clg, + databuffer, + UserDataLen + ); + return(xsxx); +} + +/***********************************************************************/ +/* sual_ConnReq : send connect request to SUAL/SUA */ +/***********************************************************************/ +sual_id_t sual_ConnReq( sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + unsigned char *pUserData, + uint UserDataLen + ) +{ + + unsigned int Sua_ConnId = 0; + sccp_addr_str clg, cld; + sccp_QOS_str QOS; + unsigned int xsxx; + + QOS.prot_class = class2; + QOS.in_sequence = false; + QOS.sequence_number = 0; + QOS.return_msg_on_error = 0; + QOS.importance = 0; + + /* indicate to SUA to get own(=source) address from the sua database */ + clg.address_fields_present.pc = no_pc_present; + clg.address_fields_present.name_gt = no_name_present; + clg.address_fields_present.ssn_port = no_sap_present; + clg.address_fields_present.field_in_header = include_nothing; + + /* convert destination address (only pointcodes supported) */ + cld.address_fields_present.pc = ipvx_pc_present; + cld.address_fields_present.name_gt = no_name_present; + cld.address_fields_present.ssn_port = no_sap_present; + cld.address_fields_present.field_in_header = include_nothing; + cld.routing_ind = route_on_ssn; + + if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV4) + { + cld.pc.ipvx.sa.sa_family = AF_INET; + cld.pc.ipvx.sin.sin_addr = pPeerAddr->uPeerAddr.ip4; + cld.pc.ipvx.sin.sin_port = SUAL_DEF_PORTNUMBER; + } + else if (pPeerAddr->AddrType == SUAL_ADDRTYPE_IPV6) + { + cld.pc.ipvx.sa.sa_family = AF_INET6; + cld.pc.ipvx.sin6.sin6_addr = pPeerAddr->uPeerAddr.ip6; + cld.pc.ipvx.sin6.sin6_port = SUAL_DEF_PORTNUMBER; + } + else + { + cout << "Invalid Destination address option\n"; + } + + char *databuffer = (char *) pUserData; + + xsxx = Send_sua_primitive(N_UNITDATA, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + UserDataLen + ); + return(xsxx); + +} + +/***********************************************************************/ +/* sual_ConnResp : send connect response to SUAL/SUA */ +/***********************************************************************/ +int sual_ConnResp( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen + ) +{ + return(0); +} + +/***********************************************************************/ +/* sual_CoDataReq : send Connection-oriented Data request to SUAL/SUA */ +/***********************************************************************/ +int sual_CoDataReq( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen + ) +{ + + unsigned int Sua_ConnId = sual_ConnId; + sccp_addr_str clg, cld; + sccp_QOS_str QOS; + unsigned int xsxx; + + QOS.prot_class = class2; + QOS.in_sequence = false; + QOS.sequence_number = 0; + QOS.return_msg_on_error = 0; + QOS.importance = 0; + + /* no source address needed */ + clg.address_fields_present.pc = no_pc_present; + clg.address_fields_present.name_gt = no_name_present; + clg.address_fields_present.ssn_port = no_sap_present; + clg.address_fields_present.field_in_header = include_nothing; + + /* no destinationaddres needed */ + cld.address_fields_present.pc = no_pc_present; + cld.address_fields_present.name_gt = no_name_present; + cld.address_fields_present.ssn_port = no_sap_present; + cld.address_fields_present.field_in_header = include_nothing; + + char *databuffer = (char *) pUserData; + + xsxx = Send_sua_primitive(N_DATA_REQ, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + UserDataLen + ); + return(xsxx); +} + + +/***********************************************************************/ +/* sual_DisconnReq : send Disconnect request to SUAL/SUA */ +/***********************************************************************/ +int sual_DisconnReq( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen + ) +{ + return(0); +} + +/***********************************************************************/ +/* sual_CoDataRead : read Connection-oriented Data from SUA/SUAL */ +/***********************************************************************/ +int sual_CoDataRead( sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pBuff, + uint BuffLen + ) +{ + sual_save_str temp = sual_rec_msg.front(); + sual_rec_msg.erase( sual_rec_msg.begin()); + + sual_ConnId = temp.user_ref; + InstId = temp.local_sua_id; + // put in supplied byte array(space is allocated beforehand by application) + temp.userdata.copy((char *)pBuff, temp.userdata.length(),0); + BuffLen = temp.userdata.length(); + return(SUAL_OK); +} + +/***********************************************************************/ +/* sual_ClDataRead : read Connectionless Data from SUA/SUAL */ +/***********************************************************************/ +int sual_ClDataRead( sual_id_t InstId, + sual_DataId_t DataId, + unsigned char *pBuff, + uint BuffLen + ) +{ + sual_save_str temp = sual_rec_msg.front(); + sual_rec_msg.erase( sual_rec_msg.begin()); + + DataId = temp.user_ref; + InstId = temp.local_sua_id; + // put in supplied byte array(space is allocated beforehand by application) + temp.userdata.copy((char *)pBuff, temp.userdata.length(),0); + BuffLen = temp.userdata.length(); + return(SUAL_OK); +} + + +/***********************************************************************/ +/* sual_snapshot : get snapshot of sua data */ +/***********************************************************************/ +extern int sual_snapshot( unsigned char *pSnapshotFile /* if NULL: stdout */ + ) + +{ + return(0); +} + +// end of module sua_sual.c++ + diff --git a/sualibrary/sua/sua_sual.h b/sualibrary/sua/sua_sual.h new file mode 100644 index 0000000..dd92084 --- /dev/null +++ b/sualibrary/sua/sua_sual.h @@ -0,0 +1,459 @@ +/*************************************************************************** + sua_sual.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_sual.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Marie-Ange + * "A ligth weigth version of SUA, just what the doctor ordered" + * + * Purpose: This header-file defines the SUA light interface: + * - SUAL address structure + * - SUAL Callback function + * - SUAL function return values + * and SUA light functions for: + * - SUAL initialisation + * - SUAL Connectionless data Notification + * - SUAL CO Connect Notification + * - SUAL CO Connect Confirm Notification + * - SUAL CO Data Notification + * - SUAL CO DisConnect Notification + * - SUAL Register Instance + * - SUAL Connectionless Data Request to SUA + * - SUAL CO Connect Request to SUA + * - SUAL CO Connect Confirm Request to SUA + * - SUAL CO Data Request to SUA + * - SUAL CO DisConnect Request to SUA + * - SUAL CO Data read from SUA + * - SUAL Connectionless Data read from SUA + */ + +#ifndef SUA_SUAL_H +#define SUA_SUAL_H + +/* + *************************************************************************** + * + * Module: sua_sual.h + * + * Purpose: definition of SUALight API + * + *************************************************************************** + */ + +#ifdef LINUX + #include +#endif + +//#include + +#include +#include + +#define SUAL_SUALSERVICE_NAME "sual" +#define SUAL_SUALSERVICE_TRANSPORTPCOL "sctp" +#define SUAL_DEF_PORTNUMBER 14002 + +#define SUA_SCTP_PAYLOAD_PCOL_ID 0x04 + + +/* structures for API functions */ +typedef int sual_id_t; +typedef unsigned short sual_port_t; +typedef sual_id_t sual_InstId_t; +typedef sual_id_t sual_ConnId_t; +typedef sual_id_t sual_DataId_t; +typedef int reason_t; + +#define SUAL_DEF_NOSTREAMS 127 + + +extern int sual_errno; + + +typedef struct sual_PeerAddr { + int AddrType; /* predefined values for AddrType to indicate which + type is used in uPeerAddr: SUAL_ADDRTYPE_IPV4, + SUAL_ADDRTYPE_IPV6 */ + union uPeerAddr { + struct in_addr ip4; + struct in6_addr ip6; + } uPeerAddr; +} sual_PeerAddr_t; + +/* SUAL_ULP_CallBacks definitions */ +typedef struct sual_ULPcallbackFunctions { + + void (*ConnIndNotif)( sual_id_t sual_ConnId, + sual_PeerAddr_t *pPeerAddr, + uint UserDataLen + ); + void (*ConnConfNotif)( sual_id_t sual_ConnId, + uint UserDataLen + ); + void (*CoDataIndNotif)( sual_id_t sual_ConnId, + uint UserDataLen + ); + void (*DisconnIndNotif)( sual_id_t sual_ConnId, + reason_t reason, + uint UserDataLen + ); + void (*ClDataIndNotif)( sual_id_t sual_DataId, + uint ControlNumer, + sual_PeerAddr_t *pPeerAddr, + uint UserDataLen + ); +} sual_ULPcallbackFunctions_t; + + +typedef sual_ULPcallbackFunctions_t sualUif_Cbacks_t; + +typedef sual_ULPcallbackFunctions_t SUAL_ULP_CallBacks; + +typedef enum { + SUAL_ADDRTYPE_IPV4, + SUAL_ADDRTYPE_IPV6 +} sual_IpAddrType_t; + + +/* + * API-functions + */ +extern int sual_init( + unsigned char *pConfFile +); + +extern sual_InstId_t sual_RegisterSUAL_Instance( + sual_port_t LocalPort, + sual_ULPcallbackFunctions_t *pULPcallbackFunctions +); + + +sual_id_t +sual_ConnReq( + sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_ConnResp( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_DisconnReq( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_CoDataRead( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pBuff, + uint BuffLen +); + +int +sual_ClDataRead( + sual_id_t InstId, + sual_DataId_t DataId, + unsigned char *pBuff, + uint BuffLen +); + + +int +sual_CoDataReq( + sual_id_t InstId, + sual_id_t sual_ConnId, + unsigned char *pUserData, + uint UserDataLen +); + +int +sual_ClDataReq( + sual_id_t InstId, + sual_PeerAddr_t *pPeerAddr, + uint ControlNumber, + unsigned char *pUserData, + uint UserDataLen +); + +extern int +sual_snapshot( + unsigned char *pSnapshotFile /* if NULL: stdout */ +); + +/*====================== reasons of ulp_DisconnIndNotif: ======================*/ + +typedef enum { + SUAL_DISCONN_NOMORE_STREAMS=100, + SUAL_DISCONN_SCTP_ASSOCIATION_LOST, + SUAL_DISCONN_USERDATA_NOTREAD, + SUAL_DISCONN_READUSERDATA_ILLPARAM, + SUAL_DISCONN_CO_DATAREQ_WITHOUT_PAYLOAD, + SUAL_DISCONN_WRONGEVENT_FROM_OTHER_PEER, + SUAL_DISCONN_BY_COMMUNICATION_LOST, + SUAL_DISCONN_BY_NETWORKSTATUSCHANGE, + SUAL_DISCONN_COAC_CC_NOT_IN_CONNREQ_SENT, /* new */ + SUAL_DISCONN_BY_COAK_REF, /*new*/ + SUAL_DISCONN_NOMEM, + + SUAL_DISCONN_NOTABLE2SEND_SCTP_RELEASEREQUEST_MSG, + + SUAL_DISCONN_NOTABLE2SEND_SCTP_CONNECTREQUEST_MSG, + SUAL_DISCONN_NOTABLE2SEND_SCTP_MSG, + SUAL_DISCONN_NOTABLE2SEND_SCTP_COAK_REF_MSG, + + SUAL_DISCONN_SENDFAILURENOTIF, /* new */ + + SUAL_DISCONN_LAST +} sual_disconnReason_t; + +/*====================== returns of sual-API-functions: ======================*/ + +#define SUAL_OK 0 + + +typedef enum { + SUAL_API_RETURNS_FIRST=-1999, /* is no return */ + + +/* + * Returns of all function exept sual_init() + */ + SUAL_EERR_ENTITYSTATE, /* entity error */ + SUAL_UERR_WRONG_INSTID, /* ULP error */ + SUAL_ERR_NOMEM, /* no more memory */ + +/* + * Returns of all connection oriented api-functions + */ + SUAL_UERR_NOSUCH_CONN, /* obsolete */ + SUAL_UERR_CONNSTATE, + SUAL_UERR_ILLPARAM_USERDATA,/* concerning UserDataLen, pUserData */ + SUAL_UERR_USERDATA_NOTREAD, /* new */ + +/* + * sual_init() + */ + SUAL_EERR_ILLPARAM, /* e.g. Null-pointer */ + SUAL_CFG_ENOFILENAME, + SUAL_CFG_EOPENFILE, + SUAL_CFG_ENOPARAM, + SUAL_CFG_EPARAMVALUE, + SUAL_CFG_EPARAMFORMAT, + SUAL_CFG_EBUFFERLNG, + SUAL_CERR_NOLOCAL_ADDRS_IN_CONFFILE, + SUAL_SERR_SCTP_REGISTER, /* sctp error */ +/* new */ + SUAL_WARN_LOCKED_REINIT, + +/* + * Returns of sual_RegisterSUAL_Instance() + */ + SUAL_UERR_NULLPOINTER_CALLBACK, + SUAL_UERR_CBMISSING_CONCONFNOTIF, + SUAL_UERR_CBMISSING_CONINDNOTIF, + SUAL_UERR_CBMISSING_DISCONNINDNOTIF, + SUAL_UERR_CBMISSING_CODATAINDNOTIF, + SUAL_UERR_CBMISSING_CLDATAINDNOTIF, + + SUAL_UERR_LOCALPORT_NOTUNIQUE, + +/* + * Returns of sual_ConnReq() + */ + SUAL_UERR_NO_PEERADDR, + SUAL_UERR_IPV4_NOTYET, + SUAL_UERR_WRONG_ADDRTYPE, + SUAL_WARN_SHORTAGE_OF_STREAMS, + +/* + * Returns of sual_ConnResp() + * see common returns: + - SUAL_UERR_ILLPARAM_USERDATA + - SUAL_UERR_CONNSTATE + */ + + +/* + * Returns of sual_DisconnReq() + * see common returns: + - SUAL_UERR_ILLPARAM_USERDATA + - SUAL_UERR_CONNSTATE + */ + + +/* + * Returns of sual_CoDataRead() and sual_ClDataRead() + */ + SUAL_UERR_MISSING_DATABUFFER, + SUAL_UERR_MISSING_USERDATALEN, + SUAL_UERR_BUFFLEN_TOOLESS, + /* + * Returns of sual_CoDataRead() + */ + SUAL_UERR_WRONG_CONNID, + SUAL_UERR_CO_NODATA2READ, + /* + * Returns of sual_ClDataRead() + */ + SUAL_UERR_WRONG_DATAID, + SUAL_UERR_CL_NODATA2READ, /* e.g. already read */ + +/* + * Returns of sual_CoDataReq() and sual_ClDataReq() + */ + SUAL_UERR_DATAREQ_MISSING_DATABUFFER, /* obsolete */ + SUAL_UERR_DATAREQ_MISSING_USERDATALEN,/* obsolete */ + +/* + * Returns of sual_ClDataReq() + - SUAL_UERR_NO_PEERADDR + - SUAL_UERR_IPV4_NOTYET + - SUAL_UERR_WRONG_ADDRTYPE + */ + SUAL_UERR_CONTROLNUMBER_OUT_OF_RANGE, + +/*==============================================*/ + + +/* + * errors on LIF + */ + + SUAL_RCVCLDATATRANSFER_USERDATA_NOTREAD, /* new */ + + SUAL_ERR_NOSUCH_SCTP_ASSOCIATION, + SUAL_ERR_ULP_SSN_NOTREGISTERED, + SUAL_ERR_STREAMID_TOOBIG, + SUAL_ERR_NOMEM_TO_RECEIVE_SCTPCHUNK, + SUAL_ERR_FAILURE_SCTP_ASSOCIATE, + SUAL_ERR_WRONG_AF_INET_TYPE, + SUAL_ERR_SUAL_RELRE_MSG_ON_FREE_STREAM, + SUAL_ERR_SUAL_COAK_CC_MSG_ON_FREE_STREAM, + SUAL_ERR_SUAL_RELCO_MSG_ON_FREE_STREAM, + SUAL_ERR_SUAL_CODT_MSG_ON_FREE_STREAM, + SUAL_ERR_COAC_CC_NOT_IN_CONNREQ_SENT, + SUAL_ERR_RCV_RELCO_BUTNOTWAITING_FOR, + + SUAL_SERR_NOTEXIST_DESTADDR, + SUAL_SERR_NOTSUPPORTED_ADDRFORMAT, + SUAL_SERR_WRONG_MSGTYP_ONSTREAM, + SUAL_SERR_WRONG_MSGLEN, + SUAL_SERR_WRONGEVENT_FROM_OTHER_PEER, + SUAL_SERR_NOMORE_STREAMS, + SUAL_SERR_NOTABLE2SEND_SCTP_MSG, + + + +/* + * Errors concerning the SUAL-message + */ + SUAL_MSGERR_WRONG_PCOL_VERS=-600, + SUAL_MSGERR_WRONG_MSGLEN, /* new */ + SUAL_MSGERR_LEN_TOOLESS_MSGHDR, + SUAL_MSGERR_UNKNOWN_MSGTYPE, + SUAL_MSGERR_WRONG_VALUES4SPARE, + +/* + * Errors in syslog + */ + SUAL_SSN_NOTREGISTERED, + +/* + * Program errors, which should newer occur + */ + SUAL_PERR_NO_SNAPSHOT_FD=-580, + SUAL_PERR_ASS_NOTESTABL, + SUAL_PERR_ASS_STATE_UNKNOWN, + SUAL_PERR_WRONG_STATE, + SUAL_PERR_ALREADY_REGISTERED, + + SUAL_PERR_NULLPOINTER, + SUAL_PERR_PARAM_NULLPOINTER, + + SUAL_PERR_NULLPOINTER_PEERADDR, + SUAL_PERR_NULLPOINTER_SOCKUNION, + + SUAL_PERR_NULLPOINTER_INSTEL, + SUAL_PERR_NULLPOINTER_ASSEL, + SUAL_PERR_NULLPOINTER_CONNEL, + SUAL_PERR_NULLPOINTER_STREAMEL, + + SUAL_PERR_NULLPOINTER_RCVMSG, + SUAL_PERR_NULLPOINTER_POIPOIRCVMSG, + SUAL_PERR_NULLPOINTER_USERDATA, + + SUAL_PERR_WRONG_CONNID_INREAD, + SUAL_PERR_CONNSTATE, + SUAL_PERR_INCONSISTENT_LEN, + SUAL_PERR_NOASS_IN_CONNEL, + SUAL_PERR_ARG_IS_NULL_POINTER, + + SUAL_PERR_WRONG_ASS_STATE, + SUAL_PERR_WRONG_EVENT_ONFREESTREAM, + SUAL_PERR_NOSUCH_SCTPASSOC, + + /* 19.06.2001: additional errors: */ + /* sual_init(): */ + SUAL_SERR_SYSTEMFUNCTION, + SUAL_PERR_ERROR, + SUAL_CFG_ERROR, + + SUAL_LAST_RET_VALUE +} sual_api_returns_t; + +#endif // SUA_SUAL_H + +// end of module sua_sual.h diff --git a/sualibrary/sua/sua_syntax.cpp b/sualibrary/sua/sua_syntax.cpp new file mode 100644 index 0000000..f7d67f4 --- /dev/null +++ b/sualibrary/sua/sua_syntax.cpp @@ -0,0 +1,4733 @@ +/*************************************************************************** + sua_syntax.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_syntax.cpp,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 8. + * + * Author(s): Gery Verwimp + * Lode Coene + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Dorine + * "route some msg and get a hug from the Easter bunny." + * "question: which bunny, the right one , the left one or both " + * "(and don't forget to apply the KISS (ME *) methodology)" + * + * Purpose: This header-file defines the SUA syntax class for SUA + * primitives and messages, including the en/decoding routines. + */ + +#include "sua_syntax.h" +#include +#include +using namespace std; + +/********************************************************************/ +/* General error structure, returned by main en/decoder */ +/********************************************************************/ + +Sua_syntax_error_struct SYNTAX_ERR; + +/********************************************************************/ +/* General purpose overlay structure, used everywhere */ +/********************************************************************/ + +union Four_bytes_overlay { + uint32_t dq; + uint16_t dw[2]; + uint8_t db[4]; +}; + +Four_bytes_overlay OVERLAY; + +/********************************************************************/ +/* Sua_container method sua_init : Initialize SUA container element */ +/********************************************************************/ + +void Sua_container::sua_init () { + /* Initialize primitive */ + /* Initialize SUA header */ + sua_prim.hdr_version = Sua_unknown; + sua_prim.hdr_msg_class = sua_mngt; + sua_prim.hdr_msg_type.mngt = mngt_error; + /* Initialize every boolean parameter to FALSE */ + sua_prim.data_pres = FALSE; + sua_prim.info_pres = FALSE; + sua_prim.rout_con_pres = FALSE; + sua_prim.diag_info_pres = FALSE; + sua_prim.hb_data_pres = FALSE; + sua_prim.traf_mode_pres = FALSE; + sua_prim.err_code_pres = FALSE; + sua_prim.status_pres = FALSE; + sua_prim.cong_lvl_pres = FALSE; + sua_prim.ASP_id_pres = FALSE; + sua_prim.aff_pc_pres = FALSE; + sua_prim.hop_count_pres = FALSE; + sua_prim.source_addr_pres = FALSE; + sua_prim.dest_addr_pres = FALSE; + sua_prim.source_ref_pres = FALSE; + sua_prim.dest_ref_pres = FALSE; + sua_prim.SCCP_cause_pres = FALSE; + sua_prim.seq_nr_pres = FALSE; + sua_prim.rec_seq_nr_pres = FALSE; + sua_prim.asp_cap_pres = FALSE; + sua_prim.credit_pres = FALSE; + sua_prim.importance_pres = FALSE; + sua_prim.prot_class_pres = FALSE; + sua_prim.seq_control_pres = FALSE; + sua_prim.segm_pres = FALSE; + sua_prim.TID_label_pres = FALSE; + sua_prim.DRN_label_pres = FALSE; + sua_prim.dest_addr.ssn_incl = FALSE; + sua_prim.dest_addr.gt_incl = FALSE; + sua_prim.dest_addr.pc_incl = FALSE; + sua_prim.dest_addr.pc_pres = FALSE; + sua_prim.dest_addr.ip_addr_pres = FALSE; + sua_prim.dest_addr.gt_pres = FALSE; + sua_prim.dest_addr.hostname_pres = FALSE; + sua_prim.source_addr.ssn_incl = FALSE; + sua_prim.source_addr.gt_incl = FALSE; + sua_prim.source_addr.pc_incl = FALSE; + sua_prim.source_addr.pc_pres = FALSE; + sua_prim.source_addr.ip_addr_pres = FALSE; + sua_prim.source_addr.gt_pres = FALSE; + sua_prim.source_addr.hostname_pres = FALSE; + /* The message string is NOT explicitly initialized !! */ +} + +/********************************************************************/ +/* Sua_container method sua_encode : Encode primitive */ +/********************************************************************/ + +/* The encoder function expects a valid local syntax (sua_prim) + and returns the transfer syntax (message) in the sua_msg string field. + A number of plausibility checks are done : + - mandatory parameters (depending on msg type and class) must be present + - parameters which are not applicable are ignored, even when present + - parameters are checked on validity (range, compatibility with other parameters) +*/ + +/* 1. Definition of encoding procedures */ +/* 1.1 Parameter encoding procedures */ + +/* 1.1.1 Common parameters */ + +boolean encode_netw_app (string& msg, uint32_t netw_app) { + /* Kept for RK syntax */ + /* Reserve 8 bytes */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x010D); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + OVERLAY.dq = htonl(netw_app); + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_data (string& msg, string& data) { + /* Reserve 4 bytes for tag and length */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 4); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0003); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(data.size() + 4); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + /* Encode data */ + if (data.size() > 0) { + msg += data; + /* Encode possible padding bytes */ + if ((data.size() % 4) != 0) { + OVERLAY.db[0] = 0; // padding byte is zero + int nr_of_pad = 4 - (data.size() % 4); + for (int i = 0; i < nr_of_pad; i++) + msg += OVERLAY.db[0]; + } + return TRUE; + } + else { + /* Signal error : empty parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Empty Data parameter"; + return FALSE; + } +} + +boolean encode_ASP_id (string& msg, uint32_t asp_id) { + /* Reserve 4 bytes for tag and length */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0011); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode data */ + OVERLAY.dq = htonl(asp_id); + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + + return TRUE; + +} + +boolean encode_info (string& msg, string& info) { + /* Reserve 4 bytes for tag and length */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 4); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0004); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(info.size() + 4); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + /* Encode data */ + if (info.size() > 0) { + msg += info; + /* Encode possible padding bytes */ + if ((info.size() % 4) != 0) { + OVERLAY.db[0] = 0; // padding byte is zero + int nr_of_pad = 4 - (info.size() % 4); + for (int i = 0; i < nr_of_pad; i++) + msg += OVERLAY.db[0]; + } + return TRUE; + } + else { + /* Signal error : empty parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Empty Info parameter"; + return FALSE; + } +} + +boolean encode_rout_con (string& msg, uint32_t routing_ctxt) { + /* Reserve 8 bytes for routing context */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0006); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + OVERLAY.dq = htonl(routing_ctxt); + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_diag_info (string& msg, string& diag_info) { + /* Reserve 4 bytes for tag and length */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 4); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0007); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(diag_info.size() + 4); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + /* Encode data */ + if (diag_info.size() > 0) { + msg += diag_info; + /* Encode possible padding bytes */ + if ((diag_info.size() % 4) != 0) { + OVERLAY.db[0] = 0; // padding byte is zero + int nr_of_pad = 4 - (diag_info.size() % 4); + for (int i = 0; i < nr_of_pad; i++) + msg += OVERLAY.db[0]; + } + return TRUE; + } + else { + /* Signal error : empty parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Empty Diagnostics Info parameter"; + return FALSE; + } +} + +boolean encode_hb_data (string& msg, string& hb_data) { + /* Reserve 4 bytes for tag and length */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 4); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0009); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(hb_data.size() + 4); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + /* Encode data */ + if (hb_data.size() > 0) { + msg += hb_data; + /* Encode possible padding bytes */ + if ((hb_data.size() % 4) != 0) { + OVERLAY.db[0] = 0; // padding byte is zero + int nr_of_pad = 4 - (hb_data.size() % 4); + for (int i = 0; i < nr_of_pad; i++) + msg += OVERLAY.db[0]; + } + return TRUE; + } + else { + /* Signal error : empty parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Empty Heartbeat data parameter"; + return FALSE; + } +} + +boolean encode_traf_mode (string& msg, Sua_traffic_mode_type traffic_mt) { + /* Reserve 8 bytes for traffic mode type */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x000B); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + /* Check traffic mode type */ + if (traffic_mt < tmt_max) { + OVERLAY.dq = htonl(uint32_t(traffic_mt)); + for (int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; + } + else { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid Traffic Mode"; + return FALSE; + } +} + +boolean encode_error_code (string& msg, Sua_error_code_type err_code) { + /* Reserve 8 bytes for error code type */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x000C); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + /* Check error code type */ + if (err_code < ect_max) { + OVERLAY.dq = htonl(uint32_t(err_code)); + for (int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; + } + else { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid Error Code"; + return FALSE; + } +} + +/* 1.1.2 SUA specific parameters */ + +boolean encode_hop_count (string& msg, uint8_t hop_count) { + /* Reserve 8 bytes for hop count */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0101); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + for(int i = 0; i < 3; i++) + msg[pdu_index + i] = 0; // spare bytes + pdu_index += 3; // value + if (hop_count < 16) + msg[pdu_index] = hop_count; + else { + /* Signal error : parameter out of range */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Hop counter too high"; + return FALSE; + } + return TRUE; +} + +boolean encode_addr (string& msg, Sua_address_struct& address) { + /* Encode address parameters */ + /* Reserve 4 bytes for routing and address indicator */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 4); + /* Routing indicator : in this version only route on IP, hostname and SSN is allowed */ + if ((address.rout_ind != ri_route_IP_SSN) && + (address.rout_ind != ri_route_PC_SSN) && + (address.rout_ind != ri_route_hostname)) { + /* Signal error : invalid routing indicator used */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid routing indicator"; + return FALSE; + } + OVERLAY.dw[0] = htons(address.rout_ind); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Address indicator : depending on routing indicator, we set the appropriate flags */ + OVERLAY.dw[0] = 0; // Include nothing + if ((address.rout_ind == ri_route_PC_SSN) || (address.rout_ind == ri_route_IP_SSN) || (address.ssn_incl)) + OVERLAY.db[0] |= 0x01; + if (address.pc_incl) + OVERLAY.db[0] |= 0x02; + if ((address.rout_ind == ri_route_GT) || (address.gt_incl)) + OVERLAY.db[0] |= 0x04; + OVERLAY.dw[0] = htons(OVERLAY.dw[0]); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Address element checks : when routing on + - GT, a GT must be present + - SSN, either an IP address or PC must be present; these may never appear together + - hostname, a hostname must be present + Currently, we only allow SSN + IP address or hostname + */ + /* Reserve 8 bytes for SSN address parameter */ + msg.resize(pdu_index + 8); + /* Encode SSN tag */ + OVERLAY.dw[0] = htons(0x8003); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode SSN length : always 8 bytes, no padding */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode SSN value */ + for(int i = 0; i < 3; i++) + msg[pdu_index + i] = 0; // spare bytes + pdu_index += 3; // value + msg[pdu_index] = address.ssn; + pdu_index++; // next tag + /* Encode IP address or hostname */ + char* pdu_c; + if (address.ip_addr_pres) { + /* Check type */ + switch (address.ip_addr_type) { + case short(ip_v4) : + /* An IPv4 address is 4 bytes long (NBO), so reserve 8 bytes */ + msg.resize(pdu_index + 8); + OVERLAY.dw[0] = htons(0x8004); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + OVERLAY.dq = address.ip_addr.ipv4.sin_addr.s_addr; + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + break; + case short(ip_v6) : + /* An IPv6 address is 16 bytes long (NBO), so reserve 20 bytes */ + msg.resize(pdu_index + 20); + OVERLAY.dw[0] = htons(0x8006); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + OVERLAY.dw[1] = htons(20); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + pdu_c = (char*) &address.ip_addr.ipv6.sin6_addr.s6_addr; + for(int i = 0; i < 16; i++) { + msg[pdu_index + i] = *pdu_c; + pdu_c++; + } + pdu_index += 16; // next tag + break; + default : { + /* Signal error : invalid IP address type */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid IP address type"; + return FALSE; + } + } // End switch IP type + } // Endif + else if (address.pc_pres) { + /* An point code address is 4 bytes long (NBO), so reserve 8 bytes */ + msg.resize(pdu_index + 8); + OVERLAY.dw[0] = htons(0x8002); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + OVERLAY.dq = address.pc; + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[3-i]; + + } // Endif + else if (address.hostname_pres){ + msg.resize(pdu_index + address.hostname.length() + 2 + 4); + OVERLAY.dw[0] = htons(0x8005); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + OVERLAY.dw[1] = htons(address.hostname.length() + 6); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + + string name_str; + int numchar = 0; + int i,first= 0; /* start of name array */ + int last= address.hostname.size(); + unsigned int current = address.hostname.find('.'); + while(current != string::npos) + { + /* determine the length of each label(except the last)*/ + numchar = current - first; + /* copy length of label into PDU */ + OVERLAY.dw[0] = numchar; + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + /* copy the label in the PDU */ + for (i=0; i < numchar; i++) { + OVERLAY.dw[0] = address.hostname[first + i]; + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + } + first= current + 1; + current = address.hostname.find('.', first); + } + /* determine lenght of last label */ + numchar = last - first; + OVERLAY.dw[0] = numchar; + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + for (i=0; i < numchar; i++) { + OVERLAY.dw[0] = address.hostname[first + i]; + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + } + /* end of hostname */ + msg[pdu_index] = htons(0x00); + pdu_index++; + /* padding out up a 32 bit boundary */ + int mod_nr = 0; + if ((mod_nr = pdu_index % 4) != 0) + { + for (i=0; i < (4 - mod_nr); i++) { + OVERLAY.dw[0] = htons(0x0000);; + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + } + } + } + else { + /* Signal error : IP address missing */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Address parameter missing"; + return FALSE; + } + return TRUE; +} + +boolean encode_src_addr (string& msg, Sua_address_struct& address) { + boolean no_error = TRUE; + /* Reserve extra 4 bytes for tag, length */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 4); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0102); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Lenght is encoded when known, at the end */ + /* Encode value */ + no_error = encode_addr (msg, address); + if (no_error) { + /* Encode length : calculate as current size - pdu_index + 2 (tag) */ + OVERLAY.dw[1] = htons(msg.size() - pdu_index + 2); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + } + return no_error; +} + +boolean encode_dest_addr (string& msg, Sua_address_struct& address) { + boolean no_error = TRUE; + /* Reserve extra 4 bytes for tag, length */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 4); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0103); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Lenght is encoded when known, at the end */ + /* Encode value */ + no_error = encode_addr (msg, address); + if (no_error) { + /* Encode length : calculate as current size - pdu_index + 2 (tag) */ + OVERLAY.dw[1] = htons(msg.size() - pdu_index + 2); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + } + return no_error; +} + +boolean encode_source_ref (string& msg, uint32_t src_ref) { + /* Reserve 8 bytes for source reference */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0104); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + OVERLAY.dq = htonl(src_ref); + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_dest_ref (string& msg, uint32_t dest_ref) { + /* Reserve 8 bytes for destination reference */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0105); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + OVERLAY.dq = htonl(dest_ref); + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_SCCP_cause (string& msg, SCCP_cause_struct cause) { + /* Reserve 8 bytes */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0106); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value : 2 spare bytes, then cause type and value */ + OVERLAY.dw[0] = 0; + OVERLAY.db[2] = uint8_t(cause.cause_type); + OVERLAY.db[3] = cause.cause_value; + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_seq_nr (string& msg, Sua_seq_nr_struct seq_nr) { + /* Reserve 8 bytes for sequence number */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0107); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value : 2 spare bytes, then received seq nr, more data flag and sent seq nr */ + OVERLAY.dw[0] = 0; + OVERLAY.db[2] = 0; // No rcvd seq nr, only more data flag will be set + OVERLAY.db[3] = 0; // No sent seq nr for protocol class 2 + if (seq_nr.more_data) + OVERLAY.db[2] |= 0x01; + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_asp_cap (string& msg, Sua_asp_cap_struct asp_cap) { + /* Reserve 8 bytes for ASP capabilities */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0109); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + msg[pdu_index] = 0; // spare byte + pdu_index++; + msg[pdu_index] = 0; // spare byte + pdu_index++; + OVERLAY.db[0] = 0; // clear byte + /* Protocol class 0 is always supported */ + OVERLAY.db[0] |= 0x01; + if (asp_cap.cl1_supp) + OVERLAY.db[0] |= 0x02; + if (asp_cap.cl2_supp) + OVERLAY.db[0] |= 0x04; + if (asp_cap.cl3_supp) + OVERLAY.db[0] |= 0x08; + msg[pdu_index] = OVERLAY.db[0]; // Supported protocol classes + pdu_index++; + /* Check interworking type */ + if (asp_cap.interworking < iw_max) { + msg[pdu_index] = uint8_t(asp_cap.interworking); + return TRUE; + } + else { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid Interworking type"; + return FALSE; + } +} + +boolean encode_seq_ctrl (string& msg, uint32_t seq_ctrl) { + /* Reserve 8 bytes for sequence control */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0116); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + OVERLAY.dq = htonl(seq_ctrl); + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_importance (string& msg, uint8_t importance) { + /* Reserve 8 bytes for importance */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0113); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + for(int i = 0; i < 3; i++) + msg[pdu_index + i] = 0; // spare bytes + pdu_index += 3; // value + if (importance < 8) + msg[pdu_index] = importance; + else { + /* Signal error : parameter out of range */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Importance too high"; + return FALSE; + } + return TRUE; +} + +boolean encode_prot_class (string& msg, Sua_protocol_class_struct pr_cl) { + /* Reserve 8 bytes for protocol class */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0115); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + for(int i = 0; i < 3; i++) + msg[pdu_index + i] = 0; // spare bytes + pdu_index += 3; // value + /* Encode protocol class and special options */ + if (pr_cl.pcl < prot_max) { + OVERLAY.db[0] = uint8_t(pr_cl.pcl); + if ((pr_cl.return_option) && ((pr_cl.pcl == prot_class_0) || (pr_cl.pcl == prot_class_1))) + OVERLAY.db[0] |= 0x80; // Set return on error flag + } + else { + /* Signal error : invalid parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid Protocol Class"; + return FALSE; + } + msg[pdu_index] = OVERLAY.db[0]; + return TRUE; +} + +boolean encode_segmentation (string& msg, Sua_segm_struct segments) { + /* Reserve 8 bytes for segmentation parameter */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0117); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + OVERLAY.dq = htonl(segments.segm_ref); + if (OVERLAY.db[0] == 0) { + if (segments.remain < 16) { + OVERLAY.db[0] = segments.remain; + if (segments.first) + OVERLAY.db[0] |= 0x80; // Set first segment flag + } + else { + /* Signal error : parameter out of range */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Remaining segments too high"; + return FALSE; + } + } + else { + /* Signal error : parameter out of range */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Segmentation reference out of range"; + return FALSE; + } + /* Copy into message */ + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_TID_label (string& msg, Sua_label_struct TID_label) { + /* Reserve 8 bytes for TID label */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x0119); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + int max_label = 2; + if ((TID_label.start < 32) && (TID_label.start >= TID_label.end) && ((TID_label.start - TID_label.end) < 16)) { + for (int i = 0; i < (TID_label.start - TID_label.end); i++) + max_label = max_label * 2; + if (TID_label.label_value < max_label) { + OVERLAY.db[0] = TID_label.start; + OVERLAY.db[1] = TID_label.end; + OVERLAY.dw[1] = htons(TID_label.label_value); + } + else { + /* Signal error : paramater syntax error */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid TID label"; + return FALSE; + } + } + else { + /* Signal error : parameter syntax error */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid TID label position or length"; + return FALSE; + } + /* Copy into message */ + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +boolean encode_DRN_label (string& msg, Sua_label_struct DRN_label) { + /* Reserve 8 bytes for DRN label */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x011A); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value */ + int max_label = 2; + if ((DRN_label.start < 32) && (DRN_label.start >= DRN_label.end) && ((DRN_label.start - DRN_label.end) < 16)) { + for (int i = 0; i < (DRN_label.start - DRN_label.end); i++) + max_label = max_label * 2; + if (DRN_label.label_value < max_label) { + OVERLAY.db[0] = DRN_label.start; + OVERLAY.db[1] = DRN_label.end; + OVERLAY.dw[1] = htons(DRN_label.label_value); + } + else { + /* Signal error : paramater syntax error */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid DRN label"; + return FALSE; + } + } + else { + /* Signal error : parameter syntax error */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Encoding : Invalid DRN label position or length"; + return FALSE; + } + /* Copy into message */ + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = OVERLAY.db[i]; + return TRUE; +} + +/* 1.2 Message encoding procedures */ + +/* 1.2.3 ASP Server Management messages */ + +boolean encode_ASP_up_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - ASP Identifier (dynamic assignment not supported) + - Info string + */ + boolean no_error = TRUE; + if (prim.ASP_id_pres) + no_error = encode_ASP_id (msg, prim.ASP_id); + if (prim.info_pres) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +boolean encode_ASP_down_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Info string + */ + boolean no_error = TRUE; + if (prim.info_pres) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +boolean encode_ASP_beat_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Heartbeat data + */ + boolean no_error = TRUE; + if (prim.hb_data_pres) + no_error = encode_hb_data (msg, prim.hb_data); + return no_error; +} + +boolean encode_ASP_up_ack_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - ASP Identifier (dynamic assignment not supported) + - Info string + */ + boolean no_error = TRUE; + if (prim.info_pres) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +boolean encode_ASP_down_ack_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Info string + */ + boolean no_error = TRUE; + if (prim.info_pres) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +boolean encode_ASP_beat_ack_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Heartbeat data + */ + boolean no_error = TRUE; + if (prim.hb_data_pres) + no_error = encode_hb_data (msg, prim.hb_data); + return no_error; +} + +/* 1.2.4 ASP Traffic Management messages */ + +boolean encode_ASP_act_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Traffic mode type + - Routing context + - TID label + - DRN label + - Info string + */ + boolean no_error = TRUE; + if (prim.traf_mode_pres) + no_error = encode_traf_mode (msg, prim.traf_mode); + if (prim.rout_con_pres && no_error) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.TID_label_pres && no_error) + no_error = encode_TID_label (msg, prim.TID_label); + if (prim.DRN_label_pres && no_error) + no_error = encode_DRN_label (msg, prim.DRN_label); + if (prim.info_pres && no_error) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +boolean encode_ASP_inact_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Routing context + - Info string + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.info_pres && no_error) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +boolean encode_ASP_act_ack_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Traffic mode type + - Routing context + - Info string + */ + boolean no_error = TRUE; + if (prim.traf_mode_pres) + no_error = encode_traf_mode (msg, prim.traf_mode); + if (prim.rout_con_pres && no_error) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.info_pres && no_error) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +boolean encode_ASP_inact_ack_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters are optional : + - Routing context + - Info string + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.info_pres && no_error) + no_error = encode_info (msg, prim.info_string); + return no_error; +} + +/* 1.2.7 Connectionless messages */ + +boolean encode_cl_data_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Protocol class + - Source address + - Destination address + - Sequence control + - Data + Following parameters are optional : + - Routing context + - Hop count + - Importance + - Message priority (we don't use it) + - Correlation ID (we don't use Broadcast mode) + - Segmentation + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.prot_class_pres && no_error) { + /* Protocol class must be 0 or 1 */ + if ((prim.prot_class.pcl == prot_class_0) || (prim.prot_class.pcl == prot_class_1)) + no_error = encode_prot_class (msg, prim.prot_class); + else { + /* Signal error : invalid parameter */ + SYNTAX_ERR.msg_index = msg.size(); + SYNTAX_ERR.error_text = "Encoding : Invalid protocol class for connectionless msg"; + return FALSE; + } + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing"; + return FALSE; + } + } + if (prim.source_addr_pres && no_error) + no_error = encode_src_addr (msg, prim.source_addr); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Source address parameter missing"; + return FALSE; + } + } + if (prim.dest_addr_pres && no_error) + no_error = encode_dest_addr (msg, prim.dest_addr); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination address parameter missing"; + return FALSE; + } + } + if (prim.seq_control_pres && no_error) + no_error = encode_seq_ctrl (msg, prim.seq_control); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Sequence control parameter missing"; + return FALSE; + } + } + if (prim.hop_count_pres && no_error) + no_error = encode_hop_count (msg, prim.hop_count); + if (prim.importance_pres && no_error) + no_error = encode_importance (msg, prim.importance); + if (prim.segm_pres && no_error) + no_error = encode_segmentation (msg, prim.segm); + if (prim.data_pres && no_error) + no_error = encode_data (msg, prim.data_string); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Data parameter missing"; + return FALSE; + } + } + return no_error; +} + +boolean encode_cl_data_resp_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - SCCP Cause + - Source address + - Destination address + Following parameters are optional : + - Routing context + - Hop count + - Importance + - Message priority (we don't use it) + - Correlation ID (we don't use Broadcast mode) + - Data + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.SCCP_cause_pres && no_error) { + /* Cause type must be return cause */ + prim.SCCP_cause.cause_type = ctp_return_cause; + no_error = encode_SCCP_cause (msg, prim.SCCP_cause); + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : SCCP cause parameter missing"; + return FALSE; + } + } + if (prim.source_addr_pres && no_error) + no_error = encode_src_addr (msg, prim.source_addr); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Source address parameter missing"; + return FALSE; + } + } + if (prim.dest_addr_pres && no_error) + no_error = encode_dest_addr (msg, prim.dest_addr); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination address parameter missing"; + return FALSE; + } + } + if (prim.hop_count_pres && no_error) + no_error = encode_hop_count (msg, prim.hop_count); + if (prim.importance_pres && no_error) + no_error = encode_importance (msg, prim.importance); + if (prim.data_pres && no_error) + no_error = encode_data (msg, prim.data_string); + return no_error; +} + +/* 1.2.8 Connection-oriented messages */ +/* Only protocol class 2 messages are supported */ + +boolean encode_co_conn_req_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Protocol class + - Source reference + - Destination address + - Sequence control + Following parameters are optional : + - Routing context + - Source address + - Hop count + - Importance + - Message priority (we don't use it) + - Credit (no support for protocol class 3) + - Data + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.prot_class_pres && no_error) { + /* Return option not applicable */ + prim.prot_class.return_option = FALSE; + /* Protocol class must be 2 or 3 */ + if ((prim.prot_class.pcl == prot_class_2) || (prim.prot_class.pcl == prot_class_3)) + no_error = encode_prot_class (msg, prim.prot_class); + else { + /* Signal error : invalid parameter */ + SYNTAX_ERR.msg_index = msg.size(); + SYNTAX_ERR.error_text = "Encoding : Invalid protocol class for connection-oriented msg"; + return FALSE; + } + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing"; + return FALSE; + } + } + if (prim.source_ref_pres && no_error) + no_error = encode_source_ref (msg, prim.source_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing"; + return FALSE; + } + } + if (prim.dest_addr_pres && no_error) + no_error = encode_dest_addr (msg, prim.dest_addr); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination address parameter missing"; + return FALSE; + } + } + if (prim.seq_control_pres && no_error) + no_error = encode_seq_ctrl (msg, prim.seq_control); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Sequence control parameter missing"; + return FALSE; + } + } + if (prim.source_addr_pres && no_error) + no_error = encode_src_addr (msg, prim.source_addr); + if (prim.hop_count_pres && no_error) + no_error = encode_hop_count (msg, prim.hop_count); + if (prim.importance_pres && no_error) + no_error = encode_importance (msg, prim.importance); + if (prim.data_pres && no_error) + no_error = encode_data (msg, prim.data_string); + return no_error; +} + +boolean encode_co_conn_ack_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Protocol class + - Destination reference + - Source reference + Following parameters are optional : + - Routing context + - Destination address + - Importance + - Message priority (we don't use it) + - Credit (no support for protocol class 3) + - Data + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.prot_class_pres && no_error) { + /* Return option not applicable */ + prim.prot_class.return_option = FALSE; + /* Protocol class must be 2 or 3 */ + if ((prim.prot_class.pcl == prot_class_2) || (prim.prot_class.pcl == prot_class_3)) + no_error = encode_prot_class (msg, prim.prot_class); + else { + /* Signal error : invalid parameter */ + SYNTAX_ERR.msg_index = msg.size(); + SYNTAX_ERR.error_text = "Encoding : Invalid protocol class for connection-oriented msg"; + return FALSE; + } + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing"; + return FALSE; + } + } + if (prim.dest_ref_pres && no_error) + no_error = encode_dest_ref (msg, prim.dest_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing"; + return FALSE; + } + } + if (prim.source_ref_pres && no_error) + no_error = encode_source_ref (msg, prim.source_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing"; + return FALSE; + } + } + if (prim.dest_addr_pres && no_error) + no_error = encode_dest_addr (msg, prim.dest_addr); + if (prim.importance_pres && no_error) + no_error = encode_importance (msg, prim.importance); + if (prim.data_pres && no_error) + no_error = encode_data (msg, prim.data_string); + return no_error; +} + +boolean encode_co_conn_ref_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Destination reference + - SCCP cause + Following parameters are optional : + - Routing context + - Destination address + - Importance + - Data + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.dest_ref_pres && no_error) + no_error = encode_dest_ref (msg, prim.dest_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing"; + return FALSE; + } + } + if (prim.SCCP_cause_pres && no_error) { + /* Cause type must be refusal cause */ + prim.SCCP_cause.cause_type = ctp_refusal_cause; + no_error = encode_SCCP_cause (msg, prim.SCCP_cause); + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : SCCP Cause parameter missing"; + return FALSE; + } + } + if (prim.dest_addr_pres && no_error) + no_error = encode_dest_addr (msg, prim.dest_addr); + if (prim.importance_pres && no_error) + no_error = encode_importance (msg, prim.importance); + if (prim.data_pres && no_error) + no_error = encode_data (msg, prim.data_string); + return no_error; +} + +boolean encode_co_rel_req_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Destination reference + - Source reference + - SCCP cause + Following parameters are optional : + - Routing context + - Importance + - Data + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.dest_ref_pres && no_error) + no_error = encode_dest_ref (msg, prim.dest_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing"; + return FALSE; + } + } + if (prim.source_ref_pres && no_error) + no_error = encode_source_ref (msg, prim.source_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing"; + return FALSE; + } + } + if (prim.SCCP_cause_pres && no_error) { + /* Cause type must be release cause */ + prim.SCCP_cause.cause_type = ctp_release_cause; + no_error = encode_SCCP_cause (msg, prim.SCCP_cause); + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : SCCP Cause parameter missing"; + return FALSE; + } + } + if (prim.importance_pres && no_error) + no_error = encode_importance (msg, prim.importance); + if (prim.data_pres && no_error) + no_error = encode_data (msg, prim.data_string); + return no_error; +} + +boolean encode_co_rel_conf_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Destination reference + - Source reference + Following parameters are optional : + - Routing context + - Importance + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.dest_ref_pres && no_error) + no_error = encode_dest_ref (msg, prim.dest_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing"; + return FALSE; + } + } + if (prim.source_ref_pres && no_error) + no_error = encode_source_ref (msg, prim.source_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing"; + return FALSE; + } + } + if (prim.importance_pres && no_error) + no_error = encode_importance (msg, prim.importance); + return no_error; +} + +boolean encode_co_data_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Sequence number + - Destination reference + - Data + Following parameters are optional : + - Routing context + - Message priority (we don't use it) + - Correlation ID (we don't support Broadcast mode) + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.seq_nr_pres && no_error) { + /* Sent and received sequence number don't apply */ + prim.seq_nr.sent_seq_nr = 0; + prim.seq_nr.rcvd_seq_nr = 0; + no_error = encode_seq_nr (msg, prim.seq_nr); + } + else { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Sequence number parameter missing"; + return FALSE; + } + if (prim.dest_ref_pres && no_error) + no_error = encode_dest_ref (msg, prim.dest_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing"; + return FALSE; + } + } + if (prim.data_pres && no_error) + no_error = encode_data (msg, prim.data_string); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Data parameter missing"; + return FALSE; + } + } + return no_error; +} + +boolean encode_co_err_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Destination reference + - SCCP cause + Following parameters are optional : + - Routing context + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.dest_ref_pres && no_error) + no_error = encode_dest_ref (msg, prim.dest_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing"; + return FALSE; + } + } + if (prim.SCCP_cause_pres && no_error) { + /* Cause type must be error cause */ + prim.SCCP_cause.cause_type = ctp_error_cause; + no_error = encode_SCCP_cause (msg, prim.SCCP_cause); + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : SCCP Cause parameter missing"; + return FALSE; + } + } + return no_error; +} + +boolean encode_co_it_msg (Sua_primitive_struct& prim, string& msg) { + /* Following parameters MUST be present : + - Protocol class + - Destination reference + - Source reference + - Sequence number (coded zero for protocol class 2) + - Credit (coded zero for protocol class 2) + Following parameters are optional : + - Routing context + */ + boolean no_error = TRUE; + if (prim.rout_con_pres) + no_error = encode_rout_con (msg, prim.rout_con); + if (prim.prot_class_pres && no_error) { + /* Return option not applicable */ + prim.prot_class.return_option = FALSE; + /* Protocol class is set to 2 */ + prim.prot_class.pcl = prot_class_2; + no_error = encode_prot_class (msg, prim.prot_class); + } + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Protocol class parameter missing"; + return FALSE; + } + } + if (prim.dest_ref_pres) + no_error = encode_dest_ref (msg, prim.dest_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Destination Reference parameter missing"; + return FALSE; + } + } + if (prim.source_ref_pres && no_error) + no_error = encode_source_ref (msg, prim.source_ref); + else { + if (no_error) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Encoding : Source Reference parameter missing"; + return FALSE; + } + } + if (no_error) { + prim.seq_nr.sent_seq_nr = 0; + prim.seq_nr.rcvd_seq_nr = 0; + prim.seq_nr.more_data = FALSE; + no_error = encode_seq_nr (msg, prim.seq_nr); + } + if (no_error) { + prim.credit = 0; + /* Reserve 8 bytes */ + int pdu_index = msg.size(); + msg.resize(pdu_index + 8); + /* Encode tag */ + OVERLAY.dw[0] = htons(0x010A); + msg[pdu_index] = OVERLAY.db[0]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[1]; + pdu_index++; + /* Encode length, always 8 bytes */ + OVERLAY.dw[1] = htons(8); + msg[pdu_index] = OVERLAY.db[2]; + pdu_index++; + msg[pdu_index] = OVERLAY.db[3]; + pdu_index++; + /* Encode value : completely zero */ + for(int i = 0; i < 4; i++) + msg[pdu_index + i] = 0; + } + return no_error; +} + +/* 1.3 Sua encoding method */ +Sua_syntax_error_struct Sua_container::sua_encode () { + + /* Syntax Error struct initialization */ + SYNTAX_ERR.msg_index = 0; + SYNTAX_ERR.no_error = TRUE; + SYNTAX_ERR.error_text = "Encoding : no error"; + + /* Encoding variables */ + int pdu_index = 0; + boolean no_error = TRUE; + string strBlank; + + /* Initialize message string to clean up old mess */ + sua_msg = strBlank; + + /* Reserve 8 bytes for msg header */ + sua_msg.resize(8); + + /* Only version 1 is supported */ + sua_prim.hdr_version = Sua_version1; + sua_msg[pdu_index] = uint8_t(Sua_version1); + pdu_index++; + /* Reserved byte coded 0 */ + sua_msg[pdu_index] = 0; + pdu_index++; + /* Encode message class */ + sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_class); + pdu_index++; + + /* Encode message type according to class */ + switch (sua_prim.hdr_msg_class) { + case sua_aspsm : + sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.aspsm); + pdu_index++; + break; + case sua_asptm : + sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.asptm); + pdu_index++; + break; + case sua_cl : + sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.cl); + pdu_index++; + break; + case sua_co : + sua_msg[pdu_index] = uint8_t(sua_prim.hdr_msg_type.co); + pdu_index++; + break; + default : { + /* Signal error : invalid message class */ + SYNTAX_ERR.msg_index = 2; + SYNTAX_ERR.error_text = "Encoding : Invalid message class"; + no_error = FALSE; + } + } // End switch message class + + if (no_error) { + /* The message length field is encoded at the end, pdu_index is kept at this position */ + /* Start encoding of message parameters : double switch ! */ + switch (sua_prim.hdr_msg_class) { + case sua_aspsm : + switch (sua_prim.hdr_msg_type.aspsm) { + case aspsm_up : + no_error = encode_ASP_up_msg (sua_prim, sua_msg); + break; + case aspsm_down : + no_error = encode_ASP_down_msg (sua_prim, sua_msg); + break; + case aspsm_beat : + no_error = encode_ASP_beat_msg (sua_prim, sua_msg); + break; + case aspsm_up_ack : + no_error = encode_ASP_up_ack_msg (sua_prim, sua_msg); + break; + case aspsm_down_ack : + no_error = encode_ASP_down_ack_msg (sua_prim, sua_msg); + break; + case aspsm_beat_ack : + no_error = encode_ASP_beat_ack_msg (sua_prim, sua_msg); + break; + default : { + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Encoding : Invalid sua_aspsm message type"; + no_error = FALSE; + } + } // End switch aspsm msg type + break; + case sua_asptm : + switch (sua_prim.hdr_msg_type.asptm) { + case asptm_act : + no_error = encode_ASP_act_msg (sua_prim, sua_msg); + break; + case asptm_inact : + no_error = encode_ASP_inact_msg (sua_prim, sua_msg); + break; + case asptm_act_ack : + no_error = encode_ASP_act_ack_msg (sua_prim, sua_msg); + break; + case asptm_inact_ack : + no_error = encode_ASP_inact_ack_msg (sua_prim, sua_msg); + break; + default : { + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Encoding : Invalid sua_asptm message type"; + no_error = FALSE; + } + } // End switch asptm msg type + break; + case sua_cl : + switch (sua_prim.hdr_msg_type.cl) { + case cl_data_transfer : + no_error = encode_cl_data_msg (sua_prim, sua_msg); + break; + case cl_data_response : + no_error = encode_cl_data_resp_msg (sua_prim, sua_msg); + break; + default : { + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Encoding : Invalid sua_cl message type"; + no_error = FALSE; + } + } // End switch cl msg type + break; + case sua_co : + switch (sua_prim.hdr_msg_type.co) { + case co_core : + no_error = encode_co_conn_req_msg (sua_prim, sua_msg); + break; + case co_coak : + no_error = encode_co_conn_ack_msg (sua_prim, sua_msg); + break; + case co_coref : + no_error = encode_co_conn_ref_msg (sua_prim, sua_msg); + break; + case co_relre : + no_error = encode_co_rel_req_msg (sua_prim, sua_msg); + break; + case co_relco : + no_error = encode_co_rel_conf_msg (sua_prim, sua_msg); + break; + case co_data : + no_error = encode_co_data_msg (sua_prim, sua_msg); + break; + case co_err : + no_error = encode_co_err_msg (sua_prim, sua_msg); + break; + case co_it : + no_error = encode_co_it_msg (sua_prim, sua_msg); + break; + default : { + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Encoding : Invalid sua_co message type"; + no_error = FALSE; + } + } // End switch co msg type + break; + default : { + /* Signal error : invalid message class */ + SYNTAX_ERR.msg_index = 2; + SYNTAX_ERR.error_text = "Encoding : Invalid message class"; + no_error = FALSE; + } + } // End switch message class + } // End message encoding + + if (no_error) { + // Also padding bytes of final parameter are included in the total message length + OVERLAY.dq = htonl(sua_msg.size()); + for (int i = 0; i < 4; i++) + sua_msg[pdu_index + i] = OVERLAY.db[i]; + pdu_index += 4; // next tag + } + else { + /* Printout error text */ + SYNTAX_ERR.no_error = FALSE; + cout << "Error position = " << SYNTAX_ERR.msg_index << endl; + cout << SYNTAX_ERR.error_text << endl; + } + return SYNTAX_ERR; +} + +/********************************************************************/ +/* Sua_container method sua_decode : Decode SUA container element */ +/********************************************************************/ + +/* The decoder function expects a valid transfer syntax (sua_msg) + and returns the local syntax (primitive) in the sua_prim field. + A number of plausibility checks are done : + - the message and parameter length fields must be consistent + - mandatory parameters (depending on msg type and class) must be present + - unrecognized parameters or parameters that are not applicable, are ignored + - parameters are checked on validity (range, compatibility with other parameters) + - duplicate parameters are not allowed +*/ + +/* 2. Definition of decoding procedures */ +/* 2.1 Parameter decoding procedures */ + +/* Input pdu_index always points to the tag field of the parameter in the message */ +/* Output pdu_index always points to the tag field of the next parameter in the message */ + +/* 2.1.1 Common parameters */ + +boolean decode_netw_app (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* Kept for RK syntax */ + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode network appearance */ + prim.netw_app_pres = TRUE; + pdu_index += 4; + for (int i = 0; i < 4; i++) { + OVERLAY.db[i] = msg[pdu_index + i]; + } + prim.netw_app = ntohl(OVERLAY.dq); + pdu_index += 4; // Next tag + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Network Appearance length"; + return FALSE; + } +} + +boolean decode_data (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* Get the parameter length */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + /* There should be at least 1 byte of data */ + if (par_len > 4) { + /* Copy to the data string */ + prim.data_pres = TRUE; + prim.data_string = msg.substr(pdu_index + 4, par_len - 4); + /* Set pdu_index to next tag */ + pdu_index += par_len; + pdu_index += (4 - (par_len % 4)) % 4; // don't forget padding bytes + return TRUE; + } + else { + /* Signal error : empty parameter */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Empty Data parameter"; + return FALSE; + } +} + +boolean decode_info (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* Get the parameter length */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + /* There should be at least 1 byte of info */ + if (par_len > 4) { + /* Copy to the info string */ + prim.info_pres = TRUE; + prim.info_string = msg.substr(pdu_index + 4, par_len - 4); + /* Set pdu_index to next tag */ + pdu_index += par_len; + pdu_index += (4 - (par_len % 4)) % 4; // don't forget padding bytes + return TRUE; + } + else { + /* Signal error : empty parameter */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Empty Info parameter"; + return FALSE; + } +} + +boolean decode_rout_con (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode routing context */ + prim.rout_con_pres = TRUE; + pdu_index += 4; + for (int i = 0; i < 4; i++) { + OVERLAY.db[i] = msg[pdu_index + i]; + } + prim.rout_con = ntohl(OVERLAY.dq); + pdu_index += 4; // Next tag + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Routing Context length"; + return FALSE; + } +} + +boolean decode_hb_data (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* Get the parameter length */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + /* There should be at least 1 byte of data */ + if (par_len > 4) { + /* Copy to the hb_data string */ + prim.hb_data_pres = TRUE; + prim.hb_data = msg.substr(pdu_index + 4, par_len - 4); + /* Set pdu_index to next tag */ + pdu_index += par_len; + pdu_index += (4 - (par_len % 4)) % 4; // don't forget padding bytes + return TRUE; + } + else { + /* Signal error : empty parameter */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Empty Heartbeat data parameter"; + return FALSE; + } +} + +boolean decode_traf_mode (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode traffic mode type */ + pdu_index += 4; + for (int i = 0; i < 4; i++) { + OVERLAY.db[i] = msg[pdu_index + i]; + } + OVERLAY.dq = ntohl(OVERLAY.dq); + /* Check traffic mode type value */ + if (OVERLAY.dq < tmt_max) { + pdu_index += 4; // Next tag + prim.traf_mode_pres = TRUE; + prim.traf_mode = Sua_traffic_mode_type(OVERLAY.dq); + return TRUE; + } + else { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Invalid Traffic Mode Type value"; + return FALSE; + } + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Traffic Mode Type length"; + return FALSE; + } +} + +boolean decode_error_code (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode error code */ + pdu_index += 4; + for (int i = 0; i < 4; i++) { + OVERLAY.db[i] = msg[pdu_index + i]; + } + OVERLAY.dq = ntohl(OVERLAY.dq); + /* Check error code value */ + if (OVERLAY.dq < ect_max) { + pdu_index += 4; // Next tag + prim.err_code_pres = TRUE; + prim.err_code = Sua_error_code_type(OVERLAY.dq); + return TRUE; + } + else { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Invalid Error Code value"; + return FALSE; + } + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Error Code length"; + return FALSE; + } +} + +/* 2.1.2 SUA specific parameters */ + +boolean decode_hop_count (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode hop counter */ + prim.hop_count = uint8_t(msg[pdu_index + 7]); + /* Check whether hop counter within range */ + if (prim.hop_count > 15) { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index + 7; + SYNTAX_ERR.error_text = "Decoding : Invalid Hop Counter value"; + return FALSE; + } + pdu_index += 8; // next tag + prim.hop_count_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Hop Counter length"; + return FALSE; + } +} + +boolean decode_addr (Sua_address_struct& addr, string& msg, unsigned int& pdu_index) { + unsigned int next_tag_pdu_idx = 0; + int j = 0; + unsigned int numchar = 0; + bool look_for_next_label = FALSE; + /* Get the parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[1]); + /* There must be at least a routing and address indicator, plus 1 parameter */ + if (par_len > 12) { + /* Evaluate address parameters, the address structure has been cleaned up */ + /* Routing indicator */ + pdu_index += 4; + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + uint16_t pdu_word = ntohs(OVERLAY.dw[0]); + /* Check validity of routing indicator, only route on IP and SSN is supported */ + if ((pdu_word != uint16_t(ri_route_IP_SSN)) && + (pdu_word != uint16_t(ri_route_PC_SSN)) && + (pdu_word != uint16_t(ri_route_hostname))){ + /* Signal error : routing indicator not supported */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Routing Indicator not supported"; + return FALSE; + } + addr.rout_ind = Sua_rout_ind(pdu_word); + /* Address indicator */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + pdu_word = ntohs(OVERLAY.dw[1]); + if ((pdu_word & 0x01) != 0) + addr.ssn_incl = TRUE; + if ((pdu_word & 0x02) != 0) + addr.pc_incl = TRUE; + if ((pdu_word & 0x04) != 0) + addr.gt_incl = TRUE; + /* Address parameters */ + pdu_index += 4; // pdu_index points to first address parameter tag + par_len -= 8; // remaining address length + uint16_t addr_par_len, addr_par_tag; + uint32_t addr_par_val; + char* pdu_c; + while (par_len > 4) { + /* Evaluate address parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + addr_par_len = ntohs(OVERLAY.dw[1]); + /* Check for length overflow */ + if (addr_par_len <= par_len) { + /* Evaluate address parameter tag and decode or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + addr_par_tag = ntohs(OVERLAY.dw[0]); + switch (addr_par_tag) { + case 0x8001 : + /* Global Title not supported, so we jump over it */ + addr_par_len += (4 - (addr_par_len % 4)) % 4; // don't forget padding bytes + pdu_index += addr_par_len; // next tag + if (par_len >= addr_par_len) + par_len -= addr_par_len; // adjust remaining parameter length + else + par_len = 0; + break; + case 0x8002 : + /* SS7 Point code , length 8 bytes */ + if (addr_par_len == 8) { + /* Fill in point code address parameters */ + addr.pc_pres = TRUE; + pdu_index += 4; + for (int i = 0; i < 4; i++) + OVERLAY.db[3-i] = msg[pdu_index + i]; + addr.pc = OVERLAY.dq; + pdu_index += 4; // next tag + par_len -= 8; // adjust remaining parameter length + } + else { + /* Signal error : invalid point code parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid point code length"; + return FALSE; + } + break; + case 0x8003 : + /* SSN parameter, length 8 bytes */ + if (addr_par_len == 8) { + pdu_index += 4; + for (int i = 0; i < 4; i++) + OVERLAY.db[i] = msg[pdu_index + i]; + addr_par_val = ntohl(OVERLAY.dq); + if (addr_par_val <= 255) + addr.ssn = addr_par_val; + else + addr.ssn = 0; + pdu_index += 4; // next tag + par_len -= 8; // adjust remaining parameter length + } + else { + /* Signal error : invalid address parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid SSN length"; + return FALSE; + } + break; + case 0x8004 : + /* IPv4 address, length 8 bytes */ + if (addr_par_len == 8) { + /* Fill in IP address parameters */ + addr.ip_addr_pres = TRUE; + addr.ip_addr_type = ip_v4; + pdu_index += 4; + for (int i = 0; i < 4; i++) + OVERLAY.db[i] = msg[pdu_index + i]; + addr.ip_addr.ipv4.sin_addr.s_addr = OVERLAY.dq; + pdu_index += 4; // next tag + par_len -= 8; // adjust remaining parameter length + } + else { + /* Signal error : invalid address parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid IPv4 address length"; + return FALSE; + } + break; + case 0x8005 : + /* Hostname, variable length */ + addr_par_len += (4 - (addr_par_len % 4)) % 4; // don't forget padding bytes + addr.hostname_pres = TRUE; + next_tag_pdu_idx = pdu_index + addr_par_len; // next tag + j = 0; + numchar = 0; + // resize the string to receive the hostname in + addr.hostname.resize(addr_par_len - 6); + // get length of first label + pdu_index += 4; + OVERLAY.dq = 0; + OVERLAY.db[0] = msg[pdu_index]; + numchar = uint8_t(OVERLAY.db[0]); + //cout << "numchar = " << numchar << ", " << msg[pdu_index] << "\n"; + pdu_index++; // go to first char of label + look_for_next_label = (numchar != 0) && + ( pdu_index < next_tag_pdu_idx); + while (look_for_next_label) { + // copy contents of label into the string + for (unsigned int i = 0; i < numchar; i++){ + OVERLAY.db[0] = msg[pdu_index + i]; + addr.hostname[j] = OVERLAY.db[0]; + j++; + } + pdu_index += (numchar); // next label length field ? + // get length of next label + OVERLAY.db[0] = msg[pdu_index]; + numchar = uint8_t(OVERLAY.db[0]); + //cout << "numchar = " << numchar << ", j = " << j <<"\n"; + if (numchar != 0){ + addr.hostname[j]= '.'; + pdu_index++; // go to first char of label + j++; + } + /* else end of name */ + + look_for_next_label = (numchar != 0) && + ( pdu_index < next_tag_pdu_idx); + } + if (par_len >= addr_par_len) + par_len -= addr_par_len; // adjust remaining parameter length + else + par_len = 0; + /* set pdu_index onto next following tag of sua msg */ + pdu_index = next_tag_pdu_idx; + break; + case 0x8006 : + /* IPv6 address, length 20 bytes */ + if (addr_par_len == 20) { + /* Fill in IP address parameters */ + addr.ip_addr_pres = TRUE; + addr.ip_addr_type = ip_v6; + pdu_index += 4; + pdu_c = (char*) &addr.ip_addr.ipv6.sin6_addr.s6_addr; + for (int i = 0; i < 16; i++) { + *pdu_c = msg[pdu_index + i]; + pdu_c++; + } + pdu_index += 16; // next tag + par_len -= 20; // adjust remaining parameter length + } + else { + /* Signal error : invalid address parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid IPv6 address length"; + return FALSE; + } + break; + default : { + /* Jump over this unknown address parameter */ + addr_par_len += (4 - (addr_par_len % 4)) % 4; // don't forget padding bytes + pdu_index += addr_par_len; // next tag + if (par_len >= addr_par_len) + par_len -= addr_par_len; // adjust remaining parameter length + else + par_len = 0; + } + } // End switch address parameter tag + } + else { + /* Signal error : invalid address parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Address parameter length overflow"; + return FALSE; + } // End check valid address parameter length + } //End while address parameters present + } + else { + /* Signal error : address parameters missing */ + SYNTAX_ERR.msg_index = pdu_index + 4; + SYNTAX_ERR.error_text = "Decoding : Mandatory address parameters missing"; + return FALSE; + } + /* Address parameter check */ + /* An SSN different from "unknown" (0) and an IP address must be present */ + if (addr.ssn == 0) { + /* Signal error : unknown SSN */ + SYNTAX_ERR.error_text = "Decoding : SSN missing or unknown"; + return FALSE; + } + if (!addr.ip_addr_pres) { + /* Signal error : missing IP address */ + //SYNTAX_ERR.error_text = "Decoding : IP address missing"; + //return FALSE; + } + return TRUE; +} + +boolean decode_src_addr (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + boolean no_error = TRUE; + /* Clear source address */ + prim.source_addr.rout_ind = ri_reserved0; + prim.source_addr.ssn_incl = FALSE; + prim.source_addr.gt_incl = FALSE; + prim.source_addr.pc_incl = FALSE; + prim.source_addr.pc_pres = FALSE; + prim.source_addr.ip_addr_pres = FALSE; + prim.source_addr.gt_pres = FALSE; + prim.source_addr.hostname_pres = FALSE; + /* Decode source address */ + no_error = decode_addr (prim.source_addr, msg, pdu_index); + if (no_error) + prim.source_addr_pres = TRUE; + return no_error; +} + +boolean decode_dest_addr (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + boolean no_error = TRUE; + /* Clear destination address */ + prim.dest_addr.rout_ind = ri_reserved0; + prim.dest_addr.ssn_incl = FALSE; + prim.dest_addr.gt_incl = FALSE; + prim.dest_addr.pc_incl = FALSE; + prim.dest_addr.pc_pres = FALSE; + prim.dest_addr.ip_addr_pres = FALSE; + prim.dest_addr.gt_pres = FALSE; + prim.dest_addr.hostname_pres = FALSE; + /* Decode destination address */ + no_error = decode_addr (prim.dest_addr, msg, pdu_index); + if (no_error) + prim.dest_addr_pres = TRUE; + return no_error; +} + +boolean decode_source_ref (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode source reference */ + prim.source_ref_pres = TRUE; + pdu_index += 4; + for (int i = 0; i < 4; i++) { + OVERLAY.db[i] = msg[pdu_index + i]; + } + prim.source_ref = ntohl(OVERLAY.dq); + pdu_index += 4; // Next tag + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Source Reference length"; + return FALSE; + } +} + +boolean decode_dest_ref (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode destination reference */ + prim.dest_ref_pres = TRUE; + pdu_index += 4; + for (int i = 0; i < 4; i++) { + OVERLAY.db[i] = msg[pdu_index + i]; + } + prim.dest_ref = ntohl(OVERLAY.dq); + pdu_index += 4; // Next tag + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Destination Reference length"; + return FALSE; + } +} + +boolean decode_SCCP_cause (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode SCCP cause */ + pdu_index += 6; + /* Check cause type within range */ + OVERLAY.db[2] = msg[pdu_index]; + if ((OVERLAY.db[2] > uint8_t(ctp_reserved0)) && (OVERLAY.db[2] < uint8_t(ctp_max))) { + prim.SCCP_cause.cause_type = SCCP_cause_type(OVERLAY.db[2]); + prim.SCCP_cause.cause_value = msg[pdu_index + 1]; + pdu_index += 2; // Next tag + prim.SCCP_cause_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type"; + return FALSE; + } + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause length"; + return FALSE; + } +} + +boolean decode_seq_nr (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode sequence number */ + pdu_index += 6; + /* Clear sequence number, only interpret more data flag */ + prim.seq_nr.sent_seq_nr = 0; + prim.seq_nr.rcvd_seq_nr = 0; + prim.seq_nr.more_data = ((msg[pdu_index] & 0x01) != 0); + pdu_index += 2; // Next tag + prim.seq_nr_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Sequence Number length"; + return FALSE; + } +} + +boolean decode_asp_cap (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode ASP capabilities */ + pdu_index += 6; + /* Get supported protocol classes, at least protocol class 0 must be supported */ + prim.asp_cap.cl0_supp = (msg[pdu_index] && 0x01); + prim.asp_cap.cl1_supp = (msg[pdu_index] && 0x02); + prim.asp_cap.cl2_supp = (msg[pdu_index] && 0x04); + prim.asp_cap.cl3_supp = (msg[pdu_index] && 0x08); + if (!prim.asp_cap.cl0_supp) { + /* Signal error : basic protocol class not supported */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : No support of protocol class 0"; + return FALSE; + } + pdu_index++; + /* Check whether interworking type allowed */ + if (uint8_t(msg[pdu_index]) < uint8_t(iw_max)) { + prim.asp_cap.interworking = Sua_interworking_type(msg[pdu_index]); + } + else { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Invalid Interworking type"; + return FALSE; + } + pdu_index++; // next tag + prim.asp_cap_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid ASP capabilities length"; + return FALSE; + } +} + +boolean decode_seq_ctrl (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode sequence control */ + prim.seq_control_pres = TRUE; + pdu_index += 4; + for (int i = 0; i < 4; i++) { + OVERLAY.db[i] = msg[pdu_index + i]; + } + prim.seq_control = ntohl(OVERLAY.dq); + pdu_index += 4; // Next tag + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Sequence Control length"; + return FALSE; + } +} + +boolean decode_importance (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode importance */ + prim.importance = uint8_t(msg[pdu_index + 7]); + /* Check whether importance within range */ + if (prim.importance > 7) { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index + 7; + SYNTAX_ERR.error_text = "Decoding : Invalid Importance value"; + return FALSE; + } + pdu_index += 8; // next tag + prim.importance_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Importance length"; + return FALSE; + } +} + +boolean decode_prot_class (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode protocol class */ + uint8_t prot_cl = uint8_t(msg[pdu_index + 7]); + prim.prot_class.return_option = ((prot_cl & 0x80) != 0); + prot_cl &= 0x03; + prim.prot_class.pcl = Sua_protocol_class(prot_cl); + pdu_index += 8; // next tag + prim.prot_class_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Protocol Class length"; + return FALSE; + } +} + +boolean decode_segmentation (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + if (par_len == 8) { + /* Decode segmentation */ + uint8_t first_rem = uint8_t(msg[pdu_index + 4]); + prim.segm.first = ((first_rem & 0x80) != 0); + first_rem &= 0x0F; + prim.segm.remain = first_rem; + OVERLAY.db[0] = 0; + OVERLAY.db[1] = uint8_t(msg[pdu_index + 5]); + OVERLAY.db[2] = uint8_t(msg[pdu_index + 6]); + OVERLAY.db[3] = uint8_t(msg[pdu_index + 7]); + prim.segm.segm_ref = ntohl(OVERLAY.dq); + pdu_index += 8; // next tag + prim.segm_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid Segmentation length"; + return FALSE; + } +} + +boolean decode_TID_label (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + uint16_t max_label = 2; + if (par_len == 8) { + /* Decode TID label */ + prim.TID_label.start = uint8_t(msg[pdu_index + 4]); + prim.TID_label.end = uint8_t(msg[pdu_index + 5]); + OVERLAY.db[2] = uint8_t(msg[pdu_index + 6]); + OVERLAY.db[3] = uint8_t(msg[pdu_index + 7]); + prim.TID_label.label_value = ntohs(OVERLAY.dw[1]); + /* Check values */ + if ((prim.TID_label.start < 32) && (prim.TID_label.start >= prim.TID_label.end) + && ((prim.TID_label.start - prim.TID_label.end) < 16)) { + for (int i = 0; i < (prim.TID_label.start - prim.TID_label.end); i++) + max_label = max_label * 2; + if (prim.TID_label.label_value >= max_label) { + /* Signal error : paramater syntax error */ + SYNTAX_ERR.msg_index = pdu_index + 6; + SYNTAX_ERR.error_text = "Decoding : Invalid TID label"; + return FALSE; + } + } + else { + /* Signal error : parameter syntax error */ + SYNTAX_ERR.msg_index = pdu_index + 4; + SYNTAX_ERR.error_text = "Decoding : Invalid TID label position or length"; + return FALSE; + } + pdu_index += 8; // next tag + prim.TID_label_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid TID label length"; + return FALSE; + } +} + +boolean decode_DRN_label (Sua_primitive_struct& prim, string& msg, unsigned int& pdu_index) { + /* The parameter length should be 8 bytes */ + OVERLAY.db[0] = msg[pdu_index + 2]; + OVERLAY.db[1] = msg[pdu_index + 3]; + uint16_t par_len = ntohs(OVERLAY.dw[0]); + uint16_t max_label = 2; + if (par_len == 8) { + /* Decode DRN label */ + prim.DRN_label.start = uint8_t(msg[pdu_index + 4]); + prim.DRN_label.end = uint8_t(msg[pdu_index + 5]); + OVERLAY.db[2] = uint8_t(msg[pdu_index + 6]); + OVERLAY.db[3] = uint8_t(msg[pdu_index + 7]); + prim.DRN_label.label_value = ntohs(OVERLAY.dw[1]); + /* Check values */ + if ((prim.DRN_label.start < 32) && (prim.DRN_label.start >= prim.DRN_label.end) + && ((prim.DRN_label.start - prim.DRN_label.end) < 16)) { + for (int i = 0; i < (prim.DRN_label.start - prim.DRN_label.end); i++) + max_label = max_label * 2; + if (prim.DRN_label.label_value >= max_label) { + /* Signal error : paramater syntax error */ + SYNTAX_ERR.msg_index = pdu_index + 6; + SYNTAX_ERR.error_text = "Decoding : Invalid DRN label"; + return FALSE; + } + } + else { + /* Signal error : parameter syntax error */ + SYNTAX_ERR.msg_index = pdu_index + 4; + SYNTAX_ERR.error_text = "Decoding : Invalid DRN label position or length"; + return FALSE; + } + pdu_index += 8; // next tag + prim.DRN_label_pres = TRUE; + return TRUE; + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Invalid DRN label length"; + return FALSE; + } +} + +/* 2.2 Message decoding procedures */ + +/* 2.2.3 ASP Server Management messages */ + +boolean decode_ASP_up_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_down_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_beat_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0009 : + if (!prim.hb_data_pres) + no_error = decode_hb_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Heartbeat data parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_up_ack_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_down_ack_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_beat_ack_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0009 : + if (!prim.hb_data_pres) + no_error = decode_hb_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Heartbeat data parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +/* 2.2.4 ASP Traffic Management messages */ + +boolean decode_ASP_act_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x000B : + if (!prim.traf_mode_pres) + no_error = decode_traf_mode (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Traffic Mode type parameter"; + return FALSE; + } + break; + case 0x0119 : + if (!prim.TID_label_pres) + no_error = decode_TID_label (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate TID label parameter"; + return FALSE; + } + break; + case 0x011A : + if (!prim.DRN_label_pres) + no_error = decode_DRN_label (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate DRN label parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_inact_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_act_ack_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x000B : + if (!prim.traf_mode_pres) + no_error = decode_traf_mode (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Traffic Mode type parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +boolean decode_ASP_inact_ack_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; + /* Check whether further parameters are present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0004 : + if (!prim.info_pres) + no_error = decode_info (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Info parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End parameter length check + } // End while parameters present + + /* No checks for mandatory parameters are needed */ + return no_error; +} + +/* 2.2.7 Connectionless messages */ + +boolean decode_cl_data_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0003 : + if (!prim.data_pres) + no_error = decode_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0101 : + if (!prim.hop_count_pres) + no_error = decode_hop_count (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Hop Counter parameter"; + return FALSE; + } + break; + case 0x0102 : + if (!prim.source_addr_pres) + no_error = decode_src_addr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Address parameter"; + return FALSE; + } + break; + case 0x0103 : + if (!prim.dest_addr_pres) + no_error = decode_dest_addr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter"; + return FALSE; + } + break; + case 0x0116 : /* tag may change, see SUA v9 */ + if (!prim.seq_control_pres) + no_error = decode_seq_ctrl (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Sequence Control parameter"; + return FALSE; + } + break; + case 0x0113 : + if (!prim.importance_pres) + no_error = decode_importance (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter"; + return FALSE; + } + break; + case 0x0115 : + if (!prim.prot_class_pres) + no_error = decode_prot_class (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter"; + return FALSE; + } + if (no_error && (prim.prot_class.pcl != prot_class_0) && (prim.prot_class.pcl != prot_class_1)) { + /* Signal error : invalid protocol class */ + SYNTAX_ERR.msg_index = pdu_index - 1; + SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connectionless msg"; + return FALSE; + } + break; + case 0x0117 : + if (!prim.segm_pres) + no_error = decode_segmentation (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Segmentation parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Protocol class + - Source address + - Destination address + - Sequence control + - Data + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.prot_class_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing"; + return FALSE; + } + if (no_error && !prim.source_addr_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Source Address missing"; + return FALSE; + } + if (no_error && !prim.dest_addr_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Address missing"; + return FALSE; + } + if (no_error && !prim.seq_control_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Sequence Control missing"; + return FALSE; + } + if (no_error && !prim.data_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Data missing"; + return FALSE; + } + return no_error; +} + +boolean decode_cl_data_resp_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0003 : + if (!prim.data_pres) + no_error = decode_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0101 : + if (!prim.hop_count_pres) + no_error = decode_hop_count (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Hop Counter parameter"; + return FALSE; + } + break; + case 0x0102 : + if (!prim.source_addr_pres) + no_error = decode_src_addr(prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Address parameter"; + return FALSE; + } + break; + case 0x0103 : + if (!prim.dest_addr_pres) + no_error = decode_dest_addr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter"; + return FALSE; + } + break; + case 0x0106 : + if (!prim.SCCP_cause_pres) + no_error = decode_SCCP_cause (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter"; + return FALSE; + } + if (no_error && (prim.SCCP_cause.cause_type != ctp_return_cause)) { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index - 2; + SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for connectionless msg"; + return FALSE; + } + break; + case 0x0113 : + if (!prim.importance_pres) + no_error = decode_importance (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - SCCP Cause + - Source address + - Destination address + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.SCCP_cause_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing"; + return FALSE; + } + if (no_error && !prim.source_addr_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Source Address missing"; + return FALSE; + } + if (no_error && !prim.dest_addr_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Address missing"; + return FALSE; + } + return no_error; +} + +/* 2.2.8 Connection-oriented messages */ +/* Only protocol class 2 messages are supported */ + +boolean decode_co_conn_req_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0003 : + if (!prim.data_pres) + no_error = decode_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0101 : + if (!prim.hop_count_pres) + no_error = decode_hop_count (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Hop Counter parameter"; + return FALSE; + } + break; + case 0x0102 : + if (!prim.source_addr_pres) + no_error = decode_src_addr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Address parameter"; + return FALSE; + } + break; + case 0x0103 : + if (!prim.dest_addr_pres) + no_error = decode_dest_addr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter"; + return FALSE; + } + break; + case 0x0104 : + if (!prim.source_ref_pres) + no_error = decode_source_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter"; + return FALSE; + } + break; + case 0x0113 : + if (!prim.importance_pres) + no_error = decode_importance (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter"; + return FALSE; + } + break; + case 0x0115 : + if (!prim.prot_class_pres) + no_error = decode_prot_class (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter"; + return FALSE; + } + prim.prot_class.return_option = FALSE; + if (no_error && (prim.prot_class.pcl != prot_class_2) && (prim.prot_class.pcl != prot_class_3)) { + /* Signal error : invalid protocol class */ + SYNTAX_ERR.msg_index = pdu_index - 1; + SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connection-oriented msg"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Protocol class + - Source reference + - Destination address + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.prot_class_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing"; + return FALSE; + } + if (no_error && !prim.source_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing"; + return FALSE; + } + if (no_error && !prim.dest_addr_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Address missing"; + return FALSE; + } + return no_error; +} + +boolean decode_co_conn_ack_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0003 : + if (!prim.data_pres) + no_error = decode_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0103 : + if (!prim.dest_addr_pres) + no_error = decode_dest_addr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter"; + return FALSE; + } + break; + case 0x0104 : + if (!prim.source_ref_pres) + no_error = decode_source_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter"; + return FALSE; + } + break; + case 0x0105 : + if (!prim.dest_ref_pres) + no_error = decode_dest_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter"; + return FALSE; + } + break; + case 0x0113 : + if (!prim.importance_pres) + no_error = decode_importance (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter"; + return FALSE; + } + break; + case 0x0115 : + if (!prim.prot_class_pres) + no_error = decode_prot_class (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter"; + return FALSE; + } + prim.prot_class.return_option = FALSE; + if (no_error && (prim.prot_class.pcl != prot_class_2) && (prim.prot_class.pcl != prot_class_3)) { + /* Signal error : invalid protocol class */ + SYNTAX_ERR.msg_index = pdu_index - 1; + SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connection-oriented msg"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Protocol class + - Destination reference + - Source reference + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.prot_class_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing"; + return FALSE; + } + if (no_error && !prim.dest_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing"; + return FALSE; + } + if (no_error && !prim.source_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing"; + return FALSE; + } + return no_error; +} + +boolean decode_co_conn_ref_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0003 : + if (!prim.data_pres) + no_error = decode_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0103 : + if (!prim.dest_addr_pres) + no_error = decode_dest_addr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Address parameter"; + return FALSE; + } + break; + case 0x0105 : + if (!prim.dest_ref_pres) + no_error = decode_dest_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter"; + return FALSE; + } + break; + case 0x0106 : + if (!prim.SCCP_cause_pres) + no_error = decode_SCCP_cause (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter"; + return FALSE; + } + if (no_error && (prim.SCCP_cause.cause_type != ctp_refusal_cause)) { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index - 2; + SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for connection refused msg"; + return FALSE; + } + break; + case 0x0113 : + if (!prim.importance_pres) + no_error = decode_importance (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Destination reference + - SCCP cause + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.dest_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing"; + return FALSE; + } + if (no_error && !prim.SCCP_cause_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing"; + return FALSE; + } + return no_error; +} + +boolean decode_co_rel_req_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0003 : + if (!prim.data_pres) + no_error = decode_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0104 : + if (!prim.source_ref_pres) + no_error = decode_source_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter"; + return FALSE; + } + break; + case 0x0105 : + if (!prim.dest_ref_pres) + no_error = decode_dest_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter"; + return FALSE; + } + break; + case 0x0106 : + if (!prim.SCCP_cause_pres) + no_error = decode_SCCP_cause (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter"; + return FALSE; + } + if (no_error && (prim.SCCP_cause.cause_type != ctp_release_cause)) { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index - 2; + SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for release req msg"; + return FALSE; + } + break; + case 0x0113 : + if (!prim.importance_pres) + no_error = decode_importance (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Destination reference + - Source reference + - SCCP cause + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.dest_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing"; + return FALSE; + } + if (no_error && !prim.source_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing"; + return FALSE; + } + if (no_error && !prim.SCCP_cause_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing"; + return FALSE; + } + return no_error; +} + +boolean decode_co_rel_conf_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0104 : + if (!prim.source_ref_pres) + no_error = decode_source_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter"; + return FALSE; + } + break; + case 0x0105 : + if (!prim.dest_ref_pres) + no_error = decode_dest_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter"; + return FALSE; + } + break; + case 0x0113 : + if (!prim.importance_pres) + no_error = decode_importance (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Importance parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Destination reference + - Source reference + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.dest_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing"; + return FALSE; + } + if (no_error && !prim.source_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing"; + return FALSE; + } + return no_error; +} + +boolean decode_co_data_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0003 : + if (!prim.data_pres) + no_error = decode_data (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Data parameter"; + return FALSE; + } + break; + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0105 : + if (!prim.dest_ref_pres) + no_error = decode_dest_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter"; + return FALSE; + } + break; + case 0x0107 : + if (!prim.seq_nr_pres) + no_error = decode_seq_nr (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Sequence Number parameter"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Sequence number + - Destination reference + - Data + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.seq_nr_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Sequence Number missing"; + return FALSE; + } + if (no_error && !prim.dest_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing"; + return FALSE; + } + if (no_error && !prim.data_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Data missing"; + return FALSE; + } + return no_error; +} + +boolean decode_co_err_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0105 : + if (!prim.dest_ref_pres) + no_error = decode_dest_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter"; + return FALSE; + } + break; + case 0x0106 : + if (!prim.SCCP_cause_pres) + no_error = decode_SCCP_cause (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate SCCP Cause parameter"; + return FALSE; + } + if (no_error && (prim.SCCP_cause.cause_type != ctp_error_cause)) { + /* Signal error : invalid parameter value */ + SYNTAX_ERR.msg_index = pdu_index - 2; + SYNTAX_ERR.error_text = "Decoding : Invalid SCCP Cause type for error msg"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Destination reference + - SCCP cause + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.dest_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing"; + return FALSE; + } + if (no_error && !prim.SCCP_cause_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter SCCP Cause missing"; + return FALSE; + } + return no_error; +} + +boolean decode_co_it_msg (Sua_primitive_struct& prim, string& msg) { + boolean no_error = TRUE; + uint32_t msg_len = ntohl(OVERLAY.dq); + unsigned int pdu_index = 8; // Start with first tag + /* Check whether a further parameter is present, at least tag & length fields must be there */ + uint16_t par_tag, par_len; + while ((msg_len >= (pdu_index + 3)) && no_error) { + /* Evaluate parameter length */ + OVERLAY.db[2] = msg[pdu_index + 2]; + OVERLAY.db[3] = msg[pdu_index + 3]; + par_len = ntohs(OVERLAY.dw[1]); + if ((pdu_index + par_len) <= msg_len) { + /* Evaluate parameter tag and call corresponding decoding routine or jump over it */ + OVERLAY.db[0] = msg[pdu_index]; + OVERLAY.db[1] = msg[pdu_index + 1]; + par_tag = ntohs(OVERLAY.dw[0]); + switch (par_tag) { + case 0x0006 : + if (!prim.rout_con_pres) + no_error = decode_rout_con (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Routing Context parameter"; + return FALSE; + } + break; + case 0x0104 : + if (!prim.source_ref_pres) + no_error = decode_source_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Source Reference parameter"; + return FALSE; + } + break; + case 0x0105 : + if (!prim.dest_ref_pres) + no_error = decode_dest_ref (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Destination Reference parameter"; + return FALSE; + } + break; + case 0x0115 : + if (!prim.prot_class_pres) + no_error = decode_prot_class (prim, msg, pdu_index); + else { + /* Signal error : duplicate parameter */ + SYNTAX_ERR.msg_index = pdu_index; + SYNTAX_ERR.error_text = "Decoding : Duplicate Protocol Class parameter"; + return FALSE; + } + prim.prot_class.return_option = FALSE; + if (no_error && (prim.prot_class.pcl != prot_class_2) && (prim.prot_class.pcl != prot_class_3)) { + /* Signal error : invalid protocol class */ + SYNTAX_ERR.msg_index = pdu_index - 1; + SYNTAX_ERR.error_text = "Decoding : Invalid protocol class for connection-oriented msg"; + return FALSE; + } + break; + default : { + /* Jump over this totally uninteresting parameter to next double word position */ + par_len += (4 - (par_len % 4)) % 4; + pdu_index += par_len; + } + } // End switch parameter tag + } + else { + /* Signal error : invalid parameter length */ + SYNTAX_ERR.msg_index = pdu_index + 2; + SYNTAX_ERR.error_text = "Decoding : Parameter length overflow"; + return FALSE; + } // End check valid parameter length + } // End while parameters present + + /* Start checks for mandatory parameters : + - Protocol class + - Destination reference + - Source reference + The local syntax is filled out unless an error has occurred. + */ + if (no_error && !prim.prot_class_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Protocol Class missing"; + return FALSE; + } + if (no_error && !prim.dest_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Destination Reference missing"; + return FALSE; + } + if (no_error && !prim.source_ref_pres) { + /* Signal error : mandatory parameter missing */ + SYNTAX_ERR.error_text = "Decoding : Parameter Source Reference missing"; + return FALSE; + } + return no_error; +} + +/* 2.3 Sua decoding method */ +Sua_syntax_error_struct Sua_container::sua_decode () { + + /* Syntax Error struct initialization */ + SYNTAX_ERR.msg_index = 0; + SYNTAX_ERR.no_error = TRUE; + SYNTAX_ERR.error_text = "Decoding no error"; + + /* Decoding variables */ + uint8_t pdu_byte; + boolean no_error = TRUE; + + /* Initialize primitive container to clean up old mess */ + this->sua_init (); + + /* Start decoding message header, at least 8 bytes must be present */ + uint32_t msg_len; + if (sua_msg.size() >= 8) { + for (int i = 0; i < 4; i++) + OVERLAY.db[i] = sua_msg[i + 4]; + msg_len = ntohl(OVERLAY.dq); + } + else + msg_len = 0; + if ((msg_len >= 8) && (msg_len <= sua_msg.size())) { + /* Check Sua version, only version 1 is supported */ + pdu_byte = uint8_t(sua_msg[0]); + if (pdu_byte == uint8_t(Sua_version1)) { + sua_prim.hdr_version = Sua_version1; + /* Check message class and type, with call to corresponding msg decoding procedure */ + pdu_byte = uint8_t(sua_msg[2]); + switch (pdu_byte) { + case uint8_t(sua_aspsm) : + sua_prim.hdr_msg_class = sua_aspsm; + /* Check ASP server management msg type */ + pdu_byte = uint8_t(sua_msg[3]); + switch (pdu_byte) { + case uint8_t(aspsm_up) : + sua_prim.hdr_msg_type.aspsm = aspsm_up; + no_error = decode_ASP_up_msg (sua_prim, sua_msg); + break; + case uint8_t(aspsm_down) : + sua_prim.hdr_msg_type.aspsm = aspsm_down; + no_error = decode_ASP_down_msg (sua_prim, sua_msg); + break; + case uint8_t(aspsm_beat) : + sua_prim.hdr_msg_type.aspsm = aspsm_beat; + no_error = decode_ASP_beat_msg (sua_prim, sua_msg); + break; + case uint8_t(aspsm_up_ack) : + sua_prim.hdr_msg_type.aspsm = aspsm_up_ack; + no_error = decode_ASP_up_ack_msg (sua_prim, sua_msg); + break; + case uint8_t(aspsm_down_ack) : + sua_prim.hdr_msg_type.aspsm = aspsm_down_ack; + no_error = decode_ASP_down_ack_msg (sua_prim, sua_msg); + break; + case uint8_t(aspsm_beat_ack) : + sua_prim.hdr_msg_type.aspsm = aspsm_beat_ack; + no_error = decode_ASP_beat_ack_msg (sua_prim, sua_msg); + break; + default : { + sua_prim.hdr_msg_type.aspsm = aspsm_reserved0; + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Decoding : Invalid ASP server management message type"; + no_error = FALSE; + } + } // End switch aspsm msg + break; + case uint8_t(sua_asptm) : + sua_prim.hdr_msg_class = sua_asptm; + /* Check ASP traffic management msg type */ + pdu_byte = uint8_t(sua_msg[3]); + switch (pdu_byte) { + case uint8_t(asptm_act) : + sua_prim.hdr_msg_type.asptm = asptm_act; + no_error = decode_ASP_act_msg (sua_prim, sua_msg); + break; + case uint8_t(asptm_inact) : + sua_prim.hdr_msg_type.asptm = asptm_inact; + no_error = decode_ASP_inact_msg (sua_prim, sua_msg); + break; + case uint8_t(asptm_act_ack) : + sua_prim.hdr_msg_type.asptm = asptm_act_ack; + no_error = decode_ASP_act_ack_msg (sua_prim, sua_msg); + break; + case uint8_t(asptm_inact_ack) : + sua_prim.hdr_msg_type.asptm = asptm_inact_ack; + no_error = decode_ASP_inact_ack_msg (sua_prim, sua_msg); + break; + default : { + sua_prim.hdr_msg_type.asptm = asptm_reserved0; + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Decoding : Invalid connectionless message type"; + no_error = FALSE; + } + } // End switch asptm msg + break; + case uint8_t(sua_cl): + sua_prim.hdr_msg_class = sua_cl; + /* Check connectionless msg type */ + pdu_byte = uint8_t(sua_msg[3]); + switch (pdu_byte) { + case uint8_t(cl_data_transfer) : + sua_prim.hdr_msg_type.cl = cl_data_transfer; + no_error = decode_cl_data_msg (sua_prim, sua_msg); + break; + case uint8_t(cl_data_response) : + sua_prim.hdr_msg_type.cl = cl_data_response; + no_error = decode_cl_data_resp_msg (sua_prim, sua_msg); + break; + default : { + sua_prim.hdr_msg_type.cl = cl_reserved0; + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Decoding : Invalid connectionless message type"; + no_error = FALSE; + } + } // End switch cl msg + break; + case uint8_t(sua_co) : + sua_prim.hdr_msg_class = sua_co; + /* Check connection-oriented msg type */ + pdu_byte = uint8_t(sua_msg[3]); + switch (pdu_byte) { + case uint8_t(co_core) : + sua_prim.hdr_msg_type.co = co_core; + no_error = decode_co_conn_req_msg (sua_prim, sua_msg); + break; + case uint8_t(co_coak) : + sua_prim.hdr_msg_type.co = co_coak; + no_error = decode_co_conn_ack_msg (sua_prim, sua_msg); + break; + case uint8_t(co_coref) : + sua_prim.hdr_msg_type.co = co_coref; + no_error = decode_co_conn_ref_msg (sua_prim, sua_msg); + break; + case uint8_t(co_relre) : + sua_prim.hdr_msg_type.co = co_relre; + no_error = decode_co_rel_req_msg (sua_prim, sua_msg); + break; + case uint8_t(co_relco) : + sua_prim.hdr_msg_type.co = co_relco; + no_error = decode_co_rel_conf_msg (sua_prim, sua_msg); + break; + case uint8_t(co_data) : + sua_prim.hdr_msg_type.co = co_data; + no_error = decode_co_data_msg (sua_prim, sua_msg); + break; + case uint8_t(co_err) : + sua_prim.hdr_msg_type.co = co_err; + no_error = decode_co_err_msg (sua_prim, sua_msg); + break; + case uint8_t(co_it) : + sua_prim.hdr_msg_type.co = co_it; + no_error = decode_co_it_msg (sua_prim, sua_msg); + break; + default : { + sua_prim.hdr_msg_type.co = co_reserved0; + /* Signal error : invalid message type */ + SYNTAX_ERR.msg_index = 3; + SYNTAX_ERR.error_text = "Decoding : Invalid connection-oriented message type"; + no_error = FALSE; + } + } // End switch co msg + break; + default : { + /* Signal error : invalid message class */ + SYNTAX_ERR.msg_index = 2; + SYNTAX_ERR.error_text = "Decoding : Unknown message class"; + no_error = FALSE; + } + } // End msg class switch + } + else { + sua_prim.hdr_version = Sua_unknown; + /* Signal error : invalid Sua version */ + SYNTAX_ERR.msg_index = 0; + SYNTAX_ERR.error_text = "Decoding : Invalid Sua version"; + no_error = FALSE; + } // Endif version + } + else { + /* Signal error : invalid message length */ + SYNTAX_ERR.msg_index = 4; + SYNTAX_ERR.error_text = "Decoding : Invalid message length"; + no_error = FALSE; + } // Endif msg length + + if (!no_error) { + /* Printout error text */ + SYNTAX_ERR.no_error = FALSE; + cout << "Error position = " << SYNTAX_ERR.msg_index << endl; + cout << SYNTAX_ERR.error_text << endl; + } + return SYNTAX_ERR; +} + + + + ///:~ + + + + + + diff --git a/sualibrary/sua/sua_syntax.h b/sualibrary/sua/sua_syntax.h new file mode 100644 index 0000000..0295a8f --- /dev/null +++ b/sualibrary/sua/sua_syntax.h @@ -0,0 +1,447 @@ +/*************************************************************************** + sua_syntax.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_syntax.h,v 1.1.1.1 2002/02/04 14:30:41 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 5. + * + * Author(s): Gery Verwimp + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Kathleen + * "Computers/networks must be female, because if they were male, " + * "they would be perfectably predictable and computers/networks are " + * "never predictable. If you do not believe this, just ask any women." + * + * Purpose: This header-file defines the SUA syntax class for SUA + * primitives and messages, including the en/decoding routines. + */ + +#ifndef SUA_SYNTAX_H +#define SUA_SYNTAX_H + +#include "sua.h" +#include + +/********************************/ +/* 0. SUA message header syntax */ +/********************************/ + +enum Sua_version { + Sua_unknown, + Sua_version1 +}; + +enum Sua_msg_class { + sua_mngt, + sua_reserved1, + sua_ssnm, + sua_aspsm, + sua_asptm, + sua_reserved5, + sua_reserved6, + sua_cl, + sua_co, + sua_rkm, + sua_max +}; + +enum Sua_mngt_msg_type { + mngt_error, + mngt_notify, + mngt_max +}; + +enum Sua_ssnm_msg_type { + ssnm_reserved0, + ssnm_duna, + ssnm_dava, + ssnm_daud, + ssnm_scon, + ssnm_dupu, + ssnm_drst, + ssnm_max +}; + +enum Sua_aspsm_msg_type { + aspsm_reserved0, + aspsm_up, + aspsm_down, + aspsm_beat, + aspsm_up_ack, + aspsm_down_ack, + aspsm_beat_ack, + aspsm_max +}; + +enum Sua_asptm_msg_type { + asptm_reserved0, + asptm_act, + asptm_inact, + asptm_act_ack, + asptm_inact_ack, + asptm_max +}; + +enum Sua_cl_msg_type { + cl_reserved0, + cl_data_transfer, /* unitdata */ + cl_data_response, /* unitdata service */ + cl_max +}; + +enum Sua_co_msg_type { + co_reserved0, + co_core, /* connection request */ + co_coak, /* connection confirm */ + co_coref, /* connection refused */ + co_relre, /* release request */ + co_relco, /* release confirm */ + co_resco, /* reset confirm */ + co_resre, /* reset request */ + co_data, /* data transfer, expedited data */ + co_data_ack, /* (expedited) data acknowledge */ + co_err, /* PDU error */ + co_it, /* inactivity test */ + co_max +}; + +enum Sua_rkm_msg_type { + rkm_reserved0, + rkm_reg_req, /* registration request */ + rkm_reg_resp, /* registration response */ + rkm_dereg_req, /* deregistration request */ + rkm_dereg_resp, /* deregistration response */ + rkm_max +}; + +union Sua_msg_type { + Sua_mngt_msg_type mngt; + Sua_ssnm_msg_type ssnm; + Sua_aspsm_msg_type aspsm; + Sua_asptm_msg_type asptm; + Sua_cl_msg_type cl; + Sua_co_msg_type co; + Sua_rkm_msg_type rkm; +}; + +/***********************************/ +/* 1. SUA management message modes */ +/***********************************/ + +enum Sua_traffic_mode_type { + tmt_unknown, + tmt_override, + tmt_loadshare, + tmt_broadcast, + tmt_max +}; + +enum Sua_error_code_type { + ect_unknown, + ect_invalid_version, + ect_invalid_interface_id, + ect_unsupported_msg_class, + ect_unsupported_msg_type, + ect_unsupported_traffic_handling_mode, + ect_unexpected_msg, + ect_protocol_error, + ect_unsupported_interface_id_type, /* not used in SUA */ + ect_invalid_stream_id, + ect_unassigned_TEI, /* not used in SUA */ + ect_unrecognized_SAPI, /* not used in SUA */ + ect_invalid_TEI_SAPI_comb, /* not used in SUA */ + ect_refused_mngt_blocking, + ect_ASP_id_required, + ect_invalid_ASP_id, + ect_invalid_routing_context, + ect_invalid_parameter_value, + ect_parameter_field_error, + ect_unexpected_parameter, + ect_destination_status_unknown, + ect_invalid_network_appearance, + ect_missing_parameter, + ect_routing_key_change_refused, + ect_invalid_loadsharing_label, + ect_max +}; + +typedef struct { + uint8_t status_type; + uint8_t status_ID; +} Sua_status_struct; + +/* ASP capabilities */ + +enum Sua_interworking_type { + iw_none, /* no interworking with SS7 */ + iw_asp, /* IP endpoint ASP */ + iw_sg, /* Signalling Gateway */ + iw_relay, /* IP relay point */ + iw_max +}; + +typedef struct { + boolean cl0_supp; + boolean cl1_supp; + boolean cl2_supp; + boolean cl3_supp; + uint8_t interworking; +} Sua_asp_cap_struct; + +/*********************************/ +/* 2. SUA protocol message modes */ +/*********************************/ + +enum Sua_protocol_class { + prot_class_0, + prot_class_1, + prot_class_2, + prot_class_3, + prot_max +}; + +typedef struct { + Sua_protocol_class pcl; + boolean return_option; +} Sua_protocol_class_struct; + +/* The SUA address parameter contains following fields : + - routing indicator : see below + - address indicator : for SS7 interworking, defines inclusion of SSN, PC or GT in SS7 address + - address parameters : combination of GT, hostname, IPaddress, SSN, PC +*/ + +enum Sua_rout_ind { + ri_reserved0, + ri_route_GT, + ri_route_PC_SSN, + ri_route_hostname, + ri_route_IP_SSN, + ri_max +}; + +typedef struct { + uint8_t translation_type; + uint8_t num_plan; + uint8_t nat_addr; + uint8_t nr_of_digits; + uint8_t digits[24]; +} SCCP_GT_struct; + +enum Sua_ip_addr_type { + ip_reserved0, + ip_v4, + ip_v6, + ip_max +}; + +union Ip_address { + sockaddr_in ipv4; + sockaddr_in6 ipv6; +}; + +typedef struct { + Sua_rout_ind rout_ind; + /* Flags for address indicator */ + boolean ssn_incl; + boolean gt_incl; + boolean pc_incl; + /* Indication of elements present */ + boolean pc_pres; + boolean ip_addr_pres; + boolean gt_pres; + boolean hostname_pres; + /* An SSN must always be present on the primitive interface, even if unknown (=0) */ + uint8_t ssn; + int pc; + Sua_ip_addr_type ip_addr_type; + Ip_address ip_addr; + SCCP_GT_struct gt; + string hostname; +} Sua_address_struct; + +/* The SCCP Cause parameter can contain the following : + - return cause (in CLDR messages) + - refusal cause (in COREF messages) + - release cause (in RELRE messages) + - reset cause (in RESRE messages) + - error cause (in COERR messages) +*/ +enum SCCP_cause_type { + ctp_reserved0, + ctp_return_cause, + ctp_refusal_cause, + ctp_release_cause, + ctp_reset_cause, + ctp_error_cause, + ctp_max +}; + +typedef struct { + SCCP_cause_type cause_type; + uint16_t cause_value; +} SCCP_cause_struct; + +/* The sequence number parameter contains : + - the sent and received seq numbers (0..127) for protocol class 3 + - the more data indicator for protocol classes 2 and 3 +*/ + +typedef struct { + uint8_t sent_seq_nr; + uint8_t rcvd_seq_nr; + boolean more_data; +} Sua_seq_nr_struct; + +/* The segmentation parameter contains : + - first segment indication + - number of remaining segments (0..15) + - segmentation reference (0..2~24-1) +*/ + +typedef struct { + boolean first; + uint8_t remain; + uint32_t segm_ref; +} Sua_segm_struct; + +/* The label parameter contains : + - start of the label bits (0..31) + - end of the label bits (0..31) + - label value (0..2~16-1) +*/ + +typedef struct { + uint8_t start; + uint8_t end; + uint16_t label_value; +} Sua_label_struct; + +/* And now, we present to you the SUA container, mother of all interfaces */ + +typedef struct { + /* 0. Mandatory header */ + Sua_version hdr_version; + Sua_msg_class hdr_msg_class; + Sua_msg_type hdr_msg_type; + /* 1. Common parameter part presence */ + boolean data_pres; + boolean info_pres; + boolean rout_con_pres; + boolean diag_info_pres; + boolean hb_data_pres; + boolean traf_mode_pres; + boolean err_code_pres; + boolean status_pres; + boolean cong_lvl_pres; + boolean ASP_id_pres; + boolean aff_pc_pres; + /* 1. Common parameter part */ + string data_string; + string info_string; + uint32_t rout_con; + string diag_info; + string hb_data; + Sua_traffic_mode_type traf_mode; + Sua_error_code_type err_code; + Sua_status_struct status; + uint8_t cong_lvl; + uint32_t ASP_id; + uint32_t aff_pc; + /* 2. SUA specific parameter part presence */ + boolean netw_app_pres; + boolean hop_count_pres; + boolean source_addr_pres; + boolean dest_addr_pres; + boolean source_ref_pres; + boolean dest_ref_pres; + boolean SCCP_cause_pres; + boolean seq_nr_pres; + boolean rec_seq_nr_pres; + boolean asp_cap_pres; + boolean credit_pres; + boolean importance_pres; + boolean prot_class_pres; + boolean seq_control_pres; + boolean segm_pres; + boolean TID_label_pres; + boolean DRN_label_pres; + /* 2. SUA specific parameter part */ + uint32_t netw_app; + Sua_address_struct source_addr; + Sua_address_struct dest_addr; + uint32_t source_ref; + uint32_t dest_ref; + SCCP_cause_struct SCCP_cause; + Sua_seq_nr_struct seq_nr; + Sua_asp_cap_struct asp_cap; + Sua_protocol_class_struct prot_class; + uint8_t hop_count; + uint8_t rec_seq_nr; + uint8_t credit; + uint8_t importance; + uint32_t seq_control; + Sua_segm_struct segm; + Sua_label_struct TID_label; + Sua_label_struct DRN_label; +} Sua_primitive_struct; + +typedef struct { + int msg_index; // position in transfer syntax + boolean no_error; + string error_text; // error text, specifying details +} Sua_syntax_error_struct; + +class Sua_container { + public: + Sua_primitive_struct sua_prim; + string sua_msg; + void sua_init (); + Sua_syntax_error_struct sua_encode (); + Sua_syntax_error_struct sua_decode (); +}; + +#endif // SUA_SYNTAX_H + + + + + + diff --git a/sualibrary/sua/sua_tcb.cpp b/sualibrary/sua/sua_tcb.cpp new file mode 100644 index 0000000..e896cb1 --- /dev/null +++ b/sualibrary/sua/sua_tcb.cpp @@ -0,0 +1,218 @@ +/*************************************************************************** + sua_tcb.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_tcb.cpp,v 1.1.1.1 2002/02/04 14:30:42 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Daphne + * "Listen very carefully, I shall say this only once:" + * "a TCB, a TCB, my kingdom for a TCB" + * + * Purpose: This code-file defines the SUA Transaction Control Block(TCB) pool + * functions for(needed for SUA connection oriented): + * - initialising a single TCB + * - initialising the TCB pool + * - allocate a TCB + * - get a TCB + * - release a TCB + * And for the Saved SUA msg queue pool + * - add SUA msg to queue + * - get sua msg from queue + * - release the SUA msg from the queue + */ + +#include "sua_debug.h" +#include "sua_tcb.h" +#include "sua_database.h" +#include "sua_logging.h" +#include "sua.h" + +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include + +using namespace std; + +/* sua SCOC tcb pool */ +tcb_Sua_TCB_arr tcb_pool; + +/* sua temporary message store */ +tcb_Sua_msgqueue_pool msg_store; + +/***********************************************************************/ +/* Sua SCOC TCB: initialise TCB element */ +/***********************************************************************/ +void tcb_Sua_TCB_str::init_TCB_elem() +{ + state = scoc_idle; + Dest_LR = 0; + Source_LR = 0; + User_ref_id = 0; + sctp_Association_id = 0; + prcl_class = class0 ; + return_option = FALSE; +} + +/***********************************************************************/ +/* Sua SCOC TCB arr: initialise TCB pool */ +/***********************************************************************/ +void tcb_Sua_TCB_arr::init_TCB_pool() +{ + cout << "Initialising ?? \n"; + last_allocated_tcb = 0; +} + + +/***********************************************************************/ +/* Sua SCOC TCB arr: allocate a TCB */ +/***********************************************************************/ +tcb_Sua_TCB_str *tcb_Sua_TCB_arr:: allocate_TCB(unsigned int &local_ref){ + + last_allocated_tcb++; + // allocate the TCB + tcb_Sua_TCB_str new_tcb; + new_tcb.init_TCB_elem(); + tcb_sua_pair_str tcb_ref_pair(last_allocated_tcb,new_tcb); + + tcb_sua_map_iterator_str p = tcb.insert(tcb_ref_pair); + + if (p.second) + { + char logstring[100]; + sprintf(logstring, "TCB %d allocated",last_allocated_tcb); + event_log("sua_tcb.c",logstring); + } + else + { + char logstring[100]; + sprintf(logstring, "No TCB allocated, damm"); + event_log("sua_tcb.c",logstring); + } + + local_ref = last_allocated_tcb; + cout << "tcb local ref = " << local_ref << "\n"; + return(&tcb[last_allocated_tcb]); +} + +/***********************************************************************/ +/* Sua SCOC TCB arr: get address of TCB */ +/***********************************************************************/ +tcb_Sua_TCB_str *tcb_Sua_TCB_arr:: get_tcb(unsigned int local_ref) { + + return(&tcb[local_ref]); +} + +/***********************************************************************/ +/* Sua SCOC TCB arr: release the TCB */ +/***********************************************************************/ +void tcb_Sua_TCB_arr:: release_TCB(unsigned int local_reference){ + + int count = tcb.erase(local_reference); + + if (count != 0) + { + char logstring[100]; + sprintf(logstring, "TCB instances %d of LR %d Released : ",count,local_reference); + event_log("sua_tcb.c",logstring); + } + else + { + char logstring[100]; + sprintf(logstring, "TCB instance not released"); + event_log("sua_tcb.c",logstring); + } + +} + +/***********************************************************************/ +/* Sua_msg : save msg */ +/***********************************************************************/ +void tcb_Sua_msgqueue_pool:: add_msg( unsigned int sua_assoc_idx, + tcb_Sua_msg_elem sua_msg + ) +{ + sua_msg.valid = true; + msg_store.instance[sua_assoc_idx].push(sua_msg); +} + +/***********************************************************************/ +/* Sua_msg : get msg */ +/***********************************************************************/ +tcb_Sua_msg_elem tcb_Sua_msgqueue_pool:: get_msg( unsigned int sua_assoc_idx ) +{ + tcb_Sua_msg_elem temp_sua_msg; + + temp_sua_msg.valid = false; + if ( !msg_store.instance[sua_assoc_idx].empty() ) + { + return( msg_store.instance[sua_assoc_idx].front()); + } + else + { + + return(temp_sua_msg); + } +} + +/***********************************************************************/ +/* Sua_msg : Delete msg */ +/***********************************************************************/ +void tcb_Sua_msgqueue_pool:: delete_msg( unsigned int sua_assoc_idx ) +{ + if ( !msg_store.instance[sua_assoc_idx].empty() ) + msg_store.instance[sua_assoc_idx].pop(); +} + +// end of module sua_tcb.c + + + + diff --git a/sualibrary/sua/sua_tcb.h b/sualibrary/sua/sua_tcb.h new file mode 100644 index 0000000..dd2ec60 --- /dev/null +++ b/sualibrary/sua/sua_tcb.h @@ -0,0 +1,153 @@ +/*************************************************************************** + sua_tcb.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: sua_tcb.h,v 1.1.1.1 2002/02/04 14:30:42 p82609 Exp $ + * + * SUA implementation according to SUA draft issue 6. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * The alternative comment + * inspiration : Isabelle + * " + * "" + * + * Purpose: This header-file defines the SUA Transaction Control Block(TCB) + * pool functions for(needed for SUA connection oriented): + * - initialising a single TCB + * - initialising the TCB pool + * - allocate a TCB + * - get a TCB + * - release a TCB + * And for the Saved SUA msg queue pool + * - add SUA msg to queue + * - get sua msg from queue + * - release the SUA msg from the queue + */ + +#ifndef SUA_TCB_H +#define SUA_TCB_H + +#include "sua_database.h" +#include "sua_syntax.h" +#include "sua.h" + +#include +#include +#include +#include + +enum tcb_scoc_state_set { + scoc_idle, // idle state + scoc_incoming, + scoc_wait_m_CC, + scoc_outgoing, + scoc_active, + scoc_disconnect +}; + +class tcb_Sua_TCB_str +{ + public: + tcb_scoc_state_set state; + unsigned int Dest_LR; + unsigned int Source_LR; + unsigned int User_ref_id; + unsigned int sctp_Association_id; + protocol_class_set prcl_class; + unsigned int seq_number; + bool return_option; + sccp_addr_str remote_address; + public: + void init_TCB_elem(); +}; ///:~ + +typedef map tcb_sua_map_str; + +class tcb_Sua_TCB_arr +{ + public: + tcb_sua_map_str tcb; + /*private:*/ + unsigned int last_allocated_tcb; + public: + void init_TCB_pool(); + tcb_Sua_TCB_str *allocate_TCB(unsigned int &Sua_ConnId); + tcb_Sua_TCB_str *get_tcb(unsigned int Sua_ConnId); + void release_TCB(unsigned int Sua_ConnId); +}; ///:~ + +typedef pair tcb_sua_pair_str; + +typedef pair tcb_sua_map_iterator_str; + +struct tcb_Sua_msg_elem { + string byte; + int delivery_type; + int stream_id; + bool valid; +}; + +typedef queue tcb_Sua_msgqueue; + +class tcb_Sua_msgqueue_pool +{ + public: + tcb_Sua_msgqueue instance[db_MAX_REMOTE_SUA]; + public: + void add_msg( unsigned int sua_assoc_idx, + tcb_Sua_msg_elem sua_msg + ); + tcb_Sua_msg_elem get_msg( unsigned int sua_assoc_idx ); + void delete_msg( unsigned int sua_assoc_idx ); +}; ///:~ + + +#endif // SUA_TCB_H + +//end of module sua_tcb.h + + + + + + + + diff --git a/sualibrary/testup/Makefile.am b/sualibrary/testup/Makefile.am new file mode 100644 index 0000000..d535bf8 --- /dev/null +++ b/sualibrary/testup/Makefile.am @@ -0,0 +1,20 @@ +####### kdevelop will overwrite this part!!! (begin)########## +noinst_LIBRARIES = libtestup.a + +libtestup_a_SOURCES = testuser.cpp main.cpp + + +EXTRA_DIST = main.cpp testuser.cpp testuser.h + +####### kdevelop will overwrite this part!!! (end)############ +noinst_PROGRAMS = testup + +testup_SOURCES = main.cpp testuser.cpp testuser.h +#testup_LDADD = -L/usr/local/lib -lsua @glib_LIBS@ @sctp_LIBS@ +testup_LDADD = ../sua/libsua.a @glib_LIBS@ @sctp_LIBS@ + +INCLUDES = -I/usr/local/include +#the library path search path +#sualib_LDFLAGS = $(all_libraries) + +AUTOMAKE_OPTIONS = no-dependencies diff --git a/sualibrary/testup/main.cpp b/sualibrary/testup/main.cpp new file mode 100644 index 0000000..c032d62 --- /dev/null +++ b/sualibrary/testup/main.cpp @@ -0,0 +1,321 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: main.cpp,v 1.1.1.1 2002/02/04 14:30:42 p82609 Exp $ + * + * SUA Test user part implementation. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * Purpose: This code-file defines the SUA Test User Part application and + * has functions for: + * - get single argument from commandline + * - get input commandline parameters + * - get own host parameters + * - main function + */ + +#ifdef LINUX + #include +#endif + +#include "sua.h" +#include "sctp.h" + +#include "testuser.h" + +#include +#include +#include +#include + +#include +#include /* includes also ! */ +#include +#include +#include +#include + +using namespace std; + +char own_hostname[512]; +int nr_local_instances = 0; + +/***********************************************************************/ +/* TEST USER PART: get argument from commandline */ +/***********************************************************************/ +string get_argument( char *argv) +{ + int num_of_char = 0; + while ((argv[num_of_char]) != '\0') + { + // convert to lowercase characters for easier processing + argv[num_of_char] = tolower(argv[num_of_char]); + num_of_char++; + } + return(argv); +} + +/***********************************************************************/ +/* TEST USER PART: get input commandline parameters */ +/***********************************************************************/ +int sua_get_arguments(int argc, char **argv) +{ + string address_str; + string nr_of_streams; + bool help_flag = false; + string sua_filename; + char ch1,ch2; + string sua_arg; + int result; + int num_of_arg = 0; + + /* copy all charachters from the comandline into a string */ + while (num_of_arg < argc) + { + sua_arg =get_argument(argv[num_of_arg]); + +#ifdef DEBUG + //cout << "num_of_arg =" << num_of_arg <<" " << sua_arg << " \n"; +#endif + + // look at each of the arguments + if (num_of_arg == 0) + { + ch1 = 'i'; // ignore character + } + else + { + if (sua_arg[0] == '-') + { + ch1 = sua_arg[1]; + ch2 = sua_arg[2]; +#ifdef DEBUG + //cout << "character =" << ch1 <<" \n"; +#endif + } + else + { + cout << "weird option \n"; + ch1 = ' '; + } + } + + switch (ch1) + { + case 's': + { // source address option: read a ipv4/v6 address or hostname + num_of_arg++; + + break; + } + case 'd': + { // destination address option: read a ipv4/v6 address or hostname + num_of_arg++; + + break; + } + case 'u': + { // + break; + } + case 'm': + { // + break; + } + case 'f': + { // file option: read a file with all the info needed + num_of_arg++; + sua_filename = argv[num_of_arg]; + result = sua_read_config_file( argv[num_of_arg]); + + break; + } + case 'i': + { + // ignore character, is not a error, go to next argument + break; + } + default: + { + help_flag = true; + break; + } + } + + + + num_of_arg++; + } + + + /* no input parameters, display the help text */ + if (help_flag) { + cout << "usage: \n"; + cout << " sua [-s sourceaddr1,sourceaddr2,... -l localPort] \\ \n"; + cout << " [-d destaddr1,destaddr2 ....-r remotePort] \\ \n"; + cout << " [-m number-of-streams] \\ \n"; + cout << " [-f sua-address-filename] \\ \n"; + cout << " [-n subsystem-number] \n"; + cout << "use -s option to define source address(es) as IPv4/6 numerical/(hex) addresses.\n"; + cout << "use -d option to define destination address(es) as IPv4/6 numerical/(hex) addresses.\n"; + cout << "use -l option to define the local port where inits are accepted.\n"; + cout << "use -r option to define the remote port where init is sent to.\n"; + cout << "use -n option to define the subsytem number used\n"; + cout << "use -m '#of streams' enter number of streams, default is 15 streams\n"; + cout << "for multihoming multiple source addresses can be entered after the -s option.\n"; + cout << "They must be separated by commas and no spaces may be included.\n"; + cout << "To establish more than one association, use the -f 'sua-address-filename' file option \n"; + cout << "format is as follows:\n"; + cout << "-d can be ommitted to start a sua that listens only for incoming inits\n"; + cout << "Default local/remote portnumber = 14001\n"; + } + + return(0); + +} /* end of sua_get_arguments */ + +/***********************************************************************/ +/* TEST USER PART: get own host parameters */ +/***********************************************************************/ +int tstup_get_host_parm() +{ + struct hostent *hptr; + struct utsname myhostname; + char str[INET6_ADDRSTRLEN]; + char **pptr; + + if (uname(&myhostname) < 0){ + cout << "Determination of own name failed\n"; + return(-1); + } + cout << "Own name = " << myhostname.nodename << "\n"; + if ((hptr = gethostbyname(myhostname.nodename)) == NULL){ + cout << "Determination of hostname failed\n"; + return (-2); + } + + cout << "Host OS " << myhostname.sysname << " " << myhostname.release << " " << myhostname.version << "\n"; + cout << "Hostname = " << hptr->h_name << "\n"; + strcpy ( own_hostname, hptr->h_name ); + switch (hptr->h_addrtype){ + case AF_INET: + cout << "Host ip address type = AF_INET\n"; + break; + case AF_INET6: + cout << "Host ip address type = AF_INET6\n"; + break; + default: + cout << "Host ip address type = " << hptr->h_addrtype << "\n"; + break; + } + cout << "Hostname ip address length = "<< hptr->h_length << "\n"; + pptr = hptr->h_addr_list; + for ( ; *pptr != NULL;pptr++) + { + cout << inet_ntop(hptr->h_addrtype, *pptr, str,sizeof(str)) << "\n"; + } + return(0); +} + +/***********************************************************************/ +/* TEST USER PART: main function */ +/***********************************************************************/ +int main(int argc, char **argv ) +{ + int res; + Sua_ULP_CallBacks SUACallbackFunctions; + + cout << "Welcome to Test User Part(TSTUP) for SCCP User Adaptation Layer (SUA)\n"; + + sua_initialisation(); + + + SUACallbackFunctions.ulp_ClDataIndNotif = &ulp_ClDataIndNotif; + SUACallbackFunctions.ulp_ConnIndNotif = &ulp_ConnIndNotif; + SUACallbackFunctions.ulp_ConnConfIndNotif = &ulp_ConnConfIndNotif; + SUACallbackFunctions.ulp_ConnDataIndNotif = &ulp_ConnDataIndNotif; + SUACallbackFunctions.ulp_DisConnIndNotif = &ulp_DisConnIndNotif; + + // determine own hostname and address + res = tstup_get_host_parm(); + + // read cmdline paremeters (including a file containing cmds) + res = sua_get_arguments(argc, argv); + + // register sua and its users + + // register all the local SUA together with their SCTP instances + res = sua_registerInstance( 255, + SUACallbackFunctions + ); + // initiate all the SUA associations with their respective peers + res = sua_associate(); + + // register sua and its users + sctp_registerUserCallback( fileno(stdin), + &testip_stdin_cb, + NULL + ); + + init_testip_stdin(); + + // go into infinite loop( = handle all events) + cout << "Let Test User Part run free!!!! \n"; + while (sctp_eventLoop() >= 0); + + // close the program + //close_logging_file(); + exit (0); + +} + +// end of module sua_main.c + + + + + + + + + + + diff --git a/sualibrary/testup/testuser.cpp b/sualibrary/testup/testuser.cpp new file mode 100644 index 0000000..2a9d69f --- /dev/null +++ b/sualibrary/testup/testuser.cpp @@ -0,0 +1,887 @@ +/*************************************************************************** + testuser.cpp - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: testuser.cpp,v 1.2 2002/02/15 16:20:29 p82609 Exp $ + * + * SUA Test user part implementation. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * Purpose: This code-file defines the SUA Test User Part application and + * has definitions for: + * - Do pingpong with remote TESTUP + * - Handle pong + * - initialise the Test User part application + * - Test User Part STDIN function -> reading keyboard and + * sending the info to SUA + * - Handle TESTUP expired timers + * - TESTUP Connectionless Data Ind Notification(from SUA) + * - TESTUP CO Connection Ind Notification(from SUA) + * - TESTUP CO Connection Confirmation Ind Notification(from SUA) + * - TESTUP CO Data Ind Notification(from SUA) + * - TESTUP CO DisConnection Ind Notification(from SUA) + */ + +#include "sctp.h" +#include "sua.h" + +#ifdef LINUX + #include +#endif + +#include +#include + + + + +using namespace std; + +#include +#define MAX_DATA_LENGTH 2000 +#define MAX_DATACHUNK_PDU_LENGTH 251 + +extern char own_hostname[512]; + +//global variable for ULP instance(one connection only) +unsigned int timerID = 0; +unsigned int refID = 0; +unsigned int sendNo = 10; +unsigned int sendcnt = 0; +unsigned int timeoutval= 1000; +unsigned int rep_timer = 0; + +sua_Path_str pathinfo; +sccp_addr_str calling_pty_addr,called_pty_addr; +short network_app = 0; +short seq_control_num = 0; +boolean return_option = FALSE; + +/***********************************************************************/ +/* Test User Part : doPingPong */ +/***********************************************************************/ +int doPingPong(unsigned int Sua_ConnId ) +{ + int length; + sccp_addr_str co_clg, co_cld; + sccp_QOS_str co_QOS; + unsigned int xsxx; + string cmdline= "ping"; + + co_QOS.prot_class = class2; + co_QOS.in_sequence = false; + co_QOS.sequence_number = 0; + co_QOS.return_msg_on_error = 0; + co_QOS.importance = 0; + + co_clg.address_fields_present.pc = no_pc_present; + co_clg.address_fields_present.name_gt = no_name_present; + co_clg.address_fields_present.ssn_port = no_sap_present; + co_clg.address_fields_present.field_in_header = include_nothing; + + co_cld.address_fields_present.pc = no_pc_present; + co_cld.address_fields_present.name_gt = no_name_present; + co_cld.address_fields_present.ssn_port = no_sap_present; + co_cld.address_fields_present.field_in_header = include_nothing; + + + char *databuffer = new char[cmdline.length()]; + cmdline.copy(databuffer, cmdline.length()); + length = cmdline.length(); + + xsxx = Send_sua_primitive(N_DATA_REQ, + Sua_ConnId, + co_QOS, + co_cld, + co_clg, + databuffer, + length + ); + +#ifdef DEBUG + cout << "testuser.c++: Returned "<< xsxx <<" from the send (1==association error, 0==success, -1==could not send)\n"; +#endif + + delete databuffer; + return(xsxx); +} + +/***********************************************************************/ +/* Test User Part : handle_Pong */ +/***********************************************************************/ +int handlePong() +{ + + + return(0); +} +/***********************************************************************/ +/* Test User Part : init_testip_stdin */ +/***********************************************************************/ +void init_testip_stdin() +{ + unsigned int xsxx; + + xsxx= sua_getPath( 1, + pathinfo + ); + + /*cout << "result getpath = " << xsxx << "\n"; */ + + calling_pty_addr.address_fields_present.pc = ipvx_pc_present; + calling_pty_addr.address_fields_present.name_gt = no_name_present; + calling_pty_addr.address_fields_present.ssn_port = ssn_present; + calling_pty_addr.address_fields_present.field_in_header = include_nothing; + calling_pty_addr.pc.ipvx = pathinfo.local_addr.pc.ipvx; + calling_pty_addr.pc.ss7 = pathinfo.local_addr.pc.ss7; + calling_pty_addr.ssn = pathinfo.local_addr.ssn; + calling_pty_addr.routing_ind = route_on_ssn; + calling_pty_addr.network_apperance = network_app; + + called_pty_addr.address_fields_present.pc = ipvx_pc_present; + called_pty_addr.address_fields_present.name_gt = no_name_present; + called_pty_addr.address_fields_present.ssn_port = ssn_present; + called_pty_addr.address_fields_present.field_in_header = include_nothing; + called_pty_addr.pc.ipvx = pathinfo.remote_addr.pc.ipvx; + called_pty_addr.pc.ss7 = pathinfo.remote_addr.pc.ss7; + called_pty_addr.ssn = pathinfo.remote_addr.ssn; + called_pty_addr.routing_ind = route_on_ssn; + called_pty_addr.network_apperance = network_app; +} + +/***********************************************************************/ +/* Test User Part : testip_stdin_cb */ +/***********************************************************************/ +void testip_stdin_cb( int fd, + short int revents, + void *dummy + ) +{ + int i,length; + char readBuffer[256]; + unsigned int xsxx; + + sccp_QOS_str udt_QOS, co_QOS; + unsigned int Sua_ConnId=0; + + cin.getline(readBuffer,256,'\n'); + string cmdline(readBuffer,strlen(readBuffer)); + + if (cmdline.length() == 0) + { + cout << ">>"; + cout << flush; + + return; + } + else if (cmdline.find("help") != cmdline.npos) + { + cout << "Available commands are:\n"; + cout << " help - display this page\n"; + cout << " quit/exit - exit the program\n"; + cout << " destaddr6: - set destination ipv6 address \n"; + cout << " destaddr4: - set destination ipv4 address \n"; + cout << " destname: - set destination hostname\n"; + cout << " destpc: - set destination SS7 pointcode(decimal)\n"; + cout << " some-other-string - send this Connectionless to destaddrx\n"; + cout << " co:some-other-string - send this Connection-oriented\n"; + cout << " disp mngt - display ASP status of remote nodes\n"; + cout << " return-option: - change return-option(toggle) on/off\n"; + //cout << " rep:x - repeat sending x CLDT/CODT msg to remote\n"; + //cout << " term - terminate all the present associations(SCTP & SUA)\n"; + //cout << " restart - restart all the present associations(SCTP & SUA)\n"; + } + else if ((cmdline.find("quit") != cmdline.npos) || + (cmdline.find("exit") != cmdline.npos)) + { + /* add some cleanups */ + sua_terminate(); + cout << "exiting the Test User program\n"; + /* exit program */ + exit(0); + } + else if ((cmdline.find("rep:") != cmdline.npos)) + { + cout << "Repeat sending CL/CO data to remote end every " << rep_timer << " sec\n"; + } + else if ((cmdline.find("return-option:") != cmdline.npos)) + { + return_option = !return_option; + cout << "Return option = " << return_option << " (0= FALSE, 1= TRUE)\n"; + } + else if (cmdline.find("lock") != cmdline.npos) + { + /* lock up all SUA instances for ASP management */ + cout << "SUA mgnt administratived locked\n"; + } + else if (cmdline.find("disp mngt") != cmdline.npos) + { + /* Display the management status of all SUA instances */ + cout << "| Association | SUA management status |\n"; + cout << "+-------------+-----------------------+\n"; + i = 1; + while ( SUA_PATH_NO_ERROR == sua_getPath(i,pathinfo) ) + { + cout << "| " << i <<" | "<< pathinfo.ASP_status << " |\n"; + i++; + } + cout << "+-------------+-----------------------+\n"; + cout << "ASP status values: see sua_asp_mgnt.h\n"; + } + else if (cmdline.find("term") != cmdline.npos) + { + /* Terminate the following associations */ + cout << "| Association | SUA management status |\n"; + + } + else if (cmdline.find("destaddr6:") != cmdline.npos) + { + /* get destination address, convert it and store in cld */ + string addr_str(cmdline, (cmdline.find("destaddr6:")+10),cmdline.length()); + cout << "dest address = " << addr_str << "\n"; + char *addr_char = new char [addr_str.length()+1]; + addr_str.copy(addr_char, addr_str.length()); + addr_char[addr_str.length()] = '\0'; + called_pty_addr.address_fields_present.pc = ipvx_pc_present; + called_pty_addr.address_fields_present.name_gt = no_name_present; + called_pty_addr.address_fields_present.ssn_port = ssn_present; + called_pty_addr.address_fields_present.field_in_header = include_nothing; + called_pty_addr.pc.ipvx.sa.sa_family = AF_INET6; + called_pty_addr.pc.ipvx.sin6.sin6_port = SUA_PORT; + inet_pton( AF_INET6, + addr_char, + &called_pty_addr.pc.ipvx.sin6.sin6_addr + ); + called_pty_addr.ssn = 255; + called_pty_addr.routing_ind = route_on_ssn; + + calling_pty_addr.ssn = 255; + calling_pty_addr.routing_ind = route_on_ssn; + + cout << "Address of remote end stored. Msg will be sent to this one\n"; + } + else if (cmdline.find("destaddr4:") != cmdline.npos) + { + /* get destination address, convert it and store in cld */ + string addr_str( cmdline, (cmdline.find("destaddr4:")+10),cmdline.length()); + cout << "dest address " << addr_str << "\n"; + char *addr_char = new char [addr_str.length()+1]; + addr_str.copy(addr_char, addr_str.length()); + addr_char[addr_str.length()] = '\0'; + called_pty_addr.address_fields_present.pc = ipvx_pc_present; + called_pty_addr.address_fields_present.name_gt = no_name_present; + called_pty_addr.address_fields_present.ssn_port = ssn_present; + called_pty_addr.address_fields_present.field_in_header = include_nothing; + called_pty_addr.pc.ipvx.sa.sa_family = AF_INET; + called_pty_addr.pc.ipvx.sin.sin_port = SUA_PORT; + inet_pton( AF_INET, + addr_char, + &called_pty_addr.pc.ipvx.sin.sin_addr + ); + called_pty_addr.ssn = 255; + called_pty_addr.routing_ind = route_on_ssn; + + calling_pty_addr.ssn = 255; + calling_pty_addr.routing_ind = route_on_ssn; + + cout << "Address of remote end stored. Msg will be sent to this one\n"; + } + else if (cmdline.find("destname:") != cmdline.npos) + { + /* get destination hostname, convert it and store in cld */ + string addr_str(cmdline, (cmdline.find("destname:")+9),cmdline.length()); + + called_pty_addr.address_fields_present.pc = no_pc_present; + called_pty_addr.address_fields_present.name_gt = hostname_present; + called_pty_addr.address_fields_present.ssn_port = ssn_present; + called_pty_addr.address_fields_present.field_in_header = include_nothing; + strcpy(called_pty_addr.name.HostName,addr_str.c_str()); + called_pty_addr.ssn = 255; + called_pty_addr.routing_ind = route_on_name_gt; + + cout << "DNS/SUA dest hostname = " << addr_str << "\n"; + cout << "Address of remote end stored. Msg will be sent to this one\n"; + + string addr2_str = own_hostname; + /*char *name2_char = new char [addr2_str.length()+1]; */ + /*name2_char = shost_to_suaname ( addr2_str ); */ + + calling_pty_addr.address_fields_present.name_gt = hostname_present; + strcpy(calling_pty_addr.name.HostName, own_hostname); + calling_pty_addr.ssn = 255; + calling_pty_addr.routing_ind = route_on_name_gt; + cout << "DNS/SUA source hostname = " << addr2_str << "\n"; + + } + else if (cmdline.find("destpc:") != cmdline.npos) + { + /* get destination address, convert it and store in cld */ + string addr_str(cmdline, (cmdline.find("destpc:")+7),cmdline.length()); + cout << "dest address = " << addr_str << "\n"; + char *addr_char = new char [addr_str.length()+1]; + addr_str.copy(addr_char, addr_str.length()); + addr_char[addr_str.length()] = '\0'; + called_pty_addr.address_fields_present.pc = ss7_pc_present; + called_pty_addr.address_fields_present.name_gt = no_name_present; + called_pty_addr.address_fields_present.ssn_port = ssn_present; + called_pty_addr.address_fields_present.field_in_header = include_nothing; + called_pty_addr.pc.ss7.ITU24.family = ITU24bit; + called_pty_addr.pc.ss7.ITU24.pc = atoi(addr_char); + called_pty_addr.ssn = 255; + called_pty_addr.routing_ind = route_on_ssn; + + calling_pty_addr.ssn = 255; + calling_pty_addr.routing_ind = route_on_ssn; + + cout << "Address of remote end stored. Msg will be sent to this one\n"; + } + else if (cmdline.find("co:") != cmdline.npos) + { + + co_QOS.prot_class = class2; + co_QOS.in_sequence = false; + co_QOS.sequence_number = 0; + co_QOS.return_msg_on_error = return_option; + co_QOS.importance = 0; + + xsxx= sua_getPath( 1, + pathinfo + ); + + //cout << "result getpath = " << xsxx << "\n"; + + calling_pty_addr.address_fields_present.pc = called_pty_addr.address_fields_present.pc; + calling_pty_addr.address_fields_present.name_gt = called_pty_addr.address_fields_present.name_gt; + calling_pty_addr.routing_ind = called_pty_addr.routing_ind; + calling_pty_addr.address_fields_present.ssn_port = called_pty_addr.address_fields_present.ssn_port; + calling_pty_addr.address_fields_present.field_in_header = called_pty_addr.address_fields_present.field_in_header ; + + string addr3_str = own_hostname; + /*char *name3_char = new char [addr3_str.length()+1];*/ + /*name3_char = shost_to_suaname ( addr3_str );*/ + strcpy(calling_pty_addr.name.HostName, own_hostname); + + + calling_pty_addr.pc.ipvx = pathinfo.local_addr.pc.ipvx; + calling_pty_addr.ssn = pathinfo.local_addr.ssn; + calling_pty_addr.pc.ss7 = pathinfo.local_addr.pc.ss7 ; + + char *databuffer = new char[cmdline.length()]; + cmdline.copy(databuffer, cmdline.length()); + length = cmdline.length(); + + xsxx = Send_sua_primitive(N_CONNECT_REQ, + Sua_ConnId, + co_QOS, + called_pty_addr, + calling_pty_addr, + databuffer, + length + ); + + refID = Sua_ConnId; + +#ifdef DEBUG + cout << "testuser.c++: Returned "<< xsxx <<" from the send (1==association error, 0==success, -1==could not send)\n"; +#endif + + delete databuffer; + } + else + { + + udt_QOS.prot_class = class0; + udt_QOS.in_sequence = false; + udt_QOS.sequence_number = seq_control_num++; + udt_QOS.return_msg_on_error = return_option; + udt_QOS.importance = 0; + + xsxx= sua_getPath( 1, + pathinfo + ); + +#ifdef DEBUG + cout << "Sequence control parameter = " << udt_QOS.sequence_number << "\n"; +#endif + + calling_pty_addr.address_fields_present.pc = called_pty_addr.address_fields_present.pc; + calling_pty_addr.address_fields_present.name_gt = called_pty_addr.address_fields_present.name_gt; + calling_pty_addr.routing_ind = called_pty_addr.routing_ind; + calling_pty_addr.address_fields_present.ssn_port = called_pty_addr.address_fields_present.ssn_port; + calling_pty_addr.address_fields_present.field_in_header = called_pty_addr.address_fields_present.field_in_header; + + string addr4_str = own_hostname; + /*char *name4_char = new char [addr4_str.length()+1]; */ + /*name4_char = shost_to_suaname ( addr4_str ); */ + strcpy(calling_pty_addr.name.HostName, own_hostname); + + calling_pty_addr.pc.ipvx = pathinfo.local_addr.pc.ipvx; + calling_pty_addr.ssn = pathinfo.local_addr.ssn; + calling_pty_addr.pc.ss7 = pathinfo.local_addr.pc.ss7 ; + + char *databuffer = new char[cmdline.length()]; + cmdline.copy(databuffer, cmdline.length()); + length = cmdline.length(); + + xsxx = Send_sua_primitive(N_UNITDATA, + Sua_ConnId, + udt_QOS, + called_pty_addr, + calling_pty_addr, + databuffer, + length + ); + +#ifdef DEBUG + cout << "testuser.c++: Returned "<< xsxx <<" from the send (1==association error, 0==success, -1==could not send)\n"; +#endif + + delete databuffer; + } + cout << ">"; + cout << flush; + +} + + +#define SEND_EVENTS_WHEN_TIMER_EXPIRES 1 +/***********************************************************************/ +/* Test user part : timer_expired */ +/***********************************************************************/ +void timer_expired(unsigned int tID, + void *associationIDvoid, + void *unused + ) +{ + int length; + sccp_addr_str co_clg, co_cld; + sccp_QOS_str co_QOS; + string cmdline= "ping"; + + unsigned int Sua_ConnId=refID; + + cout << "************************************************************\n"; + cout << "** Timer expired **\n"; + if (sendcnt < sendNo) { + sendcnt++; + cout << "Send a PING\n"; + doPingPong(Sua_ConnId); + timerID = sctp_startTimer( 10000, + &timer_expired, + NULL, + NULL + ); + } + else + { + cout << "Terminate the SUA connection\n"; + unsigned int xsxx; + + co_QOS.prot_class = class2; + co_QOS.in_sequence = false; + co_QOS.sequence_number = 0; + co_QOS.return_msg_on_error = 0; + co_QOS.importance = 0; + + + char *databuffer = new char[cmdline.length()]; + cmdline.copy(databuffer, cmdline.length()); + length = cmdline.length(); + + xsxx = Send_sua_primitive( N_RELEASE_REQ, + Sua_ConnId, + co_QOS, + co_cld, + co_clg, + databuffer, + length + ); + +#ifdef DEBUG + cout << "testuser.c++: Returned "<< xsxx <<" from the send (1==association error, 0==success, -1==could not send)\n"; +#endif + + delete databuffer; + } +} + +/***********************************************************************/ +/* Test user part: ulp_ClDataIndNotif */ +/***********************************************************************/ +void ulp_ClDataIndNotif( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int datalen + ) +{ + int length=datalen; + int index; + unsigned int Sua_ConnId; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + index = 0; + + cout << "testuser.c++: Hey, we received ClDataIndNotif \n"; + + //check for primitive, receive only unitdata's up till know + switch (primitive) + { + case (N_UNITDATA): + called_pty_addr = clg; + cout << "************************************************************\n"; + cout << "** UNITDATA message received **\n"; + break; + default: + break; + } + + + string disp_output(databuffer,index, (length - index)); + cout << "************************************************************\n"; + cout << disp_output << "\n"; + cout << "************************************************************\n"; + cout << ">"; + cout << flush; + +} + + +/***********************************************************************/ +/* Test user part: ulp_ConnIndNotif */ +/***********************************************************************/ +void ulp_ConnIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int datalen + ) +{ + int length=datalen; + int index; + unsigned int Sua_ConnId, primitive; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + index = 0; + + string cmdline(databuffer,index, (length - index)); + + cout << "testuser.c++: Hey, we received ConnIndNotif \n"; + + //check for primitive + switch (primitive) + { + case (N_CONNECT_IND): + called_pty_addr = clg; + cld = called_pty_addr; + clg = calling_pty_addr; + cout << "************************************************************\n"; + cout << "** CONNECT REQ IND message received **\n"; + // send Connect confirm back + // this is the responding side of the connection + + sccp_QOS_str co_QOS; + unsigned int xsxx; + + co_QOS.prot_class = class2; + co_QOS.in_sequence = false; + co_QOS.sequence_number = 0; + co_QOS.return_msg_on_error = 0; + co_QOS.importance = 0; + + if (cmdline.find("refused") != cmdline.npos) + { + // mirror received data back to initiator + cout << "length = " << length << "\n"; + + xsxx = Send_sua_primitive(N_CONNECT_REFUSED, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + } + else + { + xsxx = Send_sua_primitive(N_CONNECT_RESP, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + } + + cout << "testuser.c++: Returned "<< xsxx <<" from the send (1==association error, 0==success, -1==could not send)\n"; + + + break; + default: + break; + } + + + string disp_output(databuffer,index, (length - index)); + cout << "************************************************************\n"; + cout << disp_output << "\n"; + cout << "************************************************************\n"; + cout << ">"; + cout << flush; + +} + + + +/***********************************************************************/ +/* Test user part: ulp_ConnConfIndNotif */ +/***********************************************************************/ +void ulp_ConnConfIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int datalen + ) +{ + int length=datalen; + int index; + unsigned int Sua_ConnId, primitive; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + index = 0; + + cout << "testuser.c++: Hey, we received ConnConfIndNotif\n"; + + //check for primitive, receive only unitdata's up till know + switch (primitive) + { + case (N_CONNECT_CONF): + + cout << "************************************************************\n"; + cout << "** CONNECT CONFIRM IND message received **\n"; + // received the connection confirmed msg + // this is the initiator of the connection + // start a timer for sending the data to the responder + timerID = sctp_startTimer( 5000, + &timer_expired, + NULL, + NULL + ); + + break; + default: + break; + } + + + string disp_output(databuffer,index, (length - index)); + cout << "************************************************************\n"; + cout << disp_output << "\n"; + cout << "************************************************************\n"; + cout << ">"; + cout << flush; + +} + + +/***********************************************************************/ +/* Test user part: ulp_ConnDataIndNotif */ +/***********************************************************************/ +void ulp_ConnDataIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int datalen + ) +{ + int length=datalen; + int index; + unsigned int Sua_ConnId, primitive; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + index = 0; + string cmdline(databuffer,length); + + cout << "testuser.c++: Hey, we received ConnDataIndNotif \n"; + + //check for primitive, receive only unitdata's up till know + switch (primitive) + { + case (N_DATA_IND): + + cout << "************************************************************\n"; + cout << "** CO DATA message received **\n"; + // received a connection oriented data + // if it is a ping send back a pong + // if it is a pong, start timer for the next data or disconnect + + if (cmdline.find("ping") != cmdline.npos) + {} + else if (cmdline.find("pong") != cmdline.npos) + { + cout << "End: pong received\n"; + } + else + cout << "Not in ping-pong mode\n"; + + break; + default: + break; + } + + + string disp_output(databuffer,index, (length - index)); + cout << "************************************************************\n"; + cout << disp_output << "\n"; + cout << "************************************************************\n"; + cout << ">"; + cout << flush; + +} + + +/***********************************************************************/ +/* Test user part: ulp_DisconnIndNotif */ +/***********************************************************************/ +void ulp_DisConnIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int cause, + unsigned int datalen + ) +{ + int length=datalen; + int index; + unsigned int Sua_ConnId, primitive; + char databuffer[MAX_DATA_LENGTH]; + sccp_QOS_str QOS; + sccp_addr_str clg,cld; + + Receive_sua_primitive ( primitive, + Sua_ConnId, + QOS, + cld, + clg, + databuffer, + length + ); + + index = 0; + + cout << "testuser.c++: Hey, we received DisConnIndNotif\n"; + + //check for primitive, receive only unitdata's up till know + switch (primitive) + { + case (N_RELEASE_REQ): + + cout << "************************************************************\n"; + cout << "** RELEASE REQUEST:DISCONNECT IND message received **\n"; + break; + case (N_RELEASE_CONF): + + cout << "************************************************************\n"; + cout << "** RELEASE CONFIRM:DISCONNECT IND message received **\n"; + break; + default: + break; + } + + + string disp_output(databuffer,index, (length - index)); + cout << "************************************************************\n"; + cout << disp_output << "\n"; + cout << "************************************************************\n"; + cout << ">"; + cout << flush; + +} + +// end of module testuser.c++ + + + + + + + + + + + + + diff --git a/sualibrary/testup/testuser.h b/sualibrary/testup/testuser.h new file mode 100644 index 0000000..3b9a7b8 --- /dev/null +++ b/sualibrary/testup/testuser.h @@ -0,0 +1,128 @@ +/*************************************************************************** + testuser.h - description + ------------------- + begin : Tue Jan 8 2002 + copyright : (C) 2002 by Lode Coene + email : lode.coene@siemens.atea.be + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* + * $Id: testuser.h,v 1.1.1.1 2002/02/04 14:30:42 p82609 Exp $ + * + * SUA Test user part implementation. + * + * Author(s): Lode Coene + * + * + * Copyright (C) 2001 by Siemens Atea, Herentals, Belgium. + * + * Realized in co-operation between Siemens Atea and + * Siemens AG, Munich, Germany. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact: gery.verwimp@siemens.atea.be + * lode.coene@siemens.atea.be + * + * Purpose: This header-file defines the SUA Test User Part application and + * has definitions for: + * - initialise the Test User part application + * - Test User Part STDIN function -> reading keyboard and + * sending the info to SUA + * - TESTUP Connectionless Data Ind Notification(from SUA) + * - TESTUP CO Connection Ind Notification(from SUA) + * - TESTUP CO Connection Confirmation Ind Notification(from SUA) + * - TESTUP CO Data Ind Notification(from SUA) + * - TESTUP CO DisConnection Ind Notification(from SUA) + */ + +#ifndef SUA_TSTUP_H +#define SUA_TSTUP_H + +#include "sua.h" + +#ifdef LINUX + #include +#endif + +#include +#include + + + + +using namespace std; + +#include + +void init_testip_stdin(void ); + +void testip_stdin_cb( int fd, + short int revents, + void *dummy + ); + + +void ulp_ClDataIndNotif( unsigned int local_sua_Id, + unsigned int primitive, + unsigned int datalen + ); + +void ulp_ConnIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int datalen + ); + +void ulp_ConnConfIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int datalen + ); + +void ulp_ConnDataIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int datalen + ); + +void ulp_DisConnIndNotif( unsigned int local_sua_Id, + unsigned int ConnId, + unsigned int cause, + unsigned int datalen + ); + +#endif // SUA_TSTUP_H + + +// end of module sua_test_user.c + + + + + + + + + + + + +