dect
/
dectmon
Archived
13
0
Fork 0

Import dectmon

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2010-10-28 01:31:00 +02:00
commit 902da5b9f5
24 changed files with 5115 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@ -0,0 +1,18 @@
# Dependency and object files
.*.d
*.o
# Generated by autoconf/configure
Makefile
Makefile.defs
Makefile.rules
config.h
config.h.in
config.h.in~
config.log
config.status
configure
autom4te.cache
# vim swap files
.*.swp

340
COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 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
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

46
Makefile.defs.in Normal file
View File

@ -0,0 +1,46 @@
DEBUG = @CONFIG_DEBUG@
CC = @CC@
CPP = @CPP@
LEX = @LEX@
YACC = @YACC@
MKDIR_P = @MKDIR_P@
LN_S = @LN_S@
INSTALL = @INSTALL@
DOXYGEN = @DOXYGEN@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_VERSION = @PACKAGE_VERSION@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
prefix = @prefix@
exec_prefix = @exec_prefix@
sysconfdir = @sysconfdir@
datarootdir = @datarootdir@
mandir = @mandir@
docdir = @docdir@
pdfdir = @pdfdir@
confdir = @sysconfdir@/dect
LDFLAGS += @LDFLAGS@
LDFLAGS += @LIBS@
CPPFLAGS += @CPPFLAGS@
CFLAGS += @CFLAGS@ @DEFS@
CFLAGS += -include config.h -I include
CFLAGS += -fvisibility=hidden
CFLAGS += -fstack-protector-all
CFLAGS += -Wall
CFLAGS += -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations
CFLAGS += -Wdeclaration-after-statement -Wsign-compare -Winit-self
CFLAGS += -Wformat-nonliteral -Wformat-security -Wmissing-format-attribute
CFLAGS += -Wcast-align -Wundef -Wbad-function-cast # -Wshadow
CFLAGS += -Waggregate-return -Wunused -Wwrite-strings
ifeq ($(DEBUG),y)
CFLAGS += -g -DDEBUG
endif
EVENT_CFLAGS += @EVENT_CFLAGS@
EVENT_LDFLAGS += @EVENT_LDFLAGS@

3
Makefile.in Normal file
View File

@ -0,0 +1,3 @@
SUBDIRS += src
include Makefile.rules

114
Makefile.rules.in Normal file
View File

@ -0,0 +1,114 @@
include Makefile.defs
makedeps += $(SUBDIR)Makefile
makedeps += Makefile
makedeps += Makefile.defs
makedeps += Makefile.rules
configure: configure.ac
sh autogen.sh
%: %.in configure
sh configure
%.o: %.c $(makedeps)
@/bin/echo -e " CC\t\t$<"
$(CC) $(CFLAGS) -c -o $@ $<
.%.d: %.c $(makedeps)
@/bin/echo -e " DEP\t\t$<"
$(RM) $@
$(CC) -M $(CFLAGS) $< | sed 's,$(*F)\.o[ :]*,$*.o $@ : ,g' > $@
%.c %.h: %.y $(makedeps)
@/bin/echo -e " YACC\t\t$<"
$(YACC) $(YACCFLAGS) -d -o $@ $<
%.c %.h: %.l $(makedeps)
@/bin/echo -e " LEX\t\t$<"
$(LEX) -t --header-file=$(<:.l=.h) $< > $@
%.8: %.xml $(makedeps)
@/bin/echo -e " MAN\t\t$<"
docbook2x-man $<
%.pdf: %.xml $(makedeps)
@/bin/echo -e " PDF\t\t$<"
db2pdf $<
define generic_template
$(1)-obj := $$(patsubst %,$(SUBDIR)%,$$($(1)-obj))
$(1)-depfiles := $$(patsubst $(SUBDIR)%.o,$(SUBDIR).%.d,$$($(1)-obj))
.PHONY: $(1)-clean
$(1)-clean:
@/bin/echo -e " CLEAN\t\t$(1)"
$$(RM) $$($(1)-obj) $$($(1)-depfiles) \
$$($(1)-clean_files) $$($(1)-extra-clean-files)
clean_targets += $(1)-clean
.PHONY: $(1)-install
ifneq ($(MAKECMDGOALS),clean)
-include $$($(1)-depfiles)
endif
endef
define program_template
$(eval $(call generic_template,$(1)))
$(SUBDIR)$(1): $$($(1)-extra-targets) $$($(1)-obj)
@/bin/echo -e " LD\t\t$$@"
$$(CC) $$($(1)-obj) $$($(1)-ldflags) $$(LDFLAGS) -o $$@
all_targets += $(SUBDIR)$(1)
$(1)-clean_files += $(SUBDIR)$(1)
$(1)-install:
@/bin/echo -e " INSTALL\t$1"
$(MKDIR_P) $$(DESTDIR)/$$($(1)-destdir)
$(INSTALL) -m 755 -o root -g root $(SUBDIR)$(1) \
$$(DESTDIR)/$$($(1)-destdir)/$(1)
install_targets += $(1)-install
endef
define library_template
$(eval $(call generic_template,$(1)))
$(SUBDIR)lib$(1).so: $$($(1)-extra-targets) $$($(1)-obj)
@/bin/echo -e " LD\t\t$$@"
$$(CC) -shared -Wl,-soname,lib$(1).so.0 $$($(1)-obj) $$($(1)-ldflags) $$(LDFLAGS) -o $$@
$(LN_S) -f lib$(1).so $$@.0
all_targets += $(SUBDIR)lib$(1).so
$(1)-clean_files += $(SUBDIR)lib$(1).so $(SUBDIR)lib$(1).so.0
$(1)-install:
@/bin/echo -e " INSTALL\t$1"
$(MKDIR_P) $$(DESTDIR)/$$($(1)-destdir)
$(INSTALL) -m 755 -o root -g root $(SUBDIR)lib$(1).so \
$$(DESTDIR)/$$($(1)-destdir)/lib$(1).so.$(PACKAGE_VERSION)
$(LN_S) -f lib$(1).so.$(PACKAGE_VERSION) \
$(DESTDIR)/$$($(1)-destdir)/lib$(1).so.0
$(LN_S) -f lib$(1).so.$(PACKAGE_VERSION) \
$(DESTDIR)/$$($(1)-destdir)/lib$(1).so
install_targets += $(1)-install
endef
ifneq ($(SUBDIR),)
include $(SUBDIR)/Makefile
$(foreach prog,$(PROGRAMS),$(eval $(call program_template,$(prog))))
$(foreach lib,$(LIBS),$(eval $(call library_template,$(lib))))
endif
.DEFAULT_GOAL := all
.PHONY: all clean install
all: $(SUBDIRS) $(all_targets)
clean: $(SUBDIRS) $(clean_targets)
install: all $(SUBDIRS) $(install_targets)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
@/bin/echo -e " SUBDIR\t$@/"
@$(MAKE) -s -f Makefile.rules $(MAKECMDGOALS) SUBDIR="$@/" SUBDIRS=""

4
autogen.sh Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
autoreconf -fi;
rm -Rf autom4te*.cache config.h.in~

95
configure.ac Normal file
View File

@ -0,0 +1,95 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
AC_COPYRIGHT([Copyright (c) 2008 Patrick McHardy <kaber@trash.net>])
AC_INIT([libdect], [0.0.1], [kaber@trash.net])
AC_DEFINE([RELEASE_NAME], ["libdect"], [Release name])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADER([config.h])
AC_DEFINE([_GNU_SOURCE], [], [Enable various GNU extensions])
AC_DEFINE([_STDC_FORMAT_MACROS], [], [printf-style format macros])
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--enable-debug], [enable debugging [yes]]),
[CONFIG_DEBUG="$(echo $enableval | cut -b1)"],
[CONFIG_DEBUG="y"])
AC_SUBST([CONFIG_DEBUG])
# Checks for programs.
AC_PROG_CC
AC_PROG_MKDIR_P
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_SED
AC_ARG_ENABLE([doc],
AS_HELP_STRING([--enable-doc], [build documentation [no]]),
AC_CHECK_PROG(DOXYGEN, doxygen, doxygen),
AC_MSG_NOTICE([Documentation build disabled])
DOXYGEN=/bin/true)
# Checks for libraries.
AC_CHECK_LIB([nl], [nl_socket_alloc], ,
AC_MSG_ERROR([No suitable version of libnl found]))
AC_CHECK_LIB([nl-dect], [nl_dect_cluster_alloc], ,
AC_MSG_ERROR([No suitable version of libnl-dect found]))
AC_CHECK_LIB(ev, event_init,
[EVENTLIB="-lev"],
[AC_CHECK_LIB([event], [event_init],
[EVENTLIB="-levent"],
[AC_ERROR([libev or libevent not found])])])
EVENT_LDFLAGS=$EVENTLIB
AC_SUBST(EVENT_LDFLAGS)
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_ASSERT
AC_CHECK_HEADERS([fcntl.h inttypes.h libintl.h limits.h malloc.h \
stddef.h stdint.h stdlib.h string.h unistd.h \
sys/socket.h], ,
AC_MSG_ERROR([Header file not found]))
AC_CHECK_HEADERS([linux/dect.h linux/dect_netlink.h], ,
AC_MSG_ERROR([DECT kernel header files not found]),
[#include <sys/socket.h>])
AC_CHECK_HEADER([event.h],
[EVENTINC="-include event.h"],
[AC_CHECK_HEADER([libev/event.h],
[EVENTINC="-include libev/event.h"],
[AC_MSG_ERROR([event.h not found])])])
EVENT_CFLAGS=$EVENTINC
AC_SUBST(EVENT_CFLAGS)
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_CONST
AC_C_INLINE
AC_C_TYPEOF
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UID_T
AC_TYPE_INT8_T
AC_TYPE_INT16_T
AC_TYPE_INT32_T
AC_TYPE_INT64_T
AC_TYPE_UINT8_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
# Checks for library functions.
# AC_FUNC_MALLOC
# AC_FUNC_REALLOC
AC_CHECK_FUNCS([memmove memset strchr strdup strerror strtoull])
AC_CONFIG_FILES([Makefile Makefile.defs Makefile.rules])
AC_CONFIG_FILES([src/Makefile])
AC_OUTPUT

101
include/dectmon.h Normal file
View File

@ -0,0 +1,101 @@
#ifndef _DECTMON_H
#define _DECTMON_H
#include <stdbool.h>
#include <list.h>
#include <dect/auth.h>
extern struct dect_handle *dh;
enum {
DECTMON_DUMP_MAC = 0x1,
DECTMON_DUMP_DLC = 0x2,
DECTMON_DUMP_NWK = 0x4,
};
extern uint32_t dumpopts;
struct dect_ops;
extern int dect_event_ops_init(struct dect_ops *ops);
extern void dect_event_loop_stop(void);
extern void dect_event_loop(void);
extern void dect_event_ops_cleanup(void);
extern void dect_dummy_ops_init(struct dect_ops *ops);
extern void dect_hexdump(const char *prefix, const uint8_t *buf, size_t size);
enum dect_mm_procedures {
DECT_MM_NONE,
DECT_MM_KEY_ALLOCATION,
DECT_MM_AUTHENTICATION,
DECT_MM_CIPHERING,
};
struct dect_pt {
struct list_head list;
struct dect_ie_portable_identity *portable_identity;
struct dect_tbc *tbc;
uint8_t uak[DECT_AUTH_KEY_LEN];
uint8_t dck[DECT_CIPHER_KEY_LEN];
enum dect_mm_procedures procedure;
uint8_t last_msg;
struct dect_ie_auth_type *auth_type;
struct dect_ie_auth_value *rand_f;
struct dect_ie_auth_value *rs;
struct dect_ie_auth_res *res;
};
/* DLC */
struct dect_dl {
struct dect_pt *pt;
struct dect_tbc *tbc;
};
struct dect_msg_buf;
extern void dect_dl_data_ind(struct dect_dl *dl, struct dect_msg_buf *mb);
struct dect_lc {
uint16_t lsig;
struct dect_msg_buf *rx_buf;
uint8_t rx_len;
};
struct dect_mac_con {
struct dect_lc *lc;
uint32_t pmid;
struct dect_tbc *tbc;
};
enum dect_data_channels;
extern void dect_mac_co_data_ind(struct dect_mac_con *mc,
enum dect_data_channels chan,
struct dect_msg_buf *mb);
/* MAC */
struct dect_mbc {
bool cs_seq;
bool cf_seq;
struct dect_mac_con mc;
};
struct dect_tbc {
struct dect_mbc mbc[2];
struct dect_dl dl;
bool ciphered;
};
extern void dect_mac_rcv(struct dect_msg_buf *mb, uint8_t slot);
/* DSC */
extern void dect_dsc_keystream(uint64_t iv, const uint8_t *key,
uint8_t *output, unsigned int len);
extern uint64_t dect_dsc_iv(uint32_t mfn, uint8_t framenum);
#endif /* _DECTMON_H */

463
include/dlc.h Normal file
View File

@ -0,0 +1,463 @@
/*
* DECT DLC Layer
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#ifndef _NET_DECT_DLC_H
#define _NET_DECT_DLC_H
/*
* C-Plane data link service
*/
/*
* FA-Frame
*/
#define DECT_FA_HDR_SIZE 3
struct dect_fa_hdr {
uint8_t addr;
uint8_t ctrl;
uint8_t li;
};
/*
* Address field
*/
#define DECT_FA_ADDR_OFF 0
/* New link flag */
#define DECT_FA_ADDR_NLF_FLAG 0x80
/* Logical Link Number */
#define DECT_FA_ADDR_LLN_MASK 0x70
#define DECT_FA_ADDR_LLN_SHIFT 4
/* Service Access Point Identifier */
#define DECT_FA_ADDR_SAPI_MASK 0x0c
#define DECT_FA_ADDR_SAPI_SHIFT 2
/* Command/Response flag */
#define DECT_FA_ADDR_CR_FLAG 0x02
/* Reserved bit */
#define DECT_FA_ADDR_RES_BIT 0x01
/*
* Control field
*/
#define DECT_FA_CTRL_OFF 1
/*
* I-Format: numbered information
*/
#define DECT_FA_CTRL_I_FMT_MASK 0x01
#define DECT_FA_CTRL_I_FMT_ID 0x00
/* Receive sequence number */
#define DECT_FA_CTRL_I_NR_MASK 0xe0
#define DECT_FA_CTRL_I_NR_SHIFT 5
/* Poll bit */
#define DECT_FA_CTRL_I_P_FLAG 0x10
/* Send sequence number */
#define DECT_FA_CTRL_I_NS_MASK 0x0e
#define DECT_FA_CTRL_I_NS_SHIFT 1
/* Command */
#define DECT_FA_CTRL_I_CMD_I (0x0)
/*
* S-Format: supervisory functions
*/
#define DECT_FA_CTRL_S_FMT_MASK 0x03
#define DECT_FA_CTRL_S_FMT_ID 0x01
/* Receive sequence number */
#define DECT_FA_CTRL_S_NR_MASK 0xe0
#define DECT_FA_CTRL_S_NR_SHIFT 5
/* Poll/final bit */
#define DECT_FA_CTRL_S_PF_FLAG 0x10
/* Command/Response */
#define DECT_FA_CTRL_S_CR_MASK 0x0c
#define DECT_FA_CTRL_S_CR_RR 0x00
#define DECT_FA_CTRL_S_CR_RNR 0x40
#define DECT_FA_CTRL_S_CR_REJ 0x80
/*
* U-Format: unnumbered information
*/
#define DECT_FA_CTRL_U_FMT_MASK 0x03
#define DECT_FA_CTRL_U_FMT_ID 0x03
/* Unnumbered function bits */
#define DECT_FA_CTRL_U_U1_MASK 0xec
/* Poll/final bit */
#define DECT_FA_CTRL_U_PF_FLAG 0x10
/* Command/Response */
#define DECT_FA_CTRL_U_CR_MASK 0xef
#define DECT_FA_CTRL_U_CR_SABM 0x2c
#define DECT_FA_CTRL_U_CR_DM 0x0c
#define DECT_FA_CTRL_U_CR_UI 0x00
#define DECT_FA_CTRL_U_CR_DISC 0x40
#define DECT_FA_CTRL_U_CR_UA 0x60
/*
* Length Indicator
*/
#define DECT_FA_LI_OFF 2
/* Length (octets) */
#define DECT_FA_LI_LENGTH_MASK 0xfc
#define DECT_FA_LI_LENGTH_SHIFT 2
/* More data flag */
#define DECT_FA_LI_M_FLAG 0x02
/* Extended length indicator bit */
#define DECT_FA_LI_EXT_FLAG 0x01
/* maximum length value */
#define DECT_FA_LI_MAX 63
/*
* Extended Length indicator
*/
#define DECT_FA_ELI_OFF 3
/* Length (octets) */
#define DECT_FA_ELI_LENGTH_MASK 0xfc
#define DECT_FA_ELI_LENGTH_SHIFT 2
struct dect_fa_len {
uint8_t len;
bool more;
};
/*
* Fill Field
*/
#define DECT_FA_FILL_PATTERN 0xf0
/*
* Checksum field
*/
#define DECT_FA_CSUM_SIZE 2
/*
* Information field
*/
#define DECT_FA_I_MAX (DECT_FA_LI_MAX - DECT_FA_HDR_SIZE - DECT_FA_CSUM_SIZE)
/**
* struct dect_dli - DECT Data Link Identifier (DLI)
*
* @lln: Logical Link Number
* @mci: Mac Connection Identifier
*/
struct dect_dli {
//enum dect_llns lln;
//struct dect_mci mci;
};
/**
* @DECT_LAPC_ULI: unassigned link identifier state (class U/A)
* @DECT_LAPC_ALI: assigned link identifier state (class B established)
* @DECT_LAPC_ASM: assigned Link Identifier/multiple frame state (class B suspended)
*/
enum dect_lapc_states {
DECT_LAPC_ULI,
DECT_LAPC_ALI,
DECT_LAPC_ASM,
};
/**
* struct dect_lapc - DECT LAPC entity
*
* @lc: Associated Lc entity
* @dli: Data Link Identifier
* @sapi: Service Access Point Identifier
* @cmd: CR bit setting for commands (PT: 1, FT: 0)
* @nlf: New link flag
* @v_s: Send state Variable V(S): sequence number of next I-frame
* @v_a: Acknowledge state Variable V(A): last I-frame that has been acknowledged
* @v_r: Receive state Variable V(R): next expected sequence number
* busy: LAPC is in receiver busy condition
* @peer_busy: Peer is in receiver busy condition
* @window: maximum number of oustanding unacknowledged I-frames
* @mod: modulus for sequence number calculations
* @retransmit_cnt: Retransmission counter
* @retransmit_queue: Retransmission queue
* @timer: Retransmission timer (DL.04)
*/
#if 0
struct dect_lapc {
struct sock *sk;
struct dect_lc *lc;
struct dect_dli dli;
enum dect_sapis sapi;
bool cmd;
enum dect_lapc_states state;
bool nlf;
uint8_t v_s;
uint8_t v_a;
uint8_t v_r;
bool busy;
bool peer_busy;
uint8_t window;
uint8_t mod;
uint8_t retransmit_cnt;
struct sk_buff_head retransmit_queue;
struct timer_list timer;
struct sk_buff *rcv_head;
};
#endif
/* class A window size and sequence number modulus */
#define DECT_LAPC_CLASS_A_WINDOW 1
#define DECT_LAPC_CLASS_A_MOD 2
/* class B window size and sequence number modulus */
#define DECT_LAPC_CLASS_B_INITIAL_WINDOW 1
#define DECT_LAPC_CLASS_B_WINDOW 3
#define DECT_LAPC_CLASS_B_MOD 8
/* maximum number of retransmissions */
#define DECT_LAPC_RETRANSMIT_MAX 3
/* various timer parameters specified in Annex A */
#define DECT_LAPC_CLASS_A_ESTABLISH_TIMEOUT (2 * HZ)
#define DECT_LAPC_CLASS_B_ESTABLISH_TIMEOUT (2 * HZ)
#define DECT_LAPC_RETRANSMISSION_TIMEOUT (1 * HZ)
#define DECT_LAPC_LINK_RELEASE_TIMEOUT (2 * HZ)
#define DECT_LAPC_LINK_SUSPEND_TIMEOUT (2 * HZ)
#define DECT_LAPC_LINK_RESUME_TIMEOUT (2 * HZ)
#define DECT_LAPC_CONNECTION_HANDOVER_TIMEOUT (10 * HZ)
#define DECT_LAPC_CONNECTION_HANDOVER_INTERVAL (4 * HZ)
#if 0
extern struct dect_lapc *dect_lapc_init(struct sock *sk, const struct dect_dli *dli,
enum dect_sapis sapi, struct dect_lc *lc,
gfp_t gfp);
extern void dect_lapc_destroy(struct dect_lapc *lapc);
extern int dect_lapc_establish(struct dect_lapc *lapc);
extern void dect_lapc_release(struct dect_lapc *lapc, bool normal);
extern int dect_lapc_transmit(struct dect_lapc *lapc);
extern struct dect_lapc *dect_ssap_rcv_request(struct dect_lc *lc,
const struct dect_dli *dli,
enum dect_sapis sapi);
/**
* struct dect_lc - DECT Lc entity
*
* @mc: MAC connection
* @lsig: link signature for checksumming (lower 16 bits of PMID or 0)
* @rx_head: reassembly queue head
* @rx_len: target length of current reassembly buffer
* @txq: transmit queue
* @tx_head: current TX LAPC frame
* @tx_len: TX target fragment length
* @use: usage count
* @lapcs: LAPC entities associated with the Lc
* @e_lapc: LAPC performing establishment procedures
*
* The Lc entity is responsible for framing, logical channel selection and
* fragmenting of LAPC PDUs. There is one Lc entity per MAC connection.
*/
struct dect_lc {
struct dect_mac_conn *mc;
uint16_t lsig;
struct sk_buff *rx_head;
uint8_t rx_len;
struct sk_buff_head txq;
struct sk_buff *tx_head;
uint8_t tx_len;
uint8_t use;
struct dect_lapc *lapcs[DECT_LLN_MAX + 1];
struct dect_lapc *elapc;
};
#define DECT_LC_LSIG_MASK 0xffff
extern struct dect_lc *dect_lc_init(struct dect_mac_conn *mc, gfp_t gfp);
extern void dect_lc_destroy(struct dect_lc *lc);
extern void dect_lc_bind(struct dect_lc *lc, struct dect_lapc *lapc);
extern void dect_lc_unbind(struct dect_lc *lc, struct dect_lapc *lapc);
/**
* struct dect_lb - DECT Lb entity (C-plane broadcast service)
*
*
*/
struct dect_lb {
};
#define DECT_LB_SHORT_FRAME_SIZE 3
#define DECT_LB_LONG_FRAME_SIZE 5
#define DECT_LB_EXTENDED_FRAME_SIZE_MAX (6 * DECT_LB_LONG_FRAME_SIZE)
#include <net/sock.h>
/**
* struct dect_dlc_fbx_ops - DLC U-plane lower (FBx) entity ops
*
*/
struct dect_fbx;
struct dect_fbx_ops {
struct sk_buff *(*dequeue)(struct dect_fbx *fbx);
void (*enqueue)(struct dect_fbx *fbx,
struct sk_buff *skb);
};
struct dect_fbx {
const struct dect_fbx_ops *ops;
};
extern const struct dect_fbx_ops dect_fbn_ops;
struct dect_lux;
struct dect_lux_ops {
struct sk_buff *(*dequeue)(struct dect_lux *lux);
void (*enqueue)(struct dect_lux *lux,
struct sk_buff *skb);
void (*disconnect)(struct dect_lux *lux);
};
/**
* struct dect_lux - DLC U-plane upper (LUx) entity
*
* @fpx: FBx entity
*/
struct dect_lux {
const struct dect_lux_ops *ops;
struct dect_fbx fbx;
};
/**
* dect_mac_connection_states - DECT MAC connection states as viewed by the DLC
*
* @DECT_MAC_CONN_CLOSED:
* @DECT_MAC_CONN_OPEN_PENDING:
* @DECT_MAC_CONN_OPEN:
*/
enum dect_mac_conn_states {
DECT_MAC_CONN_CLOSED,
DECT_MAC_CONN_OPEN_PENDING,
DECT_MAC_CONN_OPEN,
};
/**
* struct dect_mac_conn - DECT MAC connection as viewed by the DLC
*
* @list: Cluster connection list node
* @cl: Cluster
* @mcei: MAC Connection Endpoint Identification
* @mci: MAC Connection Identifier (BMCI or AMCI)
* @state: Connection state
* @service: Service offered by the connection
* @ck: cipher key
*/
struct dect_mac_conn {
struct list_head list;
struct dect_cluster *cl;
u32 mcei;
struct dect_mci mci;
enum dect_mac_conn_states state;
enum dect_mac_service_types service;
u64 ck;
uint8_t use;
struct dect_lc *lc;
struct dect_fbx *fbx;
};
extern struct dect_mac_conn *dect_mac_conn_init(struct dect_cluster *cl,
const struct dect_mci *mci,
const struct dect_mbc_id *id);
extern void dect_dlc_mac_conn_destroy(struct dect_mac_conn *mc);
extern struct dect_mac_conn *dect_mac_conn_get_by_mci(const struct dect_cluster *cl,
const struct dect_mci *mci);
extern void dect_dlc_mac_conn_bind(struct dect_mac_conn *mc);
extern void dect_dlc_mac_conn_unbind(struct dect_mac_conn *mc);
extern int dect_dlc_mac_conn_establish(struct dect_mac_conn *mc);
extern int dect_mac_con_cfm(struct dect_cluster *cl, u32 mcei,
enum dect_mac_service_types service);
extern int dect_mac_con_ind(struct dect_cluster *cl,
const struct dect_mbc_id *id);
extern int dect_dlc_mac_conn_enc_key_req(struct dect_mac_conn *mc, u64 key);
extern int dect_dlc_mac_conn_enc_eks_req(struct dect_mac_conn *mc,
enum dect_cipher_states status);
extern void dect_mac_enc_eks_cfm(struct dect_cluster *cl, u32 mcei,
enum dect_cipher_states status);
extern void dect_mac_enc_eks_ind(struct dect_cluster *cl, u32 mcei,
enum dect_cipher_states status);
extern void dect_dlc_mac_dis_req(struct dect_mac_conn *mc);
extern int dect_mac_dis_ind(struct dect_cluster *cl, u32 mcei,
enum dect_release_reasons reason);
extern void dect_cplane_notify_state_change(struct dect_mac_conn *mc);
extern void dect_cplane_mac_dis_ind(const struct dect_mac_conn *mc,
enum dect_release_reasons reason);
extern void dect_cplane_mac_enc_eks_ind(const struct dect_mac_conn *mc,
enum dect_cipher_states status);
extern void dect_cplane_rcv(struct dect_mac_conn *mc,
enum dect_data_channels chan,
struct sk_buff *skb);
extern struct sk_buff *dect_cplane_dtr(struct dect_mac_conn *mc,
enum dect_data_channels chan);
extern void dect_uplane_rcv(struct dect_mac_conn *mc,
enum dect_data_channels chan,
struct sk_buff *skb);
extern struct sk_buff *dect_uplane_dtr(struct dect_mac_conn *mc,
enum dect_data_channels chan);
extern void dect_mac_co_data_ind(struct dect_cluster *cl, u32 mcei,
enum dect_data_channels chan,
struct sk_buff *skb);
extern struct sk_buff *dect_mac_co_dtr_ind(struct dect_cluster *cl, u32 mcei,
enum dect_data_channels chan);
extern void dect_bsap_rcv(const struct dect_cluster *cl, struct sk_buff *skb);
extern void dect_mac_page_ind(struct dect_cluster *cl, struct sk_buff *skb);
#endif
#endif /* _NET_DECT_DLC_H */

636
include/list.h Normal file
View File

@ -0,0 +1,636 @@
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
#include <stddef.h>
#define prefetch(x) ((void)0)
#define LIST_POISON1 ((void *)0x12345678)
#define LIST_POISON2 ((void *)0x87654321)
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
static inline void init_list_head(struct list_head *list)
{
list->next = list;
list->prev = list;
}
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
/**
* list_replace - replace old entry by new one
* @old : the element to be replaced
* @new : the new element to insert
*
* If @old was empty, it will be overwritten.
*/
static inline void list_replace(struct list_head *old,
struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
static inline void list_replace_init(struct list_head *old,
struct list_head *new)
{
list_replace(old, new);
init_list_head(old);
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
init_list_head(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
*/
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{
return list->next == head;
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}
/**
* list_empty_careful - tests whether a list is empty and not being modified
* @head: the list to test
*
* Description:
* tests whether a list is empty _and_ checks that no other CPU might be
* in the process of modifying either member (next or prev)
*
* NOTE: using list_empty_careful() without synchronization
* can only be safe if the only activity that can happen
* to the list entry is list_del_init(). Eg. it cannot be used
* if another CPU could re-list_add() it.
*/
static inline int list_empty_careful(const struct list_head *head)
{
struct list_head *next = head->next;
return (next == head) && (next == head->prev);
}
/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
static inline int list_is_singular(const struct list_head *head)
{
return !list_empty(head) && (head->next == head->prev);
}
static inline void __list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
struct list_head *new_first = entry->next;
list->next = head->next;
list->next->prev = list;
list->prev = entry;
entry->next = list;
head->next = new_first;
new_first->prev = head;
}
/**
* list_cut_position - cut a list into two
* @list: a new list to add all removed entries
* @head: a list with entries
* @entry: an entry within head, could be the head itself
* and if so we won't cut the list
*
* This helper moves the initial part of @head, up to and
* including @entry, from @head to @list. You should
* pass on @entry an element you know is on @head. @list
* should be an empty list or a list you do not care about
* losing its data.
*
*/
static inline void list_cut_position(struct list_head *list,
struct list_head *head, struct list_head *entry)
{
if (list_empty(head))
return;
if (list_is_singular(head) &&
(head->next != entry && head != entry))
return;
if (entry == head)
init_list_head(list);
else
__list_cut_position(list, head, entry);
}
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
first->prev = prev;
prev->next = first;
last->next = next;
next->prev = last;
}
/**
* list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head, head->next);
}
/**
* list_splice_tail - join two lists, each list being a queue
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice_tail(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head->prev, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head, head->next);
init_list_head(list);
}
}
/**
* list_splice_tail_init - join two lists and reinitialise the emptied list
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* Each of the lists is a queue.
* The list at @list is reinitialised
*/
static inline void list_splice_tail_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head->prev, head);
init_list_head(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
/**
* list_last_entry - get the last element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*
* Note, that list is expected to be not empty.
*/
#define list_last_entry(ptr, type, member) \
list_entry((ptr)->prev, type, member)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
* @member: the name of the list_struct within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
#define list_prepare_entry(pos, head, member) \
((pos) ? : list_entry(head, typeof(*pos), member))
/**
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_continue_reverse - iterate backwards from the given point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Start to iterate over list of given type backwards, continuing after
* the current position.
*/
#define list_for_each_entry_continue_reverse(pos, head, member) \
for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
prefetch(pos->member.prev), &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
for (; prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_continue
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
for (pos = list_entry(pos->member.next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_from
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
for (n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
* list_for_each_entry_safe_reverse
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member), \
n = list_entry(pos->member.prev, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
/*
* Double linked lists with a single pointer list head.
* Mostly useful for hash tables where the two pointer list head is
* too wasteful.
* You lose the ability to access the tail in O(1).
*/
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define init_hlist_head(ptr) ((ptr)->first = NULL)
static inline void init_hlist_node(struct hlist_node *h)
{
h->next = NULL;
h->pprev = NULL;
}
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
*pprev = next;
if (next)
next->pprev = pprev;
}
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
n->next = LIST_POISON1;
n->pprev = LIST_POISON2;
}
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
__hlist_del(n);
init_hlist_node(n);
}
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
n->next = first;
if (first)
first->pprev = &n->next;
h->first = n;
n->pprev = &h->first;
}
/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
struct hlist_node *next)
{
n->pprev = next->pprev;
n->next = next;
next->pprev = &n->next;
*(n->pprev) = n;
}
static inline void hlist_add_after(struct hlist_node *n,
struct hlist_node *next)
{
next->next = n->next;
n->next = next;
next->pprev = &n->next;
if(next->next)
next->next->pprev = &next->next;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
/**
* hlist_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_continue(tpos, pos, member) \
for (pos = (pos)->next; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_from(tpos, pos, member) \
for (; pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @n: another &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
#endif

936
include/mac.h Normal file
View File

@ -0,0 +1,936 @@
/*
* DECT MAC Layer - Header and global definitions
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#ifndef _NET_DECT_MAC_H
#define _NET_DECT_MAC_H
#include <stdbool.h>
#include <stdint.h>
#define DECT_FRAME_SIZE 24
#define DECT_HALF_FRAME_SIZE (DECT_FRAME_SIZE / 2)
/*
* A-Field
*/
#define DECT_A_FIELD_SIZE 8
#define DECT_RA_FIELD_SIZE 2
#define DECT_RA_FIELD_OFF 6
/*
* Header field
*/
#define DECT_HDR_FIELD_SIZE 1
#define DECT_HDR_FIELD_OFF 0
#define DECT_HDR_TA_OFF 0
#define DECT_HDR_TA_MASK 0xe0
#define DECT_HDR_TA_SHIFT 5
#define DECT_HDR_Q1_OFF 0
#define DECT_HDR_Q1_FLAG 0x10
#define DECT_HDR_BA_OFF 0
#define DECT_HDR_BA_MASK 0x0e
#define DECT_HDR_BA_SHIFT 1
#define DECT_HDR_Q2_OFF 0
#define DECT_HDR_Q2_FLAG 0x01
/*
* T-Field
*/
#define DECT_T_FIELD_OFF 1
#define DECT_T_FIELD_SIZE 5
/**
* dect_tail_identification - MAC layer T-Field identification
*
* @DECT_TI_CT_PKT_0: C_T data packet number 0
* @DECT_TI_CT_PKT_1: C_T data packet number 1
* @DECT_TI_NT_CL: Identities information on connectionless bearer
* @DECT_TI_NT: Identities information
* @DECT_TI_QT: Multiframe synchronisation und system information
* @DECT_TI_RESERVED: Reserved
* @DECT_TI_MT: MAC layer control
* @DECT_TI_PT: Paging tail (RFP only)
* @DECT_TI_MT_PKT_0: MAC layer control (first PP transmission, PP only)
*/
enum dect_tail_identifications {
DECT_TI_CT_PKT_0 = 0x0 << DECT_HDR_TA_SHIFT,
DECT_TI_CT_PKT_1 = 0x1 << DECT_HDR_TA_SHIFT,
DECT_TI_NT_CL = 0x2 << DECT_HDR_TA_SHIFT,
DECT_TI_NT = 0x3 << DECT_HDR_TA_SHIFT,
DECT_TI_QT = 0x4 << DECT_HDR_TA_SHIFT,
DECT_TI_RESERVED = 0x5 << DECT_HDR_TA_SHIFT,
DECT_TI_MT = 0x6 << DECT_HDR_TA_SHIFT,
DECT_TI_PT = 0x7 << DECT_HDR_TA_SHIFT,
DECT_TI_MT_PKT_0 = 0x7 << DECT_HDR_TA_SHIFT,
};
struct dect_skb_a_cb {
enum dect_tail_identifications id;
};
#define DECT_A_CB(skb) ((struct dect_skb_a_cb *)(skb)->cb)
/*
* Identities channel (N-channel)
*/
/* Identities information */
#define DECT_NT_ID_RFPI_LEN 5
/*
* Acess Rights Identity (ARI)
*/
#define DECT_ARI_ARC_MASK 0xe000000000000000ULL
#define DECT_ARI_ARC_SHIFT 61
/* Class A */
#define DECT_ARI_A_EMC_MASK 0x1fffe00000000000ULL
#define DECT_ARI_A_EMC_SHIFT 45
#define DECT_ARI_A_FPN_MASK 0x00001ffff0000000ULL
#define DECT_ARI_A_FPN_SHIFT 28
/* Class B */
#define DECT_ARI_B_EIC_MASK 0x1fffe00000000000ULL
#define DECT_ARI_B_EIC_SHIFT 45
#define DECT_ARI_B_FPN_MASK 0x00001fe000000000ULL
#define DECT_ARI_B_FPN_SHIFT 37
#define DECT_ARI_B_FPS_MASK 0x0000001e00000000ULL
#define DECT_ARI_B_FPS_SHIFT 33
/* Class C */
#define DECT_ARI_C_POC_MASK 0x1fffe00000000000ULL
#define DECT_ARI_C_POC_SHIFT 45
#define DECT_ARI_C_FPN_MASK 0x00001fe000000000ULL
#define DECT_ARI_C_FPN_SHIFT 37
#define DECT_ARI_C_FPS_MASK 0x0000001e00000000ULL
#define DECT_ARI_C_FPS_SHIFT 33
/* Class D */
#define DECT_ARI_D_GOP_MASK 0x1ffffe0000000000ULL
#define DECT_ARI_D_GOP_SHIFT 41
#define DECT_ARI_D_FPN_MASK 0x000001fe00000000ULL
#define DECT_ARI_D_FPN_SHIFT 33
/* Class E */
#define DECT_ARI_E_FIL_MASK 0x1fffe00000000000ULL
#define DECT_ARI_E_FIL_SHIFT 45
#define DECT_ARI_E_FPN_MASK 0x00001ffe00000000ULL
#define DECT_ARI_E_FPN_SHIFT 33
#include <linux/dect_netlink.h>
struct dect_ari_ {
enum dect_ari_classes arc;
uint32_t fpn;
uint32_t fps;
union {
uint16_t emc;
uint16_t eic;
uint16_t poc;
uint32_t gop;
uint16_t fil;
};
};
#if 0
enum dect_ari_lengths {
DECT_ARC_A_LEN = 36,
DECT_ARC_B_LEN = 31,
DECT_ARC_C_LEN = 31,
DECT_ARC_D_LEN = 31,
DECT_ARC_E_LEN = 31,
};
#endif
/*
* RFPI
*/
#define DECT_RFPI_E_FLAG 0x8000000000000000ULL
#define DECT_RFPI_ARI_SHIFT 1
#define DECT_RFPI_RPN_SHIFT 24
/**
* @e: indicates whether SARIs are available
* @pari: primary access rights identifier
* @rpn: radio part number
*/
struct dect_idi {
bool e;
struct dect_ari pari;
uint8_t rpn;
};
/*
* System information and multiframe marker (Q-channel)
*/
/* RFP Q-channel T-MUX rules: only frame 8 */
#define DECT_Q_CHANNEL_FRAME 8
/* System information header */
#define DECT_QT_H_MASK 0xf000000000000000ULL
#define DECT_QT_H_SHIFT 60
/**
* dect_system_information_types - codes for system information messages
*
* @DECT_QT_SI_SSI: static system information
* @DECT_QT_SI_ERFC: extended RF carriers
* @DECT_QT_SI_FPC: fixed part capabilities
* @DECT_QT_SI_EFPC: extended fixed part capabilities
* @DECT_QT_SI_SARI: SARI list contents
* @DECT_QT_SI_MFN: multi-frame number
* @DECT_QT_SI_ESC: escape
* @DECT_QT_SI_ERFC2: extended RF carriers part 2
* @DECT_QT_SI_TXI transmit information
* @DECT_QT_SI_EFPC2: extended fixed part capabilities part 2
*/
enum dect_mac_system_information_types {
DECT_QT_SI_SSI = 0x0ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_SSI2 = 0x1ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_ERFC = 0x2ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_FPC = 0x3ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_EFPC = 0x4ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_SARI = 0x5ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_MFN = 0x6ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_ESC = 0x7ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_ERFC2 = 0x9ULL << DECT_QT_H_SHIFT,
DECT_QT_SI_TXI = 0xbULL << DECT_QT_H_SHIFT,
DECT_QT_SI_EFPC2 = 0xcULL << DECT_QT_H_SHIFT,
};
/*
* Static system information - repeated every 8 multiframes
*/
#define DECT_QT_SSI_FREQ 8
/* normal reverse */
#define DECT_QT_SSI_NR_FLAG 0x1000000000000000ULL
/* slot number */
#define DECT_QT_SSI_SN_MASK 0x0f00000000000000ULL
#define DECT_QT_SSI_SN_SHIFT 56
/* start position */
#define DECT_QT_SSI_SP_MASK 0x00c0000000000000ULL
#define DECT_QT_SSI_SP_SHIFT 54
/* escape bit */
#define DECT_QT_SSI_ESC_FLAG 0x0020000000000000ULL
/* number of transceivers */
#define DECT_QT_SSI_TXS_MASK 0x0018000000000000ULL
#define DECT_QT_SSI_TXS_SHIFT 51
/* extended RF carrier information available */
#define DECT_QT_SSI_MC_FLAG 0x0004000000000000ULL
/* RF carriers available */
#define DECT_QT_SSI_RFCARS_MASK 0x0003ff0000000000ULL
#define DECT_QT_SSI_RFCARS_SHIFT 40
/* carrier number */
#define DECT_QT_SSI_CN_MASK 0x0000003f00000000ULL
#define DECT_QT_SSI_CN_SHIFT 32
/* primary scan carrier number */
#define DECT_QT_SSI_PSCN_MASK 0x000000003f000000ULL
#define DECT_QT_SSI_PSCN_SHIFT 24
struct dect_ssi {
bool nr;
bool mc;
uint16_t rfcars;
uint8_t sn;
uint8_t sp;
uint8_t txs;
uint8_t cn;
uint8_t pscn;
};
/*
* Extended RF carrier information
*/
#define DECT_QT_ERFC_FREQ 8
#define DECT_QT_ERFC_RFCARS_MASK 0x0fffffe000000000ULL
#define DECT_QT_ERFC_RFCARS_SHIFT 9
#define DECT_QT_ERFC_RFBAND_MASK 0x0000001f00000000ULL
#define DECT_QT_ERFC_RFBAND_SHIFT 32
#define DECT_QT_ERFC_ERFC2_FLAG 0x0000000080000000ULL
#define DECT_QT_ERFC_NUM_RFCARS_MASK 0x000000003f000000ULL
#define DECT_QT_ERFC_NUM_RFCARS_SHIFT 24
struct dect_erfc {
uint32_t rfcars;
uint8_t band;
uint8_t num_rfcars;
bool erfc2;
};
/*
* Fixed Part capabilities
*/
#define DECT_QT_FPC_FREQ 8
#define DECT_QT_FPC_CAPABILITY_MASK 0x0fffff0000000000ULL
#define DECT_QT_FPC_CAPABILITY_SHIFT 40
#define DECT_QT_FPC_HLC_MASK 0x000000ffff000000ULL
#define DECT_QT_FPC_HLC_SHIFT 24
struct dect_fpc {
uint32_t fpc;
uint16_t hlc;
};
/*
* Extended Fixed Part capabilities
*/
#define DECT_QT_EFPC_EFPC_MASK 0x0fff800000000000ULL
#define DECT_QT_EFPC_EFPC_SHIFT 47
#define DECT_QT_EFPC_EHLC_MASK 0x00007fffff000000ULL
#define DECT_QT_EFPC_EHLC_SHIFT 24
struct dect_efpc {
uint16_t fpc;
uint32_t hlc;
};
#define DECT_QT_EFPC2_FPC_MASK 0x0fff000000000000ULL
#define DECT_QT_EFPC2_FPC_SHIFT 48
#define DECT_QT_EFPC2_HLC_MASK 0x0000ffffff000000ULL
#define DECT_QT_EFPC2_HLC_SHIFT 24
struct dect_efpc2 {
uint16_t fpc;
uint32_t hlc;
};
/*
* SARI message
*/
#define DECT_QT_SARI_FREQ 4
#define DECT_QT_SARI_LIST_CYCLE_MASK 0x000e000000000000ULL
#define DECT_QT_SARI_LIST_CYCLE_SHIFT 49
#define DECT_QT_SARI_TARI_FLAG 0x0001000000000000ULL
#define DECT_QT_SARI_BLACK_FLAG 0x0000800000000000ULL
#define DECT_QT_SARI_ARI_MASK 0x00007fffffff0000ULL
#define DECT_QT_SARI_ARI_SHIFT 17
struct dect_sari {
uint8_t list_cycle;
bool tari;
bool black;
//struct dect_ari ari;
};
#define DECT_SARI_CYCLE_MAX 16
/*
* Multiframe number - repeated every 8 multiframes if supported
*/
#define DECT_QT_MFN_FREQ 8
#define DECT_QT_MFN_MASK 0x0000ffffff000000ULL
#define DECT_QT_MFN_SHIFT 24
struct dect_mfn {
uint32_t num;
};
/*
* Extended RF carrier information part 2
*/
#define DECT_QT_TXI_ERFC2_FREQ 8
#define DECT_QT_ERFC2_RFCARS_MASK 0x0fffffffe0000000ULL
#define DECT_QT_ERFC2_RFCARS_SHIFT 29
struct dect_erfc2 {
uint32_t rfcars;
};
/*
* Transmit Information
*/
#define DECT_QT_TXI_FREQ 8
#define DECT_QT_TXI_TYPE_MASK 0x0f00000000000000ULL
#define DECT_QT_TXI_TYPE_SHIFT 56
#define DECT_QT_TXI_PWL_MASK 0x00ff000000000000ULL
#define DECT_QT_TXI_PWL_SHIFT 48
/*
* Extended fixed part capabilitiees part 2
*/
/*
* Paging Tail (P-channel)
*/
#define DECT_PT_HDR_EXTEND_FLAG 0x8000000000000000ULL
#define DECT_PT_HDR_LENGTH_MASK 0x7000000000000000ULL
#define DECT_PT_HDR_LENGTH_SHIFT 60
/**
* @DECT_PT_ZERO_PAGE: zero length page
* @DECT_PT_SHORT_PAGE: short page
* @DECT_PT_FULL_PAGE: full page
* @DECT_PT_MAX_RESUME_PAGE: MAC resume and control page
* @DECT_PT_LONG_PAGE: not the last 36 bits of a long page
* @DECT_PT_LONG_PAGE_FIRST: the first 36 bits of a long page
* @DECT_PT_LONG_PAGE_LAST: the last 36 bits of a long page
* @DECT_PT_LONG_PAGE_ALL: all of a long page (first and last)
*
*/
enum dect_page_lengths {
DECT_PT_ZERO_PAGE = 0x0ULL << DECT_PT_HDR_LENGTH_SHIFT,
DECT_PT_SHORT_PAGE = 0x1ULL << DECT_PT_HDR_LENGTH_SHIFT,
DECT_PT_FULL_PAGE = 0x2ULL << DECT_PT_HDR_LENGTH_SHIFT,
DECT_PT_RESUME_PAGE = 0x3ULL << DECT_PT_HDR_LENGTH_SHIFT,
DECT_PT_LONG_PAGE = 0x4ULL << DECT_PT_HDR_LENGTH_SHIFT,
DECT_PT_LONG_PAGE_FIRST = 0x5ULL << DECT_PT_HDR_LENGTH_SHIFT,
DECT_PT_LONG_PAGE_LAST = 0x6ULL << DECT_PT_HDR_LENGTH_SHIFT,
DECT_PT_LONG_PAGE_ALL = 0x7ULL << DECT_PT_HDR_LENGTH_SHIFT,
};
/* zero length pages */
#define DECT_PT_ZP_RFPI_MASK 0x0fffff0000000000ULL
#define DECT_PT_ZP_RFPI_SHIFT 40
/* short page B_S channel data */
#define DECT_PT_SP_BS_DATA_MASK 0x0fffff0000000000ULL
#define DECT_PT_SP_BS_DATA_SHIFT 40
#define DECT_PT_SP_BS_DATA_SIZE 3
/* long and full page B_S channel data */
#define DECT_PT_LFP_BS_DATA_MASK 0x0fffffffff000000ULL
#define DECT_PT_LFP_BS_DATA_SHIFT 24
#define DECT_PT_LFP_BS_DATA_SIZE 5
struct dect_page {
bool extend;
enum dect_page_lengths length;
uint32_t rfpi;
};
/* MAC layer information */
#define DECT_PT_INFO_TYPE_MASK 0x000000f000000000ULL
#define DECT_PT_INFO_TYPE_SHIFT 36
#define DECT_PT_INFO_TYPE_SIZE 2
/**
* @DECT_PT_IT_FILL_BITS_OR_BLIND_LONG_SLOTS: fill bits/blind long slots if bit 47 set
* @DECT_PT_IT_BLIND_FULL_SLOT: blind full slot information
* @DECT_PT_IT_OTHER_BEARER:
* @DECT_PT_IT_RECOMMENDED_OTHER_BEARER:
* @DECT_PT_IT_GOOD_RFP_BEARER:
* @DECT_PT_IT_DUMMY_OR_CL_BEARER_POSITION:
* @DECT_PT_IT_RFP_IDENTITY:
* @DECT_PT_IT_ESCAPE:
* @DECT_PT_IT_DUMMY_OR_CL_BEARER_MARKER:
* @DECT_PT_IT_BEARER_HANDOVER_INFO:
* @DECT_PT_IT_RFP_STATUS:
* @DECT_PT_IT_ACTIVE_CARRIERS:
* @DECT_PT_IT_CL_BEARER_POSITION:
* @DECT_PT_IT_RECOMMENDED_POWER_LEVEL:
* @DECT_PT_IT_BLIND_DOUBLE_SLOT:
* @DECT_PT_IT_BLIND_FULL_SLOT_PACKET_MODE:
*
*/
enum dect_pt_info_types {
DECT_PT_IT_FILL_BITS_OR_BLIND_LONG_SLOTS= 0x0ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_BLIND_FULL_SLOT = 0x1ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_OTHER_BEARER = 0x2ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_RECOMMENDED_OTHER_BEARER = 0x3ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_GOOD_RFP_BEARER = 0x4ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_DUMMY_OR_CL_BEARER_POSITION = 0x5ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_RFP_IDENTITY = 0x6ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_ESCAPE = 0x7ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_DUMMY_OR_CL_BEARER_MARKER = 0x8ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_BEARER_HANDOVER_INFO = 0x9ULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_RFP_STATUS = 0xaULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_ACTIVE_CARRIERS = 0xbULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_CL_BEARER_POSITION = 0xcULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_RECOMMENDED_POWER_LEVEL = 0xdULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_BLIND_DOUBLE_SLOT = 0xeULL << DECT_PT_INFO_TYPE_SHIFT,
DECT_PT_IT_BLIND_FULL_SLOT_PACKET_MODE = 0xfULL << DECT_PT_INFO_TYPE_SHIFT,
};
/* blind full slot information */
#define DECT_PT_BFS_MASK 0x0000000fff000000ULL
#define DECT_PT_BFS_SHIFT 24
struct dect_bfs {
struct dect_page page;
uint16_t mask;
};
/* Bearer description */
#define DECT_PT_BEARER_SN_MASK 0x0000000f00000000ULL
#define DECT_PT_BEARER_SN_SHIFT 32
#define DECT_PT_BEARER_SP_MASK 0x00000000c0000000ULL
#define DECT_PT_BEARER_SP_SHIFT 30
#define DECT_PT_BEARER_CN_MASK 0x000000003f000000ULL
#define DECT_PT_BEARER_CN_SHIFT 24
struct dect_bearer_desc {
struct dect_page page;
enum dect_pt_info_types bt;
uint8_t sn;
uint8_t sp;
uint8_t cn;
};
/* RFP identity */
#define DECT_PT_RFP_ID_MASK 0x0000000fff000000ULL
#define DECT_PT_RFP_ID_SHIFT 24
struct dect_rfp_id {
struct dect_page page;
uint16_t id;
};
/* RFP status */
#define DECT_PT_RFPS_RFP_BUSY_FLAG 0x0000000100000000ULL
#define DECT_PT_RFPS_SYS_BUSY_FLAG 0x0000000200000000ULL
struct dect_rfp_status {
struct dect_page page;
bool rfp_busy;
bool sys_busy;
};
/* Active carriers */
#define DECT_PT_ACTIVE_CARRIERS_MASK 0x0000000ffc000000ULL
#define DECT_PT_ACTIVE_CARRIERS_SHIFT 26
struct dect_active_carriers {
struct dect_page page;
uint16_t active;
};
/*
* MAC control (M-channel)
*/
#define DECT_MT_FRAME_RATE 2
#define DECT_MT_HDR_MASK 0xf000000000000000ULL
#define DECT_MT_HDR_SHIFT 60
#define DECT_MT_CMD_MASK 0x0f00000000000000ULL
#define DECT_MT_CMD_SHIFT 56
/**
* enum dect_mt_hdr_type - MAC tail header types
*/
enum dect_mt_hdr_type {
DECT_MT_BASIC_CCTRL = 0x0ULL << DECT_MT_HDR_SHIFT,
DECT_MT_ADV_CCTRL = 0x1ULL << DECT_MT_HDR_SHIFT,
DECT_MT_MAC_TEST = 0x2ULL << DECT_MT_HDR_SHIFT,
DECT_MT_QUALITY_CTRL = 0x3ULL << DECT_MT_HDR_SHIFT,
DECT_MT_BRD_CL_SERVICE = 0x4ULL << DECT_MT_HDR_SHIFT,
DECT_MT_ENC_CTRL = 0x5ULL << DECT_MT_HDR_SHIFT,
DECT_MT_XYZ = 0x6ULL << DECT_MT_HDR_SHIFT,
DECT_MT_ESC = 0x7ULL << DECT_MT_HDR_SHIFT,
DECT_MT_TARI = 0x8ULL << DECT_MT_HDR_SHIFT,
DECT_MT_REP_CCTRL = 0x9ULL << DECT_MT_HDR_SHIFT,
};
/* advanced connection control */
enum dect_cctrl_cmds {
DECT_CCTRL_ACCESS_REQ = 0x0ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_BEARER_HANDOVER_REQ = 0x1ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_CONNECTION_HANDOVER_REQ = 0x2ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_UNCONFIRMED_ACCESS_REQ = 0x3ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_BEARER_CONFIRM = 0x4ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_WAIT = 0x5ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_ATTRIBUTES_T_REQUEST = 0x6ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_ATTRIBUTES_T_CONFIRM = 0x7ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_BANDWIDTH_T_REQUEST = 0x8ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_BANDWIDTH_T_CONFIRM = 0x9ULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_CHANNEL_LIST = 0xaULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_UNCONFIRMED_DUMMY = 0xbULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_UNCONFIRMED_HANDOVER = 0xcULL << DECT_MT_CMD_SHIFT,
DECT_CCTRL_RELEASE = 0xfULL << DECT_MT_CMD_SHIFT,
};
/* Most messages */
#define DECT_CCTRL_FMID_MASK 0x00fff00000000000ULL
#define DECT_CCTRL_FMID_SHIFT 44
#define DECT_CCTRL_PMID_MASK 0x00000fffff000000ULL
#define DECT_CCTRL_PMID_SHIFT 24
/* Attributes-T request/confirm */
#define DECT_CCTRL_ATTR_ECN_MASK 0x00f0000000000000ULL
#define DECT_CCTRL_ATTR_ECN_SHIFT 52
#define DECT_CCTRL_ATTR_LBN_MASK 0x000f000000000000ULL
#define DECT_CCTRL_ATTR_LBN_SHIFT 48
#define DECT_CCTRL_ATTR_TYPE_MASK 0x0000c00000000000ULL
#define DECT_CCTRL_ATTR_TYPE_SHIFT 46
enum dect_cctrl_connection_types {
DECT_CCTRL_TYPE_ASYMETRIC_UPLINK = 0x0,
DECT_CCTRL_TYPE_ASYMETRIC_DOWNLINK = 0x1,
DECT_CCTRL_TYPE_SYMETRIC_MULTIBEARER = 0x2,
DECT_CCTRL_TYPE_SYMETRIC_BEARER = 0x3,
};
#define DECT_CCTRL_ATTR_SERVICE_MASK 0x00003f0000000000ULL
#define DECT_CCTRL_ATTR_SERVICE_SHIFT 40
enum dect_mac_service_types {
DECT_SERVICE_IN_MIN_DELAY = 0x0,
DECT_SERVICE_IPX_ENCODED_PROTECTED = 0x1,
DECT_SERVICE_IN_NORM_DELAY = 0x2,
DECT_SERVICE_UNKNOWN = 0x4,
DECT_SERVICE_C_ONLY = 0x5,
DECT_SERVICE_IP_ERROR_DETECTION = 0x10,
DECT_SERVICE_IPQ_ERROR_DETECTION = 0x14,
/* Lifetime encoded in low three bits */
DECT_SERVICE_IP_ERROR_CORRECTION = 0x18,
DECT_SERVICE_IPQ_ERROR_CORRECTION = 0x38,
};
#define DECT_SERVICE_LIFETIME_MASK = 0x7
#define DECT_CCTRL_ATTR_SLOT_MASK 0x000000f000000000ULL
#define DECT_CCTRL_ATTR_SLOT_SHIFT 36
#define DECT_CCTRL_ATTR_CF_FLAG 0x0000000800000000ULL
#define DECT_CCTRL_ATTR_BZ_EXT_MOD_MASK 0x0000000700000000ULL
#define DECT_CCTRL_ATTR_BZ_EXT_MOD_SHIFT 32
#define DECT_CCTRL_ATTR_ACR_MASK 0x00000000f0000000ULL
#define DECT_CCTRL_ATTR_ACR_SHIFT 28
enum dect_adaptive_code_rates {
DECT_ACR_NONE = 0x0,
};
#define DECT_CCTRL_ATTR_A_MOD_MASK 0x000000000c000000ULL
#define DECT_CCTRL_ATTR_A_MOD_SHIFT 26
#define DECT_CCTRL_ATTR_BZ_MOD_MASK 0x0000000003000000ULL
#define DECT_CCTRL_ATTR_BZ_MOD_SHIFT 24
enum dect_modulation_type {
DECT_MODULATION_2_LEVEL = 0x3,
DECT_MODULATION_4_LEVEL = 0x2,
DECT_MODULATION_8_LEVEL = 0x1,
};
/* Release */
#define DECT_CCTRL_RELEASE_INFO1_MASK 0x00f0000000000000ULL
#define DECT_CCTRL_RELEASE_INFO1_SHIFT 52
#define DECT_CCTRL_RELEASE_LBN_MASK 0x000f000000000000ULL
#define DECT_CCTRL_RELEASE_LBN_SHIFT 48
#define DECT_CCTRL_RELEASE_REASON_MASK 0x0000f00000000000ULL
#define DECT_CCTRL_RELEASE_REASON_SHIFT 44
enum dect_mac_release_reasons {
DECT_REASON_UNKNOWN = 0x0,
DECT_REASON_BEARER_RELEASE = 0x1,
DECT_REASON_CONNECTION_RELEASE = 0x2,
DECT_REASON_BEARER_SETUP_OR_HANDOVER_FAILED = 0x3,
DECT_REASON_BEARER_HANDOVER_COMPLETED = 0x4,
DECT_REASON_BEARER_HANDOVER_CLUSTER = 0x5,
DECT_REASON_TIMEOUT_LOST_SIGNAL = 0x6,
DECT_REASON_TIMEOUT_LOST_HANDSHAKE = 0x7,
DECT_REASON_REQUESTED_UNACCEPTABLE_SLOT_TYPE = 0x8,
DECT_REASON_REQUESTED_UNACCEPTABLE_MAC_SERVICE = 0x9,
DECT_REASON_BASE_STATION_BUSY = 0xa,
DECT_REASON_REVERSE_DIRECTION = 0xb,
DECT_REASON_DUPLICATE_PMID = 0xc,
DECT_REASON_UNACCEPTABLE_PMID = 0xd,
DECT_REASON_STAY_ON_LISTEN = 0xe,
};
#define DECT_CCTRL_RELEASE_PMID_MASK 0x00000fffff000000ULL
#define DECT_CCTRL_RELEASE_PMID_SHIFT 24
struct dect_cctrl {
enum dect_cctrl_cmds cmd;
union {
struct {
uint32_t pmid;
uint16_t fmid;
};
struct {
uint8_t lbn;
uint8_t ecn;
uint8_t type;
uint8_t service;
uint8_t slot;
bool cf;
uint8_t a_mod;
uint8_t bz_mod;
uint8_t bz_ext_mod;
uint8_t acr;
};
struct {
uint32_t pmid;
uint8_t lbn;
uint8_t reason;
};
};
};
/* Encryption Control */
#define DECT_ENCCTRL_FILL_MASK 0x5000000000000000ULL
#define DECT_ENCCTRL_CMD_MASK 0x0f00000000000000ULL
#define DECT_ENCCTRL_CMD_SHIFT 56
enum dect_encctrl_cmds {
DECT_ENCCTRL_START_REQUEST = 0x0,
DECT_ENCCTRL_START_CONFIRM = 0x1,
DECT_ENCCTRL_START_GRANT = 0x2,
DECT_ENCCTRL_STOP_REQUEST = 0x4,
DECT_ENCCTRL_STOP_CONFIRM = 0x5,
DECT_ENCCTRL_STOP_GRANT = 0x6,
};
#define DECT_ENCCTRL_FMID_MASK 0x00fff00000000000ULL
#define DECT_ENCCTRL_FMID_SHIFT 44
#define DECT_ENCCTRL_PMID_MASK 0x00000fffff000000ULL
#define DECT_ENCCTRL_PMID_SHIFT 24
struct dect_encctrl {
enum dect_encctrl_cmds cmd;
uint32_t pmid;
uint16_t fmid;
};
/* marker for T-MUX exceptions */
#define DECT_MT_HIGH_PRIORITY 0x1
/*
* C_T data
*/
#define DECT_C_S_SDU_SIZE 5
struct dect_ct_data {
uint8_t seq;
};
/*
* Flat representation of tail message contents
*/
enum dect_tail_msg_types {
DECT_TM_TYPE_INVALID,
DECT_TM_TYPE_ID,
DECT_TM_TYPE_SSI,
DECT_TM_TYPE_ERFC,
DECT_TM_TYPE_FPC,
DECT_TM_TYPE_EFPC,
DECT_TM_TYPE_EFPC2,
DECT_TM_TYPE_SARI,
DECT_TM_TYPE_MFN,
DECT_TM_TYPE_PAGE,
DECT_TM_TYPE_BFS,
DECT_TM_TYPE_BD,
DECT_TM_TYPE_RFP_ID,
DECT_TM_TYPE_RFP_STATUS,
DECT_TM_TYPE_ACTIVE_CARRIERS,
DECT_TM_TYPE_BCCTRL,
DECT_TM_TYPE_ACCTRL,
DECT_TM_TYPE_ENCCTRL,
DECT_TM_TYPE_CT,
};
struct dect_tail_msg {
enum dect_tail_identifications ti;
enum dect_tail_msg_types type;
union {
struct dect_idi idi;
struct dect_ssi ssi;
struct dect_erfc erfc;
struct dect_fpc fpc;
struct dect_efpc efpc;
struct dect_efpc2 efpc2;
struct dect_sari sari;
struct dect_mfn mfn;
struct dect_page page;
struct dect_bfs bfs;
struct dect_bearer_desc bd;
struct dect_rfp_id rfp_id;
struct dect_rfp_status rfp_status;
struct dect_active_carriers active_carriers;
struct dect_cctrl cctl;
struct dect_encctrl encctl;
struct dect_ct_data ctd;
};
};
struct dect_si {
uint32_t mask;
struct dect_ssi ssi;
struct dect_erfc erfc;
struct dect_fpc fpc;
struct dect_efpc efpc;
struct dect_efpc2 efpc2;
struct dect_sari sari[DECT_SARI_CYCLE_MAX];
struct dect_mfn mfn;
uint8_t num_saris;
};
/*
* B-Field
*/
#define DECT_B_FIELD_SIZE 40
/**
* dect_b_identitifications - MAC layer B-Field Identification
*
* @DECT_BI_UTYPE_0: U-Type, I_N, SI_N, SI_P or I_P packet number 0
* @DECT_BI_UTYPE_1: U-Type, I_P error detect or I_P packet number 1
* @DECT_BI_ETYPE_CF_0: E-Type, all C_F or CL_F, packet number 0
* @DECT_BI_ETYPE_CF_1: E-Type, all C_F, packet number 1
* @DECT_BI_ETYPE_MAC: E-Type, all MAC control (unnumbered)
* @DECT_BI_NONE: no B-Field
*/
enum dect_b_identifications {
DECT_BI_UTYPE_0 = 0x0 << DECT_HDR_BA_SHIFT,
DECT_BI_UTYPE_1 = 0x1 << DECT_HDR_BA_SHIFT,
DECT_BI_ETYPE_CF_0 = 0x2 << DECT_HDR_BA_SHIFT,
DECT_BI_ETYPE_CF_1 = 0x3 << DECT_HDR_BA_SHIFT,
DECT_BI_ETYPE_NOT_ALL_CF_0 = 0x4 << DECT_HDR_BA_SHIFT,
DECT_BI_ETYPE_NOT_ALL_CF_1 = 0x5 << DECT_HDR_BA_SHIFT,
DECT_BI_ETYPE_MAC = 0x6 << DECT_HDR_BA_SHIFT,
DECT_BI_NONE = 0x7 << DECT_HDR_BA_SHIFT,
};
struct dect_skb_b_cb {
enum dect_b_identifications id;
};
#define DECT_B_CB(skb) ((struct dect_skb_b_cb *)(skb)->cb)
#define DECT_C_F_SDU_SIZE 8
#define DECT_G_F_SDU_SIZE 8
/**
* enum dect_mac_channels - internal MAC control channels
*
* @DECT_MC_Q: System information and multiframe marker
* @DECT_MC_N: Identities information
* @DECT_MC_M: MAC control channel
* @DECT_MC_P: MAC Paging channel
*/
enum dect_mac_channels {
DECT_MC_Q,
DECT_MC_N,
DECT_MC_M,
DECT_MC_P,
};
/**
* enum dect_data_channels - logical MAC data channels
*
* @DECT_MC_G_F:
* @DECT_MC_C_S: Higher layer C-Plane channel (slow)
* @DECT_MC_C_F: Higher layer C-Plane channel (fast)
* @DECT_MC_I_N: Higher layer U-Plane channel (numbered)
* @DECT_MC_I_P: Higher layer U-Plane channel (protected)
* @DECT_MC_SI_N: Higher layer connectionless U-Plane channel (numbered)
* @DECT_MC_SI_P: Higher layer connectionless U-Plane channel (protected)
*/
enum dect_data_channels {
DECT_MC_G_F,
DECT_MC_C_S,
DECT_MC_C_F,
DECT_MC_I_N,
DECT_MC_I_P,
DECT_MC_SI_N,
DECT_MC_SI_P,
__DECT_MC_MAX
};
#define DECT_MC_MAX (__DECT_MC_MAX - 1)
/**
* enum dect_mac_connection_types - MAC Connection types
*
* @DECT_MAC_CONN_BASIC: Basic connection, always I_N_min_delay service
* @DECT_MAC_CONN_ADVANCED: Advanced connection
* @DECT_MAC_CONN_COMPLEMENT: Complementary connection
*/
enum dect_mac_connection_types {
DECT_MAC_CONN_BASIC,
DECT_MAC_CONN_ADVANCED,
DECT_MAC_CONN_COMPLEMENT,
};
/**
* struct dect_mbc_id
*
* @mcei: MAC Connection Endpoint Identifier
* @type: Connection Type (Basic/Advanced)
* @ari: FT identifier
* @pmid: Portable MAC Identity
* @ecn: Exchanged Connection Number
* @service: Service type
*/
struct dect_mbc_id {
uint32_t mcei;
enum dect_mac_connection_types type;
//struct dect_ari ari;
//struct dect_pmid pmid;
uint8_t ecn;
enum dect_mac_service_types service;
};
#endif /* _NET_DECT_MAC_H */

73
include/nwk.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef _NWK_H
#define _NWK_H
/* LCE message types */
enum dect_lce_msg_types {
DECT_LCE_PAGE_RESPONSE = 0x71,
DECT_LCE_PAGE_REJECT = 0x72,
};
/**
* Call Control message types
*/
enum dect_cc_msg_types {
DECT_CC_RESERVED = 0x0,
DECT_CC_ALERTING = 0x1,
DECT_CC_CALL_PROC = 0x2,
DECT_CC_SETUP = 0x5,
DECT_CC_CONNECT = 0x7,
DECT_CC_SETUP_ACK = 0xd,
DECT_CC_CONNECT_ACK = 0xf,
DECT_CC_SERVICE_CHANGE = 0x20,
DECT_CC_SERVICE_ACCEPT = 0x21,
DECT_CC_SERVICE_REJECT = 0x22,
DECT_CC_RELEASE = 0x4d,
DECT_CC_RELEASE_COM = 0x5a,
DECT_CC_IWU_INFO = 0x60,
DECT_CC_NOTIFY = 0x6e,
DECT_CC_INFO = 0x7b,
};
/**
* Call Independant Supplementary Services messages types
*/
enum dect_ciss_msg_types {
DECT_CISS_RELEASE_COM = 0x5a,
DECT_CISS_FACILITY = 0x62,
DECT_CISS_REGISTER = 0x64,
};
/**
* MM message types
*/
enum dect_mm_msg_types {
DECT_MM_AUTHENTICATION_REQUEST = 0x40,
DECT_MM_AUTHENTICATION_REPLY = 0x41,
DECT_MM_KEY_ALLOCATE = 0x42,
DECT_MM_AUTHENTICATION_REJECT = 0x43,
DECT_MM_ACCESS_RIGHTS_REQUEST = 0x44,
DECT_MM_ACCESS_RIGHTS_ACCEPT = 0x45,
DECT_MM_ACCESS_RIGHTS_REJECT = 0x47,
DECT_MM_ACCESS_RIGHTS_TERMINATE_REQUEST = 0x48,
DECT_MM_ACCESS_RIGHTS_TERMINATE_ACCEPT = 0x49,
DECT_MM_ACCESS_RIGHTS_TERMINATE_REJECT = 0x4b,
DECT_MM_CIPHER_REQUEST = 0x4c,
DECT_MM_CIPHER_SUGGEST = 0x4e,
DECT_MM_CIPHER_REJECT = 0x4f,
DECT_MM_INFO_REQUEST = 0x50,
DECT_MM_INFO_ACCEPT = 0x51,
DECT_MM_INFO_SUGGEST = 0x52,
DECT_MM_INFO_REJECT = 0x53,
DECT_MM_LOCATE_REQUEST = 0x54,
DECT_MM_LOCATE_ACCEPT = 0x55,
DECT_MM_DETACH = 0x56,
DECT_MM_LOCATE_REJECT = 0x57,
DECT_MM_IDENTITY_REQUEST = 0x58,
DECT_MM_IDENTITY_REPLY = 0x59,
DECT_MM_IWU = 0x5b,
DECT_MM_TEMPORARY_IDENTITY_ASSIGN = 0x5c,
DECT_MM_TEMPORARY_IDENTITY_ASSIGN_ACK = 0x5d,
DECT_MM_TEMPORARY_IDENTITY_ASSIGN_REJ = 0x5f,
};
#endif /* _NWK_H */

61
include/phl.h Normal file
View File

@ -0,0 +1,61 @@
/*
* DECT Transceiver Layer
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#include <linux/dect_netlink.h>
#ifndef _NET_DECT_TRANSCEIVER_H
#define _NET_DECT_TRANSCEIVER_H
#define DECT_FRAME_SIZE 24
#define DECT_HALF_FRAME_SIZE (DECT_FRAME_SIZE / 2)
#define DECT_FRAMES_PER_SECOND 100
#define DECT_SCAN_SLOT 0
#define DECT_SLOT_MASK 0x00ffffff
static inline uint8_t dect_next_slotnum(uint8_t slot)
{
if (++slot == DECT_FRAME_SIZE)
slot = 0;
return slot;
}
static inline uint8_t dect_slot_add(uint8_t s1, uint8_t s2)
{
return (s1 + s2) % DECT_FRAME_SIZE;
}
static inline uint8_t dect_slot_distance(uint8_t s1, uint8_t s2)
{
return s2 >= s1 ? s2 - s1 : DECT_FRAME_SIZE + s2 - s1;
}
#define dect_foreach_slot(slot) \
for ((slot) = 0; (slot) < DECT_FRAME_SIZE; (slot)++)
static inline uint8_t dect_normal_transmit_base(enum dect_cluster_modes mode)
{
return mode == DECT_MODE_FP ? 0 : DECT_HALF_FRAME_SIZE;
}
static inline uint8_t dect_normal_receive_base(enum dect_cluster_modes mode)
{
return mode == DECT_MODE_FP ? DECT_HALF_FRAME_SIZE : 0;
}
static inline uint8_t dect_normal_receive_end(enum dect_cluster_modes mode)
{
return mode == DECT_MODE_FP ? DECT_FRAME_SIZE - 1 :
DECT_HALF_FRAME_SIZE - 1;
}
static inline uint8_t dect_tdd_slot(uint8_t slot)
{
return slot < DECT_HALF_FRAME_SIZE ? slot + DECT_HALF_FRAME_SIZE :
slot - DECT_HALF_FRAME_SIZE;
}
#endif /* _NET_DECT_TRANSCEIVER_H */

269
install-sh Executable file
View File

@ -0,0 +1,269 @@
#!/bin/sh
#
# install - install a program, script, or datafile
#
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

1
src/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
dectmon

13
src/Makefile.in Normal file
View File

@ -0,0 +1,13 @@
CFLAGS += $(EVENT_CFLAGS)
LDFLAGS += -ldect $(EVENT_LDFLAGS)
PROGRAMS = dectmon
dectmon-obj += event_ops.o
dectmon-obj += dummy_ops.o
dectmon-obj += debug.o
dectmon-obj += dsc.o
dectmon-obj += mac.o
dectmon-obj += dlc.o
dectmon-obj += nwk.o
dectmon-obj += main.o

33
src/debug.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <inttypes.h>
#include <unistd.h>
#include <ctype.h>
#include <dectmon.h>
#define BLOCKSIZE 16
void dect_hexdump(const char *prefix, const uint8_t *buf, size_t size)
{
unsigned int i, off, plen = 0;
char hbuf[3 * BLOCKSIZE + 1], abuf[BLOCKSIZE + 1];
for (i = 0; i < strlen(prefix); i++)
plen += prefix[i] == '\t' ? 8 : 1;
for (i = 0; i < size; i++) {
off = i % BLOCKSIZE;
sprintf(hbuf + 3 * off, "%.2x ", buf[i]);
abuf[off] = isascii(buf[i]) && isprint(buf[i]) ? buf[i] : '.';
if (off == BLOCKSIZE - 1 || i == size - 1) {
abuf[off + 1] = '\0';
printf("%s: %-*s |%s|\n", prefix, 64 - plen, hbuf, abuf);
}
}
}

141
src/dlc.c Normal file
View File

@ -0,0 +1,141 @@
/*
* dectmon DLC message reassembly
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h>
#include <stdio.h>
#include <dect/libdect.h>
#include <dectmon.h>
#include <mac.h>
#include <dlc.h>
#define dlc_print(fmt, args...) \
do { \
if (dumpopts & DECTMON_DUMP_DLC) \
printf(fmt, ## args); \
} while (0)
#if 1
#define lc_debug(lc, fmt, args...) dlc_print(fmt, ## args)
#else
#define lc_debug(lc, fmt, args...)
#endif
static void dect_fa_parse_len(struct dect_fa_len *len,
const struct dect_msg_buf *mb)
{
uint8_t l;
l = mb->data[DECT_FA_LI_OFF];
len->len = (l & DECT_FA_LI_LENGTH_MASK) >> DECT_FA_LI_LENGTH_SHIFT;
len->more = (l & DECT_FA_LI_M_FLAG);
}
static struct dect_lc *dect_lc_init(struct dect_mac_con *mc)
{
struct dect_lc *lc;
lc = calloc(1, sizeof(*lc));
if ((mc->pmid & 0xf0000) != 0xe0000)
lc->lsig = mc->pmid;
return lc;
}
static bool dect_fa_frame_csum_verify(const struct dect_lc *lc,
struct dect_msg_buf *mb)
{
uint8_t *data = mb->data;
unsigned int i;
uint8_t c0 = 0, c1 = 0;
uint16_t t;
data[mb->len - 2] ^= lc->lsig >> 8;
data[mb->len - 1] ^= lc->lsig & 0xff;
for (i = 0; i < mb->len; i++) {
t = c0 + data[i];
c0 = (t & 0xffU) + ((t >> 8) & 0x1U);
t = c1 + c0;
c1 = (t & 0xffU) + ((t >> 8) & 0x1U);
}
lc_debug(lc, "csum verify: lsig %.4x c0: %.2x c1: %.2x\n",
lc->lsig, c0, c1);
return c0 == (uint8_t)~0 && c1 == (uint8_t)~0;
}
static const uint8_t channel_sdu_size[] = {
[DECT_MC_C_S] = DECT_C_S_SDU_SIZE,
[DECT_MC_C_F] = DECT_C_F_SDU_SIZE,
};
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
static struct dect_msg_buf *dect_lc_reassemble(struct dect_lc *lc,
enum dect_data_channels chan,
struct dect_msg_buf *mb)
{
struct dect_fa_len fl;
uint8_t sdu_len, len;
sdu_len = channel_sdu_size[chan];
if (lc->rx_buf == NULL) {
dect_fa_parse_len(&fl, mb);
len = fl.len;
len += DECT_FA_HDR_SIZE + DECT_FA_CSUM_SIZE;
lc->rx_len = roundup(len, sdu_len);
lc->rx_buf = dect_mbuf_alloc(dh);
if (lc->rx_buf == NULL)
goto err;
}
memcpy(dect_mbuf_put(lc->rx_buf, sdu_len), mb->data, sdu_len);
mb = NULL;
if (lc->rx_buf->len >= lc->rx_len) {
assert(lc->rx_buf->len == lc->rx_len);
mb = lc->rx_buf;
lc->rx_buf = NULL;
if (!dect_fa_frame_csum_verify(lc, mb))
goto err;
/* Trim checksum and filling */
dect_fa_parse_len(&fl, mb);
mb->len = fl.len + DECT_FA_HDR_SIZE;
lc_debug(lc, "reassembled SDU len %u\n", mb->len);
}
return mb;
err:
lc_debug(lc, "reassembly failed\n");
return NULL;
}
void dect_mac_co_data_ind(struct dect_mac_con *mc, enum dect_data_channels chan,
struct dect_msg_buf *mb)
{
struct dect_lc *lc;
//printf("MAC_CO_DATA-ind\n");
if (mc->lc == NULL) {
lc = dect_lc_init(mc);
if (lc == NULL)
return;
mc->lc = lc;
}
mb = dect_lc_reassemble(mc->lc, chan, mb);
if (mb != NULL && mb->len > DECT_FA_HDR_SIZE) {
dect_mbuf_pull(mb, DECT_FA_HDR_SIZE);
dect_dl_data_ind(&mc->tbc->dl, mb);
}
}

147
src/dsc.c Normal file
View File

@ -0,0 +1,147 @@
/*
* DECT Standard Cipher
*
* Copyright (c) 2010 Erik Tews <e_tews@cdc.informatik.tu-darmstadt.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <string.h>
#include <linux/byteorder/little_endian.h>
#include <dectmon.h>
#define R1_LEN 17
#define R2_LEN 19
#define R3_LEN 21
#define R4_LEN 23
#define MASK_R1 (65536 | 32)
#define MASK_R2 (262144 | 4096 | 8 | 4)
#define MASK_R3 (1048576 | 2)
#define MASK_R4 (256 | 4194304)
#define R1_CLOCKMASK (1 << 8)
#define R2_CLOCKMASK (1 << 9)
#define R3_CLOCKMASK (1 << 10)
#define R1_R4_CLOCKMASK (1 << 0)
#define R2_R4_CLOCKMASK (1 << 1)
#define R3_R4_CLOCKMASK (1 << 2)
static uint32_t clock(uint32_t lfsr, int length, uint32_t mask)
{
return (lfsr >> 1) ^ (-(lfsr & 1) & mask);
}
static uint32_t combine(uint32_t comb, uint32_t r1, uint32_t r2, uint32_t r3)
{
uint32_t c, x10, x11, x20, x21, x30, x31;
c = comb;
x10 = r1 & 1;
x11 = (r1 >> 1) & 1;
x20 = r2 & 1;
x21 = (r2 >> 1) & 1;
x30 = r3 & 1;
x31 = (r3 >> 1) & 1;
return (x11 & x10 & c) ^
(x20 & x11 & x10) ^
(x21 & x10 & c) ^
(x21 & x20 & x10) ^
(x30 & x10 & c) ^
(x30 & x20 & x10) ^
(x11 & c) ^
(x11 & x10) ^
(x20 & x11) ^
(x30 & c) ^
(x31 & c) ^
(x31 & x10) ^
(x21) ^
(x31);
}
void dect_dsc_keystream(uint64_t iv, const uint8_t *key,
uint8_t *output, unsigned int len)
{
uint8_t input[16];
uint32_t R1, R2, R3, R4, N1, N2, N3, COMB;
unsigned int i, keybit;
memset(output, 0, len);
input[0] = iv & 0xff;
input[1] = (iv >> 8) & 0xff;
input[2] = (iv >> 16) & 0xff;
input[3] = (iv >> 24) & 0xff;
input[4] = (iv >> 32) & 0xff;
for (i = 5; i < 8; i++)
input[i] = 0;
for (i = 0; i < 8; i++)
input[i + 8] = key[i];
R1 = R2 = R3 = R4 = COMB = 0;
/* load IV and KEY */
for (i = 0; i < 128; i++) {
keybit = (input[i / 8] >> ((i) & 7)) & 1;
R1 = clock(R1, R1_LEN, MASK_R1) ^ (keybit << (R1_LEN - 1));
R2 = clock(R2, R2_LEN, MASK_R2) ^ (keybit << (R2_LEN - 1));
R3 = clock(R3, R3_LEN, MASK_R3) ^ (keybit << (R3_LEN - 1));
R4 = clock(R4, R4_LEN, MASK_R4) ^ (keybit << (R4_LEN - 1));
}
for (i = 0; i < 40 + (len * 8); i++) {
N1 = R1;
N2 = R2;
N3 = R3;
COMB = combine(COMB, R1, R2, R3);
if (((R2 & R2_CLOCKMASK) != 0) ^
((R3 & R3_CLOCKMASK) != 0) ^
((R4 & R1_R4_CLOCKMASK) != 0))
N1 = clock(R1, R1_LEN, MASK_R1);
if (((R1 & R1_CLOCKMASK) != 0) ^
((R3 & R3_CLOCKMASK) != 0) ^
((R4 & R2_R4_CLOCKMASK) != 0))
N2 = clock(R2, R2_LEN, MASK_R2);
if (((R1 & R1_CLOCKMASK) != 0) ^
((R2 & R2_CLOCKMASK) != 0) ^
((R4 & R3_R4_CLOCKMASK) != 0))
N3 = clock(R3, R3_LEN, MASK_R3);
/* Check whether any registers are zero after 11 pre-ciphering
* steps. If a register is all-zero after 11 steps, set input
* bit to one (see U.S. patent 5608802)
*/
if (i == 11) {
if (!R1)
N1 ^= (1 << (R1_LEN - 1));
if (!R2)
N2 ^= (1 << (R2_LEN - 1));
if (!R3)
N3 ^= (1 << (R3_LEN - 1));
if (!R4)
R4 ^= (1 << (R4_LEN - 1));
}
N1 = clock(N1, R1_LEN, MASK_R1);
R1 = clock(N1, R1_LEN, MASK_R1);
N2 = clock(N2, R2_LEN, MASK_R2);
R2 = clock(N2, R2_LEN, MASK_R2);
N3 = clock(N3, R3_LEN, MASK_R3);
R3 = clock(N3, R3_LEN, MASK_R3);
R4 = clock(R4, R4_LEN, MASK_R4);
R4 = clock(R4, R4_LEN, MASK_R4);
R4 = clock(R4, R4_LEN, MASK_R4);
if (i >= 40)
output[(i - 40) / 8] |= ((COMB) << (7 - ((i - 40) & 7)));
}
}
uint64_t dect_dsc_iv(uint32_t mfn, uint8_t framenum)
{
return __cpu_to_le64((mfn << 4) + framenum);
}

443
src/dummy_ops.c Normal file
View File

@ -0,0 +1,443 @@
#include <dect/libdect.h>
#include <dectmon.h>
/*
* LLME Ops
*/
static void llme_mac_me_info_ind(struct dect_handle *dh,
const struct dect_fp_capabilities *fpc)
{
}
static struct dect_llme_ops_ dummy_llme_ops;
/*
* LCE Ops
*/
static bool lce_page_response(struct dect_handle *dh,
struct dect_lce_page_param *param)
{
return false;
}
static void lce_group_ring_ind(struct dect_handle *dh,
enum dect_alerting_patterns pattern)
{
}
static struct dect_lce_ops dummy_lce_ops;
/*
* CC Ops
*/
static void mncc_setup_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_setup_param *param)
{
}
static void mncc_setup_ack_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_setup_ack_param *param)
{
}
static void mncc_reject_ind(struct dect_handle *dh, struct dect_call *call,
enum dect_causes cause,
struct dect_mncc_release_param *param)
{
}
static void mncc_call_proc_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_call_proc_param *param)
{
}
static void mncc_alert_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_alert_param *param)
{
}
static void mncc_connect_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_connect_param *param)
{
}
static void mncc_connect_cfm(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_connect_param *param)
{
}
static void mncc_release_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_release_param *param)
{
}
static void mncc_release_cfm(struct dect_handle *dh, struct dect_call *call,
enum dect_causes cause,
struct dect_mncc_release_param *param)
{
}
static void mncc_facility_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_facility_param *param)
{
}
static void mncc_info_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_info_param *param)
{
}
static void mncc_modify_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_modify_param *param)
{
}
static void mncc_modify_cfm(struct dect_handle *dh, struct dect_call *call,
bool success,
struct dect_mncc_modify_param *param)
{
}
static void mncc_hold_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_hold_param *param)
{
}
static void mncc_hold_cfm(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_hold_param *param)
{
}
static void mncc_retrieve_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_hold_param *param)
{
}
static void mncc_retrieve_cfm(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_hold_param *param)
{
}
static void mncc_iwu_info_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_iwu_info_param *param)
{
}
static void dl_u_data_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_msg_buf *mb)
{
}
static struct dect_cc_ops dummy_cc_ops;
/*
* MM Ops
*/
static void mm_access_rights_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_access_rights_param *param)
{
struct dect_mm_access_rights_param reply = {};
dect_mm_access_rights_res(dh, mme, false, &reply);
}
static void mm_access_rights_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme, bool accept,
struct dect_mm_access_rights_param *param)
{
}
static void mm_access_rights_terminate_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_access_rights_terminate_param *param)
{
struct dect_mm_access_rights_terminate_param reply = {};
dect_mm_access_rights_terminate_res(dh, mme, false, &reply);
}
static void mm_access_rights_terminate_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme, bool accept,
struct dect_mm_access_rights_terminate_param *param)
{
}
static void mm_key_allocate_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_key_allocate_param *param)
{
}
static void mm_authenticate_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_authenticate_param *param)
{
struct dect_mm_authenticate_param reply = {};
dect_mm_authenticate_res(dh, mme, false, &reply);
}
static void mm_authenticate_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme, bool accept,
struct dect_mm_authenticate_param *param)
{
}
static void mm_cipher_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_cipher_param *param)
{
struct dect_mm_cipher_param reply = {};
dect_mm_cipher_res(dh, mme, false, &reply, NULL);
}
static void mm_cipher_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme, bool accept,
struct dect_mm_cipher_param *param)
{
}
static void mm_locate_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_locate_param *param)
{
struct dect_mm_locate_param reply = {};
dect_mm_locate_res(dh, mme, false, &reply);
}
static void mm_locate_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme, bool accept,
struct dect_mm_locate_param *param)
{
}
static void mm_detach_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_detach_param *param)
{
}
static void mm_identity_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_identity_param *param)
{
}
static void mm_identity_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_identity_param *param)
{
}
static void mm_identity_assign_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_identity_assign_param *param)
{
struct dect_mm_identity_assign_param reply = {};
dect_mm_identity_assign_res(dh, mme, false, &reply);
}
static void mm_identity_assign_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme, bool accept,
struct dect_mm_identity_assign_param *param)
{
}
static void mm_info_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_info_param *param)
{
struct dect_mm_info_param reply = {};
dect_mm_info_res(dh, mme, false, &reply);
}
static void mm_info_cfm(struct dect_handle *dh,
struct dect_mm_endpoint *mme, bool accept,
struct dect_mm_info_param *param)
{
}
static void mm_iwu_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_iwu_param *param)
{
}
static struct dect_mm_ops dummy_mm_ops;
/*
* SS Ops
*/
static void mnss_setup_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static void mnss_facility_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static void mnss_release_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static struct dect_ss_ops dummy_ss_ops;
/*
* CLMS Ops
*/
static void mncl_unitdata_ind(struct dect_handle *dh,
enum dect_clms_message_types type,
struct dect_mncl_unitdata_param *param,
struct dect_msg_buf *mb)
{
}
static struct dect_clms_ops dummy_clms_ops;
void dect_dummy_ops_init(struct dect_ops *ops)
{
struct dect_llme_ops_ *llme_ops;
struct dect_lce_ops *lce_ops;
struct dect_cc_ops *cc_ops;
struct dect_mm_ops *mm_ops;
struct dect_ss_ops *ss_ops;
struct dect_clms_ops *clms_ops;
if (!ops->llme_ops)
ops->llme_ops = &dummy_llme_ops;
llme_ops = (void *)ops->llme_ops;
if (!llme_ops->mac_me_info_ind)
llme_ops->mac_me_info_ind = llme_mac_me_info_ind;
if (!ops->lce_ops)
ops->lce_ops = &dummy_lce_ops;
lce_ops = (void *)ops->lce_ops;
if (!lce_ops->lce_page_response)
lce_ops->lce_page_response = lce_page_response;
if (!lce_ops->lce_group_ring_ind)
lce_ops->lce_group_ring_ind = lce_group_ring_ind;
if (!ops->cc_ops)
ops->cc_ops = &dummy_cc_ops;
cc_ops = (void *)ops->cc_ops;
if (!cc_ops->mncc_setup_ind)
cc_ops->mncc_setup_ind = mncc_setup_ind;
if (!cc_ops->mncc_setup_ack_ind)
cc_ops->mncc_setup_ack_ind = mncc_setup_ack_ind;
if (!cc_ops->mncc_reject_ind)
cc_ops->mncc_reject_ind = mncc_reject_ind;
if (!cc_ops->mncc_call_proc_ind)
cc_ops->mncc_call_proc_ind = mncc_call_proc_ind;
if (!cc_ops->mncc_alert_ind)
cc_ops->mncc_alert_ind = mncc_alert_ind;
if (!cc_ops->mncc_connect_ind)
cc_ops->mncc_connect_ind = mncc_connect_ind;
if (!cc_ops->mncc_connect_cfm)
cc_ops->mncc_connect_cfm = mncc_connect_cfm;
if (!cc_ops->mncc_release_ind)
cc_ops->mncc_release_ind = mncc_release_ind;
if (!cc_ops->mncc_release_cfm)
cc_ops->mncc_release_cfm = mncc_release_cfm;
if (!cc_ops->mncc_facility_ind)
cc_ops->mncc_facility_ind = mncc_facility_ind;
if (!cc_ops->mncc_info_ind)
cc_ops->mncc_info_ind = mncc_info_ind;
if (!cc_ops->mncc_modify_ind)
cc_ops->mncc_modify_ind = mncc_modify_ind;
if (!cc_ops->mncc_modify_cfm)
cc_ops->mncc_modify_cfm = mncc_modify_cfm;
if (!cc_ops->mncc_hold_ind)
cc_ops->mncc_hold_ind = mncc_hold_ind;
if (!cc_ops->mncc_hold_cfm)
cc_ops->mncc_hold_cfm = mncc_hold_cfm;
if (!cc_ops->mncc_retrieve_ind)
cc_ops->mncc_retrieve_ind = mncc_retrieve_ind;
if (!cc_ops->mncc_retrieve_cfm)
cc_ops->mncc_retrieve_cfm = mncc_retrieve_cfm;
if (!cc_ops->mncc_iwu_info_ind)
cc_ops->mncc_iwu_info_ind = mncc_iwu_info_ind;
if (!cc_ops->dl_u_data_ind)
cc_ops->dl_u_data_ind = dl_u_data_ind;
if (!ops->mm_ops)
ops->mm_ops = &dummy_mm_ops;
mm_ops = (void *)ops->mm_ops;
if (!mm_ops->mm_access_rights_ind)
mm_ops->mm_access_rights_ind = mm_access_rights_ind;
if (!mm_ops->mm_access_rights_cfm)
mm_ops->mm_access_rights_cfm = mm_access_rights_cfm;
if (!mm_ops->mm_access_rights_terminate_ind)
mm_ops->mm_access_rights_terminate_ind = mm_access_rights_terminate_ind;
if (!mm_ops->mm_access_rights_terminate_cfm)
mm_ops->mm_access_rights_terminate_cfm = mm_access_rights_terminate_cfm;
if (!mm_ops->mm_key_allocate_ind)
mm_ops->mm_key_allocate_ind = mm_key_allocate_ind;
if (!mm_ops->mm_authenticate_ind)
mm_ops->mm_authenticate_ind = mm_authenticate_ind;
if (!mm_ops->mm_authenticate_cfm)
mm_ops->mm_authenticate_cfm = mm_authenticate_cfm;
if (!mm_ops->mm_cipher_ind)
mm_ops->mm_cipher_ind = mm_cipher_ind;
if (!mm_ops->mm_cipher_cfm)
mm_ops->mm_cipher_cfm = mm_cipher_cfm;
if (!mm_ops->mm_locate_ind)
mm_ops->mm_locate_ind = mm_locate_ind;
if (!mm_ops->mm_locate_cfm)
mm_ops->mm_locate_cfm = mm_locate_cfm;
if (!mm_ops->mm_authenticate_ind)
mm_ops->mm_detach_ind = mm_detach_ind;
if (!mm_ops->mm_identity_ind)
mm_ops->mm_identity_ind = mm_identity_ind;
if (!mm_ops->mm_identity_cfm)
mm_ops->mm_identity_cfm = mm_identity_cfm;
if (!mm_ops->mm_identity_assign_ind)
mm_ops->mm_identity_assign_ind = mm_identity_assign_ind;
if (!mm_ops->mm_identity_assign_cfm)
mm_ops->mm_identity_assign_cfm = mm_identity_assign_cfm;
if (!mm_ops->mm_info_ind)
mm_ops->mm_info_ind = mm_info_ind;
if (!mm_ops->mm_info_cfm)
mm_ops->mm_info_cfm = mm_info_cfm;
if (!mm_ops->mm_iwu_ind)
mm_ops->mm_iwu_ind = mm_iwu_ind;
if (!ops->ss_ops)
ops->ss_ops = &dummy_ss_ops;
ss_ops = (void *)ops->ss_ops;
if (!ss_ops->mnss_setup_ind)
ss_ops->mnss_setup_ind = mnss_setup_ind;
if (!ss_ops->mnss_facility_ind)
ss_ops->mnss_facility_ind = mnss_facility_ind;
if (!ss_ops->mnss_release_ind)
ss_ops->mnss_release_ind = mnss_release_ind;
if (!ops->clms_ops)
ops->clms_ops = &dummy_clms_ops;
clms_ops = (void *)ops->clms_ops;
if (!clms_ops->mncl_unitdata_ind)
clms_ops->mncl_unitdata_ind = mncl_unitdata_ind;
}

118
src/event_ops.c Normal file
View File

@ -0,0 +1,118 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <dect/libdect.h>
#include <dectmon.h>
static void event_io_callback(int fd, short mask, void *data)
{
struct dect_fd *dfd = data;
uint32_t events;
events = 0;
if (mask & EV_READ)
events |= DECT_FD_READ;
if (mask & EV_WRITE)
events |= DECT_FD_WRITE;
dect_fd_process(dh, dfd, events);
}
static int register_fd(const struct dect_handle *dh, struct dect_fd *dfd,
uint32_t events)
{
struct event *ev = dect_fd_priv(dfd);
unsigned short mask;
mask = EV_PERSIST;
if (events & DECT_FD_READ)
mask |= EV_READ;
if (events & DECT_FD_WRITE)
mask |= EV_WRITE;
event_set(ev, dect_fd_num(dfd), mask, event_io_callback, dfd);
event_add(ev, NULL);
return 0;
}
static void unregister_fd(const struct dect_handle *dh, struct dect_fd *dfd)
{
struct event *ev = dect_fd_priv(dfd);
event_del(ev);
}
static void event_timer_callback(int fd, short mask, void *data)
{
dect_timer_run(dh, data);
}
static void start_timer(const struct dect_handle *dh,
struct dect_timer *timer,
const struct timeval *tv)
{
struct event *ev = dect_timer_priv(timer);
evtimer_set(ev, event_timer_callback, timer);
evtimer_add(ev, (struct timeval *)tv);
}
static void stop_timer(const struct dect_handle *dh, struct dect_timer *timer)
{
struct event *ev = dect_timer_priv(timer);
evtimer_del(ev);
}
static const struct dect_event_ops dect_event_ops = {
.fd_priv_size = sizeof(struct event),
.register_fd = register_fd,
.unregister_fd = unregister_fd,
.timer_priv_size = sizeof(struct event),
.start_timer = start_timer,
.stop_timer = stop_timer
};
static struct event_base *ev_base;
static struct event sig_event;
static bool sigint;
static bool endloop;
static void sig_callback(int fd, short event, void *data)
{
sigint = true;
}
int dect_event_ops_init(struct dect_ops *ops)
{
ev_base = event_init();
if (ev_base == NULL)
return -1;
ops->event_ops = &dect_event_ops;
signal_set(&sig_event, SIGINT, sig_callback, NULL);
signal_add(&sig_event, NULL);
return 0;
}
void dect_event_loop_stop(void)
{
endloop = true;
}
void dect_event_loop(void)
{
endloop = false;
while (!sigint && !endloop)
event_loop(EVLOOP_ONCE);
}
void dect_event_ops_cleanup(void)
{
signal_del(&sig_event);
event_base_free(ev_base);
}

657
src/mac.c Normal file
View File

@ -0,0 +1,657 @@
/*
* dectmon MAC layer message tracing
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdlib.h>
#include <stdio.h>
#include <asm/byteorder.h>
#include <dect/libdect.h>
#include <dectmon.h>
#include <phl.h>
#include <mac.h>
#define BITS_PER_BYTE 8
#define mac_print(fmt, args...) \
do { \
if (dumpopts & DECTMON_DUMP_MAC) \
printf(fmt, ## args); \
} while (0)
/*
* Tail message parsing/construction
*/
static enum dect_tail_identifications dect_parse_tail(const struct dect_msg_buf *mb)
{
return mb->data[DECT_HDR_TA_OFF] & DECT_HDR_TA_MASK;
}
static uint8_t dect_parse_ari(struct dect_ari *ari, uint64_t a)
{
ari->arc = (a & DECT_ARI_ARC_MASK) >> DECT_ARI_ARC_SHIFT;
switch (ari->arc) {
case DECT_ARC_A:
ari->emc = (a & DECT_ARI_A_EMC_MASK) >> DECT_ARI_A_EMC_SHIFT;
ari->fpn = (a & DECT_ARI_A_FPN_MASK) >> DECT_ARI_A_FPN_SHIFT;
return DECT_ARC_A_LEN;
case DECT_ARC_B:
ari->eic = (a & DECT_ARI_B_EIC_MASK) >> DECT_ARI_B_EIC_SHIFT;
ari->fpn = (a & DECT_ARI_B_FPN_MASK) >> DECT_ARI_B_FPN_SHIFT;
ari->fps = (a & DECT_ARI_B_FPS_MASK) >> DECT_ARI_B_FPS_SHIFT;
return DECT_ARC_B_LEN;
case DECT_ARC_C:
ari->poc = (a & DECT_ARI_C_POC_MASK) >> DECT_ARI_C_POC_SHIFT;
ari->fpn = (a & DECT_ARI_C_FPN_MASK) >> DECT_ARI_C_FPN_SHIFT;
ari->fps = (a & DECT_ARI_C_FPS_MASK) >> DECT_ARI_C_FPS_SHIFT;
return DECT_ARC_C_LEN;
case DECT_ARC_D:
ari->gop = (a & DECT_ARI_D_GOP_MASK) >> DECT_ARI_D_GOP_SHIFT;
ari->fpn = (a & DECT_ARI_D_FPN_MASK) >> DECT_ARI_D_FPN_SHIFT;
return DECT_ARC_D_LEN;
case DECT_ARC_E:
ari->fil = (a & DECT_ARI_E_FIL_MASK) >> DECT_ARI_E_FIL_SHIFT;
ari->fpn = (a & DECT_ARI_E_FPN_MASK) >> DECT_ARI_E_FPN_SHIFT;
return DECT_ARC_E_LEN;
default:
return 0;
}
}
static int dect_parse_identities_information(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_idi *idi = &tm->idi;
uint8_t ari_len, rpn_len;
ari_len = dect_parse_ari(&idi->pari, t << DECT_RFPI_ARI_SHIFT);
if (ari_len == 0)
return -1;
rpn_len = BITS_PER_BYTE * DECT_NT_ID_RFPI_LEN - 1 - ari_len;
idi->e = (t & DECT_RFPI_E_FLAG);
idi->rpn = (t >> DECT_RFPI_RPN_SHIFT) & ((1 << rpn_len) - 1);
tm->type = DECT_TM_TYPE_ID;
mac_print("identities information: E: %u class: %u EMC: %.4x "
"FPN: %.5x RPN: %x\n", idi->e, idi->pari.arc,
idi->pari.emc, idi->pari.fpn, idi->rpn);
return 0;
}
static int dect_parse_static_system_information(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_ssi *ssi = &tm->ssi;
ssi->nr = (t & DECT_QT_SSI_NR_FLAG);
ssi->sn = (t & DECT_QT_SSI_SN_MASK) >> DECT_QT_SSI_SN_SHIFT;
ssi->sp = (t & DECT_QT_SSI_SP_MASK) >> DECT_QT_SSI_SP_SHIFT;
ssi->txs = (t & DECT_QT_SSI_TXS_MASK) >> DECT_QT_SSI_TXS_SHIFT;
ssi->mc = (t & DECT_QT_SSI_MC_FLAG);
ssi->rfcars = (t & DECT_QT_SSI_RFCARS_MASK) >> DECT_QT_SSI_RFCARS_SHIFT;
ssi->cn = (t & DECT_QT_SSI_CN_MASK) >> DECT_QT_SSI_CN_SHIFT;
ssi->pscn = (t & DECT_QT_SSI_PSCN_MASK) >> DECT_QT_SSI_PSCN_SHIFT;
if (ssi->sn > 11 || ssi->cn > 9 || ssi->pscn > 9 || ssi->rfcars == 0)
return -1;
tm->type = DECT_TM_TYPE_SSI;
mac_print("static system information: SN: %u CN: %u PSCN: %u NR: %u "
"Txs: %u Mc: %u RF-carriers: %x\n",
ssi->sn, ssi->cn, ssi->pscn, ssi->nr, ssi->txs, ssi->mc,
ssi->rfcars);
return 0;
}
static int dect_parse_extended_rf_carrier_information(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_erfc *erfc = &tm->erfc;
erfc->rfcars = (t & DECT_QT_ERFC_RFCARS_MASK) >>
DECT_QT_ERFC_RFCARS_SHIFT;
erfc->band = (t & DECT_QT_ERFC_RFBAND_MASK) >>
DECT_QT_ERFC_RFBAND_SHIFT;
erfc->num_rfcars = (t & DECT_QT_ERFC_NUM_RFCARS_MASK) >
DECT_QT_ERFC_NUM_RFCARS_SHIFT;
tm->type = DECT_TM_TYPE_ERFC;
mac_print("extended rf carrier information: RF-carriers: %.6x band: %u num: %u\n",
erfc->rfcars, erfc->band, erfc->num_rfcars);
return 0;
}
static int dect_parse_fixed_part_capabilities(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_fpc *fpc = &tm->fpc;
fpc->fpc = (t & DECT_QT_FPC_CAPABILITY_MASK) >>
DECT_QT_FPC_CAPABILITY_SHIFT;
fpc->hlc = (t & DECT_QT_FPC_HLC_MASK) >> DECT_QT_FPC_HLC_SHIFT;
tm->type = DECT_TM_TYPE_FPC;
mac_print("fixed part capabilities: FPC: %.5x HLC: %.4x\n",
fpc->fpc, fpc->hlc);
return 0;
}
static int dect_parse_extended_fixed_part_capabilities(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_efpc *efpc = &tm->efpc;
efpc->fpc = (t & DECT_QT_EFPC_EFPC_MASK) >> DECT_QT_EFPC_EFPC_SHIFT;
efpc->hlc = (t & DECT_QT_EFPC_EHLC_MASK) >> DECT_QT_EFPC_EHLC_SHIFT;
tm->type = DECT_TM_TYPE_EFPC;
mac_print("extended fixed part capabilities: FPC: %.5x HLC: %.6x\n",
efpc->fpc, efpc->hlc);
return 0;
}
static int dect_parse_extended_fixed_part_capabilities2(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_efpc2 *efpc2 = &tm->efpc2;
efpc2->fpc = (t & DECT_QT_EFPC2_FPC_MASK) >> DECT_QT_EFPC2_FPC_SHIFT;
efpc2->hlc = (t & DECT_QT_EFPC2_HLC_MASK) >> DECT_QT_EFPC2_HLC_SHIFT;
tm->type = DECT_TM_TYPE_EFPC2;
mac_print("extended fixed part capabilities2: FPC: %x HLC: %x\n",
efpc2->fpc, efpc2->hlc);
return 0;
}
static int dect_parse_sari(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_sari *sari = &tm->sari;
sari->list_cycle = (((t & DECT_QT_SARI_LIST_CYCLE_MASK) >>
DECT_QT_SARI_LIST_CYCLE_SHIFT) + 1) * 2;
sari->tari = (t & DECT_QT_SARI_TARI_FLAG);
sari->black = (t & DECT_QT_SARI_BLACK_FLAG);
//dect_parse_ari(&sari->ari, t << DECT_QT_SARI_ARI_SHIFT);
tm->type = DECT_TM_TYPE_SARI;
mac_print("sari: cycle %u TARI: %u black: %u\n",
sari->list_cycle, sari->tari, sari->black);
return 0;
}
static int dect_parse_multiframe_number(struct dect_tail_msg *tm, uint64_t t)
{
tm->mfn.num = (t & DECT_QT_MFN_MASK) >> DECT_QT_MFN_SHIFT;
tm->type = DECT_TM_TYPE_MFN;
mac_print("multiframe number: %u\n", tm->mfn.num);
return 0;
}
static int dect_parse_system_information(struct dect_tail_msg *tm, uint64_t t)
{
/* clear of memcmp */
memset(((void *)tm) + offsetof(struct dect_tail_msg, ssi), 0,
sizeof(*tm) - offsetof(struct dect_tail_msg, ssi));
switch (t & DECT_QT_H_MASK) {
case DECT_QT_SI_SSI:
case DECT_QT_SI_SSI2:
return dect_parse_static_system_information(tm, t);
case DECT_QT_SI_ERFC:
return dect_parse_extended_rf_carrier_information(tm, t);
case DECT_QT_SI_FPC:
return dect_parse_fixed_part_capabilities(tm, t);
case DECT_QT_SI_EFPC:
return dect_parse_extended_fixed_part_capabilities(tm, t);
case DECT_QT_SI_EFPC2:
return dect_parse_extended_fixed_part_capabilities2(tm, t);
case DECT_QT_SI_SARI:
return dect_parse_sari(tm, t);
case DECT_QT_SI_MFN:
return dect_parse_multiframe_number(tm, t);
default:
mac_print("unknown system information type %llx\n",
(unsigned long long)t & DECT_QT_H_MASK);
return -1;
}
}
static int dect_parse_blind_full_slots(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_bfs *bfs = &tm->bfs;
bfs->mask = (t & DECT_PT_BFS_MASK) >> DECT_PT_BFS_SHIFT;
tm->type = DECT_TM_TYPE_BFS;
mac_print("page: RFPI: %.3x blind full slots: %.3x\n",
tm->page.rfpi, bfs->mask);
return 0;
}
static int dect_parse_bearer_description(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_bearer_desc *bd = &tm->bd;
bd->bt = (t & DECT_PT_INFO_TYPE_MASK);
bd->sn = (t & DECT_PT_BEARER_SN_MASK) >> DECT_PT_BEARER_SN_SHIFT;
bd->sp = (t & DECT_PT_BEARER_SP_MASK) >> DECT_PT_BEARER_SP_SHIFT;
bd->cn = (t & DECT_PT_BEARER_CN_MASK) >> DECT_PT_BEARER_CN_SHIFT;
if (bd->sn >= DECT_HALF_FRAME_SIZE)
return -1;
tm->type = DECT_TM_TYPE_BD;
mac_print("page: RFPI: %.3x bearer description: BT: %llx SN: %u SP: %u CN: %u\n",
tm->page.rfpi, (unsigned long long)bd->bt, bd->sn, bd->sp, bd->cn);
return 0;
}
static int dect_parse_rfp_identity(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_rfp_id *id = &tm->rfp_id;
id->id = (t & DECT_PT_RFP_ID_MASK) >> DECT_PT_RFP_ID_SHIFT;
tm->type = DECT_TM_TYPE_RFP_ID;
mac_print("page: RFPI: %.3x RFP identity: %.3x\n",
tm->page.rfpi, id->id);
return 0;
}
static int dect_parse_rfp_status(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_rfp_status *st = &tm->rfp_status;
st->rfp_busy = t & DECT_PT_RFPS_RFP_BUSY_FLAG;
st->sys_busy = t & DECT_PT_RFPS_SYS_BUSY_FLAG;
tm->type = DECT_TM_TYPE_RFP_STATUS;
mac_print("page: RFPI: %.3x RFP status: rfp_busy: %d sys_busy: %d\n",
tm->page.rfpi, st->rfp_busy, st->sys_busy);
return 0;
}
static int dect_parse_active_carriers(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_active_carriers *ac = &tm->active_carriers;
ac->active = (t & DECT_PT_ACTIVE_CARRIERS_MASK) >>
DECT_PT_ACTIVE_CARRIERS_SHIFT;
tm->type = DECT_TM_TYPE_ACTIVE_CARRIERS;
mac_print("page: RFPI: %.3x active carriers: %.3x\n",
tm->page.rfpi, ac->active);
return 0;
}
static int dect_parse_paging_info(struct dect_tail_msg *tm, uint64_t t)
{
switch (t & DECT_PT_INFO_TYPE_MASK) {
case DECT_PT_IT_BLIND_FULL_SLOT:
return dect_parse_blind_full_slots(tm, t);
case DECT_PT_IT_OTHER_BEARER:
case DECT_PT_IT_RECOMMENDED_OTHER_BEARER:
case DECT_PT_IT_GOOD_RFP_BEARER:
case DECT_PT_IT_DUMMY_OR_CL_BEARER_POSITION:
case DECT_PT_IT_CL_BEARER_POSITION:
return dect_parse_bearer_description(tm, t);
case DECT_PT_IT_RFP_IDENTITY:
return dect_parse_rfp_identity(tm, t);
case DECT_PT_IT_DUMMY_OR_CL_BEARER_MARKER:
mac_print("dummy or connectionless bearer marker\n");
return 0;
case DECT_PT_IT_RFP_STATUS:
return dect_parse_rfp_status(tm, t);
case DECT_PT_IT_ACTIVE_CARRIERS:
return dect_parse_active_carriers(tm, t);
default:
mac_print("unknown paging info %llx\n",
(unsigned long long)t);
return -1;
}
}
static int dect_parse_paging_msg(struct dect_tail_msg *tm, uint64_t t)
{
tm->page.extend = t & DECT_PT_HDR_EXTEND_FLAG;
tm->page.length = t & DECT_PT_HDR_LENGTH_MASK;
switch (tm->page.length) {
case DECT_PT_ZERO_PAGE:
tm->page.rfpi = (t & DECT_PT_ZP_RFPI_MASK) >>
DECT_PT_ZP_RFPI_SHIFT;
return dect_parse_paging_info(tm, t);
case DECT_PT_SHORT_PAGE:
tm->page.rfpi = 0;
return dect_parse_paging_info(tm, t);
case DECT_PT_FULL_PAGE:
case DECT_PT_LONG_PAGE:
case DECT_PT_LONG_PAGE_FIRST:
case DECT_PT_LONG_PAGE_LAST:
case DECT_PT_LONG_PAGE_ALL:
tm->type = DECT_TM_TYPE_PAGE;
mac_print("full/long page: extend: %u length: %llx\n",
tm->page.extend, (unsigned long long)tm->page.length);
return 0;
default:
mac_print("invalid page length %llx\n",
(unsigned long long)tm->page.length);
return -1;
}
}
static int dect_parse_cctrl_common(struct dect_cctrl *cctl, uint64_t t)
{
cctl->fmid = (t & DECT_CCTRL_FMID_MASK) >> DECT_CCTRL_FMID_SHIFT;
cctl->pmid = (t & DECT_CCTRL_PMID_MASK) >> DECT_CCTRL_PMID_SHIFT;
mac_print("cctrl: command: %llx FMID: %.3x PMID: %.5x\n",
(unsigned long long)cctl->cmd, cctl->fmid, cctl->pmid);
return 0;
}
static int dect_parse_cctrl_attr(struct dect_cctrl *cctl, uint64_t t)
{
cctl->ecn = (t & DECT_CCTRL_ATTR_ECN_MASK) >> DECT_CCTRL_ATTR_ECN_SHIFT;
cctl->lbn = (t & DECT_CCTRL_ATTR_LBN_MASK) >> DECT_CCTRL_ATTR_LBN_SHIFT;
cctl->type = (t & DECT_CCTRL_ATTR_TYPE_MASK) >> DECT_CCTRL_ATTR_TYPE_SHIFT;
cctl->service = (t & DECT_CCTRL_ATTR_SERVICE_MASK) >> DECT_CCTRL_ATTR_SERVICE_SHIFT;
cctl->slot = (t & DECT_CCTRL_ATTR_SLOT_MASK) >> DECT_CCTRL_ATTR_SLOT_SHIFT;
cctl->cf = (t & DECT_CCTRL_ATTR_CF_FLAG);
cctl->a_mod = (t & DECT_CCTRL_ATTR_A_MOD_MASK) >> DECT_CCTRL_ATTR_A_MOD_SHIFT;
cctl->bz_mod = (t & DECT_CCTRL_ATTR_BZ_MOD_MASK) >> DECT_CCTRL_ATTR_BZ_MOD_SHIFT;
cctl->bz_ext_mod = (t & DECT_CCTRL_ATTR_BZ_EXT_MOD_MASK) >> DECT_CCTRL_ATTR_BZ_EXT_MOD_SHIFT;
cctl->acr = (t & DECT_CCTRL_ATTR_ACR_MASK) >> DECT_CCTRL_ATTR_ACR_SHIFT;
mac_print("cctrl: command: %llx ECN: %x LBN: %x type: %x "
"service: %x slot type: %x CF: %d A-modulation: %x "
"B/Z-modulation: %x B/Z extended modulation: %x ACR: %x\n",
(unsigned long long)cctl->cmd, cctl->ecn, cctl->lbn,
cctl->type, cctl->service, cctl->slot, cctl->cf,
cctl->a_mod, cctl->bz_mod, cctl->bz_ext_mod, cctl->acr);
return 0;
}
static int dect_parse_cctrl_release(struct dect_cctrl *cctl, uint64_t t)
{
cctl->lbn = (t & DECT_CCTRL_RELEASE_LBN_MASK) >>
DECT_CCTRL_RELEASE_LBN_SHIFT;
cctl->reason = (t & DECT_CCTRL_RELEASE_REASON_MASK) >>
DECT_CCTRL_RELEASE_REASON_SHIFT;
cctl->pmid = (t & DECT_CCTRL_RELEASE_PMID_MASK) >>
DECT_CCTRL_RELEASE_PMID_SHIFT;
mac_print("cctrl: release: PMID: %.5x LBN: %x reason: %x\n",
cctl->pmid, cctl->lbn, cctl->reason);
return 0;
}
static int dect_parse_basic_cctrl(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_cctrl *cctl = &tm->cctl;
cctl->cmd = t & DECT_MT_CMD_MASK;
switch (cctl->cmd) {
case DECT_CCTRL_ACCESS_REQ:
case DECT_CCTRL_BEARER_HANDOVER_REQ:
case DECT_CCTRL_CONNECTION_HANDOVER_REQ:
case DECT_CCTRL_UNCONFIRMED_ACCESS_REQ:
case DECT_CCTRL_BEARER_CONFIRM:
case DECT_CCTRL_WAIT:
return dect_parse_cctrl_common(cctl, t);
case DECT_CCTRL_ATTRIBUTES_T_REQUEST:
case DECT_CCTRL_ATTRIBUTES_T_CONFIRM:
return dect_parse_cctrl_attr(cctl, t);
case DECT_CCTRL_RELEASE:
return dect_parse_cctrl_release(cctl, t);
default:
mac_print("unknown basic cctrl command: %llx\n",
(unsigned long long)cctl->cmd);
return -1;
}
}
static int dect_parse_advanced_cctrl(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_cctrl *cctl = &tm->cctl;
cctl->cmd = t & DECT_MT_CMD_MASK;
switch (cctl->cmd) {
case DECT_CCTRL_ACCESS_REQ:
case DECT_CCTRL_BEARER_HANDOVER_REQ:
case DECT_CCTRL_CONNECTION_HANDOVER_REQ:
case DECT_CCTRL_UNCONFIRMED_ACCESS_REQ:
case DECT_CCTRL_BEARER_CONFIRM:
case DECT_CCTRL_WAIT:
case DECT_CCTRL_UNCONFIRMED_DUMMY:
case DECT_CCTRL_UNCONFIRMED_HANDOVER:
return dect_parse_cctrl_common(cctl, t);
case DECT_CCTRL_ATTRIBUTES_T_REQUEST:
case DECT_CCTRL_ATTRIBUTES_T_CONFIRM:
return dect_parse_cctrl_attr(cctl, t);
case DECT_CCTRL_BANDWIDTH_T_REQUEST:
case DECT_CCTRL_BANDWIDTH_T_CONFIRM:
return -1;
case DECT_CCTRL_RELEASE:
return dect_parse_cctrl_release(cctl, t);
default:
mac_print("unknown advanced cctrl command: %llx\n",
(unsigned long long)cctl->cmd);
return -1;
}
}
static int dect_parse_encryption_ctrl(struct dect_tail_msg *tm, uint64_t t)
{
struct dect_encctrl *ectl = &tm->encctl;
ectl->cmd = (t & DECT_ENCCTRL_CMD_MASK) >> DECT_ENCCTRL_CMD_SHIFT;
ectl->fmid = (t & DECT_ENCCTRL_FMID_MASK) >> DECT_ENCCTRL_FMID_SHIFT;
ectl->pmid = (t & DECT_ENCCTRL_PMID_MASK) >> DECT_ENCCTRL_PMID_SHIFT;
mac_print("encctrl: command: %x FMID: %.4x PMID: %.5x\n",
ectl->cmd, ectl->fmid, ectl->pmid);
return 0;
}
static int dect_parse_mac_ctrl(struct dect_tail_msg *tm, uint64_t t)
{
switch (t & DECT_MT_HDR_MASK) {
case DECT_MT_BASIC_CCTRL:
if (dect_parse_basic_cctrl(tm, t) < 0)
return -1;
tm->type = DECT_TM_TYPE_BCCTRL;
return 0;
case DECT_MT_ADV_CCTRL:
if (dect_parse_advanced_cctrl(tm, t) < 0)
return -1;
tm->type = DECT_TM_TYPE_ACCTRL;
return 0;
case DECT_MT_ENC_CTRL:
if (dect_parse_encryption_ctrl(tm, t) < 0)
return -1;
tm->type = DECT_TM_TYPE_ENCCTRL;
return 0;
default:
mac_print("Unknown MAC control %llx\n",
(unsigned long long)t & DECT_MT_HDR_MASK);
return -1;
}
}
static int dect_parse_ct_data(struct dect_tail_msg *tm, uint64_t t, uint8_t seq)
{
struct dect_ct_data *ctd = &tm->ctd;
ctd->seq = seq;
tm->type = DECT_TM_TYPE_CT;
mac_print("CS tail: sequence number: %u\n", seq);
return 0;
}
static int dect_parse_tail_msg(struct dect_tail_msg *tm, uint8_t slot,
const struct dect_msg_buf *mb)
{
uint64_t t;
tm->type = DECT_TM_TYPE_INVALID;
t = __be64_to_cpu(*(uint64_t *)&mb->data[DECT_T_FIELD_OFF]);
switch (dect_parse_tail(mb)) {
case DECT_TI_CT_PKT_0:
return dect_parse_ct_data(tm, t, 0);
case DECT_TI_CT_PKT_1:
return dect_parse_ct_data(tm, t, 1);
case DECT_TI_NT_CL:
mac_print("connectionless: ");
case DECT_TI_NT:
return dect_parse_identities_information(tm, t);
case DECT_TI_QT:
return dect_parse_system_information(tm, t);
case DECT_TI_PT:
/* Paging tail in direction FP->PP, MAC control otherwise */
if (slot < 12)
return dect_parse_paging_msg(tm, t);
case DECT_TI_MT:
return dect_parse_mac_ctrl(tm, t);
default:
mac_print("unknown tail %x\n", dect_parse_tail(mb));
return -1;
}
}
static struct dect_trx_slot {
struct dect_tbc *tbc;
} slots[DECT_FRAME_SIZE];
static struct dect_tbc *dect_tbc_init(uint32_t pmid)
{
struct dect_tbc *tbc;
tbc = calloc(1, sizeof(*tbc));
if (tbc == NULL)
return NULL;
tbc->dl.tbc = tbc;
tbc->mbc[DECT_MODE_FP].cs_seq = 1;
tbc->mbc[DECT_MODE_FP].cf_seq = 1;
tbc->mbc[DECT_MODE_FP].mc.pmid = pmid;
tbc->mbc[DECT_MODE_FP].mc.tbc = tbc;
tbc->mbc[DECT_MODE_PP].cs_seq = 1;
tbc->mbc[DECT_MODE_PP].cf_seq = 1;
tbc->mbc[DECT_MODE_PP].mc.pmid = pmid;
tbc->mbc[DECT_MODE_PP].mc.tbc = tbc;
return tbc;
}
static void dect_tbc_rcv(struct dect_tbc *tbc, uint8_t slot,
struct dect_msg_buf *mb, struct dect_tail_msg *tm)
{
enum dect_b_identifications b_id;
struct dect_mbc *mbc;
unsigned int i;
bool cf;
mbc = &tbc->mbc[slot < 12 ? DECT_MODE_FP : DECT_MODE_PP];
b_id = (mb->data[0] & DECT_HDR_BA_MASK);
if (tm->type == DECT_TM_TYPE_CT) {
if (tm->ctd.seq != mbc->cs_seq) {
printf("CS: incorrect seq: %u\n", tm->ctd.seq);
return;
}
mbc->cs_seq = !mbc->cs_seq;
dect_mbuf_pull(mb, 1);
dect_mac_co_data_ind(&mbc->mc, DECT_MC_C_S, mb);
dect_mbuf_pull(mb, 7);
} else
dect_mbuf_pull(mb, 8);
cf = true;
switch (b_id) {
case DECT_BI_ETYPE_NOT_ALL_CF_0:
case DECT_BI_ETYPE_NOT_ALL_CF_1:
mac_print("Not all CF\n");
cf = false;
case DECT_BI_ETYPE_CF_0:
case DECT_BI_ETYPE_CF_1:
if (((b_id >> DECT_HDR_BA_SHIFT) & 0x1) != mbc->cf_seq) {
printf("CF: incorrect seq: %u\n", b_id & 0x1);
return;
}
mbc->cf_seq = !mbc->cf_seq;
for (i = 0; i < mb->len / 10; i++) {
if (cf) {
mac_print("CF: seq: %u\n", i);
dect_mac_co_data_ind(&mbc->mc, DECT_MC_C_F, mb);
dect_mbuf_pull(mb, 10);
continue;
}
if (!(mb->data[0] & 0x80))
cf = true;
dect_mbuf_pull(mb, 10);
}
break;
default:
break;
}
if (tm->type == DECT_TM_TYPE_BCCTRL ||
tm->type == DECT_TM_TYPE_ACCTRL) {
if (tm->cctl.cmd == DECT_CCTRL_RELEASE) {
slots[slot].tbc = NULL;
slots[dect_tdd_slot(slot)].tbc = NULL;
free(tbc);
}
}
}
void dect_mac_rcv(struct dect_msg_buf *mb, uint8_t slot)
{
struct dect_trx_slot *ts = &slots[slot];
enum dect_tail_identifications a_id;
enum dect_b_identifications b_id;
struct dect_tail_msg tm;
struct dect_tbc *tbc;
a_id = (mb->data[0] & DECT_HDR_TA_MASK) >> DECT_HDR_TA_SHIFT;
b_id = (mb->data[0] & DECT_HDR_BA_MASK) >> DECT_HDR_BA_SHIFT;
mac_print("slot: %02u A: %x B: %x ", slot, a_id, b_id);
dect_parse_tail_msg(&tm, slot, mb);
//dect_hexdump("MAC RCV", mb->data, mb->len);
if (ts->tbc != NULL)
return dect_tbc_rcv(ts->tbc, slot, mb, &tm);
if (tm.type == DECT_TM_TYPE_BCCTRL ||
tm.type == DECT_TM_TYPE_ACCTRL) {
switch (tm.cctl.cmd) {
case DECT_CCTRL_ACCESS_REQ:
case DECT_CCTRL_BEARER_HANDOVER_REQ:
case DECT_CCTRL_CONNECTION_HANDOVER_REQ:
tbc = dect_tbc_init(tm.cctl.pmid);
if (tbc == NULL)
break;
ts->tbc = tbc;
slots[slot - 12].tbc = tbc;
printf("TBC slot %u\n", slot);
break;
default:
printf("unknown\n");
break;
}
}
}

112
src/main.c Normal file
View File

@ -0,0 +1,112 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <dect/libdect.h>
#include <dect/raw.h>
#include <dectmon.h>
struct dect_handle *dh;
static void pexit(const char *str)
{
perror(str);
exit(1);
}
static void dect_raw_rcv(struct dect_handle *dh, struct dect_fd *dfd,
struct dect_msg_buf *mb)
{
dect_mac_rcv(mb, mb->slot);
}
static struct dect_raw_ops raw_ops = {
.raw_rcv = dect_raw_rcv,
};
static struct dect_ops ops = {
.raw_ops = &raw_ops,
};
#define OPTSTRING "m:d:n:h"
enum {
OPT_DUMP_MAC = 'm',
OPT_DUMP_DLC = 'd',
OPT_DUMP_NWK = 'n',
OPT_HELP = 'h',
};
static const struct option dectmon_opts[] = {
{ .name = "dump-mac", .has_arg = true, .flag = 0, .val = OPT_DUMP_MAC, },
{ .name = "dump-dlc", .has_arg = true, .flag = 0, .val = OPT_DUMP_DLC, },
{ .name = "dump-nwk", .has_arg = true, .flag = 0, .val = OPT_DUMP_NWK, },
{ .name = "help", .has_arg = false, .flag = 0, .val = OPT_HELP, },
{ },
};
static uint32_t opt_yesno(const char *arg, uint32_t opts, uint32_t flag)
{
if (!strcmp(arg, "yes"))
opts |= flag;
else if (!strcmp(arg, "no"))
opts &= ~flag;
else
pexit("invalid argument\n");
return opts;
}
uint32_t dumpopts = DECTMON_DUMP_NWK;
int main(int argc, char **argv)
{
struct dect_fd *dfd;
int optidx = 0, c;
for (;;) {
c = getopt_long(argc, argv, OPTSTRING, dectmon_opts, &optidx);
if (c == -1)
break;
switch (c) {
case OPT_DUMP_MAC:
dumpopts = opt_yesno(optarg, dumpopts, DECTMON_DUMP_MAC);
break;
case OPT_DUMP_DLC:
dumpopts = opt_yesno(optarg, dumpopts, DECTMON_DUMP_DLC);
break;
case OPT_DUMP_NWK:
dumpopts = opt_yesno(optarg, dumpopts, DECTMON_DUMP_NWK);
break;
case OPT_HELP:
printf("%s [ options ]\n"
"\n"
"Options:\n"
" -m/--dump-mac=yes/no\n"
" -d/--dump-dlc=yes/no\n"
" -n/--dump-nwk=yes/no\n"
" -h/--help\n",
argv[0]);
exit(0);
case '?':
exit(1);
}
}
dect_event_ops_init(&ops);
dect_dummy_ops_init(&ops);
dh = dect_open_handle(&ops, NULL);
if (dh == NULL)
pexit("dect_init_handle");
dfd = dect_raw_socket(dh);
if (dfd == NULL)
pexit("dect_raw_socket");
dect_event_loop();
return 0;
}

291
src/nwk.c Normal file
View File

@ -0,0 +1,291 @@
/*
* dectmon - NWK layer message parsing
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <dect/libdect.h>
#include <dect/s_fmt.h>
#include <dectmon.h>
#include <nwk.h>
static LIST_HEAD(dect_pt_list);
static const char * const nwk_msg_types[256] = {
[DECT_LCE_PAGE_RESPONSE] = "LCE-PAGE-RESPONSE",
[DECT_LCE_PAGE_REJECT] = "LCE-PAGE-REJECT",
[DECT_CC_ALERTING] = "CC-ALERTING",
[DECT_CC_CALL_PROC] = "CC-CALL-PROC",
[DECT_CC_SETUP] = "CC-SETUP",
[DECT_CC_CONNECT] = "CC-CONNECT",
[DECT_CC_SETUP_ACK] = "CC-SETUP-ACK",
[DECT_CC_CONNECT_ACK] = "CC-CONNECT-ACK",
[DECT_CC_SERVICE_CHANGE] = "CC-SERVICE-CHANGE",
[DECT_CC_SERVICE_ACCEPT] = "CC-SERVICE-ACCEPT",
[DECT_CC_SERVICE_REJECT] = "CC-SERVICE-REJECT",
[DECT_CC_RELEASE] = "CC-RELEASE",
[DECT_CC_RELEASE_COM] = "CC-RELEASE-COM",
[DECT_CC_IWU_INFO] = "CC-IWU-INFO",
[DECT_CC_NOTIFY] = "CC-NOTIFY",
[DECT_CC_INFO] = "CC-INFO",
[DECT_CISS_FACILITY] = "CISS-FACILITY",
[DECT_CISS_REGISTER] = "CISS-REGISTER",
[DECT_MM_AUTHENTICATION_REQUEST] = "MM-AUTHENTICATION-REQUEST",
[DECT_MM_AUTHENTICATION_REPLY] = "MM-AUTHENTICATION-REPLY",
[DECT_MM_KEY_ALLOCATE] = "MM-KEY-ALLOCATE",
[DECT_MM_AUTHENTICATION_REJECT] = "MM-AUTHENTICATION-REJECT",
[DECT_MM_ACCESS_RIGHTS_REQUEST] = "MM-ACCESS-RIGHTS-REQUEST",
[DECT_MM_ACCESS_RIGHTS_ACCEPT] = "MM-ACCESS-RIGHTS-ACCEPT",
[DECT_MM_ACCESS_RIGHTS_REJECT] = "MM-ACCESS-RIGHTS-REJECT",
[DECT_MM_ACCESS_RIGHTS_TERMINATE_REQUEST] = "MM-ACCESS-RIGHTS-TERMINATE-REQUEST",
[DECT_MM_ACCESS_RIGHTS_TERMINATE_ACCEPT] = "MM-ACCESS-RIGHTS-TERMINATE-ACCEPT",
[DECT_MM_ACCESS_RIGHTS_TERMINATE_REJECT] = "MM-ACCESS-RIGHTS-TERMINATE-REJECT",
[DECT_MM_CIPHER_REQUEST] = "MM-CIPHER-REQUEST",
[DECT_MM_CIPHER_SUGGEST] = "MM-CIPHER-SUGGEST",
[DECT_MM_CIPHER_REJECT] = "MM-CIPHER-REJECT",
[DECT_MM_INFO_REQUEST] = "MM-INFO-REQUEST",
[DECT_MM_INFO_ACCEPT] = "MM-INFO-ACCEPT",
[DECT_MM_INFO_SUGGEST] = "MM-INFO-SUGGEST",
[DECT_MM_INFO_REJECT] = "MM-INFO-REJECT",
[DECT_MM_LOCATE_REQUEST] = "MM-LOCATE-REQUEST",
[DECT_MM_LOCATE_ACCEPT] = "MM-LOCATE-ACCEPT",
[DECT_MM_DETACH] = "MM-DETACH",
[DECT_MM_LOCATE_REJECT] = "MM-LOCATE-REJECT",
[DECT_MM_IDENTITY_REQUEST] = "MM-IDENTITY-REQUEST",
[DECT_MM_IDENTITY_REPLY] = "MM-IDENTITY-REPLY",
[DECT_MM_IWU] = "MM-IWU",
[DECT_MM_TEMPORARY_IDENTITY_ASSIGN] = "MM-TEMPORARY-IDENTITY-ASSIGN",
[DECT_MM_TEMPORARY_IDENTITY_ASSIGN_ACK] = "MM-TEMPORARY-IDENTITY-ASSIGN-ACK",
[DECT_MM_TEMPORARY_IDENTITY_ASSIGN_REJ] = "MM-TEMPORARY-IDENTITY-ASSIGN-REJ",
};
#define dect_ie_release(dh, ie) \
do { \
if (ie != NULL) \
dect_ie_put(dh, ie); \
ie = NULL; \
} while (0)
static struct dect_pt *dect_pt_lookup(struct dect_ie_portable_identity *portable_identity)
{
struct dect_pt *pt;
list_for_each_entry(pt, &dect_pt_list, list) {
if (!dect_ipui_cmp(&pt->portable_identity->ipui,
&portable_identity->ipui))
return pt;
}
return NULL;
}
static struct dect_pt *dect_pt_init(struct dect_ie_portable_identity *portable_identity)
{
struct dect_pt *pt;
pt = calloc(1, sizeof(*pt));
if (pt == NULL)
return NULL;
pt->portable_identity = dect_ie_hold(portable_identity);
list_add_tail(&pt->list, &dect_pt_list);
return pt;
}
static void dect_pt_track_key_allocation(struct dect_pt *pt, uint8_t msgtype,
const struct dect_sfmt_ie *ie,
struct dect_ie_common *common)
{
uint8_t k[DECT_AUTH_KEY_LEN], ks[DECT_AUTH_KEY_LEN];
uint8_t dck[DECT_CIPHER_KEY_LEN];
uint32_t res1;
uint8_t ac[4];
switch (msgtype) {
case DECT_MM_KEY_ALLOCATE:
if (pt->procedure != DECT_MM_NONE &&
pt->procedure != DECT_MM_KEY_ALLOCATION)
return;
if (ie->id == DECT_IE_RS)
pt->rs = (void *)__dect_ie_hold(common);
if (ie->id == DECT_IE_RAND)
pt->rand_f = (void *)__dect_ie_hold(common);
pt->procedure = DECT_MM_KEY_ALLOCATION;
pt->last_msg = msgtype;
return;
case DECT_MM_AUTHENTICATION_REQUEST:
if (pt->procedure != DECT_MM_KEY_ALLOCATION ||
pt->last_msg != DECT_MM_KEY_ALLOCATE)
return;
if (ie->id == DECT_IE_RES)
pt->res = (void *)__dect_ie_hold(common);
pt->last_msg = msgtype;
break;
default:
if (pt->procedure == DECT_MM_KEY_ALLOCATION) {
printf("unexpected message during key allocation\n");
goto release;
}
return;
}
if (pt->rs == NULL || pt->rand_f == NULL ||
pt->res == NULL)
return;
dect_pin_to_ac("0000", ac, sizeof(ac));
dect_auth_b1(ac, sizeof(ac), k);
dect_auth_a11(k, pt->rs->value, ks);
dect_auth_a12(ks, pt->rand_f->value, dck, &res1);
if (res1 == pt->res->value) {
printf("authentication ok\n");
dect_auth_a21(k, pt->rs->value, ks);
dect_hexdump("UAK", ks, sizeof(ks));
memcpy(pt->uak, ks, sizeof(pt->uak));
dect_hexdump("DCK", dck, sizeof(dck));
memcpy(pt->dck, dck, sizeof(pt->dck));
} else
printf("authentication failed\n");
release:
dect_ie_release(dh, pt->portable_identity);
dect_ie_release(dh, pt->rs);
dect_ie_release(dh, pt->rand_f);
dect_ie_release(dh, pt->res);
pt->procedure = DECT_MM_NONE;
}
static void dect_pt_track_auth(struct dect_pt *pt, uint8_t msgtype,
const struct dect_sfmt_ie *ie,
struct dect_ie_common *common)
{
uint8_t k[DECT_AUTH_KEY_LEN], ks[DECT_AUTH_KEY_LEN];
uint8_t dck[DECT_CIPHER_KEY_LEN];
struct dect_ie_auth_res res1;
switch (msgtype) {
case DECT_MM_AUTHENTICATION_REQUEST:
if (pt->procedure != DECT_MM_NONE &&
pt->procedure != DECT_MM_AUTHENTICATION)
return;
if (ie->id == DECT_IE_AUTH_TYPE)
pt->auth_type = (void *)__dect_ie_hold(common);
if (ie->id == DECT_IE_RS)
pt->rs = (void *)__dect_ie_hold(common);
if (ie->id == DECT_IE_RAND)
pt->rand_f = (void *)__dect_ie_hold(common);
pt->procedure = DECT_MM_AUTHENTICATION;
pt->last_msg = msgtype;
return;
case DECT_MM_AUTHENTICATION_REPLY:
if (pt->procedure != DECT_MM_AUTHENTICATION ||
pt->last_msg != DECT_MM_AUTHENTICATION_REQUEST)
return;
if (ie->id == DECT_IE_RES)
pt->res = (void *)__dect_ie_hold(common);
break;
default:
if (pt->procedure == DECT_MM_AUTHENTICATION) {
printf("unexpected message during authentication\n");
goto release;
}
return;
}
if (pt->auth_type == NULL || pt->rs == NULL || pt->rand_f == NULL ||
pt->res == NULL)
return;
dect_auth_b1(pt->uak, sizeof(pt->uak), k);
dect_auth_a11(k, pt->rs->value, ks);
dect_auth_a12(ks, pt->rand_f->value, dck, &res1.value);
if (res1.value == pt->res->value) {
printf("authentication successful\n");
if (pt->auth_type->flags & DECT_AUTH_FLAG_UPC)
memcpy(pt->dck, dck, sizeof(pt->dck));
} else
printf("authentication failed\n");
release:
dect_ie_release(dh, pt->auth_type);
dect_ie_release(dh, pt->rs);
dect_ie_release(dh, pt->rand_f);
dect_ie_release(dh, pt->res);
pt->procedure = DECT_MM_NONE;
}
static void dect_pt_track_ciphering(struct dect_pt *pt, uint8_t msgtype,
const struct dect_sfmt_ie *ie,
struct dect_ie_common *common)
{
switch (msgtype) {
case DECT_MM_CIPHER_REQUEST:
if (pt->procedure != DECT_MM_NONE)
return;
pt->tbc->ciphered = true;
break;
default:
return;
}
}
void dect_dl_data_ind(struct dect_dl *dl, struct dect_msg_buf *mb)
{
struct dect_pt *pt;
struct dect_sfmt_ie ie;
struct dect_ie_common *common;
uint8_t msgtype;
if (!(dumpopts & DECTMON_DUMP_NWK))
return;
msgtype = mb->data[1];
printf("\n");
dect_hexdump("NWK", mb->data, mb->len);
printf("{%s} message:\n", nwk_msg_types[msgtype]);
dect_mbuf_pull(mb, 2);
while (mb->len) {
if (dect_parse_sfmt_ie_header(&ie, mb) < 0)
return;
if (dect_parse_sfmt_ie(dh, ie.id, &common, &ie) < 0)
return;
if (ie.id == DECT_IE_PORTABLE_IDENTITY) {
pt = dect_pt_lookup((void *)common);
if (pt == NULL)
pt = dect_pt_init((void *)common);
dl->pt = pt;
}
if (dl->pt != NULL) {
dect_pt_track_key_allocation(dl->pt, msgtype, &ie, common);
dect_pt_track_auth(dl->pt, msgtype, &ie, common);
dect_pt_track_ciphering(dl->pt, msgtype, &ie, common);
}
__dect_ie_put(dh, common);
dect_mbuf_pull(mb, ie.len);
}
}