First commit
This commit is contained in:
		
							
								
								
									
										40
									
								
								.autom4te.cfg
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										40
									
								
								.autom4te.cfg
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
# SmartCAPWAP -- 
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 (see the file COPYING included with this
 | 
			
		||||
# distribution); if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
begin-language: "Autoheader-preselections"
 | 
			
		||||
args: --no-cache
 | 
			
		||||
end-language: "Autoheader-preselections"
 | 
			
		||||
 | 
			
		||||
begin-language: "Automake-preselections"
 | 
			
		||||
args: --no-cache
 | 
			
		||||
end-language: "Automake-preselections"
 | 
			
		||||
 | 
			
		||||
begin-language: "Autoreconf-preselections"
 | 
			
		||||
args: --no-cache
 | 
			
		||||
end-language: "Autoreconf-preselections"
 | 
			
		||||
 | 
			
		||||
begin-language: "Autoconf-without-aclocal-m4"
 | 
			
		||||
args: --no-cache
 | 
			
		||||
end-language: "Autoconf-without-aclocal-m4"
 | 
			
		||||
 | 
			
		||||
begin-language: "Autoconf"
 | 
			
		||||
args: --no-cache
 | 
			
		||||
end-language: "Autoconf"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										149
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
			
		||||
SmartCAPWAP -- An Open Source CAPWAP WTP / AC
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
 | 
			
		||||
This distribution contains multiple components, some
 | 
			
		||||
of which fall under different licenses.  By using SmartCAPWAP
 | 
			
		||||
or any of the bundled components enumerated below, you
 | 
			
		||||
agree to be bound by the conditions of the license for
 | 
			
		||||
each respective component.
 | 
			
		||||
 | 
			
		||||
SmartCAPWAP license:
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
  SmartCAPWAP is distributed under the GPL license version 2.
 | 
			
		||||
 | 
			
		||||
Libconfig license:
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
  Libconfig is Copyright (C) Mark Lindner, 
 | 
			
		||||
  and is licensed under the GPL license version 2.
 | 
			
		||||
 | 
			
		||||
OpenSSL License:
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
  The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
 | 
			
		||||
  the OpenSSL License and the original SSLeay license apply to the toolkit.
 | 
			
		||||
  See below for the actual license texts. Actually both licenses are BSD-style
 | 
			
		||||
  Open Source licenses. In case of any license issues related to OpenSSL
 | 
			
		||||
  please contact openssl-core@openssl.org.
 | 
			
		||||
 | 
			
		||||
/* ====================================================================
 | 
			
		||||
 * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer. 
 | 
			
		||||
 *
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * 3. All advertising materials mentioning features or use of this
 | 
			
		||||
 *    software must display the following acknowledgment:
 | 
			
		||||
 *    "This product includes software developed by the OpenSSL Project
 | 
			
		||||
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 | 
			
		||||
 *
 | 
			
		||||
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 | 
			
		||||
 *    endorse or promote products derived from this software without
 | 
			
		||||
 *    prior written permission. For written permission, please contact
 | 
			
		||||
 *    openssl-core@openssl.org.
 | 
			
		||||
 *
 | 
			
		||||
 * 5. Products derived from this software may not be called "OpenSSL"
 | 
			
		||||
 *    nor may "OpenSSL" appear in their names without prior written
 | 
			
		||||
 *    permission of the OpenSSL Project.
 | 
			
		||||
 *
 | 
			
		||||
 * 6. Redistributions of any form whatsoever must retain the following
 | 
			
		||||
 *    acknowledgment:
 | 
			
		||||
 *    "This product includes software developed by the OpenSSL Project
 | 
			
		||||
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 | 
			
		||||
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
			
		||||
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 | 
			
		||||
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 | 
			
		||||
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
			
		||||
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 | 
			
		||||
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 * ====================================================================
 | 
			
		||||
 *
 | 
			
		||||
 * This product includes cryptographic software written by Eric Young
 | 
			
		||||
 * (eay@cryptsoft.com).  This product includes software written by Tim
 | 
			
		||||
 * Hudson (tjh@cryptsoft.com).
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 Original SSLeay License
 | 
			
		||||
 -----------------------
 | 
			
		||||
 | 
			
		||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This package is an SSL implementation written
 | 
			
		||||
 * by Eric Young (eay@cryptsoft.com).
 | 
			
		||||
 * The implementation was written so as to conform with Netscapes SSL.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free for commercial and non-commercial use as long as
 | 
			
		||||
 * the following conditions are aheared to.  The following conditions
 | 
			
		||||
 * apply to all code found in this distribution, be it the RC4, RSA,
 | 
			
		||||
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 | 
			
		||||
 * included with this distribution is covered by the same copyright terms
 | 
			
		||||
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 | 
			
		||||
 * 
 | 
			
		||||
 * Copyright remains Eric Young's, and as such any Copyright notices in
 | 
			
		||||
 * the code are not to be removed.
 | 
			
		||||
 * If this package is used in a product, Eric Young should be given attribution
 | 
			
		||||
 * as the author of the parts of the library used.
 | 
			
		||||
 * This can be in the form of a textual message at program startup or
 | 
			
		||||
 * in documentation (online or textual) provided with the package.
 | 
			
		||||
 * 
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. All advertising materials mentioning features or use of this software
 | 
			
		||||
 *    must display the following acknowledgement:
 | 
			
		||||
 *    "This product includes cryptographic software written by
 | 
			
		||||
 *     Eric Young (eay@cryptsoft.com)"
 | 
			
		||||
 *    The word 'cryptographic' can be left out if the rouines from the library
 | 
			
		||||
 *    being used are not cryptographic related :-).
 | 
			
		||||
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 | 
			
		||||
 *    the apps directory (application code) you must include an acknowledgement:
 | 
			
		||||
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 | 
			
		||||
 * 
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 * 
 | 
			
		||||
 * The licence and distribution terms for any publically available version or
 | 
			
		||||
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 | 
			
		||||
 * copied and put under another distribution licence
 | 
			
		||||
 * [including the GNU Public Licence.]
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
GNU Public License (GPL)
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
  SmartCAWAP, Libconfig distributions are 
 | 
			
		||||
  licensed under the GPL version 2 (see COPYRIGHT.GPL).
 | 
			
		||||
							
								
								
									
										28
									
								
								INSTALL
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								INSTALL
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
==================================================
 | 
			
		||||
HOW TO BUILD AND RUN SmartCAPWAP FOR LINUX SYSTEMS
 | 
			
		||||
==================================================
 | 
			
		||||
 | 
			
		||||
NOTE: To run WTP you must have a wireless card that has Linux driver based on the
 | 
			
		||||
      Generic IEEE 802.11 Networking Stack (mac80211).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
HOW TO BUILD AC AND WTP
 | 
			
		||||
=======================
 | 
			
		||||
 | 
			
		||||
Requirements
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
* automake 1.9 or newer
 | 
			
		||||
* autoconf
 | 
			
		||||
* libtool
 | 
			
		||||
* openssl
 | 
			
		||||
 | 
			
		||||
Build
 | 
			
		||||
-----
 | 
			
		||||
 | 
			
		||||
Run:
 | 
			
		||||
 | 
			
		||||
  autoreconf -f -i
 | 
			
		||||
  ./configure
 | 
			
		||||
  make
 | 
			
		||||
  make install
 | 
			
		||||
							
								
								
									
										339
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,339 @@
 | 
			
		||||
                    GNU GENERAL PUBLIC LICENSE
 | 
			
		||||
                       Version 2, June 1991
 | 
			
		||||
 | 
			
		||||
 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 | 
			
		||||
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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.,
 | 
			
		||||
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General
 | 
			
		||||
Public License instead of this License.
 | 
			
		||||
							
								
								
									
										34
									
								
								Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Makefile.am
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
# SmartCAPWAP -- An Open Source CAPWAP WTP / AC
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 (see the file COPYING included with this
 | 
			
		||||
# distribution); if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
AUTOMAKE_OPTIONS = foreign 1.9
 | 
			
		||||
ACLOCAL_AMFLAGS = -I m4
 | 
			
		||||
 | 
			
		||||
MAINTAINERCLEANFILES = \
 | 
			
		||||
	config.log config.status \
 | 
			
		||||
	$(srcdir)/Makefile.in \
 | 
			
		||||
	$(srcdir)/config.h.in $(srcdir)/config.h.in~ $(srcdir)/configure \
 | 
			
		||||
	$(srcdir)/install-sh $(srcdir)/ltmain.sh $(srcdir)/missing \
 | 
			
		||||
	$(srcdir)/m4/libtool.m4 $(srcdir)/m4/lt~obsolete.m4 \
 | 
			
		||||
	$(srcdir)/m4/ltoptions.m4 $(srcdir)/m4/ltsugar.m4 \
 | 
			
		||||
	$(srcdir)/m4/ltversion.m4 \
 | 
			
		||||
	$(srcdir)/depcomp $(srcdir)/aclocal.m4 \
 | 
			
		||||
	$(srcdir)/config.guess $(srcdir)/config.sub
 | 
			
		||||
 | 
			
		||||
SUBDIRS = build
 | 
			
		||||
							
								
								
									
										31
									
								
								build/Makefile.am
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								build/Makefile.am
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
# SmartCAPWAP -- An Open Source CAPWAP WTP / AC
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 (see the file COPYING included with this
 | 
			
		||||
# distribution); if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
MAINTAINERCLEANFILES = \
 | 
			
		||||
	$(srcdir)/Makefile.in
 | 
			
		||||
 | 
			
		||||
SUBDIRS =
 | 
			
		||||
 | 
			
		||||
if BUILD_AC
 | 
			
		||||
SUBDIRS += ac
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
if BUILD_WTP
 | 
			
		||||
SUBDIRS += wtp
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										69
									
								
								build/Makefile_common.am
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								build/Makefile_common.am
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,69 @@
 | 
			
		||||
# SmartCAPWAP -- An Open Source CAPWAP WTP / AC
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 (see the file COPYING included with this
 | 
			
		||||
# distribution); if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
capwap_SOURCES = \
 | 
			
		||||
	$(top_srcdir)/src/common/md5.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_network.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_protocol.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_logging.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_list.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_array.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_dtls.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_dfa.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_acdescriptor.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_discoverytype.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtpboarddata.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtpdescriptor.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtpframetunnelmode.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtpmactype.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_acname.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_controlipv4.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_controlipv6.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_location.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtpname.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_sessionid.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_ecnsupport.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_localipv4.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_localipv6.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_transport.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_mtudiscovery.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_vendorpayload.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_maximumlength.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtprebootstat.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_resultcode.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_returnedmessage.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_acipv4list.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_acipv6list.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_imageidentifier.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_radioadmstate.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_statisticstimer.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_acnamepriority.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtpstaticipaddress.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_timers.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_decrypterrorreportperiod.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_idletimeout.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_wtpfallback.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_radiooprstate.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_element_80211_wtpradioinformation.c
 | 
			
		||||
 | 
			
		||||
if DEBUG_BUILD
 | 
			
		||||
capwap_SOURCES += $(top_srcdir)/src/common/capwap_debug.c
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										64
									
								
								build/ac/Makefile.am
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										64
									
								
								build/ac/Makefile.am
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
# SmartCAPWAP -- An Open Source CAPWAP WTP / AC
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 (see the file COPYING included with this
 | 
			
		||||
# distribution); if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
MAINTAINERCLEANFILES = \
 | 
			
		||||
	$(srcdir)/Makefile.in
 | 
			
		||||
 | 
			
		||||
bin_PROGRAMS = ac
 | 
			
		||||
 | 
			
		||||
AM_CFLAGS = \
 | 
			
		||||
	-DCAPWAP_MULTITHREADING_ENABLE \
 | 
			
		||||
	-D_REENTRANT \
 | 
			
		||||
	-D_GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
if DTLS_ENABLED
 | 
			
		||||
AM_CFLAGS += $(SSL_CFLAGS)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
INCLUDES = \
 | 
			
		||||
	-I$(top_srcdir)/build \
 | 
			
		||||
	-I$(top_srcdir)/src/common \
 | 
			
		||||
	-I$(top_srcdir)/src/ac
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/build/Makefile_common.am
 | 
			
		||||
 | 
			
		||||
ac_SOURCES = \
 | 
			
		||||
	$(capwap_SOURCES) \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_event.c \
 | 
			
		||||
	$(top_srcdir)/src/common/capwap_lock.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_execute.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_session.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_discovery.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_join.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_configure.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_imagedata.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_datacheck.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_dtls.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_run.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_reset.c \
 | 
			
		||||
	$(top_srcdir)/src/ac/ac_dfa_teardown.c
 | 
			
		||||
 | 
			
		||||
ac_LDADD = \
 | 
			
		||||
	$(CONFIG_LIBS) \
 | 
			
		||||
	$(PTHREAD_LIBS)
 | 
			
		||||
 | 
			
		||||
if DTLS_ENABLED
 | 
			
		||||
ac_LDADD += $(SSL_LIBS)
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										60
									
								
								build/wtp/Makefile.am
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										60
									
								
								build/wtp/Makefile.am
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,60 @@
 | 
			
		||||
# SmartCAPWAP -- An Open Source CAPWAP WTP / AC
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 (see the file COPYING included with this
 | 
			
		||||
# distribution); if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
MAINTAINERCLEANFILES = \
 | 
			
		||||
	$(srcdir)/Makefile.in
 | 
			
		||||
 | 
			
		||||
bin_PROGRAMS = wtp
 | 
			
		||||
 | 
			
		||||
AM_CFLAGS = \
 | 
			
		||||
	-D_REENTRANT \
 | 
			
		||||
	-D_GNU_SOURCE
 | 
			
		||||
 | 
			
		||||
if DTLS_ENABLED
 | 
			
		||||
AM_CFLAGS += $(SSL_CFLAGS)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
INCLUDES = \
 | 
			
		||||
	-I$(top_srcdir)/build \
 | 
			
		||||
	-I$(top_srcdir)/src/common \
 | 
			
		||||
	-I$(top_srcdir)/src/wtp
 | 
			
		||||
 | 
			
		||||
include $(top_srcdir)/build/Makefile_common.am
 | 
			
		||||
 | 
			
		||||
wtp_SOURCES = \
 | 
			
		||||
	$(capwap_SOURCES) \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_idle.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_discovery.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_sulking.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_dtls.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_join.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_configure.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_datacheck.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_run.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_reset.c \
 | 
			
		||||
	$(top_srcdir)/src/wtp/wtp_dfa_imagedata.c
 | 
			
		||||
 | 
			
		||||
wtp_LDADD = \
 | 
			
		||||
	$(CONFIG_LIBS)
 | 
			
		||||
 | 
			
		||||
if DTLS_ENABLED
 | 
			
		||||
wtp_LDADD += $(SSL_LIBS)
 | 
			
		||||
endif
 | 
			
		||||
							
								
								
									
										81
									
								
								conf/ac.conf
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										81
									
								
								conf/ac.conf
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
# AC configuration file
 | 
			
		||||
 | 
			
		||||
version = "1.0";
 | 
			
		||||
 | 
			
		||||
application: {
 | 
			
		||||
	name = "ac 1";
 | 
			
		||||
 | 
			
		||||
	binding = [
 | 
			
		||||
		"802.11"
 | 
			
		||||
	];
 | 
			
		||||
 | 
			
		||||
	descriptor: {
 | 
			
		||||
		maxstations = 20;
 | 
			
		||||
		maxwtp = 10;
 | 
			
		||||
		
 | 
			
		||||
		security: {
 | 
			
		||||
			presharedkey = false;
 | 
			
		||||
			x509 = false;
 | 
			
		||||
		};
 | 
			
		||||
		
 | 
			
		||||
		rmacfiled: {
 | 
			
		||||
			supported = false;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		dtlspolicy: {
 | 
			
		||||
			cleardatachannel = true;
 | 
			
		||||
			dtlsdatachannel = true;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		info = (
 | 
			
		||||
			{ idvendor = 12345; type = "hardware"; value = "1.0"; },
 | 
			
		||||
			{ idvendor = 33457; type = "software"; value = "2.0"; }
 | 
			
		||||
		);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	ecn = "limited";
 | 
			
		||||
 | 
			
		||||
	timer: {
 | 
			
		||||
	    discovery = 20;
 | 
			
		||||
	    echorequest = 30;
 | 
			
		||||
	    decrypterrorreport = 120;
 | 
			
		||||
	    idletimeout = 320;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	wtpfallback = true;
 | 
			
		||||
	
 | 
			
		||||
	dtls: {
 | 
			
		||||
		enable = true;
 | 
			
		||||
 | 
			
		||||
		type = "x509";
 | 
			
		||||
 | 
			
		||||
		presharedkey: {
 | 
			
		||||
			# TODO
 | 
			
		||||
		};
 | 
			
		||||
		
 | 
			
		||||
		x509: {
 | 
			
		||||
			calist = "/etc/capwap/ca.crt";
 | 
			
		||||
			certificate = "/etc/capwap/ac.crt";
 | 
			
		||||
			privatekey = "/etc/capwap/ac.key";
 | 
			
		||||
			privatekeypassword = "";
 | 
			
		||||
		};		
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	network: {
 | 
			
		||||
		#binding = "eth1";
 | 
			
		||||
		mtu = 1500;
 | 
			
		||||
		transport = "udp";
 | 
			
		||||
 | 
			
		||||
		ipv4 = true; 
 | 
			
		||||
		ipv6 = false;
 | 
			
		||||
		ipdualstack = true;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
logging: {
 | 
			
		||||
	enable = true;
 | 
			
		||||
	level = "debug";
 | 
			
		||||
	output = (
 | 
			
		||||
		{ mode = "stdout"; }
 | 
			
		||||
	);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										73
									
								
								conf/ac.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								conf/ac.crt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,73 @@
 | 
			
		||||
Certificate:
 | 
			
		||||
    Data:
 | 
			
		||||
        Version: 3 (0x2)
 | 
			
		||||
        Serial Number: 2 (0x2)
 | 
			
		||||
        Signature Algorithm: sha1WithRSAEncryption
 | 
			
		||||
        Issuer: C=IT, ST=Italy, L=Rome, O=Capwap CA, CN=CAPWAP_CA/emailAddress=ca@localhost
 | 
			
		||||
        Validity
 | 
			
		||||
            Not Before: Apr 11 17:49:25 2009 GMT
 | 
			
		||||
            Not After : Apr  9 17:49:25 2019 GMT
 | 
			
		||||
        Subject: C=IT, ST=Italy, L=Rome, O=Capwap AC, CN=CAPWAP_AC/emailAddress=ac@localhost
 | 
			
		||||
        Subject Public Key Info:
 | 
			
		||||
            Public Key Algorithm: rsaEncryption
 | 
			
		||||
            RSA Public Key: (1024 bit)
 | 
			
		||||
                Modulus (1024 bit):
 | 
			
		||||
                    00:e2:9f:90:f6:f5:c5:52:23:cc:8d:28:6c:7c:0b:
 | 
			
		||||
                    4a:ec:0d:50:de:0d:37:0d:de:75:cb:61:d8:58:e3:
 | 
			
		||||
                    3f:ec:cb:5b:b5:e0:ca:87:93:cf:22:f3:7d:35:cf:
 | 
			
		||||
                    2d:ef:ad:a4:8a:d3:8c:ec:7f:d2:7e:19:cb:11:15:
 | 
			
		||||
                    28:b0:ee:74:33:e2:21:24:70:d0:e4:22:2f:eb:59:
 | 
			
		||||
                    3d:ef:c4:c2:1b:f7:7d:1b:ac:3c:f8:46:c9:0a:f4:
 | 
			
		||||
                    12:b0:71:11:0d:52:84:d9:a9:76:84:68:33:c6:7c:
 | 
			
		||||
                    54:1a:4c:34:f4:22:ad:fb:4c:7b:2e:ee:1a:fe:b3:
 | 
			
		||||
                    0d:18:38:16:46:48:9d:7a:b7
 | 
			
		||||
                Exponent: 65537 (0x10001)
 | 
			
		||||
        X509v3 extensions:
 | 
			
		||||
            X509v3 Basic Constraints: 
 | 
			
		||||
                CA:FALSE
 | 
			
		||||
            Netscape Cert Type: 
 | 
			
		||||
                SSL Server
 | 
			
		||||
            Netscape Comment: 
 | 
			
		||||
                Easy-RSA Generated Server Certificate
 | 
			
		||||
            X509v3 Subject Key Identifier: 
 | 
			
		||||
                63:7B:01:7C:B6:2B:DC:D5:E4:BD:A1:AC:D4:BB:E0:6F:A6:07:16:A4
 | 
			
		||||
            X509v3 Authority Key Identifier: 
 | 
			
		||||
                keyid:49:62:46:06:E1:E5:D3:3A:08:79:C6:D6:FE:93:A8:D9:AA:75:EB:E4
 | 
			
		||||
                DirName:/C=IT/ST=Italy/L=Rome/O=Capwap CA/CN=CAPWAP_CA/emailAddress=ca@localhost
 | 
			
		||||
                serial:94:59:55:20:58:F6:66:33
 | 
			
		||||
 | 
			
		||||
            X509v3 Extended Key Usage: 
 | 
			
		||||
                TLS Web Server Authentication
 | 
			
		||||
            X509v3 Key Usage: 
 | 
			
		||||
                Digital Signature, Key Encipherment
 | 
			
		||||
    Signature Algorithm: sha1WithRSAEncryption
 | 
			
		||||
        0a:be:9e:6c:a1:c6:0c:a6:d3:5e:92:6b:09:21:78:99:f0:83:
 | 
			
		||||
        a1:a4:2f:56:56:55:51:61:f4:04:a5:fe:9a:c4:95:76:01:f3:
 | 
			
		||||
        72:96:18:e2:96:f9:8d:cf:6d:32:6c:39:9c:92:a2:41:39:e2:
 | 
			
		||||
        3f:32:ef:73:75:f0:3e:f4:9c:93:af:31:63:c7:55:2e:8d:de:
 | 
			
		||||
        ab:99:59:82:36:54:49:ef:ef:13:a7:26:db:8f:2e:93:0c:a1:
 | 
			
		||||
        d5:b5:e6:5d:7a:a4:3f:1d:8e:ad:73:c5:32:ba:24:d2:4a:f5:
 | 
			
		||||
        ae:95:18:98:07:80:fc:be:95:45:ce:50:ab:fc:6e:90:7a:8b:
 | 
			
		||||
        28:5d
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIDmTCCAwKgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJJVDEO
 | 
			
		||||
MAwGA1UECBMFSXRhbHkxDTALBgNVBAcTBFJvbWUxEjAQBgNVBAoTCUNhcHdhcCBD
 | 
			
		||||
QTESMBAGA1UEAxQJQ0FQV0FQX0NBMRswGQYJKoZIhvcNAQkBFgxjYUBsb2NhbGhv
 | 
			
		||||
c3QwHhcNMDkwNDExMTc0OTI1WhcNMTkwNDA5MTc0OTI1WjBxMQswCQYDVQQGEwJJ
 | 
			
		||||
VDEOMAwGA1UECBMFSXRhbHkxDTALBgNVBAcTBFJvbWUxEjAQBgNVBAoTCUNhcHdh
 | 
			
		||||
cCBBQzESMBAGA1UEAxQJQ0FQV0FQX0FDMRswGQYJKoZIhvcNAQkBFgxhY0Bsb2Nh
 | 
			
		||||
bGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOKfkPb1xVIjzI0obHwL
 | 
			
		||||
SuwNUN4NNw3edcth2FjjP+zLW7XgyoeTzyLzfTXPLe+tpIrTjOx/0n4ZyxEVKLDu
 | 
			
		||||
dDPiISRw0OQiL+tZPe/Ewhv3fRusPPhGyQr0ErBxEQ1ShNmpdoRoM8Z8VBpMNPQi
 | 
			
		||||
rftMey7uGv6zDRg4FkZInXq3AgMBAAGjggE/MIIBOzAJBgNVHRMEAjAAMBEGCWCG
 | 
			
		||||
SAGG+EIBAQQEAwIGQDA0BglghkgBhvhCAQ0EJxYlRWFzeS1SU0EgR2VuZXJhdGVk
 | 
			
		||||
IFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUY3sBfLYr3NXkvaGs1Lvgb6YH
 | 
			
		||||
FqQwgaMGA1UdIwSBmzCBmIAUSWJGBuHl0zoIecbW/pOo2ap16+ShdaRzMHExCzAJ
 | 
			
		||||
BgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTESMBAGA1UE
 | 
			
		||||
ChMJQ2Fwd2FwIENBMRIwEAYDVQQDFAlDQVBXQVBfQ0ExGzAZBgkqhkiG9w0BCQEW
 | 
			
		||||
DGNhQGxvY2FsaG9zdIIJAJRZVSBY9mYzMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAsG
 | 
			
		||||
A1UdDwQEAwIFoDANBgkqhkiG9w0BAQUFAAOBgQAKvp5socYMptNekmsJIXiZ8IOh
 | 
			
		||||
pC9WVlVRYfQEpf6axJV2AfNylhjilvmNz20ybDmckqJBOeI/Mu9zdfA+9JyTrzFj
 | 
			
		||||
x1Uujd6rmVmCNlRJ7+8Tpybbjy6TDKHVteZdeqQ/HY6tc8UyuiTSSvWulRiYB4D8
 | 
			
		||||
vpVFzlCr/G6QeosoXQ==
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										15
									
								
								conf/ac.key
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								conf/ac.key
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
-----BEGIN RSA PRIVATE KEY-----
 | 
			
		||||
MIICWwIBAAKBgQDin5D29cVSI8yNKGx8C0rsDVDeDTcN3nXLYdhY4z/sy1u14MqH
 | 
			
		||||
k88i8301zy3vraSK04zsf9J+GcsRFSiw7nQz4iEkcNDkIi/rWT3vxMIb930brDz4
 | 
			
		||||
RskK9BKwcRENUoTZqXaEaDPGfFQaTDT0Iq37THsu7hr+sw0YOBZGSJ16twIDAQAB
 | 
			
		||||
AoGAM0gEV735rsKnEPIqyk8L3yqMOBMpeBv079buS/7wgjbqQ9fgPJm376LFnJ2L
 | 
			
		||||
OYdDip6gbwvlp99SUkVFdfQfmwjmBDk1IfEWYiPO4CUrsIUzid2KtueZW5c6Cm0Q
 | 
			
		||||
RMutCQrsZw9s6VpL9bmV0zsm3MYNYfERs0rPOIW9I3YyrEECQQD5t5V4Uj7+gpZO
 | 
			
		||||
Qvb+tYAVb8NcYTPBfdVbZJ8MRrs9tH2Y2AkuE1D+g7S5qq+Ld1tBIcCeKhlG4+ee
 | 
			
		||||
ClH20s3RAkEA6FM8eGKOhZ4nmu4yzwdMJnqY0d4+56805VS5Z+uJJiXvCXKQ+wQr
 | 
			
		||||
e/8BLsWRLxXlqijshsWzHID2g8i/rlC6BwJADiHqrqWQ9Rx03zcA/YdOGWh62PaT
 | 
			
		||||
VEcH1SVLrwktvZ9CYG0Rj+797XmMt9lGGBGIM5ZybUEarx1k1VfmLZ7ekQJAKPOD
 | 
			
		||||
FTVKKgNWt9iE3DlNEvtJNLUYIX6gtEva4paB9ld5axDmvVhe0dyBON1aWhJiCTxt
 | 
			
		||||
dNQkXkHdMh2QrAlOwQJAcoEhG5Zl0wATXSCFvbvaJKiH9Ab1IjlCtNI3O/+TgQjN
 | 
			
		||||
ZQMA0nO5ZJ3p266M8zh2hgIRdNstv4oilqh/3DnO3g==
 | 
			
		||||
-----END RSA PRIVATE KEY-----
 | 
			
		||||
							
								
								
									
										20
									
								
								conf/ca.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								conf/ca.crt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIDNzCCAqCgAwIBAgIJAJRZVSBY9mYzMA0GCSqGSIb3DQEBBQUAMHExCzAJBgNV
 | 
			
		||||
BAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTESMBAGA1UEChMJ
 | 
			
		||||
Q2Fwd2FwIENBMRIwEAYDVQQDFAlDQVBXQVBfQ0ExGzAZBgkqhkiG9w0BCQEWDGNh
 | 
			
		||||
QGxvY2FsaG9zdDAeFw0wOTA0MTExNzQ2MzlaFw0xOTA0MDkxNzQ2MzlaMHExCzAJ
 | 
			
		||||
BgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsGA1UEBxMEUm9tZTESMBAGA1UE
 | 
			
		||||
ChMJQ2Fwd2FwIENBMRIwEAYDVQQDFAlDQVBXQVBfQ0ExGzAZBgkqhkiG9w0BCQEW
 | 
			
		||||
DGNhQGxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw0gvx6qo
 | 
			
		||||
B4fd23/dU5yBdj/TKzVM1/kC/bwRRFjNd2FIMpjsJ7drbwhZo5CrOSFyKn8X4Exr
 | 
			
		||||
EdkfMjjNFi6mZVmdFfJO4ex+6qJqc1m52AocUEOkyG/52LOnCTsT91yps97obPUF
 | 
			
		||||
8ezK0m9a5dnuoJ8q7lxbGu7m0PJ0Qgws3dsCAwEAAaOB1jCB0zAdBgNVHQ4EFgQU
 | 
			
		||||
SWJGBuHl0zoIecbW/pOo2ap16+QwgaMGA1UdIwSBmzCBmIAUSWJGBuHl0zoIecbW
 | 
			
		||||
/pOo2ap16+ShdaRzMHExCzAJBgNVBAYTAklUMQ4wDAYDVQQIEwVJdGFseTENMAsG
 | 
			
		||||
A1UEBxMEUm9tZTESMBAGA1UEChMJQ2Fwd2FwIENBMRIwEAYDVQQDFAlDQVBXQVBf
 | 
			
		||||
Q0ExGzAZBgkqhkiG9w0BCQEWDGNhQGxvY2FsaG9zdIIJAJRZVSBY9mYzMAwGA1Ud
 | 
			
		||||
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAsHOGDPcwslke/Ux3bp2tZj4MizTL
 | 
			
		||||
DJqTRbqoiQLOTfUI7KU0GQ2m+ywTwhpiUPhmqqmgtGKXbL9mQB/qcG6HGNzdRc56
 | 
			
		||||
4ttc1RVErhmM/LZEFjyHamuOryUY5FmS78XXBGFRkvPAap9OSQU4vXPfehYFCL+p
 | 
			
		||||
/L9CoKunApUqH3g=
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										110
									
								
								conf/wtp.conf
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										110
									
								
								conf/wtp.conf
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,110 @@
 | 
			
		||||
# WTP configuration file
 | 
			
		||||
 | 
			
		||||
version = "1.0";
 | 
			
		||||
 | 
			
		||||
application: {
 | 
			
		||||
	name = "wtp 1";
 | 
			
		||||
 | 
			
		||||
	location = "Ufficio";
 | 
			
		||||
 | 
			
		||||
	binding = "802.11";
 | 
			
		||||
 | 
			
		||||
	tunnelmode: {
 | 
			
		||||
		nativeframe = false;
 | 
			
		||||
		ethframe = false;
 | 
			
		||||
		localbridging = false;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	mactype = "localmac";
 | 
			
		||||
 | 
			
		||||
	boardinfo: {
 | 
			
		||||
		idvendor = 123456;
 | 
			
		||||
 | 
			
		||||
		element  = (
 | 
			
		||||
			{ name = "model"; value = "1.0"; },
 | 
			
		||||
			{ name = "serial"; value = "2.0"; },
 | 
			
		||||
			{ name = "id"; value = "3.0"; },
 | 
			
		||||
			{ name = "revision"; value = "4.0"; },
 | 
			
		||||
			{ name = "macaddress"; type = "interface"; value = "eth1"; }
 | 
			
		||||
		);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	descriptor: {
 | 
			
		||||
		radio = (
 | 
			
		||||
			{ device = "wifi0"; type = "bg"; status = "enabled"; }
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		encryption = [ 
 | 
			
		||||
			"802.11_AES", 
 | 
			
		||||
			"802.11_TKIP" 
 | 
			
		||||
		];
 | 
			
		||||
 | 
			
		||||
		info = (
 | 
			
		||||
			{ idvendor = 23456; type = "hardware"; value = "abcde"; },
 | 
			
		||||
			{ idvendor = 33457; type = "software"; value = "fghil"; },
 | 
			
		||||
			{ idvendor = 43458; type = "boot"; value = "mnopq"; },
 | 
			
		||||
			{ idvendor = 53459; type = "other"; value = "qwert"; }
 | 
			
		||||
		);
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	ecn = "limited";
 | 
			
		||||
 | 
			
		||||
	timer: {
 | 
			
		||||
		statistics = 120;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	dtls: {
 | 
			
		||||
		enable = true;
 | 
			
		||||
 | 
			
		||||
		dtlspolicy: {
 | 
			
		||||
			cleardatachannel = true;
 | 
			
		||||
			dtlsdatachannel = true;
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		type = "x509";
 | 
			
		||||
 | 
			
		||||
		presharedkey: {
 | 
			
		||||
			# TODO
 | 
			
		||||
		};
 | 
			
		||||
		
 | 
			
		||||
		x509: {
 | 
			
		||||
			calist = "/etc/capwap/ca.crt";
 | 
			
		||||
			certificate = "/etc/capwap/wtp.crt";
 | 
			
		||||
			privatekey = "/etc/capwap/wtp.key";
 | 
			
		||||
			privatekeypassword = "";
 | 
			
		||||
		};		
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	network: {
 | 
			
		||||
		#binding = "eth1";
 | 
			
		||||
		mtu = 1500;
 | 
			
		||||
 | 
			
		||||
		port = 10000;
 | 
			
		||||
		transport = "udp";
 | 
			
		||||
 | 
			
		||||
		ipv4 = true; 
 | 
			
		||||
		ipv6 = false;
 | 
			
		||||
		ipdualstack = true;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	acdiscovery: {
 | 
			
		||||
		search = false;
 | 
			
		||||
		host = [
 | 
			
		||||
			"127.0.0.1"
 | 
			
		||||
		];
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	acprefered: {
 | 
			
		||||
		host = [
 | 
			
		||||
			"127.0.0.1"
 | 
			
		||||
		];
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
logging: {
 | 
			
		||||
	enable = true;
 | 
			
		||||
	level = "debug";
 | 
			
		||||
	output = (
 | 
			
		||||
		{ mode = "stdout"; }
 | 
			
		||||
	);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										70
									
								
								conf/wtp.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								conf/wtp.crt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
Certificate:
 | 
			
		||||
    Data:
 | 
			
		||||
        Version: 3 (0x2)
 | 
			
		||||
        Serial Number: 3 (0x3)
 | 
			
		||||
        Signature Algorithm: sha1WithRSAEncryption
 | 
			
		||||
        Issuer: C=IT, ST=Italy, L=Rome, O=Capwap CA, CN=CAPWAP_CA/emailAddress=ca@localhost
 | 
			
		||||
        Validity
 | 
			
		||||
            Not Before: Apr 11 17:50:00 2009 GMT
 | 
			
		||||
            Not After : Apr  9 17:50:00 2019 GMT
 | 
			
		||||
        Subject: C=IT, ST=Italy, L=Rome, O=Capwap WTP, CN=CAPWAP_WTP/emailAddress=wtp@localhost
 | 
			
		||||
        Subject Public Key Info:
 | 
			
		||||
            Public Key Algorithm: rsaEncryption
 | 
			
		||||
            RSA Public Key: (1024 bit)
 | 
			
		||||
                Modulus (1024 bit):
 | 
			
		||||
                    00:d4:78:02:6f:d8:52:3b:ea:7c:13:a9:d4:74:58:
 | 
			
		||||
                    4c:d9:6d:e9:54:76:ea:6c:74:8a:70:b7:f8:72:9e:
 | 
			
		||||
                    71:63:bc:db:6e:43:d8:c6:6b:34:94:e4:28:98:a2:
 | 
			
		||||
                    5b:16:9e:a8:9e:19:50:61:01:d3:f6:fd:37:e7:8b:
 | 
			
		||||
                    be:9e:bf:bc:96:c2:3e:d3:fa:fe:1a:76:42:5c:92:
 | 
			
		||||
                    76:73:1f:97:94:42:38:93:d0:56:a5:b2:b1:5f:ba:
 | 
			
		||||
                    90:90:17:f4:88:cb:c6:35:9b:7d:0f:a4:75:6d:d2:
 | 
			
		||||
                    bb:b2:1d:cf:55:9d:e7:9b:03:35:fe:6f:1b:df:10:
 | 
			
		||||
                    3d:58:7b:77:1c:e5:ba:a5:75
 | 
			
		||||
                Exponent: 65537 (0x10001)
 | 
			
		||||
        X509v3 extensions:
 | 
			
		||||
            X509v3 Basic Constraints: 
 | 
			
		||||
                CA:FALSE
 | 
			
		||||
            Netscape Comment: 
 | 
			
		||||
                Easy-RSA Generated Certificate
 | 
			
		||||
            X509v3 Subject Key Identifier: 
 | 
			
		||||
                53:EB:37:11:23:CC:27:53:89:04:2F:08:C5:05:47:D4:65:23:73:2D
 | 
			
		||||
            X509v3 Authority Key Identifier: 
 | 
			
		||||
                keyid:49:62:46:06:E1:E5:D3:3A:08:79:C6:D6:FE:93:A8:D9:AA:75:EB:E4
 | 
			
		||||
                DirName:/C=IT/ST=Italy/L=Rome/O=Capwap CA/CN=CAPWAP_CA/emailAddress=ca@localhost
 | 
			
		||||
                serial:94:59:55:20:58:F6:66:33
 | 
			
		||||
 | 
			
		||||
            X509v3 Extended Key Usage: 
 | 
			
		||||
                TLS Web Client Authentication
 | 
			
		||||
            X509v3 Key Usage: 
 | 
			
		||||
                Digital Signature
 | 
			
		||||
    Signature Algorithm: sha1WithRSAEncryption
 | 
			
		||||
        57:93:d6:43:0b:e6:5f:b7:77:2c:1d:d3:b0:4c:6a:35:62:ec:
 | 
			
		||||
        5b:56:e5:f7:34:b9:c7:8d:9f:e7:cb:12:0d:f0:cf:c7:a3:c1:
 | 
			
		||||
        24:0f:64:f2:a2:ab:f7:80:e8:a5:66:8a:c3:2f:9b:4f:87:d7:
 | 
			
		||||
        8e:27:e7:29:73:cc:fc:4c:0d:fb:8f:74:ee:7c:bd:ce:d3:01:
 | 
			
		||||
        ee:69:1f:42:56:6f:e1:b3:6c:c3:a1:4d:60:14:06:ba:a7:38:
 | 
			
		||||
        a0:78:1d:a9:cd:39:90:f2:33:6c:fb:48:cb:6e:80:00:ce:7c:
 | 
			
		||||
        50:e2:e7:6f:83:f1:86:be:39:5c:0c:64:1f:01:7c:1b:9f:e6:
 | 
			
		||||
        ea:e2
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIDgjCCAuugAwIBAgIBAzANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJJVDEO
 | 
			
		||||
MAwGA1UECBMFSXRhbHkxDTALBgNVBAcTBFJvbWUxEjAQBgNVBAoTCUNhcHdhcCBD
 | 
			
		||||
QTESMBAGA1UEAxQJQ0FQV0FQX0NBMRswGQYJKoZIhvcNAQkBFgxjYUBsb2NhbGhv
 | 
			
		||||
c3QwHhcNMDkwNDExMTc1MDAwWhcNMTkwNDA5MTc1MDAwWjB0MQswCQYDVQQGEwJJ
 | 
			
		||||
VDEOMAwGA1UECBMFSXRhbHkxDTALBgNVBAcTBFJvbWUxEzARBgNVBAoTCkNhcHdh
 | 
			
		||||
cCBXVFAxEzARBgNVBAMUCkNBUFdBUF9XVFAxHDAaBgkqhkiG9w0BCQEWDXd0cEBs
 | 
			
		||||
b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANR4Am/YUjvqfBOp
 | 
			
		||||
1HRYTNlt6VR26mx0inC3+HKecWO8225D2MZrNJTkKJiiWxaeqJ4ZUGEB0/b9N+eL
 | 
			
		||||
vp6/vJbCPtP6/hp2QlySdnMfl5RCOJPQVqWysV+6kJAX9IjLxjWbfQ+kdW3Su7Id
 | 
			
		||||
z1Wd55sDNf5vG98QPVh7dxzluqV1AgMBAAGjggElMIIBITAJBgNVHRMEAjAAMC0G
 | 
			
		||||
CWCGSAGG+EIBDQQgFh5FYXN5LVJTQSBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD
 | 
			
		||||
VR0OBBYEFFPrNxEjzCdTiQQvCMUFR9RlI3MtMIGjBgNVHSMEgZswgZiAFEliRgbh
 | 
			
		||||
5dM6CHnG1v6TqNmqdevkoXWkczBxMQswCQYDVQQGEwJJVDEOMAwGA1UECBMFSXRh
 | 
			
		||||
bHkxDTALBgNVBAcTBFJvbWUxEjAQBgNVBAoTCUNhcHdhcCBDQTESMBAGA1UEAxQJ
 | 
			
		||||
Q0FQV0FQX0NBMRswGQYJKoZIhvcNAQkBFgxjYUBsb2NhbGhvc3SCCQCUWVUgWPZm
 | 
			
		||||
MzATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCB4AwDQYJKoZIhvcNAQEF
 | 
			
		||||
BQADgYEAV5PWQwvmX7d3LB3TsExqNWLsW1bl9zS5x42f58sSDfDPx6PBJA9k8qKr
 | 
			
		||||
94DopWaKwy+bT4fXjifnKXPM/EwN+4907ny9ztMB7mkfQlZv4bNsw6FNYBQGuqc4
 | 
			
		||||
oHgdqc05kPIzbPtIy26AAM58UOLnb4Pxhr45XAxkHwF8G5/m6uI=
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										15
									
								
								conf/wtp.key
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								conf/wtp.key
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
-----BEGIN RSA PRIVATE KEY-----
 | 
			
		||||
MIICXAIBAAKBgQDUeAJv2FI76nwTqdR0WEzZbelUdupsdIpwt/hynnFjvNtuQ9jG
 | 
			
		||||
azSU5CiYolsWnqieGVBhAdP2/Tfni76ev7yWwj7T+v4adkJcknZzH5eUQjiT0Fal
 | 
			
		||||
srFfupCQF/SIy8Y1m30PpHVt0ruyHc9VneebAzX+bxvfED1Ye3cc5bqldQIDAQAB
 | 
			
		||||
AoGAAIP2BY1xzaFpAac0079vGEvy9/h94xt5RoK7wJNv1P0dTyws93ZFH2NaUdx6
 | 
			
		||||
+hgScqe/ES0u9XdxzkcBhGMUswvNmofgk9w/ynQhey7g739TXeEh76zMphNVJf0z
 | 
			
		||||
pawFFP/FIIgYVf7CdHkQ8cU4LEvTUCxAE5bICHMuOgCiEQECQQDz5/PSc/ZuMOZq
 | 
			
		||||
ngYOCaf3p3CQdeFcFOeU3ldxW8j5eZR2Xdhu5CCeY5ELPq+yW4+J+6KBAVh6Q8Uv
 | 
			
		||||
MwDCSqrBAkEA3wEBMgaJvpEijv6P6Ryc+khazEASDAbvUmrcUD0t14aPrCoAHAUU
 | 
			
		||||
stCCcn8zV4MqETPr7bO9joh/oh7IpCGrtQJAMYzTydNpIuWoScykqkFn8DYB9jcc
 | 
			
		||||
e1p72ZB57zuYTqZWdN2H1K9fuQ29L62if/d956hJUS/2y4/tBTO1WcNVgQJBALQK
 | 
			
		||||
jJuF2cmoRV1rOma6+iW7KstCYw+gvbEtoyeI7SzXb8FQu3vjwj1HyDmGZr4doGX5
 | 
			
		||||
JF5pwf2ESH9sGRMiOA0CQGKVeegxodjqwNEY8WqJjgROHkI1aJhdHVehAcCLhtGX
 | 
			
		||||
WBcQEK73GJC5Kb4yTg0VEFkIWeGpy0aDnOyTJlNrQKc=
 | 
			
		||||
-----END RSA PRIVATE KEY-----
 | 
			
		||||
							
								
								
									
										230
									
								
								configure.ac
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								configure.ac
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,230 @@
 | 
			
		||||
# SmartCAPWAP -- An Open Source CAPWAP WTP / AC
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2012-2013 Massimo Vellucci <vemax78@gmail.com>
 | 
			
		||||
#
 | 
			
		||||
# 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 (see the file COPYING included with this
 | 
			
		||||
# distribution); if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
AC_PREREQ(2.60)
 | 
			
		||||
 | 
			
		||||
m4_include(version.m4)
 | 
			
		||||
AC_INIT([PRODUCT_NAME], [PRODUCT_VERSION], [PRODUCT_BUGREPORT], [PRODUCT_TARNAME])
 | 
			
		||||
AC_CONFIG_AUX_DIR([.])
 | 
			
		||||
AC_CONFIG_MACRO_DIR([m4])
 | 
			
		||||
AM_INIT_AUTOMAKE
 | 
			
		||||
 | 
			
		||||
# cross-compile macros
 | 
			
		||||
AC_CANONICAL_BUILD
 | 
			
		||||
AC_CANONICAL_HOST
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AC_COPYRIGHT("SmartCapwap by Massimo Vellucci <vemax78@gmail.com>")
 | 
			
		||||
AC_REVISION($Revision: 1.0 $)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AC_ARG_ENABLE(
 | 
			
		||||
	[dtls],
 | 
			
		||||
	[AS_HELP_STRING([--disable-dtls], [disable DTLS support @<:@default=yes@:>@])],
 | 
			
		||||
	,
 | 
			
		||||
	[enable_dtls="yes"]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(
 | 
			
		||||
	[debug],
 | 
			
		||||
	[AS_HELP_STRING([--disable-debug], [disable debug support @<:@default=yes@:>@])],
 | 
			
		||||
	,
 | 
			
		||||
	[enable_debug="yes"]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(
 | 
			
		||||
	[logging],
 | 
			
		||||
	[AS_HELP_STRING([--disable-logging], [disable logging support @<:@default=yes@:>@])],
 | 
			
		||||
	,
 | 
			
		||||
	[enable_logging="yes"]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(
 | 
			
		||||
	[ac],
 | 
			
		||||
	[AS_HELP_STRING([--disable-ac], [disable ac support @<:@default=yes@:>@])],
 | 
			
		||||
	,
 | 
			
		||||
	[enable_ac="yes"]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(
 | 
			
		||||
	[wtp],
 | 
			
		||||
	[AS_HELP_STRING([--disable-wtp], [disable wtp support @<:@default=yes@:>@])],
 | 
			
		||||
	,
 | 
			
		||||
	[enable_wtp="yes"]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AC_ARG_WITH(
 | 
			
		||||
	[ssl-library],
 | 
			
		||||
	[AS_HELP_STRING([--with-crypto-library=library], [build with the given crypto library, TYPE=openssl @<:@default=openssl@:>@])],
 | 
			
		||||
	[
 | 
			
		||||
	        case "${withval}" in
 | 
			
		||||
	                openssl) ;;
 | 
			
		||||
	                *) AC_MSG_ERROR([bad value ${withval} for --with-crypto-library]) ;;
 | 
			
		||||
	        esac
 | 
			
		||||
	],
 | 
			
		||||
	[with_ssl_library="openssl"]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
AC_ARG_WITH(
 | 
			
		||||
	[mem-check],
 | 
			
		||||
	[AS_HELP_STRING([--with-mem-check=TYPE], [build with debug memory checking, TYPE=no|internal|valgrind @<:@default=internal@:>@])],
 | 
			
		||||
	[
 | 
			
		||||
		case "${withval}" in
 | 
			
		||||
			valgrind|internal|no) ;;
 | 
			
		||||
			*) AC_MSG_ERROR([bad value ${withval} for --mem-check]) ;;
 | 
			
		||||
		esac
 | 
			
		||||
	],
 | 
			
		||||
	[with_mem_check="internal"]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# specify output header file
 | 
			
		||||
AM_CONFIG_HEADER(build/config.h)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
old_CFLAGS="${CFLAGS}"
 | 
			
		||||
AC_PROG_CC([gcc])
 | 
			
		||||
CFLAGS="${old_CFLAGS}"
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AM_CONDITIONAL([DEBUG_BUILD], [test "$enable_debug" = yes]) 
 | 
			
		||||
if test "${enable_debug}" = "yes"; then
 | 
			
		||||
	CFLAGS="${CFLAGS} -DDEBUG -Wall -Werror -g -O0"
 | 
			
		||||
else
 | 
			
		||||
	CFLAGS="${CFLAGS} -O2"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AC_PROG_INSTALL
 | 
			
		||||
AC_USE_SYSTEM_EXTENSIONS
 | 
			
		||||
 | 
			
		||||
AC_LANG(C)
 | 
			
		||||
 | 
			
		||||
AC_HEADER_STDC
 | 
			
		||||
 | 
			
		||||
# Check LIBCONFIG library
 | 
			
		||||
AC_CHECK_HEADER([libconfig.h], [], [AC_MSG_ERROR(You need the libconfig headers)])
 | 
			
		||||
AC_CHECK_LIB([config], [config_init], [CONFIG_LIBS="-lconfig"], [AC_MSG_ERROR(You need the libconfig library)])
 | 
			
		||||
 | 
			
		||||
# Check PTHREAD library
 | 
			
		||||
AC_CHECK_HEADER([pthread.h], [], [AC_MSG_ERROR(You need the pthread headers)])
 | 
			
		||||
AC_CHECK_LIB([pthread], [pthread_create], [PTHREAD_LIBS="-lpthread"], [AC_MSG_ERROR(You need the pthread library)])
 | 
			
		||||
 | 
			
		||||
# Check SSL library
 | 
			
		||||
PKG_CHECK_MODULES(
 | 
			
		||||
	[OPENSSL_CRYPTO],
 | 
			
		||||
	[libcrypto >= 1.0.0],
 | 
			
		||||
	[have_openssl_crypto="yes"],
 | 
			
		||||
	[AC_CHECK_LIB(
 | 
			
		||||
		[crypto],
 | 
			
		||||
		[RSA_new],
 | 
			
		||||
		[
 | 
			
		||||
			have_openssl_crypto="yes"
 | 
			
		||||
			OPENSSL_CRYPTO_LIBS="-lcrypto"
 | 
			
		||||
		]
 | 
			
		||||
	)]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(
 | 
			
		||||
	[OPENSSL_SSL],
 | 
			
		||||
	[libssl >= 1.0.0],
 | 
			
		||||
	[have_openssl_ssl="yes"],
 | 
			
		||||
	[AC_CHECK_LIB(
 | 
			
		||||
		[ssl],
 | 
			
		||||
		[SSL_CTX_new],
 | 
			
		||||
		[
 | 
			
		||||
			have_openssl_ssl="yes"
 | 
			
		||||
			OPENSSL_SSL_LIBS="-lssl"
 | 
			
		||||
		]
 | 
			
		||||
	)]
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
if test "${have_openssl_ssl}" = "yes"; then
 | 
			
		||||
	saved_CFLAGS="${CFLAGS}"
 | 
			
		||||
	saved_LIBS="${LIBS}"
 | 
			
		||||
	CFLAGS="${CFLAGS} ${OPENSSL_SSL_CFLAGS}"
 | 
			
		||||
	LIBS="${LIBS} ${OPENSSL_SSL_LIBS}"
 | 
			
		||||
	have_openssl_engine="yes"
 | 
			
		||||
	AC_CHECK_FUNC([SSL_CTX_set_cookie_generate_cb], , [AC_MSG_ERROR([${with_ssl_library} SSL_CTX_set_cookie_generate_cb function is required but missing])])
 | 
			
		||||
	AC_CHECK_FUNC([SSL_CTX_set_cookie_verify_cb], , [AC_MSG_ERROR([${with_ssl_library} SSL_CTX_set_cookie_verify_cb function is required but missing])])
 | 
			
		||||
	CFLAGS="${saved_CFLAGS}"
 | 
			
		||||
	LIBS="${saved_LIBS}"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
case "${with_ssl_library}" in
 | 
			
		||||
	openssl)
 | 
			
		||||
		have_crypto_engine="${have_openssl_engine}"
 | 
			
		||||
		have_crypto_crypto="${have_openssl_crypto}"
 | 
			
		||||
		have_crypto_ssl="${have_openssl_ssl}"
 | 
			
		||||
		SSL_CFLAGS="${OPENSSL_CRYPTO_CFLAGS} ${OPENSSL_SSL_CFLAGS}"
 | 
			
		||||
		SSL_LIBS="${OPENSSL_SSL_LIBS}"
 | 
			
		||||
		test "${have_openssl_engine}" = "yes" && AC_DEFINE([HAVE_OPENSSL_ENGINE], [1], [Use crypto library])
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
if test "${enable_dtls}" = "yes"; then
 | 
			
		||||
	test "${have_crypto_engine}" != "yes" && AC_MSG_ERROR([${with_ssl_library} engine is required but missing])
 | 
			
		||||
	test "${have_crypto_crypto}" != "yes" && AC_MSG_ERROR([${with_ssl_library} crypto is required but missing])
 | 
			
		||||
	test "${have_crypto_ssl}" != "yes" && AC_MSG_ERROR([${with_ssl_library} ssl is required but missing])
 | 
			
		||||
	AC_DEFINE([ENABLE_DTLS], [1], [Enable DTLS])
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Memory check
 | 
			
		||||
case "${with_mem_check}" in
 | 
			
		||||
	internal)
 | 
			
		||||
		LIBS="${LIBS} -rdynamic"
 | 
			
		||||
		AC_DEFINE([USE_INTERNAL_MEMCHECK], [1], [Use internal memory debugging])
 | 
			
		||||
		;;
 | 
			
		||||
	valgrind)
 | 
			
		||||
		AC_CHECK_HEADER(
 | 
			
		||||
			[valgrind/memcheck.h],
 | 
			
		||||
			[
 | 
			
		||||
				CFLAGS="${CFLAGS} -g -fno-inline"
 | 
			
		||||
				AC_DEFINE([USE_VALGRIND_MEMCHECK], [1], [Use valgrind memory debugging library])
 | 
			
		||||
			],
 | 
			
		||||
			[AC_MSG_ERROR([valgrind headers not found.])]
 | 
			
		||||
		)
 | 
			
		||||
		;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AM_CONDITIONAL([BUILD_AC], [test "${enable_ac}" = "yes"])
 | 
			
		||||
AM_CONDITIONAL([BUILD_WTP], [test "${enable_wtp}" = "yes"])
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
test "${enable_logging}" = "yes" && AC_DEFINE([ENABLE_LOGGING], [1], [Enable logging])
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AM_CONDITIONAL([BUILD_DEBUG], [test "${enable_debug}" = "yes"])
 | 
			
		||||
AM_CONDITIONAL([DTLS_ENABLED], [test "${enable_dtls}" = "yes"])
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AC_SUBST([SSL_CFLAGS])
 | 
			
		||||
AC_SUBST([SSL_LIBS])
 | 
			
		||||
AC_SUBST([CONFIG_LIBS])
 | 
			
		||||
AC_SUBST([PTHREAD_LIBS])
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
AC_CONFIG_FILES([
 | 
			
		||||
	Makefile
 | 
			
		||||
	build/Makefile
 | 
			
		||||
	build/ac/Makefile
 | 
			
		||||
	build/wtp/Makefile
 | 
			
		||||
])
 | 
			
		||||
 | 
			
		||||
AC_OUTPUT
 | 
			
		||||
							
								
								
									
										8683
									
								
								docs/rfc5415.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8683
									
								
								docs/rfc5415.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4259
									
								
								docs/rfc5416.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4259
									
								
								docs/rfc5416.txt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										655
									
								
								src/ac/ac.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										655
									
								
								src/ac/ac.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,655 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dtls.h"
 | 
			
		||||
 | 
			
		||||
#include <libconfig.h>
 | 
			
		||||
 | 
			
		||||
#ifndef CAPWAP_MULTITHREADING_ENABLE
 | 
			
		||||
#error "AC request multithreading\n"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct ac_t g_ac;
 | 
			
		||||
 | 
			
		||||
#define AC_STANDARD_NAME				"Unknown AC"
 | 
			
		||||
 | 
			
		||||
/* Local param */
 | 
			
		||||
static char g_configurationfile[260] = AC_DEFAULT_CONFIGURATION_FILE;
 | 
			
		||||
 | 
			
		||||
/* Alloc AC */
 | 
			
		||||
static int ac_init(void) {
 | 
			
		||||
	/* Network */
 | 
			
		||||
	capwap_network_init(&g_ac.net);
 | 
			
		||||
	g_ac.mtu = CAPWAP_MTU_DEFAULT;
 | 
			
		||||
	g_ac.binding = capwap_array_create(sizeof(unsigned short), 0);
 | 
			
		||||
	
 | 
			
		||||
	/* Standard name */
 | 
			
		||||
	strcpy(g_ac.acname.name, AC_STANDARD_NAME);
 | 
			
		||||
	
 | 
			
		||||
	/* Descriptor */
 | 
			
		||||
	g_ac.descriptor.stationlimit = AC_DEFAULT_MAXSTATION;
 | 
			
		||||
	g_ac.descriptor.wtplimit = AC_DEFAULT_MAXSESSIONS;
 | 
			
		||||
	g_ac.descriptor.security = 0;
 | 
			
		||||
	g_ac.descriptor.rmacfield = CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED;
 | 
			
		||||
	g_ac.descriptor.dtlspolicy = CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED;
 | 
			
		||||
	g_ac.descriptor.descsubelement = capwap_array_create(sizeof(struct capwap_acdescriptor_desc_subelement), 0);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	g_ac.dfa.ecn.flag = CAPWAP_LIMITED_ECN_SUPPORT;
 | 
			
		||||
	g_ac.dfa.transport.type = CAPWAP_UDP_TRANSPORT;
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	g_ac.dfa.timers.discovery = AC_DEFAULT_DISCOVERY_INTERVAL;
 | 
			
		||||
	g_ac.dfa.timers.echorequest = AC_DEFAULT_ECHO_INTERVAL;
 | 
			
		||||
	g_ac.dfa.decrypterrorreport_interval = AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL;
 | 
			
		||||
	g_ac.dfa.idletimeout.timeout = AC_DEFAULT_IDLE_TIMEOUT_INTERVAL;
 | 
			
		||||
	g_ac.dfa.wtpfallback.mode = AC_DEFAULT_WTP_FALLBACK_MODE;
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	g_ac.dfa.acipv4list = capwap_array_create(sizeof(struct capwap_acipv4list_element), 0);
 | 
			
		||||
	g_ac.dfa.acipv6list = capwap_array_create(sizeof(struct capwap_acipv6list_element), 0);
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	g_ac.dfa.rfcWaitJoin = AC_DEFAULT_WAITJOIN_INTERVAL;
 | 
			
		||||
	g_ac.dfa.rfcWaitDTLS = AC_DEFAULT_WAITDTLS_INTERVAL;
 | 
			
		||||
	g_ac.dfa.rfcChangeStatePendingTimer = AC_DEFAULT_CHANGE_STATE_PENDING_TIMER;
 | 
			
		||||
	g_ac.dfa.rfcDataCheckTimer = AC_DEFAULT_DATA_CHECK_TIMER;
 | 
			
		||||
	
 | 
			
		||||
	/* Sessions */
 | 
			
		||||
	capwap_event_init(&g_ac.changesessionlist);
 | 
			
		||||
	g_ac.sessions = capwap_list_create();
 | 
			
		||||
	capwap_lock_init(&g_ac.sessionslock);
 | 
			
		||||
	g_ac.datasessionshandshake = capwap_list_create();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Destroy AC */
 | 
			
		||||
static void ac_destroy(void) {
 | 
			
		||||
	/* Dtls */
 | 
			
		||||
	capwap_crypt_freecontext(&g_ac.dtlscontext);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	capwap_array_free(g_ac.descriptor.descsubelement);
 | 
			
		||||
	capwap_array_free(g_ac.binding);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	capwap_array_free(g_ac.dfa.acipv4list);
 | 
			
		||||
	capwap_array_free(g_ac.dfa.acipv6list);
 | 
			
		||||
	
 | 
			
		||||
	/* Sessions */
 | 
			
		||||
	capwap_list_free(g_ac.sessions);
 | 
			
		||||
	capwap_lock_destroy(&g_ac.sessionslock);
 | 
			
		||||
	capwap_event_destroy(&g_ac.changesessionlist);
 | 
			
		||||
	capwap_list_free(g_ac.datasessionshandshake);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Help */
 | 
			
		||||
static void ac_print_usage(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Parsing configuration */
 | 
			
		||||
static int ac_parsing_configuration_1_0(config_t* config) {
 | 
			
		||||
	int i;
 | 
			
		||||
	int configInt;
 | 
			
		||||
	int configIPv4;
 | 
			
		||||
	int configIPv6;
 | 
			
		||||
	long int configLongInt;
 | 
			
		||||
	const char* configString;
 | 
			
		||||
	config_setting_t* configSetting;
 | 
			
		||||
 | 
			
		||||
	/* Logging configuration */
 | 
			
		||||
	if (config_lookup_bool(config, "logging.enable", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
		if (!configInt) {
 | 
			
		||||
			capwap_logging_verboselevel(CAPWAP_LOGGING_NONE);
 | 
			
		||||
			capwap_logging_disable_allinterface();
 | 
			
		||||
		} else {
 | 
			
		||||
			if (config_lookup_string(config, "logging.level", &configString) == CONFIG_TRUE) {
 | 
			
		||||
				if (!strcmp(configString, "fatal")) {
 | 
			
		||||
					capwap_logging_verboselevel(CAPWAP_LOGGING_FATAL);
 | 
			
		||||
				} else if (!strcmp(configString, "error")) {
 | 
			
		||||
					capwap_logging_verboselevel(CAPWAP_LOGGING_ERROR);
 | 
			
		||||
				} else if (!strcmp(configString, "warning")) {
 | 
			
		||||
					capwap_logging_verboselevel(CAPWAP_LOGGING_WARNING);
 | 
			
		||||
				} else if (!strcmp(configString, "info")) {
 | 
			
		||||
					capwap_logging_verboselevel(CAPWAP_LOGGING_INFO);
 | 
			
		||||
				} else if (!strcmp(configString, "debug")) {
 | 
			
		||||
					capwap_logging_verboselevel(CAPWAP_LOGGING_DEBUG);
 | 
			
		||||
				} else {
 | 
			
		||||
					capwap_logging_error("Invalid configuration file, unknown logging.level value");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Logging output interface */
 | 
			
		||||
			configSetting = config_lookup(config, "logging.output");
 | 
			
		||||
			if (configSetting != NULL) {
 | 
			
		||||
				int count = config_setting_length(configSetting);
 | 
			
		||||
 | 
			
		||||
				/* Disable output interface */		
 | 
			
		||||
				capwap_logging_disable_allinterface();
 | 
			
		||||
 | 
			
		||||
				/* Enable selected interface */
 | 
			
		||||
				for (i = 0; i < count; i++) {
 | 
			
		||||
					config_setting_t* configElement = config_setting_get_elem(configSetting, i);
 | 
			
		||||
					if ((configElement != NULL) && (config_setting_lookup_string(configElement, "mode", &configString) == CONFIG_TRUE)) {
 | 
			
		||||
						if (!strcmp(configString, "stdout")) {
 | 
			
		||||
							capwap_logging_enable_console(0);
 | 
			
		||||
						} else if (!strcmp(configString, "stderr")) {
 | 
			
		||||
							capwap_logging_enable_console(1);
 | 
			
		||||
						} else {
 | 
			
		||||
							capwap_logging_error("Invalid configuration file, unknown logging.output value");
 | 
			
		||||
							return 0;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set name of AC */
 | 
			
		||||
	if (config_lookup_string(config, "application.name", &configString) == CONFIG_TRUE) {
 | 
			
		||||
		if (strlen(configString) > CAPWAP_ACNAME_MAXLENGTH) {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, application.name string length exceeded");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		strcpy(g_ac.acname.name, configString);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set binding of AC */
 | 
			
		||||
	configSetting = config_lookup(config, "application.binding");
 | 
			
		||||
	if (configSetting != NULL) {
 | 
			
		||||
		int count = config_setting_length(configSetting);
 | 
			
		||||
		
 | 
			
		||||
		for (i = 0; i < count; i++) {
 | 
			
		||||
			const char* bindingName = config_setting_get_string_elem(configSetting, i);
 | 
			
		||||
			if (bindingName != NULL) {
 | 
			
		||||
				unsigned short* binding = (unsigned short*)capwap_array_get_item_pointer(g_ac.binding, g_ac.binding->count);
 | 
			
		||||
 | 
			
		||||
				if (!strcmp(bindingName, "802.11")) {
 | 
			
		||||
					*binding = CAPWAP_WIRELESS_BINDING_IEEE80211;
 | 
			
		||||
				} else if (!strcmp(bindingName, "EPCGlobal")) {
 | 
			
		||||
					*binding = CAPWAP_WIRELESS_BINDING_EPCGLOBAL;
 | 
			
		||||
				} else {
 | 
			
		||||
					capwap_logging_error("Invalid configuration file, unknown application.binding value");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set max stations of AC */
 | 
			
		||||
	if (config_lookup_int(config, "application.descriptor.maxstations", &configLongInt) == CONFIG_TRUE) {
 | 
			
		||||
		if ((configLongInt > 0) && (configLongInt < 65536)) {
 | 
			
		||||
			g_ac.descriptor.stationlimit = (unsigned short)configLongInt;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, unknown application.descriptor.maxstations value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set max wtp of AC */
 | 
			
		||||
	if (config_lookup_int(config, "application.descriptor.maxwtp", &configLongInt) == CONFIG_TRUE) {
 | 
			
		||||
		if ((configLongInt > 0) && (configLongInt < 65536)) {
 | 
			
		||||
			g_ac.descriptor.wtplimit = (unsigned short)configLongInt;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, unknown application.descriptor.maxwtp value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set security of AC */
 | 
			
		||||
	if (config_lookup(config, "application.descriptor.security") != NULL) {
 | 
			
		||||
		g_ac.descriptor.security = 0;
 | 
			
		||||
		if (config_lookup_bool(config, "application.descriptor.security.presharedkey", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
			if (configInt != 0) {
 | 
			
		||||
				g_ac.descriptor.security |= CAPWAP_ACDESC_SECURITY_PRESHARED_KEY;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (config_lookup_bool(config, "application.descriptor.security.x509", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
			if (configInt != 0) {
 | 
			
		||||
				g_ac.descriptor.security |= CAPWAP_ACDESC_SECURITY_X509_CERT;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set rmacfiled of AC */
 | 
			
		||||
	if (config_lookup_bool(config, "application.descriptor.rmacfiled.supported", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
		g_ac.descriptor.rmacfield = ((configInt != 0) ? CAPWAP_ACDESC_RMACFIELD_SUPPORTED : CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set DTLS policy of AC */
 | 
			
		||||
	if (config_lookup(config, "application.descriptor.dtlspolicy") != NULL) {
 | 
			
		||||
		g_ac.descriptor.dtlspolicy = 0;
 | 
			
		||||
		if (config_lookup_bool(config, "application.descriptor.dtlspolicy.cleardatachannel", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
			if (configInt != 0) {
 | 
			
		||||
				g_ac.descriptor.dtlspolicy |= CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (config_lookup_bool(config, "application.descriptor.dtlspolicy.dtlsdatachannel", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
			if (configInt != 0) {
 | 
			
		||||
				g_ac.descriptor.dtlspolicy |= CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set info descriptor of AC */
 | 
			
		||||
	configSetting = config_lookup(config, "application.descriptor.info");
 | 
			
		||||
	if (configSetting != NULL) {
 | 
			
		||||
		int count = config_setting_length(configSetting);
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < count; i++) {
 | 
			
		||||
			config_setting_t* configElement = config_setting_get_elem(configSetting, i);
 | 
			
		||||
			if (configElement != NULL) {
 | 
			
		||||
				long int configVendor;
 | 
			
		||||
				if (config_setting_lookup_int(configElement, "idvendor", &configVendor) == CONFIG_TRUE) {
 | 
			
		||||
					const char* configType;
 | 
			
		||||
					if (config_setting_lookup_string(configElement, "type", &configType) == CONFIG_TRUE) {
 | 
			
		||||
						const char* configValue;
 | 
			
		||||
						if (config_setting_lookup_string(configElement, "value", &configValue) == CONFIG_TRUE) {
 | 
			
		||||
							int lengthValue = strlen(configValue);
 | 
			
		||||
							if (lengthValue < CAPWAP_ACDESC_SUBELEMENT_MAXDATA) {
 | 
			
		||||
								unsigned short type;
 | 
			
		||||
								struct capwap_acdescriptor_desc_subelement* desc;
 | 
			
		||||
 | 
			
		||||
								if (!strcmp(configType, "hardware")) {
 | 
			
		||||
									type = CAPWAP_ACDESC_SUBELEMENT_HARDWAREVERSION;
 | 
			
		||||
								} else if (!strcmp(configType, "software")) {
 | 
			
		||||
									type = CAPWAP_ACDESC_SUBELEMENT_SOFTWAREVERSION;
 | 
			
		||||
								} else {
 | 
			
		||||
									capwap_logging_error("Invalid configuration file, unknown application.descriptor.info.type value");
 | 
			
		||||
									return 0;
 | 
			
		||||
								}
 | 
			
		||||
 | 
			
		||||
								desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(g_ac.descriptor.descsubelement, g_ac.descriptor.descsubelement->count);
 | 
			
		||||
								desc->vendor = (unsigned long)configVendor;
 | 
			
		||||
								desc->type = type;
 | 
			
		||||
								desc->length = lengthValue;
 | 
			
		||||
								strcpy(desc->data, configValue);
 | 
			
		||||
							} else {
 | 
			
		||||
								capwap_logging_error("Invalid configuration file, application.descriptor.info.value string length exceeded");
 | 
			
		||||
								return 0;
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							capwap_logging_error("Invalid configuration file, element application.descriptor.info.value not found");
 | 
			
		||||
							return 0;
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						capwap_logging_error("Invalid configuration file, element application.descriptor.info.type not found");
 | 
			
		||||
						return 0;
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					capwap_logging_error("Invalid configuration file, element application.descriptor.info.idvendor not found");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set ECN of AC */
 | 
			
		||||
	if (config_lookup_string(config, "application.ecn", &configString) == CONFIG_TRUE) {
 | 
			
		||||
		if (!strcmp(configString, "full")) {
 | 
			
		||||
			g_ac.dfa.ecn.flag = CAPWAP_FULL_ECN_SUPPORT;
 | 
			
		||||
		} else if (!strcmp(configString, "limited")) {
 | 
			
		||||
			g_ac.dfa.ecn.flag = CAPWAP_LIMITED_ECN_SUPPORT;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, unknown application.ecn value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set Timer of AC */
 | 
			
		||||
	if (config_lookup_int(config, "application.timer.discovery", &configLongInt) == CONFIG_TRUE) {
 | 
			
		||||
		if ((configLongInt >= AC_DEFAULT_DISCOVERY_INTERVAL) && (configLongInt <= AC_MAX_DISCOVERY_INTERVAL)) {
 | 
			
		||||
			g_ac.dfa.timers.discovery = (unsigned char)configLongInt;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, invalid application.timer.discovery value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (config_lookup_int(config, "application.timer.echorequest", &configLongInt) == CONFIG_TRUE) {
 | 
			
		||||
		if ((configLongInt > 0) && (configLongInt < AC_MAX_ECHO_INTERVAL)) {
 | 
			
		||||
			g_ac.dfa.timers.echorequest = (unsigned char)configLongInt;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, invalid application.timer.echorequest value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (config_lookup_int(config, "application.timer.decrypterrorreport", &configLongInt) == CONFIG_TRUE) {
 | 
			
		||||
		if ((configLongInt > 0) && (configLongInt < 65536)) {
 | 
			
		||||
			g_ac.dfa.decrypterrorreport_interval = (unsigned short)configLongInt;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, invalid application.timer.decrypterrorreport value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (config_lookup_int(config, "application.timer.idletimeout", &configLongInt) == CONFIG_TRUE) {
 | 
			
		||||
		if (configLongInt > 0) {
 | 
			
		||||
			g_ac.dfa.idletimeout.timeout = (unsigned long)configLongInt;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, invalid application.timer.idletimeout value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set wtpfallback of AC */
 | 
			
		||||
	if (config_lookup_bool(config, "application.wtpfallback", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
		g_ac.dfa.wtpfallback.mode = ((configInt != 0) ? CAPWAP_WTP_FALLBACK_ENABLED : CAPWAP_WTP_FALLBACK_DISABLED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set DTLS of WTP */
 | 
			
		||||
	if (config_lookup_bool(config, "application.dtls.enable", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
		if (configInt != 0) {
 | 
			
		||||
			struct capwap_dtls_param dtlsparam;
 | 
			
		||||
 | 
			
		||||
			/* Init dtls param */
 | 
			
		||||
			memset(&dtlsparam, 0, sizeof(struct capwap_dtls_param));
 | 
			
		||||
			dtlsparam.type = CAPWAP_DTLS_SERVER;
 | 
			
		||||
 | 
			
		||||
			/* Set DTLS type of AC */
 | 
			
		||||
			if (config_lookup_string(config, "application.dtls.type", &configString) == CONFIG_TRUE) {
 | 
			
		||||
				if (!strcmp(configString, "x509")) {
 | 
			
		||||
					dtlsparam.mode = CAPWAP_DTLS_MODE_CERTIFICATE;
 | 
			
		||||
				} else if (!strcmp(configString, "presharedkey")) {
 | 
			
		||||
					dtlsparam.mode = CAPWAP_DTLS_MODE_PRESHAREDKEY;
 | 
			
		||||
				} else {
 | 
			
		||||
					capwap_logging_error("Invalid configuration file, unknown application.dtls.type value");
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Set DTLS configuration of AC */
 | 
			
		||||
			if (dtlsparam.mode == CAPWAP_DTLS_MODE_CERTIFICATE) {
 | 
			
		||||
				if (config_lookup_string(config, "application.dtls.x509.calist", &configString) == CONFIG_TRUE) {
 | 
			
		||||
					if (strlen(configString) > 0) {
 | 
			
		||||
						dtlsparam.cert.fileca = capwap_duplicate_string(configString);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (config_lookup_string(config, "application.dtls.x509.certificate", &configString) == CONFIG_TRUE) {
 | 
			
		||||
					if (strlen(configString) > 0) {
 | 
			
		||||
						dtlsparam.cert.filecert = capwap_duplicate_string(configString);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (config_lookup_string(config, "application.dtls.x509.privatekey", &configString) == CONFIG_TRUE) {
 | 
			
		||||
					if (strlen(configString) > 0) {
 | 
			
		||||
						dtlsparam.cert.filekey = capwap_duplicate_string(configString);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (config_lookup_string(config, "application.dtls.x509.privatekeypassword", &configString) == CONFIG_TRUE) {
 | 
			
		||||
					if (strlen(configString) > 0) {
 | 
			
		||||
						dtlsparam.cert.pwdprivatekey = capwap_duplicate_string(configString);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (dtlsparam.cert.fileca && dtlsparam.cert.filecert && dtlsparam.cert.filekey) {
 | 
			
		||||
					if (capwap_crypt_createcontext(&g_ac.dtlscontext, &dtlsparam)) {
 | 
			
		||||
						g_ac.enabledtls = 1;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/* Free dtls param */
 | 
			
		||||
				if (dtlsparam.cert.fileca) {
 | 
			
		||||
					capwap_free(dtlsparam.cert.fileca);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if (dtlsparam.cert.filecert) {
 | 
			
		||||
					capwap_free(dtlsparam.cert.filecert);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if (dtlsparam.cert.filekey) {
 | 
			
		||||
					capwap_free(dtlsparam.cert.filekey);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if (dtlsparam.cert.pwdprivatekey) {
 | 
			
		||||
					capwap_free(dtlsparam.cert.pwdprivatekey);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (!g_ac.enabledtls) {
 | 
			
		||||
					return 0;
 | 
			
		||||
				}
 | 
			
		||||
			} else if (dtlsparam.mode == CAPWAP_DTLS_MODE_PRESHAREDKEY) {
 | 
			
		||||
				/* TODO */
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set interface binding of AC */
 | 
			
		||||
	if (config_lookup_string(config, "application.network.binding", &configString) == CONFIG_TRUE) {
 | 
			
		||||
		if (strlen(configString) > (IFNAMSIZ - 1)) {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, application.network.binding string length exceeded");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}			
 | 
			
		||||
			
 | 
			
		||||
		strcpy(g_ac.net.bind_interface, configString);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set mtu of AC */
 | 
			
		||||
	if (config_lookup_int(config, "application.network.mtu", &configLongInt) == CONFIG_TRUE) {
 | 
			
		||||
		if ((configLongInt > 0) && (configLongInt < 65536)) {
 | 
			
		||||
			g_ac.mtu = (unsigned short)configLongInt;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, invalid application.network.mtu value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set transport of AC */
 | 
			
		||||
	if (config_lookup_string(config, "application.network.transport", &configString) == CONFIG_TRUE) {
 | 
			
		||||
		if (!strcmp(configString, "udp")) {
 | 
			
		||||
			g_ac.dfa.transport.type = CAPWAP_UDP_TRANSPORT;
 | 
			
		||||
		} else if (!strcmp(configString, "udplite")) {
 | 
			
		||||
			g_ac.dfa.transport.type = CAPWAP_UDPLITE_TRANSPORT;
 | 
			
		||||
		} else {
 | 
			
		||||
			capwap_logging_error("Invalid configuration file, unknown application.network.transport value");
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set ipv4 & ipv6 of AC */
 | 
			
		||||
	if (config_lookup_bool(config, "application.network.ipv4", &configIPv4) != CONFIG_TRUE) {
 | 
			
		||||
		configIPv4 = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (config_lookup_bool(config, "application.network.ipv6", &configIPv6) != CONFIG_TRUE) {
 | 
			
		||||
		configIPv6 = 1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (configIPv4 && configIPv6) {
 | 
			
		||||
		g_ac.net.sock_family = AF_UNSPEC;
 | 
			
		||||
	} else if (!configIPv4 && !configIPv6) {
 | 
			
		||||
		capwap_logging_error("Invalid configuration file, request enable application.network.ipv4 or application.network.ipv6");
 | 
			
		||||
		return 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		g_ac.net.sock_family = (configIPv4 ? AF_INET : AF_INET6);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set ip dual stack of WTP */
 | 
			
		||||
	if (config_lookup_bool(config, "application.network.ipdualstack", &configInt) == CONFIG_TRUE) {
 | 
			
		||||
		if (!configInt) {
 | 
			
		||||
			g_ac.net.bind_ctrl_flags |= CAPWAP_IPV6ONLY_FLAG;
 | 
			
		||||
			g_ac.net.bind_data_flags |= CAPWAP_IPV6ONLY_FLAG;
 | 
			
		||||
		} else {
 | 
			
		||||
			g_ac.net.bind_ctrl_flags &= ~CAPWAP_IPV6ONLY_FLAG;
 | 
			
		||||
			g_ac.net.bind_data_flags &= ~CAPWAP_IPV6ONLY_FLAG;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Parsing configuration */
 | 
			
		||||
static int ac_parsing_configuration(config_t* config) {
 | 
			
		||||
	const char* configString;
 | 
			
		||||
	
 | 
			
		||||
	if (config_lookup_string(config, "version", &configString) == CONFIG_TRUE) {
 | 
			
		||||
		if (strcmp(configString, "1.0") == 0) {
 | 
			
		||||
			return ac_parsing_configuration_1_0(config);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		capwap_logging_error("Invalid configuration file, '%s' is not supported", configString);
 | 
			
		||||
	} else {
 | 
			
		||||
		capwap_logging_error("Invalid configuration file, unable to found version tag");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Load configuration */
 | 
			
		||||
static int ac_load_configuration(int argc, char** argv) {
 | 
			
		||||
	int c;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
	config_t config;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(argc >= 0);
 | 
			
		||||
	ASSERT(argv != NULL);
 | 
			
		||||
	
 | 
			
		||||
	/* Parsing command line */
 | 
			
		||||
	opterr = 0;
 | 
			
		||||
	while ((c = getopt(argc, argv, "hc:")) != -1) {
 | 
			
		||||
		switch (c) {
 | 
			
		||||
			case 'h': {
 | 
			
		||||
				ac_print_usage();
 | 
			
		||||
				return 0;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			case 'c': {
 | 
			
		||||
				if (strlen(optarg) < sizeof(g_configurationfile)) {
 | 
			
		||||
					strcpy(g_configurationfile, optarg);
 | 
			
		||||
				} else {
 | 
			
		||||
					capwap_logging_error("Invalid -%c argument", optopt);
 | 
			
		||||
					return -1;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
				
 | 
			
		||||
			case '?': {
 | 
			
		||||
				if (optopt == 'c') {
 | 
			
		||||
					capwap_logging_error("Option -%c requires an argument", optopt);
 | 
			
		||||
				} else {
 | 
			
		||||
					capwap_logging_error("Unknown option character `\\x%x'", optopt);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				ac_print_usage();
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Init libconfig */
 | 
			
		||||
	config_init(&config);
 | 
			
		||||
 | 
			
		||||
	/* Load configuration */
 | 
			
		||||
	if (config_read_file(&config, g_configurationfile) == CONFIG_TRUE) {
 | 
			
		||||
		result = ac_parsing_configuration(&config);
 | 
			
		||||
	} else {
 | 
			
		||||
		result = -1;
 | 
			
		||||
		capwap_logging_error("Unable load the configuration file '%s': %s (%d)", g_configurationfile, config_error_text(&config), config_error_line(&config));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Free libconfig */
 | 
			
		||||
	config_destroy(&config);
 | 
			
		||||
	return result;	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Init AC */
 | 
			
		||||
static int ac_configure(void) {
 | 
			
		||||
	/* Bind to any address */
 | 
			
		||||
	if (!capwap_bind_sockets(&g_ac.net)) {
 | 
			
		||||
		capwap_logging_fatal("Cannot bind address");
 | 
			
		||||
		return AC_ERROR_NETWORK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return CAPWAP_SUCCESSFUL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Close AC */
 | 
			
		||||
static void ac_close(void) {
 | 
			
		||||
	ASSERT(g_ac.sessions->count == 0);
 | 
			
		||||
	
 | 
			
		||||
	/* Close socket */
 | 
			
		||||
	capwap_close_sockets(&g_ac.net);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check is valid binding */
 | 
			
		||||
int ac_valid_binding(unsigned short binding) {
 | 
			
		||||
	int i;
 | 
			
		||||
	
 | 
			
		||||
	for (i = 0; i < g_ac.binding->count; i++) {
 | 
			
		||||
		if (binding == *(unsigned short*)capwap_array_get_item_pointer(g_ac.binding, i)) {
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Main*/
 | 
			
		||||
int main(int argc, char** argv) {
 | 
			
		||||
	int value;
 | 
			
		||||
	int result = CAPWAP_SUCCESSFUL;
 | 
			
		||||
 | 
			
		||||
	/* Init logging */
 | 
			
		||||
	capwap_logging_init();
 | 
			
		||||
	capwap_logging_verboselevel(CAPWAP_LOGGING_ERROR);
 | 
			
		||||
	capwap_logging_enable_console(1);
 | 
			
		||||
 | 
			
		||||
	/* Init capwap */
 | 
			
		||||
	if (geteuid() != 0) {
 | 
			
		||||
		capwap_logging_fatal("Request root privileges");
 | 
			
		||||
		return CAPWAP_REQUEST_ROOT;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Init random generator */
 | 
			
		||||
	capwap_init_rand();
 | 
			
		||||
 | 
			
		||||
	/* Init crypt */
 | 
			
		||||
	if (!capwap_crypt_init()) {
 | 
			
		||||
		capwap_logging_fatal("Error to init crypt engine");
 | 
			
		||||
		return CAPWAP_CRYPT_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Alloc AC */
 | 
			
		||||
	if (!ac_init()) {
 | 
			
		||||
		return AC_ERROR_SYSTEM_FAILER;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Read configuration file */
 | 
			
		||||
	value = ac_load_configuration(argc, argv);
 | 
			
		||||
	if (value < 0) {
 | 
			
		||||
		result = AC_ERROR_LOAD_CONFIGURATION;
 | 
			
		||||
	} else if (value > 0) {
 | 
			
		||||
		/* Complete configuration AC */
 | 
			
		||||
		result = ac_configure();
 | 
			
		||||
		if (result == CAPWAP_SUCCESSFUL) {
 | 
			
		||||
			/* Running AC */
 | 
			
		||||
			result = ac_execute();
 | 
			
		||||
			ac_close();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Free memory */
 | 
			
		||||
	ac_destroy();
 | 
			
		||||
 | 
			
		||||
	/* Free crypt */
 | 
			
		||||
	capwap_crypt_free();
 | 
			
		||||
 | 
			
		||||
	/* Check memory leak */
 | 
			
		||||
	if (capwap_check_memory_leak(1)) {
 | 
			
		||||
		if (result == CAPWAP_SUCCESSFUL)
 | 
			
		||||
			result = AC_ERROR_MEMORY_LEAK;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Close logging */
 | 
			
		||||
	capwap_logging_close();
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								src/ac/ac.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/ac/ac.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
			
		||||
#ifndef __CAPWAP_AC_HEADER__
 | 
			
		||||
#define __CAPWAP_AC_HEADER__
 | 
			
		||||
 | 
			
		||||
/* standard include */
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_network.h"
 | 
			
		||||
#include "capwap_protocol.h"
 | 
			
		||||
#include "capwap_lock.h"
 | 
			
		||||
#include "capwap_list.h"
 | 
			
		||||
#include "capwap_event.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
 | 
			
		||||
/* AC Configuration */
 | 
			
		||||
#define AC_DEFAULT_CONFIGURATION_FILE		"/etc/capwap/ac.conf"
 | 
			
		||||
 | 
			
		||||
#define AC_DEFAULT_MAXSTATION				128
 | 
			
		||||
#define AC_DEFAULT_MAXSESSIONS				128
 | 
			
		||||
 | 
			
		||||
/* AC runtime error return code */
 | 
			
		||||
#define AC_ERROR_SYSTEM_FAILER				-1000
 | 
			
		||||
#define AC_ERROR_LOAD_CONFIGURATION			-1001
 | 
			
		||||
#define AC_ERROR_NETWORK					-1002
 | 
			
		||||
#define AC_ERROR_MEMORY_LEAK				1
 | 
			
		||||
 | 
			
		||||
/* Min and max dfa values */
 | 
			
		||||
#define AC_MIN_WAITDTLS_INTERVAL					30
 | 
			
		||||
#define AC_DEFAULT_WAITDTLS_INTERVAL				60
 | 
			
		||||
#define AC_MIN_WAITJOIN_INTERVAL					20
 | 
			
		||||
#define AC_DEFAULT_WAITJOIN_INTERVAL				60
 | 
			
		||||
#define AC_DEFAULT_CHANGE_STATE_PENDING_TIMER		25
 | 
			
		||||
#define AC_MIN_DISCOVERY_INTERVAL					2
 | 
			
		||||
#define AC_DEFAULT_DISCOVERY_INTERVAL				20
 | 
			
		||||
#define AC_MAX_DISCOVERY_INTERVAL					180
 | 
			
		||||
#define AC_DEFAULT_ECHO_INTERVAL					30
 | 
			
		||||
#define AC_MAX_ECHO_INTERVAL						256
 | 
			
		||||
#define AC_DEFAULT_DECRYPT_ERROR_PERIOD_INTERVAL	120
 | 
			
		||||
#define AC_DEFAULT_IDLE_TIMEOUT_INTERVAL			300
 | 
			
		||||
#define AC_DEFAULT_WTP_FALLBACK_MODE				CAPWAP_WTP_FALLBACK_ENABLED
 | 
			
		||||
#define AC_DEFAULT_DATA_CHECK_TIMER					30
 | 
			
		||||
#define AC_DEFAULT_RETRANSMIT_INTERVAL				3
 | 
			
		||||
#define AC_MAX_RETRANSMIT							5
 | 
			
		||||
#define AC_DEFAULT_DTLS_SESSION_DELETE				5
 | 
			
		||||
 | 
			
		||||
/* AC DFA */
 | 
			
		||||
struct ac_state {
 | 
			
		||||
	/* */
 | 
			
		||||
	struct capwap_ecnsupport_element ecn;
 | 
			
		||||
	struct capwap_transport_element transport;
 | 
			
		||||
 | 
			
		||||
	struct capwap_timers_element timers;
 | 
			
		||||
	unsigned short decrypterrorreport_interval;
 | 
			
		||||
	struct capwap_idletimeout_element idletimeout;
 | 
			
		||||
	struct capwap_wtpfallback_element wtpfallback;
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	capwap_acipv4list_element_array* acipv4list;
 | 
			
		||||
	capwap_acipv6list_element_array* acipv6list;
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	int rfcWaitJoin;
 | 
			
		||||
	int rfcChangeStatePendingTimer;
 | 
			
		||||
	int rfcDataCheckTimer;
 | 
			
		||||
	int rfcDTLSSessionDelete;
 | 
			
		||||
 | 
			
		||||
	/* Request retransmit */
 | 
			
		||||
	int rfcRetransmitInterval;
 | 
			
		||||
	int rfcRetransmitCount;
 | 
			
		||||
	int rfcMaxRetransmit;
 | 
			
		||||
 | 
			
		||||
	/* Dtls */
 | 
			
		||||
	int rfcWaitDTLS;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Handshake DTLS Data Channel */
 | 
			
		||||
struct ac_data_session_handshake {
 | 
			
		||||
	struct capwap_socket socket;
 | 
			
		||||
	struct sockaddr_storage acaddress;
 | 
			
		||||
	struct sockaddr_storage wtpaddress;
 | 
			
		||||
	struct capwap_dtls dtls;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* AC */
 | 
			
		||||
struct ac_t {
 | 
			
		||||
	int running;
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	struct ac_state dfa;
 | 
			
		||||
	struct capwap_network net;
 | 
			
		||||
	unsigned short mtu;
 | 
			
		||||
 | 
			
		||||
	struct capwap_array* binding;
 | 
			
		||||
 | 
			
		||||
	struct capwap_acname_element acname;
 | 
			
		||||
	struct capwap_acdescriptor_element descriptor;
 | 
			
		||||
 | 
			
		||||
	/* Sessions */
 | 
			
		||||
	capwap_event_t changesessionlist;
 | 
			
		||||
	struct capwap_list* sessions;
 | 
			
		||||
	capwap_lock_t sessionslock;
 | 
			
		||||
	struct capwap_list* datasessionshandshake;
 | 
			
		||||
 | 
			
		||||
	/* Dtls */
 | 
			
		||||
	int enabledtls;
 | 
			
		||||
	struct capwap_dtls_context dtlscontext;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct ac_t g_ac;
 | 
			
		||||
 | 
			
		||||
/* Primary thread */
 | 
			
		||||
int ac_execute(void);
 | 
			
		||||
 | 
			
		||||
int ac_valid_binding(unsigned short binding);
 | 
			
		||||
void ac_update_statistics(void);
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_AC_HEADER__ */
 | 
			
		||||
							
								
								
									
										128
									
								
								src/ac/ac_dfa_configure.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/ac/ac_dfa_configure.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	unsigned long i;
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	
 | 
			
		||||
	if (packet) {
 | 
			
		||||
		struct capwap_build_packet* buildpacket;
 | 
			
		||||
	
 | 
			
		||||
		buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
 | 
			
		||||
		if (buildpacket) {
 | 
			
		||||
			if (!capwap_build_packet_validate(buildpacket, NULL)) {
 | 
			
		||||
				unsigned short binding;
 | 
			
		||||
 | 
			
		||||
				/* */
 | 
			
		||||
				binding = GET_WBID_HEADER(&buildpacket->header);
 | 
			
		||||
				if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CONFIGURATION_STATUS_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
 | 
			
		||||
					struct capwap_element_configurationstatus_request configurationstatusrequest;
 | 
			
		||||
					
 | 
			
		||||
					/* Configuration Status request info*/
 | 
			
		||||
					capwap_init_element_configurationstatus_request(&configurationstatusrequest, binding);
 | 
			
		||||
					
 | 
			
		||||
					/* Parsing elements list */
 | 
			
		||||
					if (capwap_parsing_element_configurationstatus_request(&configurationstatusrequest, buildpacket->elementslist->first)) {
 | 
			
		||||
						struct capwap_build_packet* responsepacket;
 | 
			
		||||
 | 
			
		||||
						/* TODO: gestione richiesta */
 | 
			
		||||
 | 
			
		||||
						/* Create response */
 | 
			
		||||
						responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
 | 
			
		||||
						responsepacket->isctrlmsg = 1;
 | 
			
		||||
 | 
			
		||||
						/* Prepare configuration status response */
 | 
			
		||||
						capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CONFIGURATION_STATUS_RESPONSE, buildpacket->ctrlmsg.seq);
 | 
			
		||||
						capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TIMERS_ELEMENT(&session->dfa.timers));
 | 
			
		||||
						
 | 
			
		||||
						for (i = 0; i < configurationstatusrequest.radioadmstatus->count; i++) {
 | 
			
		||||
							struct capwap_decrypterrorreportperiod_element report;
 | 
			
		||||
							struct capwap_radioadmstate_element* radioadm = (struct capwap_radioadmstate_element*)capwap_array_get_item_pointer(configurationstatusrequest.radioadmstatus, i);
 | 
			
		||||
 | 
			
		||||
							report.radioid = radioadm->radioid;
 | 
			
		||||
							report.interval = session->dfa.decrypterrorreport_interval;
 | 
			
		||||
							capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_DECRYPTERRORREPORTPERIOD_ELEMENT(&report));
 | 
			
		||||
						}
 | 
			
		||||
						
 | 
			
		||||
						capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_IDLETIMEOUT_ELEMENT(&session->dfa.idletimeout));
 | 
			
		||||
						capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_WTPFALLBACK_ELEMENT(&session->dfa.wtpfallback));
 | 
			
		||||
 | 
			
		||||
						if (session->dfa.acipv4list->count > 0) {
 | 
			
		||||
							capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV4LIST_ELEMENT(session->dfa.acipv4list));
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						if (session->dfa.acipv6list->count > 0) {
 | 
			
		||||
							capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACIPV6LIST_ELEMENT(session->dfa.acipv6list));
 | 
			
		||||
						}
 | 
			
		||||
						
 | 
			
		||||
						/* CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT */				/* TODO */
 | 
			
		||||
						/* CAPWAP_CREATE_WTPSTATICIPADDRESS_ELEMENT */			/* TODO */
 | 
			
		||||
						/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */		/* TODO */
 | 
			
		||||
 | 
			
		||||
						if (!capwap_build_packet_validate(responsepacket, NULL)) {
 | 
			
		||||
							int result;
 | 
			
		||||
							
 | 
			
		||||
							/* Free old reference for this request */
 | 
			
		||||
							ac_free_reference_last_response(session);
 | 
			
		||||
			
 | 
			
		||||
							/* Send configuration status response to WTP */
 | 
			
		||||
							result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
 | 
			
		||||
							if (result >= 0) {
 | 
			
		||||
								if (result == 1) {
 | 
			
		||||
									session->fragmentid++;
 | 
			
		||||
								}
 | 
			
		||||
			
 | 
			
		||||
								/* Save remote sequence number */
 | 
			
		||||
								session->remoteseqnumber = buildpacket->ctrlmsg.seq;
 | 
			
		||||
								capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
 | 
			
		||||
			
 | 
			
		||||
								/* Send */
 | 
			
		||||
								for (i = 0; i < session->responsefragmentpacket->count; i++) {
 | 
			
		||||
									struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
 | 
			
		||||
									ASSERT(txpacket != NULL);
 | 
			
		||||
									
 | 
			
		||||
									if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
 | 
			
		||||
										/* Response is already created and saved. When receive a re-request, DFA autoresponse */
 | 
			
		||||
										capwap_logging_debug("Warning: error to send configuration status response packet");
 | 
			
		||||
										break;
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
 | 
			
		||||
								/* Change status */
 | 
			
		||||
								ac_dfa_change_state(session, CAPWAP_DATA_CHECK_STATE);
 | 
			
		||||
								capwap_set_timeout(session->dfa.rfcChangeStatePendingTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							capwap_logging_debug("Warning: build invalid configuration status response packet");
 | 
			
		||||
						}
 | 
			
		||||
						
 | 
			
		||||
						/* Free memory */
 | 
			
		||||
						capwap_build_packet_free(responsepacket);
 | 
			
		||||
					} 
 | 
			
		||||
					
 | 
			
		||||
					/* Free */
 | 
			
		||||
					capwap_free_element_configurationstatus_request(&configurationstatusrequest, binding);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Free */
 | 
			
		||||
			capwap_build_packet_free(buildpacket);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Configure timeout */
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
		status = AC_DFA_NO_PACKET;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	return ac_session_teardown_connection(session);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										169
									
								
								src/ac/ac_dfa_datacheck.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/ac/ac_dfa_datacheck.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,169 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	unsigned long i;
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	
 | 
			
		||||
	if (packet) {
 | 
			
		||||
		struct capwap_build_packet* buildpacket;
 | 
			
		||||
	
 | 
			
		||||
		buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
 | 
			
		||||
		if (buildpacket) {
 | 
			
		||||
			if (!capwap_build_packet_validate(buildpacket, NULL)) {
 | 
			
		||||
				unsigned short binding;
 | 
			
		||||
 | 
			
		||||
				/* */
 | 
			
		||||
				binding = GET_WBID_HEADER(&buildpacket->header);
 | 
			
		||||
				if (ac_valid_binding(binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_CHANGE_STATE_EVENT_REQUEST) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
 | 
			
		||||
					struct capwap_element_changestateevent_request changeeventrequest;
 | 
			
		||||
					
 | 
			
		||||
					/* Change event request info */
 | 
			
		||||
					capwap_init_element_changestateevent_request(&changeeventrequest, binding);
 | 
			
		||||
					
 | 
			
		||||
					/* Parsing elements list */
 | 
			
		||||
					if (capwap_parsing_element_changestateevent_request(&changeeventrequest, buildpacket->elementslist->first)) {
 | 
			
		||||
						struct capwap_build_packet* responsepacket;
 | 
			
		||||
 | 
			
		||||
						/* TODO: gestione richiesta */
 | 
			
		||||
 | 
			
		||||
						/* Create response */
 | 
			
		||||
						responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
 | 
			
		||||
						responsepacket->isctrlmsg = 1;
 | 
			
		||||
 | 
			
		||||
						/* Prepare change event response */
 | 
			
		||||
						capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_CHANGE_STATE_EVENT_RESPONSE, buildpacket->ctrlmsg.seq);
 | 
			
		||||
						/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */		/* TODO */
 | 
			
		||||
 | 
			
		||||
						if (!capwap_build_packet_validate(responsepacket, NULL)) {
 | 
			
		||||
							int result;
 | 
			
		||||
							
 | 
			
		||||
							/* Free old reference for this request */
 | 
			
		||||
							ac_free_reference_last_response(session);
 | 
			
		||||
			
 | 
			
		||||
							/* Send change event response to WTP */
 | 
			
		||||
							result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
 | 
			
		||||
							if (result >= 0) {
 | 
			
		||||
								if (result == 1) {
 | 
			
		||||
									session->fragmentid++;
 | 
			
		||||
								}
 | 
			
		||||
			
 | 
			
		||||
								/* Save remote sequence number */
 | 
			
		||||
								session->remoteseqnumber = buildpacket->ctrlmsg.seq;
 | 
			
		||||
								capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
 | 
			
		||||
			
 | 
			
		||||
								/* Send */
 | 
			
		||||
								for (i = 0; i < session->responsefragmentpacket->count; i++) {
 | 
			
		||||
									struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
 | 
			
		||||
									ASSERT(txpacket != NULL);
 | 
			
		||||
									
 | 
			
		||||
									if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
 | 
			
		||||
										/* Response is already created and saved. When receive a re-request, DFA autoresponse */
 | 
			
		||||
										capwap_logging_debug("Warning: error to send change event response packet");
 | 
			
		||||
										break;
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
 | 
			
		||||
								/* Change status */
 | 
			
		||||
								ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_RUN_STATE);
 | 
			
		||||
								capwap_set_timeout(session->dfa.rfcDataCheckTimer, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							capwap_logging_debug("Warning: build invalid configuration status response packet");
 | 
			
		||||
						}
 | 
			
		||||
						
 | 
			
		||||
						/* Free memory */
 | 
			
		||||
						capwap_build_packet_free(responsepacket);
 | 
			
		||||
					} 
 | 
			
		||||
					
 | 
			
		||||
					/* Free */
 | 
			
		||||
					capwap_free_element_changestateevent_request(&changeeventrequest, binding);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Free */
 | 
			
		||||
			capwap_build_packet_free(buildpacket);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Configure timeout */
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
		status = AC_DFA_NO_PACKET;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	
 | 
			
		||||
	if (packet) {
 | 
			
		||||
		/* Wait Data Channel Keep-Alive packet */
 | 
			
		||||
		if (!packet->socket.isctrlsocket) {
 | 
			
		||||
			struct capwap_build_packet* buildpacket;
 | 
			
		||||
		
 | 
			
		||||
			buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
 | 
			
		||||
			if (buildpacket) {
 | 
			
		||||
				struct capwap_sessionid_element sessionid;
 | 
			
		||||
				
 | 
			
		||||
				if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
 | 
			
		||||
					if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
 | 
			
		||||
						int result;
 | 
			
		||||
						capwap_fragment_packet_array* txfragpacket;
 | 
			
		||||
						
 | 
			
		||||
						/* Receive data packet keepalive, response with same packet */
 | 
			
		||||
						txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
 | 
			
		||||
						result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0);
 | 
			
		||||
						if (!result) {
 | 
			
		||||
							struct capwap_packet* txpacket;
 | 
			
		||||
							
 | 
			
		||||
							ASSERT(txfragpacket->count == 1);
 | 
			
		||||
							
 | 
			
		||||
							txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0);
 | 
			
		||||
							ASSERT(txpacket != NULL);
 | 
			
		||||
							
 | 
			
		||||
							if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) {
 | 
			
		||||
								capwap_logging_debug("Warning: error to send data channel keepalive packet");
 | 
			
		||||
								result = -1;
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					
 | 
			
		||||
						/* */
 | 
			
		||||
						capwap_fragment_free(txfragpacket);
 | 
			
		||||
						capwap_array_free(txfragpacket);
 | 
			
		||||
						
 | 
			
		||||
						if (!result) {
 | 
			
		||||
							/* Capwap handshake complete */
 | 
			
		||||
							ac_dfa_change_state(session, CAPWAP_RUN_STATE);
 | 
			
		||||
							capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
						} else {
 | 
			
		||||
							ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
							status = AC_DFA_NO_PACKET;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				/* Free */
 | 
			
		||||
				capwap_build_packet_free(buildpacket);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Configure timeout */
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
		status = AC_DFA_NO_PACKET;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	return ac_session_teardown_connection(session);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								src/ac/ac_dfa_dtls.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/ac/ac_dfa_dtls.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* DTLS BIO send */
 | 
			
		||||
int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param) {
 | 
			
		||||
	struct ac_session_t* session = (struct ac_session_t*)param;
 | 
			
		||||
	struct capwap_socket* socket = ((dtls->session == CAPWAP_DTLS_CONTROL_SESSION) ? &session->ctrlsocket : &session->datasocket);
 | 
			
		||||
	struct sockaddr_storage* wtpaddress = ((dtls->session == CAPWAP_DTLS_CONTROL_SESSION) ? &session->wtpctrladdress : &session->wtpdataaddress);
 | 
			
		||||
	struct sockaddr_storage* acaddress = ((dtls->session == CAPWAP_DTLS_CONTROL_SESSION) ? &session->acctrladdress : &session->acdataaddress);
 | 
			
		||||
	
 | 
			
		||||
	return capwap_sendto(socket->socket[socket->type], buffer, length, acaddress, wtpaddress);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(packet == NULL);
 | 
			
		||||
 | 
			
		||||
	/* Create DTLS session */
 | 
			
		||||
	if (!capwap_crypt_createsession(&session->ctrldtls, CAPWAP_DTLS_CONTROL_SESSION, &g_ac.dtlscontext, ac_bio_send, session)) {
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_DTLS_SETUP_TO_IDLE_STATE);			/* TODO */
 | 
			
		||||
		status = AC_DFA_NO_PACKET;
 | 
			
		||||
	} else {
 | 
			
		||||
		if (capwap_crypt_open(&session->ctrldtls, &session->wtpctrladdress) == CAPWAP_HANDSHAKE_ERROR) {
 | 
			
		||||
			ac_dfa_change_state(session, CAPWAP_DTLS_SETUP_TO_IDLE_STATE);		/* TODO */
 | 
			
		||||
			status = AC_DFA_NO_PACKET;
 | 
			
		||||
		} else {
 | 
			
		||||
			ac_dfa_change_state(session, CAPWAP_DTLS_CONNECT_STATE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(packet == NULL);
 | 
			
		||||
 | 
			
		||||
	ac_dfa_change_state(session, CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE);		/* TODO */
 | 
			
		||||
	return AC_DFA_NO_PACKET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	return ac_session_teardown_connection(session);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								src/ac/ac_dfa_imagedata.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/ac/ac_dfa_imagedata.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	return ac_session_teardown_connection(session);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										272
									
								
								src/ac/ac_dfa_join.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								src/ac/ac_dfa_join.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,272 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int i;
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
	struct capwap_resultcode_element resultcode = { CAPWAP_RESULTCODE_FAILURE };
 | 
			
		||||
	struct capwap_build_packet* responsepacket;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	
 | 
			
		||||
	if (packet) {
 | 
			
		||||
		struct capwap_build_packet* buildpacket;
 | 
			
		||||
	
 | 
			
		||||
		buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
 | 
			
		||||
		if (buildpacket) {
 | 
			
		||||
			int validpacket;
 | 
			
		||||
			unsigned long checkpacket;
 | 
			
		||||
			struct capwap_array* returnedmessagearray = NULL;
 | 
			
		||||
			capwap_unrecognized_element_array* unrecognizedarray;
 | 
			
		||||
			struct capwap_element_join_request joinrequest;
 | 
			
		||||
			unsigned short binding = GET_WBID_HEADER(&buildpacket->header);
 | 
			
		||||
 | 
			
		||||
			/* */
 | 
			
		||||
			unrecognizedarray = capwap_array_create(sizeof(struct unrecognized_info), 0);
 | 
			
		||||
			
 | 
			
		||||
			/* */
 | 
			
		||||
			checkpacket = capwap_build_packet_validate(buildpacket, unrecognizedarray);
 | 
			
		||||
			if (!checkpacket) {
 | 
			
		||||
				if (ac_valid_binding(binding)) {
 | 
			
		||||
					if (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_JOIN_REQUEST) {
 | 
			
		||||
						resultcode.code = CAPWAP_RESULTCODE_SUCCESS;
 | 
			
		||||
					} else {
 | 
			
		||||
						resultcode.code = CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE;
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					resultcode.code = CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED;
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				if ((checkpacket & CAPWAP_MISSING_MANDATORY_MSG_ELEMENT) != 0) {
 | 
			
		||||
					resultcode.code = CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT;
 | 
			
		||||
				} else if ((checkpacket & CAPWAP_UNRECOGNIZED_MSG_ELEMENT) != 0) {
 | 
			
		||||
					struct capwap_list_item* itemelement;
 | 
			
		||||
					
 | 
			
		||||
					resultcode.code = CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT;
 | 
			
		||||
					returnedmessagearray = capwap_array_create(sizeof(struct capwap_returnedmessage_element), unrecognizedarray->count);
 | 
			
		||||
 | 
			
		||||
					for (i = 0; i < unrecognizedarray->count; i++) {
 | 
			
		||||
						struct unrecognized_info* reasoninfo = capwap_array_get_item_pointer(unrecognizedarray, i);
 | 
			
		||||
						
 | 
			
		||||
						/* Search element */
 | 
			
		||||
						itemelement = buildpacket->elementslist->first;
 | 
			
		||||
						while (itemelement != NULL) {
 | 
			
		||||
							struct capwap_message_element* elementitem = (struct capwap_message_element*)itemelement->item;
 | 
			
		||||
							
 | 
			
		||||
							if (ntohs(elementitem->type) == reasoninfo->element) {
 | 
			
		||||
								struct capwap_returnedmessage_element* returnedelement = capwap_array_get_item_pointer(returnedmessagearray, i);
 | 
			
		||||
								unsigned short length = sizeof(struct capwap_message_element) + ntohs(elementitem->length);
 | 
			
		||||
 | 
			
		||||
								returnedelement->reason = reasoninfo->reason;
 | 
			
		||||
								returnedelement->length = min(length, CAPWAP_RETURNED_MESSAGE_MAX_LENGTH);
 | 
			
		||||
								memcpy(&returnedelement->message[0], elementitem, returnedelement->length);
 | 
			
		||||
								
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							/* Next */
 | 
			
		||||
							itemelement = itemelement->next;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* */
 | 
			
		||||
			capwap_array_free(unrecognizedarray);
 | 
			
		||||
 | 
			
		||||
			/* */
 | 
			
		||||
			capwap_init_element_join_request(&joinrequest, binding);
 | 
			
		||||
			if (resultcode.code == CAPWAP_RESULTCODE_SUCCESS) {
 | 
			
		||||
				/* Parsing elements list */
 | 
			
		||||
				if (capwap_parsing_element_join_request(&joinrequest, buildpacket->elementslist->first)) {
 | 
			
		||||
					/* TODO: gestione richiesta */
 | 
			
		||||
					
 | 
			
		||||
					/* Get sessionid */
 | 
			
		||||
					memcpy(&session->sessionid, joinrequest.sessionid, sizeof(struct capwap_sessionid_element));
 | 
			
		||||
 | 
			
		||||
					/* Get binding */
 | 
			
		||||
					session->binding = binding;
 | 
			
		||||
 | 
			
		||||
					resultcode.code = CAPWAP_RESULTCODE_SUCCESS;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			/* Create response */
 | 
			
		||||
			responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
 | 
			
		||||
			responsepacket->isctrlmsg = 1;
 | 
			
		||||
 | 
			
		||||
			/* Prepare join response */
 | 
			
		||||
			capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_JOIN_RESPONSE, buildpacket->ctrlmsg.seq);
 | 
			
		||||
			capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RESULTCODE_ELEMENT(&resultcode));
 | 
			
		||||
 | 
			
		||||
			/* Check is valid packet after parsing request */
 | 
			
		||||
			validpacket = (((resultcode.code == CAPWAP_RESULTCODE_SUCCESS) || (resultcode.code == CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED)) ? 1 : 0);
 | 
			
		||||
			if (validpacket) {
 | 
			
		||||
				struct capwap_list* controllist;
 | 
			
		||||
				struct capwap_list_item* item;
 | 
			
		||||
			
 | 
			
		||||
				/* Update statistics */
 | 
			
		||||
				ac_update_statistics();
 | 
			
		||||
				
 | 
			
		||||
				capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor));
 | 
			
		||||
				capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname));
 | 
			
		||||
 | 
			
		||||
				if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
 | 
			
		||||
					for (i = 0; i < joinrequest.binding.ieee80211.wtpradioinformation->count; i++) {
 | 
			
		||||
						struct capwap_80211_wtpradioinformation_element* radio;
 | 
			
		||||
			
 | 
			
		||||
						radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(joinrequest.binding.ieee80211.wtpradioinformation, i);
 | 
			
		||||
						capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio));
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					capwap_logging_debug("Unknown capwap binding");
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ECNSUPPORT_ELEMENT(&session->dfa.ecn));
 | 
			
		||||
 | 
			
		||||
				/* Get information from any local address */
 | 
			
		||||
				controllist = capwap_list_create();
 | 
			
		||||
				ac_get_control_information(controllist);
 | 
			
		||||
			
 | 
			
		||||
				for (item = controllist->first; item != NULL; item = item->next) {
 | 
			
		||||
					struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
 | 
			
		||||
				
 | 
			
		||||
					if (sessioncontrol->localaddress.ss_family == AF_INET) {
 | 
			
		||||
						struct capwap_controlipv4_element element;
 | 
			
		||||
						
 | 
			
		||||
						memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr));
 | 
			
		||||
						element.wtpcount = sessioncontrol->count;
 | 
			
		||||
						capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element));
 | 
			
		||||
					} else if (sessioncontrol->localaddress.ss_family == AF_INET6) {
 | 
			
		||||
						struct capwap_controlipv6_element element;
 | 
			
		||||
						
 | 
			
		||||
						memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr));
 | 
			
		||||
						element.wtpcount = sessioncontrol->count;
 | 
			
		||||
						capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			
 | 
			
		||||
				capwap_list_free(controllist);	
 | 
			
		||||
 | 
			
		||||
				if (session->acctrladdress.ss_family == AF_INET) {
 | 
			
		||||
					struct capwap_localipv4_element addr;
 | 
			
		||||
					
 | 
			
		||||
					memcpy(&addr.address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
 | 
			
		||||
					capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV4_ELEMENT(&addr));
 | 
			
		||||
				} else if (session->acctrladdress.ss_family == AF_INET6) {
 | 
			
		||||
					struct capwap_localipv6_element addr;
 | 
			
		||||
					
 | 
			
		||||
					memcpy(&addr.address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
 | 
			
		||||
					capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_LOCALIPV6_ELEMENT(&addr));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/* CAPWAP_CREATE_ACIPV4LIST_ELEMENT */				/* TODO */
 | 
			
		||||
				/* CAPWAP_CREATE_ACIPV6LIST_ELEMENT */				/* TODO */
 | 
			
		||||
				capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_TRANSPORT_ELEMENT(&session->dfa.transport));
 | 
			
		||||
				/* CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT */			/* TODO */
 | 
			
		||||
				/* CAPWAP_CREATE_MAXIMUMMESSAGELENGTH_ELEMENT */	/* TODO */
 | 
			
		||||
				/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */	/* TODO */
 | 
			
		||||
			} else if (resultcode.code == CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT) {
 | 
			
		||||
				ASSERT(returnedmessagearray != NULL);
 | 
			
		||||
 | 
			
		||||
				for (i = 0; i < returnedmessagearray->count; i++) {
 | 
			
		||||
					capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_RETURNEDMESSAGE_ELEMENT(capwap_array_get_item_pointer(returnedmessagearray, i)));
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				capwap_array_free(returnedmessagearray);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Validate packet */
 | 
			
		||||
			if (!validpacket || !capwap_build_packet_validate(responsepacket, NULL)) {
 | 
			
		||||
				int result;
 | 
			
		||||
				
 | 
			
		||||
				/* Free old reference for this request */
 | 
			
		||||
				ac_free_reference_last_response(session);
 | 
			
		||||
 | 
			
		||||
				/* Send join response to WTP */
 | 
			
		||||
				result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
 | 
			
		||||
				if (result >= 0) {
 | 
			
		||||
					if (result == 1) {
 | 
			
		||||
						session->fragmentid++;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					/* Save remote sequence number */
 | 
			
		||||
					session->remoteseqnumber = buildpacket->ctrlmsg.seq;
 | 
			
		||||
					capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
 | 
			
		||||
 | 
			
		||||
					/* Send */
 | 
			
		||||
					for (i = 0; i < session->responsefragmentpacket->count; i++) {
 | 
			
		||||
						struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
 | 
			
		||||
						ASSERT(txpacket != NULL);
 | 
			
		||||
						
 | 
			
		||||
						if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
 | 
			
		||||
							/* Response is already created and saved. When receive a re-request, DFA autoresponse */
 | 
			
		||||
							capwap_logging_debug("Warning: error to send join response packet");
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				capwap_logging_debug("Warning: build invalid join response packet");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Free memory */
 | 
			
		||||
			capwap_build_packet_free(responsepacket);
 | 
			
		||||
			capwap_free_element_join_request(&joinrequest, binding);
 | 
			
		||||
			capwap_build_packet_free(buildpacket);
 | 
			
		||||
					
 | 
			
		||||
			/* Change state */
 | 
			
		||||
			if (validpacket) {
 | 
			
		||||
				ac_dfa_change_state(session, CAPWAP_POSTJOIN_STATE);
 | 
			
		||||
			} else {
 | 
			
		||||
				ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
				status = AC_DFA_NO_PACKET;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Join timeout */
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
		status = AC_DFA_NO_PACKET;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	
 | 
			
		||||
	if (packet) {
 | 
			
		||||
		unsigned short lengthpayload;
 | 
			
		||||
 | 
			
		||||
		lengthpayload = packet->packetsize - GET_HLEN_HEADER(packet->header) * 4;
 | 
			
		||||
		if (lengthpayload >= sizeof(struct capwap_control_message)) {
 | 
			
		||||
			struct capwap_control_message* ctrlmsg = (struct capwap_control_message*)packet->payload;
 | 
			
		||||
			unsigned long type = ntohl(ctrlmsg->type);
 | 
			
		||||
 | 
			
		||||
			if (type == CAPWAP_CONFIGURATION_STATUS_REQUEST) {
 | 
			
		||||
				ac_dfa_change_state(session, CAPWAP_CONFIGURE_STATE);
 | 
			
		||||
				status = ac_dfa_state_configure(session, packet);
 | 
			
		||||
			} else if (type == CAPWAP_IMAGE_DATA_REQUEST) {
 | 
			
		||||
				ac_dfa_change_state(session, CAPWAP_IMAGE_DATA_STATE);
 | 
			
		||||
				status = ac_dfa_state_imagedata(session, packet);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Join timeout */
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
		status = AC_DFA_NO_PACKET;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	return ac_session_teardown_connection(session);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								src/ac/ac_dfa_reset.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/ac/ac_dfa_reset.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	if (packet) {
 | 
			
		||||
		if (!capwap_compare_ip(&session->wtpctrladdress, &packet->remoteaddr)) {
 | 
			
		||||
			struct capwap_build_packet* buildpacket;
 | 
			
		||||
 | 
			
		||||
			/* Parsing packet */
 | 
			
		||||
			buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
 | 
			
		||||
			if (buildpacket) {
 | 
			
		||||
				if (!capwap_build_packet_validate(buildpacket, NULL)) {
 | 
			
		||||
					unsigned short binding;
 | 
			
		||||
					
 | 
			
		||||
					/* */
 | 
			
		||||
					binding = GET_WBID_HEADER(&buildpacket->header);
 | 
			
		||||
					if ((binding == session->binding) && (ntohl(buildpacket->ctrlmsg.type) == CAPWAP_RESET_RESPONSE) && ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) {
 | 
			
		||||
						struct capwap_element_reset_response resetresponse;
 | 
			
		||||
						
 | 
			
		||||
						/* Valid packet, free request packet */
 | 
			
		||||
						ac_free_reference_last_request(session);
 | 
			
		||||
						
 | 
			
		||||
						/* Configuration status response info */
 | 
			
		||||
						capwap_init_element_reset_response(&resetresponse, binding);
 | 
			
		||||
	
 | 
			
		||||
						/* Parsing elements list */
 | 
			
		||||
						if (capwap_parsing_element_reset_response(&resetresponse, buildpacket->elementslist->first)) {
 | 
			
		||||
							ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
							status = AC_DFA_NO_PACKET;
 | 
			
		||||
						}
 | 
			
		||||
						
 | 
			
		||||
						/* Free join response */
 | 
			
		||||
						capwap_free_element_reset_response(&resetresponse, binding);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/* Free */				
 | 
			
		||||
				capwap_build_packet_free(buildpacket);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		int i;
 | 
			
		||||
		
 | 
			
		||||
		/* No Configuration status response received */
 | 
			
		||||
		session->dfa.rfcRetransmitCount++;
 | 
			
		||||
		if (session->dfa.rfcRetransmitCount >= session->dfa.rfcMaxRetransmit) {
 | 
			
		||||
			/* Timeout join state */
 | 
			
		||||
			ac_free_reference_last_request(session);
 | 
			
		||||
			ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
			status = AC_DFA_NO_PACKET;
 | 
			
		||||
		} else {
 | 
			
		||||
			/* Retransmit configuration request */	
 | 
			
		||||
			for (i = 0; i < session->requestfragmentpacket->count; i++) {
 | 
			
		||||
				struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i);
 | 
			
		||||
				ASSERT(txpacket != NULL);
 | 
			
		||||
				
 | 
			
		||||
				if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
 | 
			
		||||
					capwap_logging_debug("Warning: error to send configuration status request packet");
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
	
 | 
			
		||||
			/* Update timeout */
 | 
			
		||||
			capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	return ac_session_teardown_connection(session);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										263
									
								
								src/ac/ac_dfa_run.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								src/ac/ac_dfa_run.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,263 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int receive_echo_request(struct ac_session_t* session, struct capwap_build_packet* buildpacket, struct capwap_packet* packet) {
 | 
			
		||||
	unsigned long i;
 | 
			
		||||
	unsigned short binding;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(buildpacket != NULL);
 | 
			
		||||
	ASSERT(packet != NULL);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	binding = GET_WBID_HEADER(&buildpacket->header);
 | 
			
		||||
	if (ac_valid_binding(binding) && IS_SEQUENCE_SMALLER(session->remoteseqnumber, buildpacket->ctrlmsg.seq)) {
 | 
			
		||||
		struct capwap_element_echo_request echorequest;
 | 
			
		||||
		
 | 
			
		||||
		/* Echo request info*/
 | 
			
		||||
		capwap_init_element_echo_request(&echorequest, binding);
 | 
			
		||||
		
 | 
			
		||||
		/* Parsing elements list */
 | 
			
		||||
		if (capwap_parsing_element_echo_request(&echorequest, buildpacket->elementslist->first)) {
 | 
			
		||||
			struct capwap_build_packet* responsepacket;
 | 
			
		||||
 | 
			
		||||
			/* Create response */
 | 
			
		||||
			responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
 | 
			
		||||
			responsepacket->isctrlmsg = 1;
 | 
			
		||||
 | 
			
		||||
			/* Prepare echo response */
 | 
			
		||||
			capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_ECHO_RESPONSE, buildpacket->ctrlmsg.seq);
 | 
			
		||||
			/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */		/* TODO */
 | 
			
		||||
 | 
			
		||||
			if (!capwap_build_packet_validate(responsepacket, NULL)) {
 | 
			
		||||
				int result;
 | 
			
		||||
				
 | 
			
		||||
				/* Free old reference for this request */
 | 
			
		||||
				ac_free_reference_last_response(session);
 | 
			
		||||
 | 
			
		||||
				/* Send echo response to WTP */
 | 
			
		||||
				result = capwap_fragment_build_packet(responsepacket, session->responsefragmentpacket, session->mtu, session->fragmentid);
 | 
			
		||||
				if (result >= 0) {
 | 
			
		||||
					if (result == 1) {
 | 
			
		||||
						session->fragmentid++;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					/* Save remote sequence number */
 | 
			
		||||
					session->remoteseqnumber = buildpacket->ctrlmsg.seq;
 | 
			
		||||
					capwap_get_packet_digest((void*)packet->header, packet->packetsize, session->lastrecvpackethash);
 | 
			
		||||
 | 
			
		||||
					/* Send */
 | 
			
		||||
					for (i = 0; i < session->responsefragmentpacket->count; i++) {
 | 
			
		||||
						struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->responsefragmentpacket, i);
 | 
			
		||||
						ASSERT(txpacket != NULL);
 | 
			
		||||
						
 | 
			
		||||
						if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
 | 
			
		||||
							/* Response is already created and saved. When receive a re-request, DFA autoresponse */
 | 
			
		||||
							capwap_logging_debug("Warning: error to send echo response packet");
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			/* Free memory */
 | 
			
		||||
			capwap_build_packet_free(responsepacket);
 | 
			
		||||
		} 
 | 
			
		||||
		
 | 
			
		||||
		/* Free */
 | 
			
		||||
		capwap_free_element_echo_request(&echorequest, binding);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	if (packet) {
 | 
			
		||||
		struct capwap_build_packet* buildpacket;
 | 
			
		||||
 | 
			
		||||
		buildpacket = capwap_rx_packet_create((void*)packet->header, packet->packetsize, packet->socket.isctrlsocket);
 | 
			
		||||
		if (buildpacket) {
 | 
			
		||||
			if (!capwap_build_packet_validate(buildpacket, NULL)) {
 | 
			
		||||
				if (packet->socket.isctrlsocket) {
 | 
			
		||||
					unsigned long typemsg = ntohl(buildpacket->ctrlmsg.type);
 | 
			
		||||
					
 | 
			
		||||
					if (capwap_is_request_type(typemsg) || ((session->localseqnumber - 1) == buildpacket->ctrlmsg.seq)) {
 | 
			
		||||
						switch (typemsg) {
 | 
			
		||||
							case CAPWAP_CONFIGURATION_UPDATE_REQUEST: {
 | 
			
		||||
								/* TODO */
 | 
			
		||||
								capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							case CAPWAP_CHANGE_STATE_EVENT_RESPONSE: {
 | 
			
		||||
								/* TODO */
 | 
			
		||||
								capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							case CAPWAP_ECHO_REQUEST: {
 | 
			
		||||
								if (!receive_echo_request(session, buildpacket, packet)) {
 | 
			
		||||
									capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								} else {
 | 
			
		||||
									ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
									status = AC_DFA_NO_PACKET;
 | 
			
		||||
								}
 | 
			
		||||
								
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							case CAPWAP_CLEAR_CONFIGURATION_REQUEST: {
 | 
			
		||||
								/* TODO */
 | 
			
		||||
								capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							case CAPWAP_WTP_EVENT_RESPONSE: {
 | 
			
		||||
								/* TODO */
 | 
			
		||||
								capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							case CAPWAP_DATA_TRANSFER_REQUEST: {
 | 
			
		||||
								/* TODO */
 | 
			
		||||
								capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							case CAPWAP_DATA_TRANSFER_RESPONSE: {
 | 
			
		||||
								/* TODO */
 | 
			
		||||
								capwap_set_timeout(AC_MAX_ECHO_INTERVAL, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								break;
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					if (IS_FLAG_K_HEADER(&buildpacket->header)) {
 | 
			
		||||
						struct capwap_sessionid_element sessionid;
 | 
			
		||||
 | 
			
		||||
						if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
 | 
			
		||||
							if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
 | 
			
		||||
								int result;
 | 
			
		||||
								capwap_fragment_packet_array* txfragpacket;
 | 
			
		||||
								
 | 
			
		||||
								/* Receive data packet keepalive, response with same packet */
 | 
			
		||||
								txfragpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
 | 
			
		||||
								result = capwap_fragment_build_packet(buildpacket, txfragpacket, CAPWAP_DONT_FRAGMENT, 0);
 | 
			
		||||
								if (!result) {
 | 
			
		||||
									struct capwap_packet* txpacket;
 | 
			
		||||
									
 | 
			
		||||
									ASSERT(txfragpacket->count == 1);
 | 
			
		||||
									
 | 
			
		||||
									txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(txfragpacket, 0);
 | 
			
		||||
									ASSERT(txpacket != NULL);
 | 
			
		||||
									
 | 
			
		||||
									if (!capwap_crypt_sendto(&session->datadtls, session->datasocket.socket[session->datasocket.type], txpacket->header, txpacket->packetsize, &session->acdataaddress, &session->wtpdataaddress)) {
 | 
			
		||||
										capwap_logging_debug("Warning: error to send data channel keepalive packet");
 | 
			
		||||
										result = -1;
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
							
 | 
			
		||||
								/* */
 | 
			
		||||
								capwap_fragment_free(txfragpacket);
 | 
			
		||||
								capwap_array_free(txfragpacket);
 | 
			
		||||
								
 | 
			
		||||
								if (result) {
 | 
			
		||||
									ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
									status = AC_DFA_NO_PACKET;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						/* TODO */
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			/* Free */
 | 
			
		||||
			capwap_build_packet_free(buildpacket);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
		status = AC_DFA_NO_PACKET;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int status = AC_DFA_NO_PACKET;
 | 
			
		||||
	struct capwap_build_packet* buildpacket;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(packet == NULL);
 | 
			
		||||
 | 
			
		||||
	/* Build packet */
 | 
			
		||||
	buildpacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, session->binding);
 | 
			
		||||
	buildpacket->isctrlmsg = 1;
 | 
			
		||||
	
 | 
			
		||||
	/* Prepare reset request */
 | 
			
		||||
	capwap_build_packet_set_control_message_type(buildpacket, CAPWAP_RESET_REQUEST, session->localseqnumber++);
 | 
			
		||||
	capwap_build_packet_add_message_element(buildpacket, CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT(&session->startupimage));
 | 
			
		||||
	/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */	/* TODO */
 | 
			
		||||
 | 
			
		||||
	if (!capwap_build_packet_validate(buildpacket, NULL)) {
 | 
			
		||||
		int i;
 | 
			
		||||
		int result;
 | 
			
		||||
		
 | 
			
		||||
		/* Free old reference for this request */
 | 
			
		||||
		ac_free_reference_last_request(session);
 | 
			
		||||
 | 
			
		||||
		/* Send reset request to WTP */
 | 
			
		||||
		result = capwap_fragment_build_packet(buildpacket, session->requestfragmentpacket, session->mtu, session->fragmentid);
 | 
			
		||||
		if (result >= 0) {
 | 
			
		||||
			if (result == 1) {
 | 
			
		||||
				session->fragmentid++;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Send */
 | 
			
		||||
			for (i = 0; i < session->requestfragmentpacket->count; i++) {
 | 
			
		||||
				struct capwap_packet* txpacket = (struct capwap_packet*)capwap_array_get_item_pointer(session->requestfragmentpacket, i);
 | 
			
		||||
				ASSERT(txpacket != NULL);
 | 
			
		||||
				
 | 
			
		||||
				if (!capwap_crypt_sendto(&session->ctrldtls, session->ctrlsocket.socket[session->ctrlsocket.type], txpacket->header, txpacket->packetsize, &session->acctrladdress, &session->wtpctrladdress)) {
 | 
			
		||||
					capwap_logging_debug("Warning: error to send reset request packet");
 | 
			
		||||
					result = -1;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (result == -1) {
 | 
			
		||||
			/* Error to send packets */
 | 
			
		||||
			ac_free_reference_last_request(session);
 | 
			
		||||
			ac_dfa_change_state(session, CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE);
 | 
			
		||||
		} else {
 | 
			
		||||
			session->dfa.rfcRetransmitCount = 0;
 | 
			
		||||
 | 
			
		||||
			capwap_killall_timeout(&session->timeout);
 | 
			
		||||
			capwap_set_timeout(session->dfa.rfcRetransmitInterval, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
 | 
			
		||||
			ac_dfa_change_state(session, CAPWAP_RESET_STATE);
 | 
			
		||||
			status = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Free memory */
 | 
			
		||||
	capwap_build_packet_free(buildpacket);
 | 
			
		||||
 | 
			
		||||
	return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	return ac_session_teardown_connection(session);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/ac/ac_dfa_teardown.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/ac/ac_dfa_teardown.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(packet == NULL);
 | 
			
		||||
 | 
			
		||||
	/* Defered free resource */
 | 
			
		||||
	ac_dfa_change_state(session, CAPWAP_DEAD_STATE);
 | 
			
		||||
	return AC_DFA_DROP_PACKET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(packet == NULL);
 | 
			
		||||
 | 
			
		||||
	return AC_DFA_DEAD;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										276
									
								
								src/ac/ac_discovery.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										276
									
								
								src/ac/ac_discovery.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,276 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_protocol.h"
 | 
			
		||||
#include "ac_discovery.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
#define AC_DISCOVERY_CLEANUP_TIMEOUT					1000
 | 
			
		||||
 | 
			
		||||
struct ac_discovery_t {
 | 
			
		||||
	pthread_t threadid;
 | 
			
		||||
	int endthread;
 | 
			
		||||
	
 | 
			
		||||
	unsigned short fragmentid;
 | 
			
		||||
	unsigned char txseqnumber;
 | 
			
		||||
	
 | 
			
		||||
	capwap_event_t waitpacket;
 | 
			
		||||
	capwap_lock_t packetslock;
 | 
			
		||||
	struct capwap_list* packets;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ac_discovery_packet {
 | 
			
		||||
	int sendsock;
 | 
			
		||||
	struct sockaddr_storage sender;
 | 
			
		||||
	char data[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct ac_discovery_t g_ac_discovery;
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_discovery_start(void) {
 | 
			
		||||
	int result;
 | 
			
		||||
	
 | 
			
		||||
	memset(&g_ac_discovery, 0, sizeof(struct ac_discovery_t));
 | 
			
		||||
 | 
			
		||||
	/* Init */
 | 
			
		||||
	capwap_event_init(&g_ac_discovery.waitpacket);
 | 
			
		||||
	capwap_lock_init(&g_ac_discovery.packetslock);
 | 
			
		||||
	g_ac_discovery.packets = capwap_list_create();
 | 
			
		||||
 | 
			
		||||
	/* Create thread */
 | 
			
		||||
	result = pthread_create(&g_ac_discovery.threadid, NULL, ac_discovery_thread, NULL);
 | 
			
		||||
	if (result) {
 | 
			
		||||
		capwap_logging_debug("Unable create discovery thread");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void ac_discovery_stop(void) {
 | 
			
		||||
	void* dummy;
 | 
			
		||||
	
 | 
			
		||||
	g_ac_discovery.endthread = 1;
 | 
			
		||||
	capwap_event_signal(&g_ac_discovery.waitpacket);
 | 
			
		||||
	pthread_join(g_ac_discovery.threadid, &dummy);
 | 
			
		||||
 | 
			
		||||
	/* Free memory */
 | 
			
		||||
	capwap_event_destroy(&g_ac_discovery.waitpacket);
 | 
			
		||||
	capwap_lock_exit(&g_ac_discovery.packetslock);
 | 
			
		||||
	capwap_list_free(g_ac_discovery.packets);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void ac_discovery_add_packet(void* buffer, int buffersize, int sock, struct sockaddr_storage* sender) {
 | 
			
		||||
	struct capwap_list_item* item;
 | 
			
		||||
	struct ac_discovery_packet* packet;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(buffer != NULL);
 | 
			
		||||
	ASSERT(buffersize > 0);
 | 
			
		||||
	ASSERT(sock >= 0);
 | 
			
		||||
	ASSERT(sender != NULL);
 | 
			
		||||
	
 | 
			
		||||
	/* TODO: mettere un history delle discovery request gi<67> processate per non eseguirle di nuovo */
 | 
			
		||||
	/* L'elemento deve rimanere per la durata minima di una discovery request */
 | 
			
		||||
	
 | 
			
		||||
	/* Copy packet */
 | 
			
		||||
	item = capwap_itemlist_create(sizeof(struct ac_discovery_packet) + buffersize);
 | 
			
		||||
	packet = (struct ac_discovery_packet*)item->item;
 | 
			
		||||
	packet->sendsock = sock;
 | 
			
		||||
	memcpy(&packet->sender, sender, sizeof(struct sockaddr_storage));
 | 
			
		||||
	memcpy(packet->data, buffer, buffersize);
 | 
			
		||||
	
 | 
			
		||||
	/* Append to packets list */
 | 
			
		||||
	capwap_lock_enter(&g_ac_discovery.packetslock);
 | 
			
		||||
	capwap_itemlist_insert_after(g_ac_discovery.packets, NULL, item);
 | 
			
		||||
	capwap_event_signal(&g_ac_discovery.waitpacket);
 | 
			
		||||
	capwap_lock_exit(&g_ac_discovery.packetslock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static struct capwap_build_packet* ac_create_discovery_response(struct capwap_build_packet* packet, struct capwap_element_discovery_request* discoveryrequest, struct sockaddr_storage* sender) {
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned short binding;
 | 
			
		||||
	struct capwap_list* controllist;
 | 
			
		||||
	struct capwap_list_item* item;
 | 
			
		||||
	struct capwap_build_packet* responsepacket;
 | 
			
		||||
 | 
			
		||||
	ASSERT(packet != NULL);
 | 
			
		||||
	ASSERT(discoveryrequest != NULL);
 | 
			
		||||
	ASSERT(sender != NULL);
 | 
			
		||||
 | 
			
		||||
	/* Check is valid binding */
 | 
			
		||||
	binding = GET_WBID_HEADER(&packet->header);
 | 
			
		||||
	if (!ac_valid_binding(binding)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Build packet */
 | 
			
		||||
	responsepacket = capwap_tx_packet_create(CAPWAP_RADIOID_NONE, binding);
 | 
			
		||||
	responsepacket->isctrlmsg = 1;
 | 
			
		||||
	
 | 
			
		||||
	/* Update statistics */
 | 
			
		||||
	ac_update_statistics();
 | 
			
		||||
	
 | 
			
		||||
	/* Prepare discovery response */
 | 
			
		||||
	capwap_build_packet_set_control_message_type(responsepacket, CAPWAP_DISCOVERY_RESPONSE, packet->ctrlmsg.seq);
 | 
			
		||||
	capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(&g_ac.descriptor));
 | 
			
		||||
	capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_ACNAME_ELEMENT(&g_ac.acname));
 | 
			
		||||
 | 
			
		||||
	if (binding == CAPWAP_WIRELESS_BINDING_IEEE80211) {
 | 
			
		||||
		for (i = 0; i < discoveryrequest->binding.ieee80211.wtpradioinformation->count; i++) {
 | 
			
		||||
			struct capwap_80211_wtpradioinformation_element* radio;
 | 
			
		||||
 | 
			
		||||
			radio = (struct capwap_80211_wtpradioinformation_element*)capwap_array_get_item_pointer(discoveryrequest->binding.ieee80211.wtpradioinformation, i);
 | 
			
		||||
			capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(radio));
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		capwap_logging_debug("Unknown capwap binding");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get information from any local address */
 | 
			
		||||
	controllist = capwap_list_create();
 | 
			
		||||
	ac_get_control_information(controllist);
 | 
			
		||||
 | 
			
		||||
	for (item = controllist->first; item != NULL; item = item->next) {
 | 
			
		||||
		struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
 | 
			
		||||
	
 | 
			
		||||
		if (sessioncontrol->localaddress.ss_family == AF_INET) {
 | 
			
		||||
			struct capwap_controlipv4_element element;
 | 
			
		||||
			
 | 
			
		||||
			memcpy(&element.address, &((struct sockaddr_in*)&sessioncontrol->localaddress)->sin_addr, sizeof(struct in_addr));
 | 
			
		||||
			element.wtpcount = sessioncontrol->count;
 | 
			
		||||
			capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV4_ELEMENT(&element));
 | 
			
		||||
		} else if (sessioncontrol->localaddress.ss_family == AF_INET6) {
 | 
			
		||||
			struct capwap_controlipv6_element element;
 | 
			
		||||
			
 | 
			
		||||
			memcpy(&element.address, &((struct sockaddr_in6*)&sessioncontrol->localaddress)->sin6_addr, sizeof(struct in6_addr));
 | 
			
		||||
			element.wtpcount = sessioncontrol->count;
 | 
			
		||||
			capwap_build_packet_add_message_element(responsepacket, CAPWAP_CREATE_CONTROLIPV6_ELEMENT(&element));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	capwap_list_free(controllist);	
 | 
			
		||||
	
 | 
			
		||||
	/* CAPWAP_CREATE_VENDORSPECIFICPAYLOAD_ELEMENT */	/* TODO */
 | 
			
		||||
 | 
			
		||||
	return responsepacket;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Cleanup info discovery */
 | 
			
		||||
static void ac_discovery_cleanup(void) {
 | 
			
		||||
	/* Clean history discovery request */
 | 
			
		||||
	/* TODO */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static void ac_discovery_run(void) {
 | 
			
		||||
	int sizedata;
 | 
			
		||||
	struct capwap_list_item* itempacket;
 | 
			
		||||
	struct capwap_build_packet* buildpacket;
 | 
			
		||||
	struct ac_discovery_packet* packet;
 | 
			
		||||
	unsigned short binding;
 | 
			
		||||
	
 | 
			
		||||
	while (!g_ac_discovery.endthread) {
 | 
			
		||||
		/* Get packet */
 | 
			
		||||
		capwap_lock_enter(&g_ac_discovery.packetslock);
 | 
			
		||||
		
 | 
			
		||||
		itempacket = NULL; 
 | 
			
		||||
		if (g_ac_discovery.packets->count > 0) {
 | 
			
		||||
			itempacket = capwap_itemlist_remove_head(g_ac_discovery.packets);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		capwap_lock_exit(&g_ac_discovery.packetslock);
 | 
			
		||||
			
 | 
			
		||||
		if (!itempacket) {
 | 
			
		||||
			/* Wait packet with timeout*/
 | 
			
		||||
			if (!capwap_event_wait_timeout(&g_ac_discovery.waitpacket, AC_DISCOVERY_CLEANUP_TIMEOUT)) {
 | 
			
		||||
				ac_discovery_cleanup();
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* */
 | 
			
		||||
		packet = (struct ac_discovery_packet*)itempacket->item;
 | 
			
		||||
		sizedata = itempacket->itemsize - sizeof(struct ac_discovery_packet);
 | 
			
		||||
 | 
			
		||||
		/* Parsing packet */
 | 
			
		||||
		buildpacket = capwap_rx_packet_create(packet->data, sizedata, 1);
 | 
			
		||||
		if (buildpacket) {
 | 
			
		||||
			if (!capwap_build_packet_validate(buildpacket, NULL)) {
 | 
			
		||||
				struct capwap_element_discovery_request discoveryrequest;
 | 
			
		||||
				
 | 
			
		||||
				/* */
 | 
			
		||||
				binding = GET_WBID_HEADER(&buildpacket->header);
 | 
			
		||||
				capwap_init_element_discovery_request(&discoveryrequest, binding);
 | 
			
		||||
				
 | 
			
		||||
				/* Parsing elements list */
 | 
			
		||||
				if (capwap_parsing_element_discovery_request(&discoveryrequest, buildpacket->elementslist->first)) {
 | 
			
		||||
					struct capwap_build_packet* txpacket;
 | 
			
		||||
					capwap_fragment_packet_array* responsefragmentpacket = NULL;
 | 
			
		||||
 | 
			
		||||
					/* Creare discovery response */
 | 
			
		||||
					txpacket = ac_create_discovery_response(buildpacket, &discoveryrequest, &packet->sender);
 | 
			
		||||
					if (txpacket) {
 | 
			
		||||
						int result = -1;
 | 
			
		||||
						
 | 
			
		||||
						if (!capwap_build_packet_validate(txpacket, NULL)) {
 | 
			
		||||
							responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
 | 
			
		||||
							result = capwap_fragment_build_packet(txpacket, responsefragmentpacket, g_ac.mtu, g_ac_discovery.fragmentid);
 | 
			
		||||
							if (result == 1) {
 | 
			
		||||
								g_ac_discovery.fragmentid++;
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							capwap_logging_debug("Warning: build invalid discovery response packet");
 | 
			
		||||
						}
 | 
			
		||||
		
 | 
			
		||||
						capwap_build_packet_free(txpacket);
 | 
			
		||||
	
 | 
			
		||||
						/* Send discovery response to WTP */
 | 
			
		||||
						if (result >= 0) {
 | 
			
		||||
							int i;
 | 
			
		||||
				
 | 
			
		||||
							for (i = 0; i < responsefragmentpacket->count; i++) {
 | 
			
		||||
								struct capwap_packet* sendpacket = (struct capwap_packet*)capwap_array_get_item_pointer(responsefragmentpacket, i);
 | 
			
		||||
								ASSERT(sendpacket != NULL);
 | 
			
		||||
								
 | 
			
		||||
								if (!capwap_sendto(packet->sendsock, sendpacket->header, sendpacket->packetsize, NULL, &packet->sender)) {
 | 
			
		||||
									capwap_logging_debug("Warning: error to send discovery response packet");
 | 
			
		||||
									break;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					
 | 
			
		||||
					/* Don't buffering a packets sent */
 | 
			
		||||
					if (responsefragmentpacket) {
 | 
			
		||||
						capwap_fragment_free(responsefragmentpacket);
 | 
			
		||||
						capwap_array_free(responsefragmentpacket);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				/* Free discovery request */
 | 
			
		||||
				capwap_free_element_discovery_request(&discoveryrequest, binding);
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			/* */
 | 
			
		||||
			capwap_build_packet_free(buildpacket);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Free packet */
 | 
			
		||||
		capwap_itemlist_free(itempacket);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* ac_discovery_thread(void* param) {
 | 
			
		||||
	
 | 
			
		||||
	capwap_logging_debug("Discovery start");
 | 
			
		||||
	ac_discovery_run();
 | 
			
		||||
	capwap_logging_debug("Discovery stop");
 | 
			
		||||
 | 
			
		||||
	/* Thread exit */
 | 
			
		||||
	pthread_exit(NULL);
 | 
			
		||||
	return NULL;	
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/ac/ac_discovery.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/ac/ac_discovery.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
#ifndef __AC_DISCOVERY_HEADER__
 | 
			
		||||
#define __AC_DISCOVERY_HEADER__
 | 
			
		||||
 | 
			
		||||
void* ac_discovery_thread(void* param);
 | 
			
		||||
 | 
			
		||||
int ac_discovery_start(void);
 | 
			
		||||
void ac_discovery_stop(void);
 | 
			
		||||
void ac_discovery_add_packet(void* buffer, int buffersize, int sock, struct sockaddr_storage* sender);
 | 
			
		||||
 | 
			
		||||
#endif /* __AC_DISCOVERY_HEADER__ */
 | 
			
		||||
							
								
								
									
										532
									
								
								src/ac/ac_execute.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										532
									
								
								src/ac/ac_execute.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,532 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "capwap_event.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
#include "ac_discovery.h"
 | 
			
		||||
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
 | 
			
		||||
/* Add packet to session */
 | 
			
		||||
static void ac_session_add_packet(struct ac_session_t* session, char* buffer, int size, int isctrlsocket, int plainbuffer) {
 | 
			
		||||
	struct capwap_list_item* item;
 | 
			
		||||
	struct ac_packet* packet;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(buffer != NULL);
 | 
			
		||||
	ASSERT(size > 0);
 | 
			
		||||
 | 
			
		||||
	/* Copy packet */
 | 
			
		||||
	item = capwap_itemlist_create(sizeof(struct ac_packet) + size);
 | 
			
		||||
	packet = (struct ac_packet*)item->item;
 | 
			
		||||
	packet->plainbuffer = plainbuffer;
 | 
			
		||||
	memcpy(packet->buffer, buffer, size);
 | 
			
		||||
	
 | 
			
		||||
	/* Append to packets list */
 | 
			
		||||
	capwap_lock_enter(&session->packetslock);
 | 
			
		||||
	capwap_itemlist_insert_after((isctrlsocket ? session->controlpackets : session->datapackets), NULL, item);
 | 
			
		||||
	capwap_event_signal(&session->waitpacket);
 | 
			
		||||
	capwap_lock_exit(&session->packetslock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find AC sessions */
 | 
			
		||||
static struct ac_session_t* ac_search_session_from_wtpaddress(struct sockaddr_storage* address, int isctrlsocket) {
 | 
			
		||||
	struct ac_session_t* result = NULL;
 | 
			
		||||
	struct capwap_list_item* search;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(address != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
	
 | 
			
		||||
	search = g_ac.sessions->first;
 | 
			
		||||
	while (search != NULL) {
 | 
			
		||||
		struct ac_session_t* session = (struct ac_session_t*)search->item;
 | 
			
		||||
		ASSERT(session != NULL);
 | 
			
		||||
		
 | 
			
		||||
		if (!capwap_compare_ip(address, (isctrlsocket ? &session->wtpctrladdress : &session->wtpdataaddress))) {
 | 
			
		||||
			session->count++;
 | 
			
		||||
			result = session;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	
 | 
			
		||||
		search = search->next;	
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
	
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static struct ac_session_t* ac_get_session_from_keepalive(void* buffer, int buffersize) {
 | 
			
		||||
	struct ac_session_t* result = NULL;
 | 
			
		||||
	struct capwap_build_packet* buildpacket;
 | 
			
		||||
 | 
			
		||||
	ASSERT(buffer != NULL);
 | 
			
		||||
	ASSERT(buffersize > 0);
 | 
			
		||||
 | 
			
		||||
	buildpacket = capwap_rx_packet_create(buffer, buffersize, 0);
 | 
			
		||||
	if (buildpacket) {
 | 
			
		||||
		struct capwap_sessionid_element sessionid;
 | 
			
		||||
		
 | 
			
		||||
		if (capwap_get_sessionid_from_keepalive(buildpacket, &sessionid)) {
 | 
			
		||||
			struct capwap_list_item* search;
 | 
			
		||||
 | 
			
		||||
			capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
			
 | 
			
		||||
			search = g_ac.sessions->first;
 | 
			
		||||
			while (search != NULL) {
 | 
			
		||||
				struct ac_session_t* session = (struct ac_session_t*)search->item;
 | 
			
		||||
				ASSERT(session != NULL);
 | 
			
		||||
				
 | 
			
		||||
				if (!memcmp(&sessionid, &session->sessionid, sizeof(struct capwap_sessionid_element))) {
 | 
			
		||||
					session->count++;
 | 
			
		||||
					result = session;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				search = search->next;	
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Free */
 | 
			
		||||
		capwap_build_packet_free(buildpacket);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return result;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Close session */
 | 
			
		||||
static void ac_close_session(struct ac_session_t* session) {
 | 
			
		||||
	session->closesession = 1;
 | 
			
		||||
	capwap_event_signal(&session->waitpacket);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Close sessions */
 | 
			
		||||
static void ac_close_sessions() {
 | 
			
		||||
	struct capwap_list_item* search;
 | 
			
		||||
 | 
			
		||||
	capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
 | 
			
		||||
	search = g_ac.sessions->first;
 | 
			
		||||
	while (search != NULL) {
 | 
			
		||||
		struct ac_session_t* session = (struct ac_session_t*)search->item;
 | 
			
		||||
		ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
		ac_close_session(session);
 | 
			
		||||
 | 
			
		||||
		search = search->next;	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* DTLS Handshake BIO send */
 | 
			
		||||
static int ac_bio_handshake_send(struct capwap_dtls* dtls, char* buffer, int length, void* param) {
 | 
			
		||||
	struct ac_data_session_handshake* handshake = (struct ac_data_session_handshake*)param;
 | 
			
		||||
	return capwap_sendto(handshake->socket.socket[handshake->socket.type], buffer, length, &handshake->acaddress, &handshake->wtpaddress);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find AC sessions */
 | 
			
		||||
static void ac_update_session_from_datapacket(struct capwap_socket* socket, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, void* buffer, int buffersize) {
 | 
			
		||||
	struct ac_session_t* session = NULL;
 | 
			
		||||
	struct capwap_preamble* preamble = (struct capwap_preamble*)buffer;
 | 
			
		||||
 | 
			
		||||
	ASSERT(buffer != NULL);
 | 
			
		||||
	ASSERT(buffersize > sizeof(struct capwap_preamble));
 | 
			
		||||
	ASSERT(socket != NULL);
 | 
			
		||||
	ASSERT(recvfromaddr != NULL);
 | 
			
		||||
	ASSERT(recvtoaddr != NULL);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	if (preamble->type == CAPWAP_PREAMBLE_HEADER) {
 | 
			
		||||
		if ((g_ac.descriptor.dtlspolicy & CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED) != 0) {
 | 
			
		||||
			session = ac_get_session_from_keepalive(buffer, buffersize);
 | 
			
		||||
			if (session) {
 | 
			
		||||
				/* Update data session */
 | 
			
		||||
				memcpy(&session->datasocket, socket, sizeof(struct capwap_socket));
 | 
			
		||||
				memcpy(&session->acdataaddress, recvtoaddr, sizeof(struct sockaddr_storage));
 | 
			
		||||
				memcpy(&session->wtpdataaddress, recvfromaddr, sizeof(struct sockaddr_storage));
 | 
			
		||||
	
 | 
			
		||||
				/* Add packet*/
 | 
			
		||||
				ac_session_add_packet(session, buffer, buffersize, 0, 1);
 | 
			
		||||
				ac_session_release_reference(session);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else if (preamble->type == CAPWAP_PREAMBLE_DTLS_HEADER) {
 | 
			
		||||
		if ((g_ac.descriptor.dtlspolicy & CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED) != 0) {
 | 
			
		||||
			struct capwap_list_item* itemlist;
 | 
			
		||||
			struct ac_data_session_handshake* handshake;
 | 
			
		||||
			
 | 
			
		||||
			/* Search active data dtls handshake */
 | 
			
		||||
			itemlist = g_ac.datasessionshandshake->first;
 | 
			
		||||
			while (itemlist != NULL) {
 | 
			
		||||
				handshake = (struct ac_data_session_handshake*)itemlist->item;
 | 
			
		||||
				
 | 
			
		||||
				if (!capwap_compare_ip(recvfromaddr, &handshake->wtpaddress) && !capwap_compare_ip(recvtoaddr, &handshake->acaddress)) {
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				/* Next */
 | 
			
		||||
				itemlist = itemlist->next;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			/* Create new DTLS handshake */
 | 
			
		||||
			if (!itemlist) {
 | 
			
		||||
				itemlist = capwap_itemlist_create(sizeof(struct ac_data_session_handshake));
 | 
			
		||||
				handshake = (struct ac_data_session_handshake*)itemlist->item;
 | 
			
		||||
				memset(handshake, 0, sizeof(struct ac_data_session_handshake));
 | 
			
		||||
				
 | 
			
		||||
				/* */
 | 
			
		||||
				memcpy(&handshake->socket, socket, sizeof(struct capwap_socket));
 | 
			
		||||
				memcpy(&handshake->acaddress, recvtoaddr, sizeof(struct sockaddr_storage));
 | 
			
		||||
				memcpy(&handshake->wtpaddress, recvfromaddr, sizeof(struct sockaddr_storage));
 | 
			
		||||
 | 
			
		||||
				/* Create DTLS session */
 | 
			
		||||
				if (!capwap_crypt_createsession(&handshake->dtls, CAPWAP_DTLS_DATA_SESSION, &g_ac.dtlscontext, ac_bio_handshake_send, handshake)) {
 | 
			
		||||
					capwap_itemlist_free(itemlist);
 | 
			
		||||
					itemlist = NULL;
 | 
			
		||||
				} else {
 | 
			
		||||
					if (capwap_crypt_open(&handshake->dtls, recvfromaddr) == CAPWAP_HANDSHAKE_ERROR) {
 | 
			
		||||
						capwap_crypt_freesession(&handshake->dtls);
 | 
			
		||||
						capwap_itemlist_free(itemlist);
 | 
			
		||||
						itemlist = NULL;
 | 
			
		||||
					} else {
 | 
			
		||||
						/* Add item to list */
 | 
			
		||||
						capwap_itemlist_insert_after(g_ac.datasessionshandshake, NULL, itemlist);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			/* Decrypt packet */
 | 
			
		||||
			if (itemlist) {
 | 
			
		||||
				char temp[CAPWAP_MAX_PACKET_SIZE];
 | 
			
		||||
 | 
			
		||||
				/* */
 | 
			
		||||
				handshake = (struct ac_data_session_handshake*)itemlist->item;
 | 
			
		||||
				buffersize = capwap_decrypt_packet(&handshake->dtls, buffer, buffersize, temp, CAPWAP_MAX_PACKET_SIZE);
 | 
			
		||||
				if (buffersize > 0) {
 | 
			
		||||
					session = ac_get_session_from_keepalive(temp, buffersize);
 | 
			
		||||
					if (!session) {
 | 
			
		||||
						capwap_itemlist_remove(g_ac.datasessionshandshake, itemlist);
 | 
			
		||||
						capwap_crypt_close(&handshake->dtls);
 | 
			
		||||
						capwap_crypt_freesession(&handshake->dtls);
 | 
			
		||||
						capwap_itemlist_free(itemlist);
 | 
			
		||||
					} else {
 | 
			
		||||
						/* Update DTLS session */
 | 
			
		||||
						capwap_crypt_change_dtls(&handshake->dtls, &session->datadtls);
 | 
			
		||||
						memcpy(&session->datasocket, &handshake->socket, sizeof(struct capwap_socket));
 | 
			
		||||
						memcpy(&session->acdataaddress, &handshake->acaddress, sizeof(struct sockaddr_storage));
 | 
			
		||||
						memcpy(&session->wtpdataaddress, &handshake->wtpaddress, sizeof(struct sockaddr_storage));
 | 
			
		||||
						capwap_crypt_change_bio_send(&session->datadtls, ac_bio_send, session);
 | 
			
		||||
 | 
			
		||||
						/* Remove temp element */
 | 
			
		||||
						capwap_itemlist_remove(g_ac.datasessionshandshake, itemlist);
 | 
			
		||||
						capwap_itemlist_free(itemlist);
 | 
			
		||||
 | 
			
		||||
						/* Add packet*/
 | 
			
		||||
						ac_session_add_packet(session, temp, buffersize, 0, 1);		/* Packet already decrypt */
 | 
			
		||||
						ac_session_release_reference(session);
 | 
			
		||||
					}
 | 
			
		||||
				} else if ((buffersize == CAPWAP_ERROR_SHUTDOWN) || (buffersize == CAPWAP_ERROR_CLOSE)) {
 | 
			
		||||
					capwap_itemlist_remove(g_ac.datasessionshandshake, itemlist);
 | 
			
		||||
					capwap_crypt_close(&handshake->dtls);
 | 
			
		||||
					capwap_crypt_freesession(&handshake->dtls);
 | 
			
		||||
					capwap_itemlist_free(itemlist);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Create new session */
 | 
			
		||||
static struct ac_session_t* ac_create_session(struct sockaddr_storage* wtpaddress, struct sockaddr_storage* acaddress, struct capwap_socket* ctrlsock) {
 | 
			
		||||
	int result;
 | 
			
		||||
	struct capwap_list_item* itemlist;
 | 
			
		||||
	struct ac_session_t* session;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(acaddress != NULL);
 | 
			
		||||
	ASSERT(wtpaddress != NULL);
 | 
			
		||||
	ASSERT(ctrlsock != NULL);
 | 
			
		||||
 | 
			
		||||
	/* Create new session */
 | 
			
		||||
	itemlist = capwap_itemlist_create(sizeof(struct ac_session_t));
 | 
			
		||||
	session = (struct ac_session_t*)itemlist->item;
 | 
			
		||||
	memset(session, 0, sizeof(struct ac_session_t));
 | 
			
		||||
 | 
			
		||||
	session->count = 2;
 | 
			
		||||
	memcpy(&session->acctrladdress, acaddress, sizeof(struct sockaddr_storage));
 | 
			
		||||
	memcpy(&session->wtpctrladdress, wtpaddress, sizeof(struct sockaddr_storage));
 | 
			
		||||
	memcpy(&session->ctrlsocket, ctrlsock, sizeof(struct capwap_socket));
 | 
			
		||||
	
 | 
			
		||||
	/* Duplicate state for DFA */
 | 
			
		||||
	memcpy(&session->dfa, &g_ac.dfa, sizeof(struct ac_state));
 | 
			
		||||
	session->dfa.acipv4list = capwap_array_clone(g_ac.dfa.acipv4list);
 | 
			
		||||
	session->dfa.acipv6list = capwap_array_clone(g_ac.dfa.acipv6list);
 | 
			
		||||
 | 
			
		||||
	session->dfa.rfcRetransmitInterval = AC_DEFAULT_RETRANSMIT_INTERVAL;
 | 
			
		||||
	session->dfa.rfcMaxRetransmit = AC_MAX_RETRANSMIT;
 | 
			
		||||
	session->dfa.rfcDTLSSessionDelete = AC_DEFAULT_DTLS_SESSION_DELETE;
 | 
			
		||||
 | 
			
		||||
	/* Add default AC list if empty*/
 | 
			
		||||
	if ((session->dfa.acipv4list->count == 0) && (session->dfa.acipv6list->count == 0)) {
 | 
			
		||||
		if (session->acctrladdress.ss_family == AF_INET) {
 | 
			
		||||
			struct capwap_acipv4list_element* acip = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(session->dfa.acipv4list, 0);
 | 
			
		||||
			memcpy(&acip->address, &((struct sockaddr_in*)&session->acctrladdress)->sin_addr, sizeof(struct in_addr));
 | 
			
		||||
		} else if (session->acctrladdress.ss_family == AF_INET6) {
 | 
			
		||||
			struct capwap_acipv6list_element* acip = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(session->dfa.acipv6list, 0);
 | 
			
		||||
			memcpy(&acip->address, &((struct sockaddr_in6*)&session->acctrladdress)->sin6_addr, sizeof(struct in6_addr));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Init */
 | 
			
		||||
	capwap_event_init(&session->waitpacket);
 | 
			
		||||
	capwap_lock_init(&session->packetslock);
 | 
			
		||||
 | 
			
		||||
	session->controlpackets = capwap_list_create();
 | 
			
		||||
	session->datapackets = capwap_list_create();
 | 
			
		||||
	session->requestfragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
 | 
			
		||||
	session->responsefragmentpacket = capwap_array_create(sizeof(struct capwap_packet), 0);
 | 
			
		||||
	session->rxfragmentpacket = capwap_defragment_init_list();
 | 
			
		||||
	
 | 
			
		||||
	session->mtu = g_ac.mtu;
 | 
			
		||||
	session->state = CAPWAP_IDLE_STATE;
 | 
			
		||||
	
 | 
			
		||||
	/* Update session list */
 | 
			
		||||
	capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
	capwap_itemlist_insert_after(g_ac.sessions, NULL, itemlist);
 | 
			
		||||
	capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
 | 
			
		||||
	/* Create thread */
 | 
			
		||||
	result = pthread_create(&session->threadid, NULL, ac_session_thread, (void*)session);
 | 
			
		||||
	if (!result) {
 | 
			
		||||
		pthread_detach(session->threadid);
 | 
			
		||||
 | 
			
		||||
		/* Notify change session list */
 | 
			
		||||
		capwap_event_signal(&g_ac.changesessionlist);
 | 
			
		||||
	} else {
 | 
			
		||||
		capwap_logging_debug("Unable create session thread, error code %d", result);
 | 
			
		||||
		
 | 
			
		||||
		/* Destroy element */
 | 
			
		||||
		capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
		capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessions, itemlist));
 | 
			
		||||
		capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
		
 | 
			
		||||
		session = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return session;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Update statistics */
 | 
			
		||||
void ac_update_statistics(void) {
 | 
			
		||||
	
 | 
			
		||||
	g_ac.descriptor.station = 0; /* TODO */
 | 
			
		||||
	
 | 
			
		||||
	capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
	g_ac.descriptor.wtp = g_ac.sessions->count;
 | 
			
		||||
	capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Handler signal */
 | 
			
		||||
static void ac_signal_handler(int signum) {
 | 
			
		||||
	if ((signum == SIGINT) || (signum == SIGTERM)) {
 | 
			
		||||
		g_ac.running = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* AC running */
 | 
			
		||||
int ac_execute(void) {
 | 
			
		||||
	int fdscount = CAPWAP_MAX_SOCKETS * 2;
 | 
			
		||||
	struct pollfd* fds;
 | 
			
		||||
	int result = CAPWAP_SUCCESSFUL;
 | 
			
		||||
	
 | 
			
		||||
	int index;
 | 
			
		||||
	int check;				
 | 
			
		||||
	int isctrlsocket = 0;
 | 
			
		||||
	struct sockaddr_storage recvfromaddr;
 | 
			
		||||
	struct sockaddr_storage recvtoaddr;
 | 
			
		||||
	int isrecvpacket = 0;
 | 
			
		||||
 | 
			
		||||
	struct ac_session_t* session;
 | 
			
		||||
	struct capwap_socket ctrlsock;
 | 
			
		||||
 | 
			
		||||
	char buffer[CAPWAP_MAX_PACKET_SIZE];
 | 
			
		||||
	int buffersize;
 | 
			
		||||
 | 
			
		||||
	/* Configure poll struct */
 | 
			
		||||
	fds = (struct pollfd*)capwap_alloc(sizeof(struct pollfd) * fdscount);
 | 
			
		||||
	if (!fds) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Retrive all socket for polling */
 | 
			
		||||
	fdscount = capwap_network_set_pollfd(&g_ac.net, fds, fdscount);
 | 
			
		||||
	ASSERT(fdscount > 0);
 | 
			
		||||
 | 
			
		||||
	/* Handler signal */
 | 
			
		||||
	g_ac.running = 1;
 | 
			
		||||
	signal(SIGINT, ac_signal_handler);
 | 
			
		||||
	signal(SIGTERM, ac_signal_handler);
 | 
			
		||||
 | 
			
		||||
	/* Start discovery thread */
 | 
			
		||||
	if (!ac_discovery_start()) {
 | 
			
		||||
		capwap_free(fds);
 | 
			
		||||
		capwap_logging_debug("Unable to start discovery thread");
 | 
			
		||||
		return AC_ERROR_SYSTEM_FAILER;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		/* Receive packet */
 | 
			
		||||
		isrecvpacket = 0;
 | 
			
		||||
		buffersize = sizeof(buffer);
 | 
			
		||||
		index = capwap_recvfrom(fds, fdscount, buffer, &buffersize, &recvfromaddr, &recvtoaddr, NULL);
 | 
			
		||||
		if (!g_ac.running) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* */
 | 
			
		||||
		if (index >= 0) {
 | 
			
		||||
			/* Detect local address */
 | 
			
		||||
			if (recvtoaddr.ss_family == AF_UNSPEC) {
 | 
			
		||||
				if (capwap_get_localaddress_by_remoteaddress(&recvtoaddr, &recvfromaddr, g_ac.net.bind_interface, (!(g_ac.net.bind_ctrl_flags & CAPWAP_IPV6ONLY_FLAG) ? 1 : 0))) {
 | 
			
		||||
					struct sockaddr_storage sockinfo;
 | 
			
		||||
					socklen_t sockinfolen = sizeof(struct sockaddr_storage);
 | 
			
		||||
 | 
			
		||||
					memset(&sockinfo, 0, sizeof(struct sockaddr_storage));
 | 
			
		||||
					if (getsockname(fds[index].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) {
 | 
			
		||||
						break; 
 | 
			
		||||
					}
 | 
			
		||||
					
 | 
			
		||||
					CAPWAP_SET_NETWORK_PORT(&recvtoaddr, CAPWAP_GET_NETWORK_PORT(&sockinfo));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			/* Search the AC session */
 | 
			
		||||
			isctrlsocket = ((index < (fdscount / 2)) ? 1 : 0);
 | 
			
		||||
			session = ac_search_session_from_wtpaddress(&recvfromaddr, isctrlsocket);
 | 
			
		||||
			
 | 
			
		||||
			if (session) {
 | 
			
		||||
				/* Add packet*/
 | 
			
		||||
				ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 0);
 | 
			
		||||
 | 
			
		||||
				/* Release reference */
 | 
			
		||||
				ac_session_release_reference(session);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (isctrlsocket) {
 | 
			
		||||
					unsigned short sessioncount;
 | 
			
		||||
			
 | 
			
		||||
					/* Get current session number */
 | 
			
		||||
					capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
					sessioncount = g_ac.sessions->count;
 | 
			
		||||
					capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
					
 | 
			
		||||
					/* PreParsing packet for reduce a DoS attack */
 | 
			
		||||
					check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, buffersize, g_ac.enabledtls, 0);
 | 
			
		||||
					if (check == CAPWAP_PLAIN_PACKET) {
 | 
			
		||||
						struct capwap_header* header = (struct capwap_header*)buffer;
 | 
			
		||||
						
 | 
			
		||||
						/* Accepted only packet without fragmentation */
 | 
			
		||||
						if (!IS_FLAG_F_HEADER(header)) {
 | 
			
		||||
							int headersize = GET_HLEN_HEADER(header) * 4;
 | 
			
		||||
							if (buffersize >= (headersize + sizeof(struct capwap_control_message))) {
 | 
			
		||||
								struct capwap_control_message* control = (struct capwap_control_message*)((char*)buffer + headersize);
 | 
			
		||||
								unsigned long type = ntohl(control->type);
 | 
			
		||||
								
 | 
			
		||||
								if (type == CAPWAP_DISCOVERY_REQUEST) {
 | 
			
		||||
									if (sessioncount < g_ac.descriptor.wtplimit) {
 | 
			
		||||
										ac_discovery_add_packet(buffer, buffersize, fds[index].fd, &recvfromaddr);
 | 
			
		||||
									}
 | 
			
		||||
								} else if (!g_ac.enabledtls && (type == CAPWAP_JOIN_REQUEST)) {
 | 
			
		||||
									if (sessioncount < g_ac.descriptor.wtplimit) {
 | 
			
		||||
										/* Retrive socket info */
 | 
			
		||||
										capwap_get_network_socket(&g_ac.net, &ctrlsock, fds[index].fd);
 | 
			
		||||
										
 | 
			
		||||
										/* Create a new session */
 | 
			
		||||
										session = ac_create_session(&recvfromaddr, &recvtoaddr, &ctrlsock);
 | 
			
		||||
										if (session) {
 | 
			
		||||
											ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 1);
 | 
			
		||||
									
 | 
			
		||||
											/* Release reference */
 | 
			
		||||
											ac_session_release_reference(session);
 | 
			
		||||
										}
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					} else if (check == CAPWAP_DTLS_PACKET) {
 | 
			
		||||
						/* Need create a new sessione for check if it is a valid DTLS handshake */
 | 
			
		||||
						if (sessioncount < g_ac.descriptor.wtplimit) {
 | 
			
		||||
							/* TODO prevent dos attack add filtering ip for multiple error */
 | 
			
		||||
	
 | 
			
		||||
							/* Retrive socket info */
 | 
			
		||||
							capwap_get_network_socket(&g_ac.net, &ctrlsock, fds[index].fd);
 | 
			
		||||
	
 | 
			
		||||
							/* Create a new session */
 | 
			
		||||
							session = ac_create_session(&recvfromaddr, &recvtoaddr, &ctrlsock);
 | 
			
		||||
							if (session) {
 | 
			
		||||
								ac_session_add_packet(session, buffer, buffersize, isctrlsocket, 0);
 | 
			
		||||
	
 | 
			
		||||
								/* Release reference */
 | 
			
		||||
								ac_session_release_reference(session);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					struct capwap_socket datasocket;
 | 
			
		||||
 | 
			
		||||
					/* Retrieve session by sessionid of data packet */
 | 
			
		||||
					capwap_get_network_socket(&g_ac.net, &datasocket, fds[index].fd);
 | 
			
		||||
					ac_update_session_from_datapacket(&datasocket, &recvfromaddr, &recvtoaddr, buffer, buffersize);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else if (index == CAPWAP_RECV_ERROR_INTR) {
 | 
			
		||||
			/* Ignore recv */
 | 
			
		||||
			continue;
 | 
			
		||||
		} else if (index == CAPWAP_RECV_ERROR_SOCKET) {
 | 
			
		||||
			/* Socket close */
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Terminate discovery thread */
 | 
			
		||||
	ac_discovery_stop();
 | 
			
		||||
 | 
			
		||||
	/* Close all sessions */
 | 
			
		||||
	ac_close_sessions();
 | 
			
		||||
 | 
			
		||||
	/* Wait to terminate all sessions */
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		int count;
 | 
			
		||||
		
 | 
			
		||||
		capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
		count = g_ac.sessions->count;
 | 
			
		||||
		capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
		
 | 
			
		||||
		if (!count) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* Wait that list is changed */
 | 
			
		||||
		capwap_logging_debug("Waiting for %d session terminate", count);
 | 
			
		||||
		capwap_event_wait(&g_ac.changesessionlist);	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Free handshark session */
 | 
			
		||||
	while (g_ac.datasessionshandshake->first != NULL) {
 | 
			
		||||
		struct ac_data_session_handshake* handshake = (struct ac_data_session_handshake*)g_ac.datasessionshandshake->first->item;
 | 
			
		||||
 | 
			
		||||
		if (handshake->dtls.enable) {
 | 
			
		||||
			capwap_crypt_freesession(&handshake->dtls);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		capwap_itemlist_free(capwap_itemlist_remove(g_ac.datasessionshandshake, g_ac.datasessionshandshake->first));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Free memory */
 | 
			
		||||
	capwap_free(fds);
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										617
									
								
								src/ac/ac_session.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										617
									
								
								src/ac/ac_session.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,617 @@
 | 
			
		||||
#include "ac.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
#include "ac_session.h"
 | 
			
		||||
 | 
			
		||||
#define PACKET_TIMEOUT			-1
 | 
			
		||||
#define DTLS_SHUTDOWN			-2
 | 
			
		||||
 | 
			
		||||
static int ac_network_read(struct ac_session_t* session, void* buffer, int length, int* isctrlpacket, struct timeout_control* timeout) {
 | 
			
		||||
	long indextimer;
 | 
			
		||||
	long waittimeout;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(buffer != NULL);
 | 
			
		||||
	ASSERT(length > 0);
 | 
			
		||||
	ASSERT(isctrlpacket != NULL);
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		if (session->closesession) {
 | 
			
		||||
			session->closesession = 0;
 | 
			
		||||
			return DTLS_SHUTDOWN;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		capwap_lock_enter(&session->packetslock);
 | 
			
		||||
		
 | 
			
		||||
		if ((session->controlpackets->count > 0) || (session->datapackets->count > 0)) {
 | 
			
		||||
			int result = 0;
 | 
			
		||||
			struct capwap_list_item* itempacket;
 | 
			
		||||
 | 
			
		||||
			*isctrlpacket = ((session->controlpackets->count > 0) ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
			/* Get packet */
 | 
			
		||||
			itempacket = capwap_itemlist_remove_head((*isctrlpacket ? session->controlpackets : session->datapackets));
 | 
			
		||||
			capwap_lock_exit(&session->packetslock);
 | 
			
		||||
 | 
			
		||||
			if (itempacket) {
 | 
			
		||||
				struct ac_packet* packet = (struct ac_packet*)itempacket->item;
 | 
			
		||||
				long packetlength = itempacket->itemsize - sizeof(struct ac_packet);
 | 
			
		||||
				struct capwap_dtls* dtls = (*isctrlpacket ? &session->ctrldtls : &session->datadtls);
 | 
			
		||||
				
 | 
			
		||||
				if (!packet->plainbuffer && dtls->enable) {
 | 
			
		||||
					int oldaction = dtls->action;
 | 
			
		||||
 | 
			
		||||
					/* Decrypt packet */
 | 
			
		||||
					result = capwap_decrypt_packet(dtls, packet->buffer, packetlength, buffer, length);
 | 
			
		||||
					if (result == CAPWAP_ERROR_AGAIN) {
 | 
			
		||||
						/* Check is handshake complete */
 | 
			
		||||
						if ((oldaction == CAPWAP_DTLS_ACTION_HANDSHAKE) && (dtls->action == CAPWAP_DTLS_ACTION_DATA)) {
 | 
			
		||||
							if (*isctrlpacket) {
 | 
			
		||||
								if (session->state == CAPWAP_DTLS_CONNECT_STATE) {
 | 
			
		||||
									ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
 | 
			
		||||
									capwap_set_timeout(session->dfa.rfcWaitJoin, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					} else if (result == CAPWAP_ERROR_SHUTDOWN) {
 | 
			
		||||
						if ((oldaction == CAPWAP_DTLS_ACTION_DATA) && (dtls->action == CAPWAP_DTLS_ACTION_SHUTDOWN)) {
 | 
			
		||||
							result = DTLS_SHUTDOWN;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					if (packetlength <= length) {
 | 
			
		||||
						memcpy(buffer, packet->buffer, packetlength);
 | 
			
		||||
						result = packetlength;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				/* Free packet */
 | 
			
		||||
				capwap_itemlist_free(itempacket);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return result;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		capwap_lock_exit(&session->packetslock);
 | 
			
		||||
 | 
			
		||||
		/* Update timeout */
 | 
			
		||||
		capwap_update_timeout(timeout);
 | 
			
		||||
		waittimeout = capwap_get_timeout(timeout, &indextimer);
 | 
			
		||||
		if ((waittimeout <= 0) && (indextimer != CAPWAP_TIMER_UNDEF)) {
 | 
			
		||||
			return PACKET_TIMEOUT;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* Wait packet */
 | 
			
		||||
		capwap_event_wait_timeout(&session->waitpacket, waittimeout);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int ac_dfa_execute(struct ac_session_t* session, struct capwap_packet* packet) {
 | 
			
		||||
	int action = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	/* Execute state */
 | 
			
		||||
	switch (session->state) {
 | 
			
		||||
		case CAPWAP_START_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_START_TO_IDLE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_IDLE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case CAPWAP_IDLE_TO_DISCOVERY_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_IDLE_TO_DTLS_SETUP_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DISCOVERY_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DISCOVERY_TO_IDLE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DISCOVERY_TO_SULKING_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_SULKING_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case CAPWAP_SULKING_TO_IDLE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_SETUP_STATE: {
 | 
			
		||||
			action = ac_dfa_state_dtlssetup(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_SETUP_TO_IDLE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_SETUP_TO_SULKING_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_SETUP_TO_AUTHORIZE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_AUTHORIZE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_AUTHORIZE_TO_DTLS_SETUP_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_AUTHORIZE_TO_DTLS_CONNECT_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_AUTHORIZE_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
					
 | 
			
		||||
		case CAPWAP_DTLS_CONNECT_STATE: {
 | 
			
		||||
			action = ac_dfa_state_dtlsconnect(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_dtlsconnect_to_dtlsteardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_CONNECT_TO_JOIN_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_teardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DTLS_TEARDOWN_TO_DEAD_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_JOIN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_join(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_POSTJOIN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_postjoin(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_join_to_dtlsteardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_JOIN_TO_IMAGE_DATA_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_JOIN_TO_CONFIGURE_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_IMAGE_DATA_STATE: {
 | 
			
		||||
			action = ac_dfa_state_imagedata(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_IMAGE_DATA_TO_RESET_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_IMAGE_DATA_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_imagedata_to_dtlsteardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_CONFIGURE_STATE: {
 | 
			
		||||
			action = ac_dfa_state_configure(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_CONFIGURE_TO_RESET_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_configure_to_dtlsteardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE: {
 | 
			
		||||
			/* Never called with this state */
 | 
			
		||||
			ASSERT(0);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_RESET_STATE: {
 | 
			
		||||
			action = ac_dfa_state_reset(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_reset_to_dtlsteardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DATA_CHECK_STATE: {
 | 
			
		||||
			action = ac_dfa_state_datacheck(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_datacheck_to_dtlsteardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DATA_CHECK_TO_RUN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_datacheck_to_run(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_RUN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_run(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE: {
 | 
			
		||||
			action = ac_dfa_state_run_to_dtlsteardown(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_RUN_TO_RESET_STATE: {
 | 
			
		||||
			action = ac_dfa_state_run_to_reset(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case CAPWAP_DEAD_STATE: {
 | 
			
		||||
			action = ac_dfa_state_dead(session, packet);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		default: {
 | 
			
		||||
			capwap_logging_debug("Unknown action event: %lu", session->state);
 | 
			
		||||
			break;
 | 
			
		||||
		}			
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return action;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ac_session_run(struct ac_session_t* session) {
 | 
			
		||||
	int check;
 | 
			
		||||
	int length;
 | 
			
		||||
	int isctrlsocket;
 | 
			
		||||
	int action = AC_DFA_ACCEPT_PACKET;
 | 
			
		||||
	char buffer[CAPWAP_MAX_PACKET_SIZE];
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	/* Configure DFA */
 | 
			
		||||
	if (g_ac.enabledtls) {
 | 
			
		||||
		action = AC_DFA_NO_PACKET;
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_DTLS_SETUP_STATE);
 | 
			
		||||
		capwap_set_timeout(session->dfa.rfcWaitDTLS, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* Wait Join request */
 | 
			
		||||
		ac_dfa_change_state(session, CAPWAP_JOIN_STATE);
 | 
			
		||||
		capwap_set_timeout(session->dfa.rfcWaitJoin, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	while (action != AC_DFA_DEAD) {
 | 
			
		||||
		/* Get packet */
 | 
			
		||||
		if ((action == AC_DFA_ACCEPT_PACKET) || (action == AC_DFA_DROP_PACKET)) {
 | 
			
		||||
			length = ac_network_read(session, buffer, sizeof(buffer), &isctrlsocket, &session->timeout);
 | 
			
		||||
			if (length < 0) {
 | 
			
		||||
				if (length == PACKET_TIMEOUT) {
 | 
			
		||||
					action = ac_dfa_execute(session, NULL);		/* Timeout */
 | 
			
		||||
				} else if (length == DTLS_SHUTDOWN) {
 | 
			
		||||
					action = ac_session_teardown_connection(session);
 | 
			
		||||
				}
 | 
			
		||||
			} else if (length > 0) {
 | 
			
		||||
				/* Accept data packet only in running state */
 | 
			
		||||
				if (isctrlsocket || (session->state == CAPWAP_DATA_CHECK_TO_RUN_STATE) || (session->state == CAPWAP_RUN_STATE)) {
 | 
			
		||||
					/* Check generic capwap packet */
 | 
			
		||||
					check = capwap_sanity_check(isctrlsocket, CAPWAP_UNDEF_STATE, buffer, length, 0, 0);
 | 
			
		||||
					if (check == CAPWAP_PLAIN_PACKET) {
 | 
			
		||||
						struct capwap_packet packet;
 | 
			
		||||
						
 | 
			
		||||
						check = capwap_defragment_packets(&session->wtpctrladdress, buffer, length, session->rxfragmentpacket, &packet);
 | 
			
		||||
						if (check == CAPWAP_RECEIVE_COMPLETE_PACKET) {
 | 
			
		||||
							int ignorepacket = 0;
 | 
			
		||||
							
 | 
			
		||||
							if (isctrlsocket) {
 | 
			
		||||
								/* Check for already response to packet */
 | 
			
		||||
								if (capwap_recv_retrasmitted_request(&session->ctrldtls, &packet, session->remoteseqnumber, session->lastrecvpackethash, &session->ctrlsocket, session->responsefragmentpacket, &session->acctrladdress, &session->wtpctrladdress)) {
 | 
			
		||||
									ignorepacket = 1;
 | 
			
		||||
								}
 | 
			
		||||
								
 | 
			
		||||
								/* Check message type */
 | 
			
		||||
								if (!capwap_check_message_type(&session->ctrldtls, &packet, session->mtu)) {
 | 
			
		||||
									ignorepacket = 1;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							/* */
 | 
			
		||||
							if (!ignorepacket && (action == AC_DFA_ACCEPT_PACKET)) {
 | 
			
		||||
								memcpy(&packet.socket, (isctrlsocket ? &session->ctrlsocket : &session->datasocket), sizeof(struct capwap_socket));
 | 
			
		||||
								action = ac_dfa_execute(session, &packet);
 | 
			
		||||
							}
 | 
			
		||||
							
 | 
			
		||||
							/* Free packet */
 | 
			
		||||
							capwap_free_packet(&packet);
 | 
			
		||||
						} else if (check != CAPWAP_REQUEST_MORE_FRAGMENT) {
 | 
			
		||||
							/* Discard fragments */
 | 
			
		||||
							capwap_defragment_remove_sender(session->rxfragmentpacket, &session->wtpctrladdress);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			action = ac_dfa_execute(session, NULL);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Release reference session */
 | 
			
		||||
	if (!ac_session_release_reference(session)) {
 | 
			
		||||
		capwap_logging_debug("Reference session is > 0 to exit thread");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Change WTP state machine */
 | 
			
		||||
void ac_dfa_change_state(struct ac_session_t* session, int state) {
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	if (state != session->state) {
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
		char sessionname[33];
 | 
			
		||||
		capwap_sessionid_printf(&session->sessionid, sessionname);
 | 
			
		||||
		capwap_logging_debug("Session AC %s change state from %s to %s", sessionname, capwap_dfa_getname(session->state), capwap_dfa_getname(state));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		session->state = state;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Teardown connection */
 | 
			
		||||
int ac_session_teardown_connection(struct ac_session_t* session) {
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	/* Close DTSL Control */
 | 
			
		||||
	if (session->ctrldtls.enable) {
 | 
			
		||||
		capwap_crypt_close(&session->ctrldtls);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Close DTLS Data */
 | 
			
		||||
	if (session->datadtls.enable) {
 | 
			
		||||
		capwap_crypt_close(&session->datadtls);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	capwap_killall_timeout(&session->timeout);
 | 
			
		||||
	capwap_set_timeout(session->dfa.rfcDTLSSessionDelete, &session->timeout, CAPWAP_TIMER_CONTROL_CONNECTION);
 | 
			
		||||
	ac_dfa_change_state(session, CAPWAP_DTLS_TEARDOWN_STATE);
 | 
			
		||||
	return AC_DFA_DROP_PACKET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Release reference of session */
 | 
			
		||||
int ac_session_release_reference(struct ac_session_t* session) {
 | 
			
		||||
	int remove = 0;
 | 
			
		||||
	struct capwap_list_item* search;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
 | 
			
		||||
	session->count--;
 | 
			
		||||
	if (!session->count) {
 | 
			
		||||
		search = g_ac.sessions->first;
 | 
			
		||||
		while (search != NULL) {
 | 
			
		||||
			struct ac_session_t* item = (struct ac_session_t*)search->item;
 | 
			
		||||
			if (session == item) {
 | 
			
		||||
				/* Free DTSL Control */
 | 
			
		||||
				capwap_crypt_freesession(&session->ctrldtls);
 | 
			
		||||
 | 
			
		||||
				/* Free DTLS Data */
 | 
			
		||||
				capwap_crypt_freesession(&session->datadtls);
 | 
			
		||||
 | 
			
		||||
				/* Free resource */
 | 
			
		||||
				capwap_event_destroy(&session->waitpacket);
 | 
			
		||||
				capwap_lock_exit(&session->packetslock);
 | 
			
		||||
				capwap_list_free(session->controlpackets);
 | 
			
		||||
				capwap_list_free(session->datapackets);
 | 
			
		||||
				capwap_defragment_free_list(session->rxfragmentpacket);
 | 
			
		||||
 | 
			
		||||
				/* Free fragments packet */
 | 
			
		||||
				capwap_fragment_free(session->requestfragmentpacket);
 | 
			
		||||
				capwap_fragment_free(session->responsefragmentpacket);
 | 
			
		||||
				capwap_array_free(session->requestfragmentpacket);
 | 
			
		||||
				capwap_array_free(session->responsefragmentpacket);
 | 
			
		||||
 | 
			
		||||
				/* Free DFA resource */
 | 
			
		||||
				capwap_array_free(session->dfa.acipv4list);
 | 
			
		||||
				capwap_array_free(session->dfa.acipv6list);
 | 
			
		||||
 | 
			
		||||
				/* Remove item from list */
 | 
			
		||||
				remove = 1;
 | 
			
		||||
				capwap_itemlist_free(capwap_itemlist_remove(g_ac.sessions, search));
 | 
			
		||||
				capwap_event_signal(&g_ac.changesessionlist);
 | 
			
		||||
				
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		
 | 
			
		||||
			search = search->next;	
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	capwap_lock_exit(&g_ac.sessionslock);
 | 
			
		||||
 | 
			
		||||
	return remove;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* ac_session_thread(void* param) {
 | 
			
		||||
	ASSERT(param != NULL);
 | 
			
		||||
 | 
			
		||||
	capwap_logging_debug("Session start");
 | 
			
		||||
	ac_session_run((struct ac_session_t*)param);
 | 
			
		||||
	capwap_logging_debug("Session end");
 | 
			
		||||
 | 
			
		||||
	/* Thread exit */
 | 
			
		||||
	pthread_exit(NULL);
 | 
			
		||||
	return NULL;	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void ac_get_control_information(struct capwap_list* controllist) {
 | 
			
		||||
	struct capwap_list* addrlist;
 | 
			
		||||
	struct capwap_list_item* item;
 | 
			
		||||
		
 | 
			
		||||
	ASSERT(controllist != NULL);
 | 
			
		||||
 | 
			
		||||
	/* Detect local address */
 | 
			
		||||
	addrlist = capwap_list_create();
 | 
			
		||||
	capwap_interface_list(&g_ac.net, addrlist);
 | 
			
		||||
	
 | 
			
		||||
	/* Prepare control list */
 | 
			
		||||
	for (item = addrlist->first; item != NULL; item = item->next) {
 | 
			
		||||
		struct capwap_list_item* itemcontrol;
 | 
			
		||||
		struct ac_session_control* sessioncontrol;
 | 
			
		||||
		struct sockaddr_storage* address = (struct sockaddr_storage*)item->item;
 | 
			
		||||
 | 
			
		||||
		/* */
 | 
			
		||||
		itemcontrol = capwap_itemlist_create(sizeof(struct ac_session_control));
 | 
			
		||||
		sessioncontrol = (struct ac_session_control*)itemcontrol->item;
 | 
			
		||||
		memcpy(&sessioncontrol->localaddress, address, sizeof(struct sockaddr_storage));
 | 
			
		||||
		sessioncontrol->count = 0;
 | 
			
		||||
		
 | 
			
		||||
		/* Add */
 | 
			
		||||
		capwap_itemlist_insert_after(controllist, NULL, itemcontrol);
 | 
			
		||||
	}	
 | 
			
		||||
 | 
			
		||||
	/* Free local address list */
 | 
			
		||||
	capwap_list_free(addrlist);
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	capwap_lock_enter(&g_ac.sessionslock);
 | 
			
		||||
	
 | 
			
		||||
	/* Get wtp count from any local address */
 | 
			
		||||
	for (item = controllist->first; item != NULL; item = item->next) {
 | 
			
		||||
		struct capwap_list_item* search;
 | 
			
		||||
		struct ac_session_control* sessioncontrol = (struct ac_session_control*)item->item;
 | 
			
		||||
		
 | 
			
		||||
		for (search = g_ac.sessions->first; search != NULL; search = search->next) {
 | 
			
		||||
			struct ac_session_t* session = (struct ac_session_t*)search->item;
 | 
			
		||||
			
 | 
			
		||||
			if (!capwap_compare_ip(&session->acctrladdress, &sessioncontrol->localaddress)) {
 | 
			
		||||
				sessioncontrol->count++;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	capwap_lock_exit(&g_ac.sessionslock);		
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void ac_free_reference_last_request(struct ac_session_t* session) {
 | 
			
		||||
	ASSERT(session);
 | 
			
		||||
 | 
			
		||||
	capwap_fragment_free(session->requestfragmentpacket);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void ac_free_reference_last_response(struct ac_session_t* session) {
 | 
			
		||||
	ASSERT(session);
 | 
			
		||||
 | 
			
		||||
	capwap_fragment_free(session->responsefragmentpacket);
 | 
			
		||||
	memset(&session->lastrecvpackethash[0], 0, sizeof(session->lastrecvpackethash));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										112
									
								
								src/ac/ac_session.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/ac/ac_session.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,112 @@
 | 
			
		||||
#ifndef __AC_SESSION_HEADER__
 | 
			
		||||
#define __AC_SESSION_HEADER__
 | 
			
		||||
 | 
			
		||||
#include "capwap_dtls.h"
 | 
			
		||||
 | 
			
		||||
#define AC_DFA_NO_PACKET			0
 | 
			
		||||
#define AC_DFA_ACCEPT_PACKET		1
 | 
			
		||||
#define AC_DFA_DROP_PACKET			2
 | 
			
		||||
#define AC_DFA_DEAD					3
 | 
			
		||||
 | 
			
		||||
/* AC packet */
 | 
			
		||||
struct ac_packet {
 | 
			
		||||
	int plainbuffer;
 | 
			
		||||
	char buffer[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct ac_session_control {
 | 
			
		||||
	struct sockaddr_storage localaddress;
 | 
			
		||||
	unsigned short count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* AC sessions */
 | 
			
		||||
struct ac_session_t {
 | 
			
		||||
	struct ac_state dfa;
 | 
			
		||||
	
 | 
			
		||||
	unsigned long count;
 | 
			
		||||
	struct sockaddr_storage acctrladdress;
 | 
			
		||||
	struct sockaddr_storage acdataaddress;
 | 
			
		||||
	struct sockaddr_storage wtpctrladdress;
 | 
			
		||||
	struct sockaddr_storage wtpdataaddress;
 | 
			
		||||
	struct capwap_socket ctrlsocket;
 | 
			
		||||
	struct capwap_socket datasocket;
 | 
			
		||||
	struct timeout_control timeout;
 | 
			
		||||
 | 
			
		||||
	struct capwap_sessionid_element sessionid;
 | 
			
		||||
	unsigned short binding;
 | 
			
		||||
 | 
			
		||||
	struct capwap_dtls ctrldtls;
 | 
			
		||||
	struct capwap_dtls datadtls;
 | 
			
		||||
 | 
			
		||||
	int closesession;
 | 
			
		||||
	pthread_t threadid;
 | 
			
		||||
	
 | 
			
		||||
	capwap_event_t waitpacket;
 | 
			
		||||
	capwap_lock_t packetslock;
 | 
			
		||||
	struct capwap_list* controlpackets;
 | 
			
		||||
	struct capwap_list* datapackets;
 | 
			
		||||
 | 
			
		||||
	unsigned char localseqnumber;
 | 
			
		||||
	unsigned char remoteseqnumber;
 | 
			
		||||
	unsigned short mtu;
 | 
			
		||||
	unsigned short fragmentid;
 | 
			
		||||
	capwap_fragment_list* rxfragmentpacket;
 | 
			
		||||
	capwap_fragment_packet_array* requestfragmentpacket;
 | 
			
		||||
	capwap_fragment_packet_array* responsefragmentpacket;
 | 
			
		||||
	unsigned char lastrecvpackethash[16];
 | 
			
		||||
 | 
			
		||||
	unsigned long state;
 | 
			
		||||
 | 
			
		||||
	struct capwap_imageidentifier_element startupimage;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void* ac_session_thread(void* param);
 | 
			
		||||
int ac_session_teardown_connection(struct ac_session_t* session);
 | 
			
		||||
int ac_session_release_reference(struct ac_session_t* session);
 | 
			
		||||
 | 
			
		||||
void ac_dfa_change_state(struct ac_session_t* session, int state);
 | 
			
		||||
 | 
			
		||||
void ac_get_control_information(struct capwap_list* controllist);
 | 
			
		||||
 | 
			
		||||
void ac_free_reference_last_request(struct ac_session_t* session);
 | 
			
		||||
void ac_free_reference_last_response(struct ac_session_t* session);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_join(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_postjoin(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_join_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_bio_send(struct capwap_dtls* dtls, char* buffer, int length, void* param);
 | 
			
		||||
int ac_dfa_state_dtlssetup(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_dtlsconnect(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_dtlsconnect_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_configure(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_configure_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_datacheck(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_datacheck_to_run(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_datacheck_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_imagedata(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_imagedata_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_run(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_run_to_reset(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_run_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_reset(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_reset_to_dtlsteardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int ac_dfa_state_teardown(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
int ac_dfa_state_dead(struct ac_session_t* session, struct capwap_packet* packet);
 | 
			
		||||
 | 
			
		||||
#endif /* __AC_SESSION_HEADER__ */
 | 
			
		||||
							
								
								
									
										151
									
								
								src/common/capwap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								src/common/capwap.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,151 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
 | 
			
		||||
/* Helper exit */
 | 
			
		||||
void capwap_exit(int errorcode) {
 | 
			
		||||
	exit(errorcode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Helper timeout calc */
 | 
			
		||||
void capwap_init_timeout(struct timeout_control* timeout) {
 | 
			
		||||
	ASSERT(timeout);
 | 
			
		||||
 | 
			
		||||
	memset(timeout, 0, sizeof(struct timeout_control));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void capwap_update_timeout(struct timeout_control* timeout) {
 | 
			
		||||
	int i;
 | 
			
		||||
	struct timeval now;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(timeout);
 | 
			
		||||
	
 | 
			
		||||
	gettimeofday(&now, NULL);
 | 
			
		||||
	
 | 
			
		||||
	for (i = 0; i < CAPWAP_MAX_TIMER; i++) {
 | 
			
		||||
		if (timeout->items[i].enable && (timeout->items[i].delta >= 0)) {
 | 
			
		||||
			timeout->items[i].delta = (timeout->items[i].timestop.tv_sec - now.tv_sec) * 1000 + (timeout->items[i].timestop.tv_usec - now.tv_usec) / 1000;
 | 
			
		||||
			if (timeout->items[i].delta < 0) {
 | 
			
		||||
				timeout->items[i].delta = 0;
 | 
			
		||||
			} else if (timeout->items[i].delta > timeout->items[i].durate) {
 | 
			
		||||
				/* Changed system time */
 | 
			
		||||
				timeout->items[i].delta = timeout->items[i].durate;
 | 
			
		||||
				memcpy(&timeout->items[i].timestop, &now, sizeof(struct timeval));
 | 
			
		||||
				timeout->items[i].timestop.tv_sec += timeout->items[i].durate;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long capwap_get_timeout(struct timeout_control* timeout, long* index) {
 | 
			
		||||
	long i;
 | 
			
		||||
	long delta = 0;
 | 
			
		||||
 | 
			
		||||
	ASSERT(timeout != NULL);
 | 
			
		||||
	ASSERT(index != NULL);
 | 
			
		||||
	
 | 
			
		||||
	*index = CAPWAP_TIMER_UNDEF;
 | 
			
		||||
	for (i = 0; i < CAPWAP_MAX_TIMER; i++) {
 | 
			
		||||
		if (timeout->items[i].enable) {
 | 
			
		||||
			if (timeout->items[i].delta <= 0) {
 | 
			
		||||
				*index = i;
 | 
			
		||||
				delta = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			} else if (!delta || (delta > timeout->items[i].delta)) {
 | 
			
		||||
				*index = i;
 | 
			
		||||
				delta = timeout->items[i].delta;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return delta;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int capwap_is_enable_timeout(struct timeout_control* timeout, unsigned long index) {
 | 
			
		||||
	ASSERT(timeout != NULL);
 | 
			
		||||
	ASSERT(index < CAPWAP_MAX_TIMER);
 | 
			
		||||
 | 
			
		||||
	return (timeout->items[index].enable ? 1 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int capwap_is_timeout(struct timeout_control* timeout, unsigned long index) {
 | 
			
		||||
	ASSERT(timeout != NULL);
 | 
			
		||||
	ASSERT(index < CAPWAP_MAX_TIMER);
 | 
			
		||||
 | 
			
		||||
	if (timeout->items[index].enable && (timeout->items[index].delta <= 0)) {
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void capwap_set_timeout(unsigned long value, struct timeout_control* timeout, unsigned long index) {
 | 
			
		||||
	ASSERT(timeout != NULL);
 | 
			
		||||
	ASSERT(index < CAPWAP_MAX_TIMER);
 | 
			
		||||
	
 | 
			
		||||
	/* Set timeout in ms */
 | 
			
		||||
	timeout->items[index].enable = 1;
 | 
			
		||||
	timeout->items[index].delta = value * 1000;
 | 
			
		||||
	timeout->items[index].durate = value * 1000;
 | 
			
		||||
	gettimeofday(&timeout->items[index].timestop, NULL);
 | 
			
		||||
	timeout->items[index].timestop.tv_sec += value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void capwap_kill_timeout(struct timeout_control* timeout, unsigned long index) {
 | 
			
		||||
	ASSERT(timeout != NULL);
 | 
			
		||||
	ASSERT(index < CAPWAP_MAX_TIMER);
 | 
			
		||||
	
 | 
			
		||||
	timeout->items[index].enable = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void capwap_killall_timeout(struct timeout_control* timeout) {
 | 
			
		||||
	long i;
 | 
			
		||||
 | 
			
		||||
	ASSERT(timeout != NULL);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < CAPWAP_MAX_TIMER; i++) {
 | 
			
		||||
		timeout->items[i].enable = 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Init randon generator */
 | 
			
		||||
void capwap_init_rand(void) {
 | 
			
		||||
	srand(time(NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get random number */
 | 
			
		||||
int capwap_get_rand(int max) {
 | 
			
		||||
	if ((max < 0) || (max > RAND_MAX)) {
 | 
			
		||||
		max = RAND_MAX;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (rand() % max);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Duplicate string */
 | 
			
		||||
char* capwap_duplicate_string(const char* source) {
 | 
			
		||||
	char* clone;
 | 
			
		||||
 | 
			
		||||
	ASSERT(source != NULL);
 | 
			
		||||
 | 
			
		||||
	clone = capwap_alloc(sizeof(char) * (strlen(source) + 1));
 | 
			
		||||
	if (!clone) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strcpy(clone, source);
 | 
			
		||||
	return clone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Buffer clone */
 | 
			
		||||
void* capwap_clone(void* buffer, int buffersize) {
 | 
			
		||||
	void* bufferclone;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(buffer != NULL);
 | 
			
		||||
	ASSERT(buffersize > 0);
 | 
			
		||||
 | 
			
		||||
	bufferclone = capwap_alloc(buffersize);
 | 
			
		||||
	if (!bufferclone) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return memcpy(bufferclone, buffer, buffersize);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										101
									
								
								src/common/capwap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/common/capwap.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
			
		||||
#ifndef __CAPWAP_HEADER__
 | 
			
		||||
#define __CAPWAP_HEADER__
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <poll.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
 | 
			
		||||
//TODO:
 | 
			
		||||
//#ifdef NATIVE_UDPLITE_HEADER
 | 
			
		||||
//#include <netinet/udplite.h>
 | 
			
		||||
//#else
 | 
			
		||||
//#define IPPROTO_UDPLITE       136
 | 
			
		||||
#define SOL_UDPLITE           136
 | 
			
		||||
#define UDPLITE_SEND_CSCOV     10
 | 
			
		||||
//#endif
 | 
			
		||||
 | 
			
		||||
/* Endian */
 | 
			
		||||
#ifdef WIN32
 | 
			
		||||
	#define CAPWAP_LITTLE_ENDIAN
 | 
			
		||||
#else
 | 
			
		||||
	#if __BYTE_ORDER == __BIG_ENDIAN
 | 
			
		||||
		#define CAPWAP_BIG_ENDIAN
 | 
			
		||||
	#else
 | 
			
		||||
		#define CAPWAP_LITTLE_ENDIAN
 | 
			
		||||
	#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Min & Max */
 | 
			
		||||
#ifndef max
 | 
			
		||||
	#define max(a,b) ((a) >= (b) ? (a) : (b))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef min
 | 
			
		||||
	#define min(a,b) ((a) <= (b) ? (a) : (b))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* config */
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* standard include */
 | 
			
		||||
#include "capwap_logging.h"
 | 
			
		||||
#include "capwap_debug.h"
 | 
			
		||||
#include "capwap_error.h"
 | 
			
		||||
 | 
			
		||||
/* Helper exit */
 | 
			
		||||
void capwap_exit(int errorcode);
 | 
			
		||||
 | 
			
		||||
/* Random generator */
 | 
			
		||||
void capwap_init_rand(void);
 | 
			
		||||
int capwap_get_rand(int max);
 | 
			
		||||
 | 
			
		||||
/* Helper timeout calc */
 | 
			
		||||
struct timeout_control_item {
 | 
			
		||||
	int enable;
 | 
			
		||||
	long delta;
 | 
			
		||||
	unsigned long durate;
 | 
			
		||||
	struct timeval timestop;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_TIMER_UNDEF						-1
 | 
			
		||||
#define CAPWAP_TIMER_CONTROL_CONNECTION			0
 | 
			
		||||
#define CAPWAP_TIMER_CONTROL_ECHO				1
 | 
			
		||||
#define CAPWAP_TIMER_DATA_KEEPALIVE				2
 | 
			
		||||
#define CAPWAP_TIMER_DATA_KEEPALIVEDEAD			3
 | 
			
		||||
#define CAPWAP_MAX_TIMER						4
 | 
			
		||||
 | 
			
		||||
struct timeout_control {
 | 
			
		||||
	struct timeout_control_item items[CAPWAP_MAX_TIMER];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_timeout(struct timeout_control* timeout);
 | 
			
		||||
long capwap_get_timeout(struct timeout_control* timeout, long* index);
 | 
			
		||||
void capwap_update_timeout(struct timeout_control* timeout);
 | 
			
		||||
void capwap_set_timeout(unsigned long value, struct timeout_control* timeout, unsigned long index);
 | 
			
		||||
void capwap_kill_timeout(struct timeout_control* timeout, unsigned long index);
 | 
			
		||||
void capwap_killall_timeout(struct timeout_control* timeout);
 | 
			
		||||
int capwap_is_enable_timeout(struct timeout_control* timeout, unsigned long index);
 | 
			
		||||
int capwap_is_timeout(struct timeout_control* timeout, unsigned long index);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
#define capwap_outofmemory()						capwap_logging_fatal("Out of memory %s(%d)", __FILE__, __LINE__);	\
 | 
			
		||||
													capwap_exit(CAPWAP_OUT_OF_MEMORY);
 | 
			
		||||
 | 
			
		||||
/* Helper buffer copy */
 | 
			
		||||
char* capwap_duplicate_string(const char* source);
 | 
			
		||||
void* capwap_clone(void* buffer, int buffersize);
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_HEADER__ */
 | 
			
		||||
							
								
								
									
										92
									
								
								src/common/capwap_array.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/common/capwap_array.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount) {
 | 
			
		||||
	struct capwap_array* array;
 | 
			
		||||
 | 
			
		||||
	ASSERT(itemsize > 0);
 | 
			
		||||
 | 
			
		||||
	array = (struct capwap_array*)capwap_alloc(sizeof(struct capwap_array));
 | 
			
		||||
	if (!array) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	memset(array, 0, sizeof(struct capwap_array));
 | 
			
		||||
	array->itemsize = itemsize;
 | 
			
		||||
	if (initcount > 0) {
 | 
			
		||||
		capwap_array_resize(array, initcount);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return array;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_array* capwap_array_clone(struct capwap_array* array) {
 | 
			
		||||
	unsigned long i;
 | 
			
		||||
	struct capwap_array* clone;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT (array != NULL);
 | 
			
		||||
	
 | 
			
		||||
	/* Clone array e items */
 | 
			
		||||
	clone = capwap_array_create(array->itemsize, array->count);
 | 
			
		||||
	for (i = 0; i < array->count; i++) {
 | 
			
		||||
		memcpy(capwap_array_get_item_pointer(clone, i), capwap_array_get_item_pointer(array, i), array->itemsize);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return clone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_array_free(struct capwap_array* array) {
 | 
			
		||||
	ASSERT(array != NULL);
 | 
			
		||||
	
 | 
			
		||||
	if (array->buffer) {
 | 
			
		||||
		capwap_free(array->buffer);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(array);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos) {
 | 
			
		||||
	ASSERT(array != NULL);
 | 
			
		||||
	ASSERT((array->count == 0) || (array->buffer != NULL));
 | 
			
		||||
 | 
			
		||||
	if (pos >= array->count) {
 | 
			
		||||
		capwap_array_resize(array, pos + 1);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return (void*)(((char*)array->buffer) + array->itemsize * pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_array_resize(struct capwap_array* array, unsigned long count) {
 | 
			
		||||
	void* newbuffer = NULL;
 | 
			
		||||
 | 
			
		||||
	ASSERT(array != NULL);
 | 
			
		||||
	ASSERT(array->itemsize > 0);
 | 
			
		||||
 | 
			
		||||
	if (array->count == count) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (count > 0) {
 | 
			
		||||
		newbuffer = capwap_alloc(array->itemsize * count);
 | 
			
		||||
		if (!newbuffer) {
 | 
			
		||||
			capwap_outofmemory();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (array->buffer) {
 | 
			
		||||
		if (newbuffer != NULL) {
 | 
			
		||||
			memcpy(newbuffer, array->buffer, array->itemsize * min(array->count, count));
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		capwap_free(array->buffer);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	array->buffer = newbuffer;
 | 
			
		||||
	array->count = count;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								src/common/capwap_array.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/common/capwap_array.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
#ifndef __CAPWAP_ARRAY_HEADER__
 | 
			
		||||
#define __CAPWAP_ARRAY_HEADER__
 | 
			
		||||
 | 
			
		||||
struct capwap_array {
 | 
			
		||||
	void* buffer;
 | 
			
		||||
	unsigned short itemsize;
 | 
			
		||||
	unsigned long count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_array* capwap_array_create(unsigned short itemsize, unsigned long initcount);
 | 
			
		||||
struct capwap_array* capwap_array_clone(struct capwap_array* array);
 | 
			
		||||
void capwap_array_free(struct capwap_array* array);
 | 
			
		||||
void* capwap_array_get_item_pointer(struct capwap_array* array, unsigned long pos);
 | 
			
		||||
void capwap_array_resize(struct capwap_array* array, unsigned long count);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define capwap_array_getitem(x, y, z)		*((z*)capwap_array_get_item_pointer((x), (y)))
 | 
			
		||||
#define capwap_array_setnewitem(x, y, z)	*((z*)capwap_array_get_item_pointer((x), (x)->count)) = (y)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ARRAY_HEADER__ */
 | 
			
		||||
							
								
								
									
										161
									
								
								src/common/capwap_debug.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/common/capwap_debug.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,161 @@
 | 
			
		||||
#include <execinfo.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "capwap_logging.h"
 | 
			
		||||
 | 
			
		||||
#define CANARY					0xaaaaaaaa
 | 
			
		||||
#define BACKTRACE_BUFFER		256
 | 
			
		||||
 | 
			
		||||
#ifndef DEBUG_BREAKPOINT
 | 
			
		||||
#define DEBUG_BREAKPOINT()			__asm__("int3")
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Memory block */
 | 
			
		||||
struct capwap_memory_block {
 | 
			
		||||
	void* item;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	const char* file;
 | 
			
		||||
	int line;
 | 
			
		||||
	void* backtrace[BACKTRACE_BUFFER];
 | 
			
		||||
	int backtrace_count;
 | 
			
		||||
	struct capwap_memory_block* next;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct capwap_memory_block* g_memoryblocks = NULL;
 | 
			
		||||
 | 
			
		||||
/* Alloc memory block */
 | 
			
		||||
void* capwap_alloc_debug(size_t size, const char* file, const int line) {
 | 
			
		||||
	struct capwap_memory_block* block;
 | 
			
		||||
 | 
			
		||||
	/* Request size > 0 */
 | 
			
		||||
	if (size <= 0) {
 | 
			
		||||
		capwap_logging_debug("%s(%d): Invalid memory size %d", file, line, size);
 | 
			
		||||
		DEBUG_BREAKPOINT();
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Alloc block with memory block and canary */
 | 
			
		||||
	block = (struct capwap_memory_block*)malloc(sizeof(struct capwap_memory_block) + size + 4);
 | 
			
		||||
	if (!block) {
 | 
			
		||||
		capwap_logging_debug("Out of memory %s(%d)", __FILE__, __LINE__);
 | 
			
		||||
		DEBUG_BREAKPOINT();
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Info memory block */
 | 
			
		||||
	block->item = (void*)(((char*)block) + sizeof(struct capwap_memory_block));
 | 
			
		||||
	block->size = size;
 | 
			
		||||
	block->file = file;
 | 
			
		||||
	block->line = line;
 | 
			
		||||
	block->backtrace_count = backtrace(block->backtrace, BACKTRACE_BUFFER);
 | 
			
		||||
	block->next = g_memoryblocks;
 | 
			
		||||
 | 
			
		||||
	/* Canary */
 | 
			
		||||
	*((unsigned long*)(((char*)block->item) + block->size)) = CANARY;
 | 
			
		||||
 | 
			
		||||
	g_memoryblocks = block;
 | 
			
		||||
 | 
			
		||||
	return block->item;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Free memory block */
 | 
			
		||||
void capwap_free_debug(void* p, const char* file, const int line) {
 | 
			
		||||
	struct capwap_memory_block* block;
 | 
			
		||||
	struct capwap_memory_block* findblock;
 | 
			
		||||
	struct capwap_memory_block* prevblock;
 | 
			
		||||
 | 
			
		||||
	if (!p) {
 | 
			
		||||
		capwap_logging_debug("%s(%d): Free NULL pointer", file, line);
 | 
			
		||||
		DEBUG_BREAKPOINT();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Memory block */
 | 
			
		||||
	if ((size_t)p <= sizeof(struct capwap_memory_block)) {
 | 
			
		||||
		capwap_logging_debug("%s(%d): Invalid pointer", file, line);
 | 
			
		||||
		DEBUG_BREAKPOINT();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	block = (struct capwap_memory_block*)((char*)p - sizeof(struct capwap_memory_block));
 | 
			
		||||
	if (block->item != p) {
 | 
			
		||||
		capwap_logging_debug("%s(%d): Invalid pointer", file, line);
 | 
			
		||||
		DEBUG_BREAKPOINT();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check canary */
 | 
			
		||||
	if (*((unsigned long*)(((char*)block->item) + block->size)) != CANARY) {
 | 
			
		||||
		capwap_logging_debug("%s(%d): Invalid canary allocted in %s(%d)", file, line, block->file, block->line);
 | 
			
		||||
		DEBUG_BREAKPOINT();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Find memory block */
 | 
			
		||||
	prevblock = NULL;
 | 
			
		||||
	findblock = g_memoryblocks;
 | 
			
		||||
	while (findblock != NULL) {
 | 
			
		||||
		if (findblock == block) {
 | 
			
		||||
			if (!prevblock) {
 | 
			
		||||
				g_memoryblocks = block->next;
 | 
			
		||||
			} else {
 | 
			
		||||
				prevblock->next = block->next;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* Invalidate block */
 | 
			
		||||
			memset(block, 0, sizeof(struct capwap_memory_block));
 | 
			
		||||
			free(block);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Next */
 | 
			
		||||
		prevblock = findblock;
 | 
			
		||||
		findblock = findblock->next;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	capwap_logging_debug("%s(%d): Unable to find memory block", file, line);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Dump memory alloced */
 | 
			
		||||
void capwap_dump_memory(void) {
 | 
			
		||||
	char** backtrace_functions;
 | 
			
		||||
	struct capwap_memory_block* findblock;
 | 
			
		||||
 | 
			
		||||
	findblock = g_memoryblocks;
 | 
			
		||||
	while (findblock != NULL) {
 | 
			
		||||
		capwap_logging_debug("%s(%d): block at %p, %d bytes long", findblock->file, findblock->line, findblock->item, findblock->size);
 | 
			
		||||
 | 
			
		||||
		backtrace_functions = backtrace_symbols(findblock->backtrace, findblock->backtrace_count);
 | 
			
		||||
		if (backtrace_functions) {
 | 
			
		||||
			int j;
 | 
			
		||||
 | 
			
		||||
			/* Skipping capwap_alloc_debug function print out */
 | 
			
		||||
			for (j = 1; j < findblock->backtrace_count; j++) {
 | 
			
		||||
				capwap_logging_debug("\t%s", backtrace_functions[j]);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			free(backtrace_functions);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		/* Next */
 | 
			
		||||
		findblock = findblock->next;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check if all memory is free */
 | 
			
		||||
int capwap_check_memory_leak(int verbose) {
 | 
			
		||||
	if ((g_memoryblocks != NULL) && (verbose != 0)) {
 | 
			
		||||
		capwap_logging_debug("*** Detected memory leaks ! ***");
 | 
			
		||||
		capwap_dump_memory();
 | 
			
		||||
		capwap_logging_debug("*******************************");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ((g_memoryblocks != NULL) ? 1 : 0);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/common/capwap_debug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/common/capwap_debug.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
#ifndef __CAPWAP_DEBUG_HEADER__
 | 
			
		||||
#define __CAPWAP_DEBUG_HEADER__
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
 | 
			
		||||
#define DEBUG_BREAKPOINT()			__asm__("int3")
 | 
			
		||||
 | 
			
		||||
#define ASSERT(expr)				if (!(expr)) {																				\
 | 
			
		||||
										capwap_logging_fatal("Assertion failed \'%s\': %s(%d)", #expr, __FILE__, __LINE__);		\
 | 
			
		||||
										DEBUG_BREAKPOINT();																		\
 | 
			
		||||
									}
 | 
			
		||||
 | 
			
		||||
/* Custom memory management */
 | 
			
		||||
#define capwap_alloc(x)				capwap_alloc_debug(x, __FILE__, __LINE__)
 | 
			
		||||
void* capwap_alloc_debug(size_t size, const char* file, const int line);
 | 
			
		||||
#define capwap_free(x)				capwap_free_debug(x, __FILE__, __LINE__)
 | 
			
		||||
void capwap_free_debug(void* p, const char* file, const int line);
 | 
			
		||||
 | 
			
		||||
int capwap_check_memory_leak(int verbose);
 | 
			
		||||
void capwap_dump_memory(void);
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define DEBUG_BREAKPOINT()
 | 
			
		||||
 | 
			
		||||
#define ASSERT(expr)
 | 
			
		||||
 | 
			
		||||
/* Standard memory management */
 | 
			
		||||
#define capwap_alloc(x)					(void*)malloc(x)
 | 
			
		||||
#define capwap_free(x)					free(x)
 | 
			
		||||
#define capwap_check_memory_leak(x)		(0)
 | 
			
		||||
#define capwap_dump_memory()			(0)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_DEBUG_HEADER__ */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										61
									
								
								src/common/capwap_dfa.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/common/capwap_dfa.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_dfa.h"
 | 
			
		||||
 | 
			
		||||
static char* l_nameofstate[] = {
 | 
			
		||||
	"START",								/* CAPWAP_START_STATE */
 | 
			
		||||
	"START_TO_IDLE",						/* CAPWAP_START_TO_IDLE_STATE */
 | 
			
		||||
	"IDLE",									/* CAPWAP_IDLE_STATE */
 | 
			
		||||
	"IDLE_TO_DISCOVERY",					/* CAPWAP_IDLE_TO_DISCOVERY_STATE */
 | 
			
		||||
	"IDLE_TO_DTLS_SETUP",					/* CAPWAP_IDLE_TO_DTLS_SETUP_STATE */
 | 
			
		||||
	"DISCOVERY",							/* CAPWAP_DISCOVERY_STATE */
 | 
			
		||||
	"DISCOVERY_TO_IDLE",					/* CAPWAP_DISCOVERY_TO_IDLE_STATE */
 | 
			
		||||
	"DISCOVERY_TO_SULKING",					/* CAPWAP_DISCOVERY_TO_SULKING_STATE */
 | 
			
		||||
	"DISCOVERY_TO_DTLS_SETUP",				/* CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE */
 | 
			
		||||
	"SULKING",								/* CAPWAP_SULKING_STATE */
 | 
			
		||||
	"SULKING_TO_IDLE",						/* CAPWAP_SULKING_TO_IDLE_STATE */
 | 
			
		||||
	"DTLS_SETUP",							/* CAPWAP_DTLS_SETUP_STATE */
 | 
			
		||||
	"DTLS_SETUP_TO_IDLE",					/* CAPWAP_DTLS_SETUP_TO_IDLE_STATE */
 | 
			
		||||
	"DTLS_SETUP_TO_SULKING",				/* CAPWAP_DTLS_SETUP_TO_SULKING_STATE */
 | 
			
		||||
	"DTLS_SETUP_TO_AUTHORIZE",				/* CAPWAP_DTLS_SETUP_TO_AUTHORIZE_STATE */
 | 
			
		||||
	"AUTHORIZE",							/* CAPWAP_AUTHORIZE_STATE */
 | 
			
		||||
	"AUTHORIZE_TO_DTLS_SETUP",				/* CAPWAP_AUTHORIZE_TO_DTLS_SETUP_STATE */
 | 
			
		||||
	"AUTHORIZE_TO_DTLS_CONNECT",			/* CAPWAP_AUTHORIZE_TO_DTLS_CONNECT_STATE */
 | 
			
		||||
	"AUTHORIZE_TO_DTLS_TEARDOWN",			/* CAPWAP_AUTHORIZE_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"DTLS_CONNECT",							/* CAPWAP_DTLS_CONNECT_STATE */
 | 
			
		||||
	"DTLS_CONNECT_TO_DTLS_TEARDOWN",		/* CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"DTLS_CONNECT_TO_JOIN",					/* CAPWAP_DTLS_CONNECT_TO_JOIN_STATE */
 | 
			
		||||
	"DTLS_TEARDOWN",						/* CAPWAP_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"DTLS_TEARDOWN_TO_IDLE",				/* CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE */
 | 
			
		||||
	"DTLS_TEARDOWN_TO_SULKING",				/* CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE */
 | 
			
		||||
	"DTLS_TEARDOWN_TO_DEAD",				/* CAPWAP_DTLS_TEARDOWN_TO_DEAD_STATE */
 | 
			
		||||
	"JOIN",									/* CAPWAP_JOIN_STATE */
 | 
			
		||||
	"POST_JOIN",								/* CAPWAP_POSTJOIN_STATE */
 | 
			
		||||
	"JOIN_TO_DTLS_TEARDOWN",				/* CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"JOIN_TO_IMAGE_DATA",					/* CAPWAP_JOIN_TO_IMAGE_DATA_STATE */
 | 
			
		||||
	"JOIN_TO_CONFIGURE",					/* CAPWAP_JOIN_TO_CONFIGURE_STATE */
 | 
			
		||||
	"IMAGE_DATA",							/* CAPWAP_IMAGE_DATA_STATE */
 | 
			
		||||
	"IMAGE_DATA_TO_RESET",					/* CAPWAP_IMAGE_DATA_TO_RESET_STATE */
 | 
			
		||||
	"IMAGE_DATA_TO_DTLS_TEARDOWN",			/* CAPWAP_IMAGE_DATA_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"CONFIGURE",							/* CAPWAP_CONFIGURE_STATE */
 | 
			
		||||
	"CONFIGURE_TO_RESET",					/* CAPWAP_CONFIGURE_TO_RESET_STATE */
 | 
			
		||||
	"CONFIGURE_TO_DTLS_TEARDOWN",			/* CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"CONFIGURE_TO_DATA_CHECK",				/* CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE */
 | 
			
		||||
	"RESET",								/* CAPWAP_RESET_STATE */
 | 
			
		||||
	"RESET_TO_DTLS_TEARDOWN",				/* CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"DATA_CHECK",							/* CAPWAP_DATA_CHECK_STATE */
 | 
			
		||||
	"DATA_CHECK_TO_DTLS_TEARDOWN",			/* CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"DATA_CHECK_TO_RUN",					/* CAPWAP_DATA_CHECK_TO_RUN_STATE */
 | 
			
		||||
	"RUN",									/* CAPWAP_RUN_STATE */
 | 
			
		||||
	"RUN_TO_DTLS_TEARDOWN",					/* CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE */
 | 
			
		||||
	"RUN_TO_RESET",							/* CAPWAP_RUN_TO_RESET_STATE */
 | 
			
		||||
	"DEAD"									/* CAPWAP_DEAD_STATE */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
char* capwap_dfa_getname(int state) {
 | 
			
		||||
	if ((state < 0) || (state > CAPWAP_LAST_STATE)) {
 | 
			
		||||
		return "";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return l_nameofstate[state];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								src/common/capwap_dfa.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/common/capwap_dfa.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
			
		||||
#ifndef __CAPWAP_DFA_HEADER__
 | 
			
		||||
#define __CAPWAP_DFA_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_UNDEF_STATE								-1
 | 
			
		||||
#define CAPWAP_START_STATE								0
 | 
			
		||||
#define CAPWAP_START_TO_IDLE_STATE						1
 | 
			
		||||
#define CAPWAP_IDLE_STATE								2
 | 
			
		||||
#define CAPWAP_IDLE_TO_DISCOVERY_STATE					3
 | 
			
		||||
#define CAPWAP_IDLE_TO_DTLS_SETUP_STATE					4
 | 
			
		||||
#define CAPWAP_DISCOVERY_STATE							5
 | 
			
		||||
#define CAPWAP_DISCOVERY_TO_IDLE_STATE					6
 | 
			
		||||
#define CAPWAP_DISCOVERY_TO_SULKING_STATE				7
 | 
			
		||||
#define CAPWAP_DISCOVERY_TO_DTLS_SETUP_STATE			8
 | 
			
		||||
#define CAPWAP_SULKING_STATE							9
 | 
			
		||||
#define CAPWAP_SULKING_TO_IDLE_STATE					10
 | 
			
		||||
#define CAPWAP_DTLS_SETUP_STATE							11
 | 
			
		||||
#define CAPWAP_DTLS_SETUP_TO_IDLE_STATE					12
 | 
			
		||||
#define CAPWAP_DTLS_SETUP_TO_SULKING_STATE				13
 | 
			
		||||
#define CAPWAP_DTLS_SETUP_TO_AUTHORIZE_STATE			14
 | 
			
		||||
#define CAPWAP_AUTHORIZE_STATE							15
 | 
			
		||||
#define CAPWAP_AUTHORIZE_TO_DTLS_SETUP_STATE			16
 | 
			
		||||
#define CAPWAP_AUTHORIZE_TO_DTLS_CONNECT_STATE			17
 | 
			
		||||
#define CAPWAP_AUTHORIZE_TO_DTLS_TEARDOWN_STATE			18
 | 
			
		||||
#define CAPWAP_DTLS_CONNECT_STATE						19
 | 
			
		||||
#define CAPWAP_DTLS_CONNECT_TO_DTLS_TEARDOWN_STATE		20
 | 
			
		||||
#define CAPWAP_DTLS_CONNECT_TO_JOIN_STATE				21
 | 
			
		||||
#define CAPWAP_DTLS_TEARDOWN_STATE						22
 | 
			
		||||
#define CAPWAP_DTLS_TEARDOWN_TO_IDLE_STATE				23
 | 
			
		||||
#define CAPWAP_DTLS_TEARDOWN_TO_SULKING_STATE			24
 | 
			
		||||
#define CAPWAP_DTLS_TEARDOWN_TO_DEAD_STATE				25
 | 
			
		||||
#define CAPWAP_JOIN_STATE								26
 | 
			
		||||
#define CAPWAP_POSTJOIN_STATE							27
 | 
			
		||||
#define CAPWAP_JOIN_TO_DTLS_TEARDOWN_STATE				28
 | 
			
		||||
#define CAPWAP_JOIN_TO_IMAGE_DATA_STATE					29
 | 
			
		||||
#define CAPWAP_JOIN_TO_CONFIGURE_STATE					30
 | 
			
		||||
#define CAPWAP_IMAGE_DATA_STATE							31
 | 
			
		||||
#define CAPWAP_IMAGE_DATA_TO_RESET_STATE				32
 | 
			
		||||
#define CAPWAP_IMAGE_DATA_TO_DTLS_TEARDOWN_STATE		33
 | 
			
		||||
#define CAPWAP_CONFIGURE_STATE							34
 | 
			
		||||
#define CAPWAP_CONFIGURE_TO_RESET_STATE					35
 | 
			
		||||
#define CAPWAP_CONFIGURE_TO_DTLS_TEARDOWN_STATE			36
 | 
			
		||||
#define CAPWAP_CONFIGURE_TO_DATA_CHECK_STATE			37
 | 
			
		||||
#define CAPWAP_RESET_STATE								38
 | 
			
		||||
#define CAPWAP_RESET_TO_DTLS_TEARDOWN_STATE				39
 | 
			
		||||
#define CAPWAP_DATA_CHECK_STATE							40
 | 
			
		||||
#define CAPWAP_DATA_CHECK_TO_DTLS_TEARDOWN_STATE		41
 | 
			
		||||
#define CAPWAP_DATA_CHECK_TO_RUN_STATE					42
 | 
			
		||||
#define CAPWAP_RUN_STATE								43
 | 
			
		||||
#define CAPWAP_RUN_TO_DTLS_TEARDOWN_STATE				44
 | 
			
		||||
#define CAPWAP_RUN_TO_RESET_STATE						45
 | 
			
		||||
#define CAPWAP_DEAD_STATE								46
 | 
			
		||||
#define CAPWAP_LAST_STATE								46
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
char* capwap_dfa_getname(int state);
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_DFA_HEADER__ */
 | 
			
		||||
							
								
								
									
										785
									
								
								src/common/capwap_dtls.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										785
									
								
								src/common/capwap_dtls.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,785 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_dtls.h"
 | 
			
		||||
#include "capwap_protocol.h"
 | 
			
		||||
 | 
			
		||||
#include <openssl/bio.h>
 | 
			
		||||
#include <openssl/err.h>
 | 
			
		||||
#include <openssl/engine.h>
 | 
			
		||||
#include <openssl/conf.h>
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_DTLS_CERT_VERIFY_DEPTH		1
 | 
			
		||||
#define	CAPWAP_DTLS_MTU_SIZE				16384
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int capwap_bio_method_new(BIO* bio);
 | 
			
		||||
static int capwap_bio_method_free(BIO* bio);
 | 
			
		||||
static int capwap_bio_method_puts(BIO* bio, const char* str);
 | 
			
		||||
static int capwap_bio_method_read(BIO* bio, char* str, int length);
 | 
			
		||||
static int capwap_bio_method_write(BIO* bio, const char* str, int length);
 | 
			
		||||
static long capwap_bio_method_ctrl(BIO* bio, int cmd, long num, void* ptr);
 | 
			
		||||
 | 
			
		||||
/* OpenSSL BIO methods */
 | 
			
		||||
static BIO_METHOD bio_methods_memory = {
 | 
			
		||||
	BIO_TYPE_DGRAM,
 | 
			
		||||
	"dtls capwap packet",
 | 
			
		||||
	capwap_bio_method_write,
 | 
			
		||||
	capwap_bio_method_read,
 | 
			
		||||
	capwap_bio_method_puts,
 | 
			
		||||
	NULL,
 | 
			
		||||
	capwap_bio_method_ctrl,
 | 
			
		||||
	capwap_bio_method_new,
 | 
			
		||||
	capwap_bio_method_free,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* OpenSSL BIO custom data */
 | 
			
		||||
struct bio_capwap_data {
 | 
			
		||||
	int mtu;
 | 
			
		||||
	struct sockaddr_storage peer;
 | 
			
		||||
	struct capwap_dtls* dtls;
 | 
			
		||||
	capwap_bio_send send;
 | 
			
		||||
	void* param;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static BIO* capwap_bio_new() {
 | 
			
		||||
	BIO* result;
 | 
			
		||||
 | 
			
		||||
	result = BIO_new(&bio_methods_memory);
 | 
			
		||||
	if (result) {
 | 
			
		||||
		memset(result->ptr, 0, sizeof(struct bio_capwap_data));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int capwap_bio_method_new(BIO* bio) {
 | 
			
		||||
	bio->init = 1;
 | 
			
		||||
	bio->num = 0;
 | 
			
		||||
	bio->flags = 0;
 | 
			
		||||
	bio->ptr = (char*)capwap_alloc(sizeof(struct bio_capwap_data));
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int capwap_bio_method_free(BIO* bio) {
 | 
			
		||||
	if (bio == NULL) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	} else if (bio->ptr) {
 | 
			
		||||
		capwap_free(bio->ptr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int capwap_bio_method_puts(BIO* bio, const char* str) {
 | 
			
		||||
	return capwap_bio_method_write(bio, str, strlen(str));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int capwap_bio_method_read(BIO* bio, char* str, int length) {
 | 
			
		||||
	struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
 | 
			
		||||
	struct capwap_dtls_header* dtlspreamble;
 | 
			
		||||
	int size;
 | 
			
		||||
 | 
			
		||||
	/* Check read packet */	
 | 
			
		||||
	if ((data->dtls->length < sizeof(struct capwap_dtls_header)) || !data->dtls->buffer) {
 | 
			
		||||
		if (!data->dtls->length && !data->dtls->buffer) {
 | 
			
		||||
			BIO_set_retry_read(bio);		/* Notify empty buffer */
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Check DTLS Capwap Preamble */
 | 
			
		||||
	dtlspreamble = (struct capwap_dtls_header*)data->dtls->buffer;
 | 
			
		||||
	if ((dtlspreamble->preamble.version != CAPWAP_PROTOCOL_VERSION) || (dtlspreamble->preamble.type != CAPWAP_PREAMBLE_DTLS_HEADER)) {
 | 
			
		||||
		capwap_logging_debug("Wrong DTLS Capwap Preamble");
 | 
			
		||||
		return -1;		/* Wrong DTLS Capwap Preamble */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	size = data->dtls->length - sizeof(struct capwap_dtls_header);
 | 
			
		||||
	data->dtls->length = 0;
 | 
			
		||||
 | 
			
		||||
	data->dtls->buffer += sizeof(struct capwap_dtls_header);
 | 
			
		||||
	if (size > length) {
 | 
			
		||||
		data->dtls->buffer = NULL;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Copy DTLS packet */
 | 
			
		||||
	memcpy(str, data->dtls->buffer, size);
 | 
			
		||||
	data->dtls->buffer = NULL;
 | 
			
		||||
 | 
			
		||||
	return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int capwap_bio_method_write(BIO* bio, const char* str, int length) {
 | 
			
		||||
	struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
 | 
			
		||||
	char buffer[CAPWAP_MAX_PACKET_SIZE];
 | 
			
		||||
	struct capwap_dtls_header* dtlspreamble = (struct capwap_dtls_header*)&buffer[0];
 | 
			
		||||
 | 
			
		||||
	/* Check for maxium size of packet */
 | 
			
		||||
	if (length > (CAPWAP_MAX_PACKET_SIZE - sizeof(struct capwap_dtls_header))) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	/* Create DTLS Capwap Preamble */
 | 
			
		||||
	dtlspreamble->preamble.version = CAPWAP_PROTOCOL_VERSION;
 | 
			
		||||
	dtlspreamble->preamble.type = CAPWAP_PREAMBLE_DTLS_HEADER;
 | 
			
		||||
	dtlspreamble->reserved1 = dtlspreamble->reserved2 = dtlspreamble->reserved3 = 0;
 | 
			
		||||
	memcpy(&buffer[0] + sizeof(struct capwap_dtls_header), str, length);
 | 
			
		||||
 | 
			
		||||
	/* Send packet */
 | 
			
		||||
	if (!data->send(data->dtls, buffer, length + sizeof(struct capwap_dtls_header), data->param)) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Don't return size of DTLS Capwap Preamble */
 | 
			
		||||
	return length;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static long capwap_bio_method_ctrl(BIO* bio, int cmd, long num, void* ptr) {
 | 
			
		||||
	long result = 1;
 | 
			
		||||
	struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
 | 
			
		||||
 | 
			
		||||
	switch (cmd) {
 | 
			
		||||
		case BIO_CTRL_RESET: {
 | 
			
		||||
			result = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_EOF: {
 | 
			
		||||
			result = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_INFO: {
 | 
			
		||||
			result = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_GET_CLOSE: {
 | 
			
		||||
			result = bio->shutdown;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_SET_CLOSE: {
 | 
			
		||||
			bio->shutdown = (int)num;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_WPENDING:
 | 
			
		||||
		case BIO_CTRL_PENDING: {
 | 
			
		||||
			result = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_DUP:
 | 
			
		||||
		case BIO_CTRL_FLUSH: {
 | 
			
		||||
			result = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_PUSH: {
 | 
			
		||||
			result = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_POP: {
 | 
			
		||||
			result = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_DGRAM_QUERY_MTU: {
 | 
			
		||||
			data->mtu = CAPWAP_DTLS_MTU_SIZE;
 | 
			
		||||
			result = data->mtu;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_DGRAM_GET_MTU: {
 | 
			
		||||
			result = data->mtu;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case BIO_CTRL_DGRAM_SET_MTU: {
 | 
			
		||||
			data->mtu = (int)num;
 | 
			
		||||
			result = data->mtu;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_DGRAM_SET_PEER: {
 | 
			
		||||
			memcpy(&data->peer, ptr, sizeof(struct sockaddr_storage));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case BIO_CTRL_DGRAM_GET_PEER: {
 | 
			
		||||
			memcpy(ptr, &data->peer, sizeof(struct sockaddr_storage));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		default: {
 | 
			
		||||
			result = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_crypt_init() {
 | 
			
		||||
	SSL_load_error_strings();
 | 
			
		||||
	SSL_library_init();
 | 
			
		||||
	OpenSSL_add_all_algorithms();
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_crypt_free() {
 | 
			
		||||
	ERR_remove_state(0);
 | 
			
		||||
	ERR_free_strings();
 | 
			
		||||
	
 | 
			
		||||
	ENGINE_cleanup();
 | 
			
		||||
	EVP_cleanup();
 | 
			
		||||
	
 | 
			
		||||
	CONF_modules_finish();
 | 
			
		||||
	CONF_modules_free();
 | 
			
		||||
	CONF_modules_unload(1);
 | 
			
		||||
	
 | 
			
		||||
	CRYPTO_cleanup_all_ex_data();
 | 
			
		||||
	sk_SSL_COMP_free (SSL_COMP_get_compression_methods()); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int check_passwd(char* buffer, int size, int rwflag, void* userdata) {
 | 
			
		||||
	int length;
 | 
			
		||||
	struct capwap_dtls_context* dtlscontext = (struct capwap_dtls_context*)userdata;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(dtlscontext != NULL);
 | 
			
		||||
	ASSERT(dtlscontext->mode == CAPWAP_DTLS_MODE_CERTIFICATE);
 | 
			
		||||
	ASSERT(dtlscontext->cert.pwdprivatekey != NULL);
 | 
			
		||||
 | 
			
		||||
	length = strlen(dtlscontext->cert.pwdprivatekey);
 | 
			
		||||
	if (!buffer || (size < (length + 1))) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	strcpy(buffer, dtlscontext->cert.pwdprivatekey);
 | 
			
		||||
	return length;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int verify_certificate(int ok, X509_STORE_CTX* ctx) {
 | 
			
		||||
	int err;
 | 
			
		||||
	int depth;
 | 
			
		||||
	X509* err_cert;
 | 
			
		||||
	char buf[256];
 | 
			
		||||
	int preverify_ok = 1;
 | 
			
		||||
 | 
			
		||||
	err_cert = X509_STORE_CTX_get_current_cert(ctx);
 | 
			
		||||
 | 
			
		||||
	err = X509_STORE_CTX_get_error(ctx);
 | 
			
		||||
	X509_verify_cert_error_string(err);
 | 
			
		||||
 | 
			
		||||
	depth = X509_STORE_CTX_get_error_depth(ctx);
 | 
			
		||||
 | 
			
		||||
	X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
 | 
			
		||||
 | 
			
		||||
	if (depth > CAPWAP_DTLS_CERT_VERIFY_DEPTH) {
 | 
			
		||||
		preverify_ok = 0;
 | 
			
		||||
		err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
 | 
			
		||||
		X509_STORE_CTX_set_error(ctx, err);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
 | 
			
		||||
		X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return preverify_ok;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int create_cookie(SSL* ssl, unsigned char* cookie, unsigned int* cookie_len) {
 | 
			
		||||
	int length;
 | 
			
		||||
	unsigned char* buffer;
 | 
			
		||||
	struct sockaddr_storage peer;
 | 
			
		||||
	struct capwap_app_data* appdata;
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	appdata = (struct capwap_app_data*)SSL_get_app_data(ssl);
 | 
			
		||||
	if (!appdata) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Read peer information */
 | 
			
		||||
	BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);
 | 
			
		||||
 | 
			
		||||
	/* Create buffer with peer's address and port */
 | 
			
		||||
	if (peer.ss_family == AF_INET) {
 | 
			
		||||
		length = sizeof(struct in_addr) + sizeof(in_port_t);
 | 
			
		||||
	} else if (peer.ss_family == AF_INET6) {
 | 
			
		||||
		length = sizeof(struct in6_addr) + sizeof(in_port_t);
 | 
			
		||||
	} else {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	buffer = capwap_alloc(length);
 | 
			
		||||
	if (!buffer) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (peer.ss_family == AF_INET) {
 | 
			
		||||
		struct sockaddr_in* peeripv4 = (struct sockaddr_in*)&peer;
 | 
			
		||||
 | 
			
		||||
		memcpy(buffer, &peeripv4->sin_port, sizeof(in_port_t));
 | 
			
		||||
		memcpy(buffer + sizeof(in_port_t), &peeripv4->sin_addr, sizeof(struct in_addr));
 | 
			
		||||
	} else if (peer.ss_family == AF_INET6) {
 | 
			
		||||
		struct sockaddr_in6* peeripv6 = (struct sockaddr_in6*)&peer;
 | 
			
		||||
 | 
			
		||||
		memcpy(buffer, &peeripv6->sin6_port, sizeof(in_port_t));
 | 
			
		||||
		memcpy(buffer + sizeof(in_port_t), &peeripv6->sin6_addr, sizeof(struct in6_addr));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Calculate HMAC of buffer using the secret */
 | 
			
		||||
	HMAC(EVP_sha1(), appdata->cookie, CAPWAP_COOKIE_SECRET_LENGTH, buffer, length, cookie, cookie_len);
 | 
			
		||||
	capwap_free(buffer);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int generate_cookie(SSL* ssl, unsigned char* cookie, unsigned int* cookie_len) {
 | 
			
		||||
	unsigned int resultlength;
 | 
			
		||||
	unsigned char result[EVP_MAX_MD_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (!create_cookie(ssl, &result[0], &resultlength)) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Cookie generated */
 | 
			
		||||
	memcpy(cookie, result, resultlength);
 | 
			
		||||
	*cookie_len = resultlength;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int verify_cookie(SSL* ssl, unsigned char* cookie, unsigned int cookie_len) {
 | 
			
		||||
	unsigned int resultlength;
 | 
			
		||||
	unsigned char result[EVP_MAX_MD_SIZE];
 | 
			
		||||
 | 
			
		||||
	if (!create_cookie(ssl, &result[0], &resultlength)) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check cookie */
 | 
			
		||||
	if ((cookie_len != resultlength) || (memcmp(result, cookie, resultlength) != 0)) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_crypt_createcontext(struct capwap_dtls_context* dtlscontext, struct capwap_dtls_param* param) {
 | 
			
		||||
	int length;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(dtlscontext != NULL);
 | 
			
		||||
	ASSERT(param != NULL);
 | 
			
		||||
	
 | 
			
		||||
	memset(dtlscontext, 0, sizeof(struct capwap_dtls_context));
 | 
			
		||||
	dtlscontext->type = param->type;
 | 
			
		||||
	dtlscontext->mode = param->mode;
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc context */
 | 
			
		||||
	dtlscontext->sslcontext = SSL_CTX_new(((param->type == CAPWAP_DTLS_SERVER) ? DTLSv1_server_method() : DTLSv1_client_method()));
 | 
			
		||||
	if (!dtlscontext->sslcontext) {
 | 
			
		||||
		capwap_logging_debug("Error to initialize dtls context");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (dtlscontext->mode == CAPWAP_DTLS_MODE_CERTIFICATE) {
 | 
			
		||||
		/* Check context */
 | 
			
		||||
		if (!param->cert.filecert || !strlen(param->cert.filecert)) {
 | 
			
		||||
			capwap_logging_debug("Error, request certificate file");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		} else if (!param->cert.filekey || !strlen(param->cert.filekey)) {
 | 
			
		||||
			capwap_logging_debug("Error, request privatekey file");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		} else if (!param->cert.fileca || !strlen(param->cert.fileca)) {
 | 
			
		||||
			capwap_logging_debug("Error, request ca file");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* Public certificate */
 | 
			
		||||
		if (!SSL_CTX_use_certificate_file(dtlscontext->sslcontext, param->cert.filecert, SSL_FILETYPE_PEM)) {
 | 
			
		||||
			capwap_logging_debug("Error to load certificate file");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* Passwork decrypt privatekey */
 | 
			
		||||
		length = (param->cert.pwdprivatekey ? strlen(param->cert.pwdprivatekey) : 0);
 | 
			
		||||
		dtlscontext->cert.pwdprivatekey = (char*)capwap_alloc(sizeof(char) * (length + 1));
 | 
			
		||||
		if (length > 0) {
 | 
			
		||||
			strcpy(dtlscontext->cert.pwdprivatekey, param->cert.pwdprivatekey);
 | 
			
		||||
		}
 | 
			
		||||
		dtlscontext->cert.pwdprivatekey[length] = 0;
 | 
			
		||||
		
 | 
			
		||||
		SSL_CTX_set_default_passwd_cb(dtlscontext->sslcontext, check_passwd);
 | 
			
		||||
		SSL_CTX_set_default_passwd_cb_userdata(dtlscontext->sslcontext, dtlscontext);
 | 
			
		||||
		
 | 
			
		||||
		/* Private key */
 | 
			
		||||
		if (!SSL_CTX_use_PrivateKey_file(dtlscontext->sslcontext, param->cert.filekey, SSL_FILETYPE_PEM)) {
 | 
			
		||||
			capwap_logging_debug("Error to load private key file");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (!SSL_CTX_check_private_key(dtlscontext->sslcontext)) {
 | 
			
		||||
			capwap_logging_debug("Error to check private key");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* Certificate Authority */
 | 
			
		||||
		if (!SSL_CTX_load_verify_locations(dtlscontext->sslcontext, param->cert.fileca, NULL)) {
 | 
			
		||||
			capwap_logging_debug("Error to load ca file");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (!SSL_CTX_set_default_verify_paths(dtlscontext->sslcontext)) {
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* Verify certificate callback */
 | 
			
		||||
		SSL_CTX_set_verify(dtlscontext->sslcontext, ((param->type == CAPWAP_DTLS_SERVER) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_PEER), verify_certificate);
 | 
			
		||||
 | 
			
		||||
		/* 	Cipher list: 
 | 
			
		||||
				TLS_RSA_WITH_AES_128_CBC_SHA
 | 
			
		||||
				TLS_DHE_RSA_WITH_AES_128_CBC_SHA
 | 
			
		||||
				TLS_RSA_WITH_AES_256_CBC_SHA
 | 
			
		||||
				TLS_DHE_RSA_WITH_AES_256_CBC_SHA
 | 
			
		||||
		*/
 | 
			
		||||
		if (!SSL_CTX_set_cipher_list(dtlscontext->sslcontext, "AES128-SHA:DHE-RSA-AES128-SHA:AES256-SHA:DHE-RSA-AES256-SHA")) {
 | 
			
		||||
			capwap_logging_debug("Error to select cipher list");
 | 
			
		||||
			capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (dtlscontext->mode == CAPWAP_DTLS_MODE_PRESHAREDKEY) {
 | 
			
		||||
		/* TODO */
 | 
			
		||||
	} else {
 | 
			
		||||
		capwap_logging_debug("Invalid DTLS mode");
 | 
			
		||||
		capwap_crypt_freecontext(dtlscontext);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Cookie callback */
 | 
			
		||||
	RAND_bytes(dtlscontext->cookie, CAPWAP_COOKIE_SECRET_LENGTH);
 | 
			
		||||
	SSL_CTX_set_cookie_generate_cb(dtlscontext->sslcontext, generate_cookie);
 | 
			
		||||
	SSL_CTX_set_cookie_verify_cb(dtlscontext->sslcontext, verify_cookie);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	SSL_CTX_set_read_ahead(dtlscontext->sslcontext, 1);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_crypt_freecontext(struct capwap_dtls_context* dtlscontext) {
 | 
			
		||||
	ASSERT(dtlscontext != NULL);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	if (dtlscontext->mode == CAPWAP_DTLS_MODE_CERTIFICATE) {
 | 
			
		||||
		if (dtlscontext->cert.pwdprivatekey) {
 | 
			
		||||
			capwap_free(dtlscontext->cert.pwdprivatekey);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Free context */	
 | 
			
		||||
	if (dtlscontext->sslcontext) {
 | 
			
		||||
		SSL_CTX_free(dtlscontext->sslcontext);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(dtlscontext, 0, sizeof(struct capwap_dtls));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_crypt_createsession(struct capwap_dtls* dtls, int sessiontype, struct capwap_dtls_context* dtlscontext, capwap_bio_send biosend, void* param) {
 | 
			
		||||
	BIO* bio;
 | 
			
		||||
	struct capwap_app_data* appdata;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(dtls != NULL);
 | 
			
		||||
	ASSERT(dtlscontext != NULL);
 | 
			
		||||
	ASSERT(biosend != NULL);
 | 
			
		||||
 | 
			
		||||
	memset(dtls, 0, sizeof(struct capwap_dtls));
 | 
			
		||||
	
 | 
			
		||||
	/* Create ssl session */
 | 
			
		||||
	dtls->sslsession = SSL_new(dtlscontext->sslcontext);
 | 
			
		||||
	if (!dtls->sslsession) {
 | 
			
		||||
		capwap_logging_debug("Error to initialize dtls session");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create BIO */
 | 
			
		||||
	bio = capwap_bio_new();
 | 
			
		||||
	if (!bio) {
 | 
			
		||||
		capwap_logging_debug("Error to initialize bio");
 | 
			
		||||
		capwap_crypt_free(dtls);
 | 
			
		||||
		return 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
 | 
			
		||||
		data->dtls = dtls;
 | 
			
		||||
		data->send = biosend;
 | 
			
		||||
		data->param = param;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Configure BIO */
 | 
			
		||||
	SSL_set_bio(dtls->sslsession, bio, bio);
 | 
			
		||||
 | 
			
		||||
	/* In server mode enable cookie exchange */
 | 
			
		||||
	if (dtlscontext->type == CAPWAP_DTLS_SERVER) {
 | 
			
		||||
		SSL_set_options(dtls->sslsession, SSL_OP_COOKIE_EXCHANGE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Set static MTU size */
 | 
			
		||||
	SSL_set_options(dtls->sslsession, SSL_OP_NO_QUERY_MTU);
 | 
			
		||||
	SSL_set_mtu(dtls->sslsession, CAPWAP_DTLS_MTU_SIZE);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	SSL_set_verify_depth(dtls->sslsession, CAPWAP_DTLS_CERT_VERIFY_DEPTH + 1);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	SSL_set_read_ahead(dtls->sslsession, 1);
 | 
			
		||||
	
 | 
			
		||||
	if (dtlscontext->type == CAPWAP_DTLS_SERVER) {
 | 
			
		||||
		SSL_set_accept_state(dtls->sslsession);
 | 
			
		||||
	} else {
 | 
			
		||||
		SSL_set_connect_state(dtls->sslsession);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* SSL session app data */
 | 
			
		||||
	appdata = (struct capwap_app_data*)capwap_alloc(sizeof(struct capwap_app_data));
 | 
			
		||||
	if (!appdata) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	appdata->cookie = &dtlscontext->cookie[0];
 | 
			
		||||
	SSL_set_app_data(dtls->sslsession, (void*)appdata);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dtls->action = CAPWAP_DTLS_ACTION_NONE;
 | 
			
		||||
	dtls->session = sessiontype;
 | 
			
		||||
	dtls->enable = 1;
 | 
			
		||||
	
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
static int capwap_crypt_handshake(struct capwap_dtls* dtls) {
 | 
			
		||||
	int result;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(dtls != NULL);
 | 
			
		||||
	ASSERT(dtls->enable != 0);
 | 
			
		||||
	ASSERT((dtls->action == CAPWAP_DTLS_ACTION_NONE) || (dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE));
 | 
			
		||||
 | 
			
		||||
	ERR_clear_error();
 | 
			
		||||
	result = SSL_do_handshake(dtls->sslsession);
 | 
			
		||||
	if (result <= 0) {
 | 
			
		||||
		result = SSL_get_error(dtls->sslsession, result);
 | 
			
		||||
		if ((result == SSL_ERROR_WANT_READ) || (result == SSL_ERROR_WANT_WRITE)) {
 | 
			
		||||
			/* Incomplete handshake */
 | 
			
		||||
			dtls->action = CAPWAP_DTLS_ACTION_HANDSHAKE;
 | 
			
		||||
			return CAPWAP_HANDSHAKE_CONTINUE;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* Handshake error */
 | 
			
		||||
		dtls->action = CAPWAP_DTLS_ACTION_ERROR;
 | 
			
		||||
		return CAPWAP_HANDSHAKE_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Check certificate */
 | 
			
		||||
	result = SSL_get_verify_result(dtls->sslsession);
 | 
			
		||||
	if (result != X509_V_OK) {
 | 
			
		||||
		dtls->action = CAPWAP_DTLS_ACTION_ERROR;
 | 
			
		||||
		return CAPWAP_HANDSHAKE_ERROR;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Handshake complete */
 | 
			
		||||
	dtls->action = CAPWAP_DTLS_ACTION_DATA;
 | 
			
		||||
	return CAPWAP_HANDSHAKE_COMPLETE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_crypt_open(struct capwap_dtls* dtls, struct sockaddr_storage* peeraddr) {
 | 
			
		||||
	BIO_dgram_set_peer(SSL_get_rbio(dtls->sslsession), peeraddr);
 | 
			
		||||
	return capwap_crypt_handshake(dtls);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_crypt_close(struct capwap_dtls* dtls) {
 | 
			
		||||
	ASSERT(dtls != NULL);
 | 
			
		||||
	ASSERT(dtls->enable != 0);
 | 
			
		||||
	
 | 
			
		||||
	if ((dtls->action == CAPWAP_DTLS_ACTION_DATA) || (dtls->action == CAPWAP_DTLS_ACTION_SHUTDOWN)) {
 | 
			
		||||
		SSL_shutdown(dtls->sslsession);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Change bio send */
 | 
			
		||||
void capwap_crypt_change_bio_send(struct capwap_dtls* dtls, capwap_bio_send biosend, void* param) {
 | 
			
		||||
	BIO* bio;
 | 
			
		||||
 | 
			
		||||
	ASSERT(dtls != NULL);
 | 
			
		||||
	ASSERT(dtls->enable != 0);
 | 
			
		||||
	ASSERT(biosend != NULL);
 | 
			
		||||
 | 
			
		||||
	bio = SSL_get_wbio(dtls->sslsession);
 | 
			
		||||
	if ((bio != NULL) && (bio->ptr != NULL)) {
 | 
			
		||||
		struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
 | 
			
		||||
 | 
			
		||||
		data->send = biosend;
 | 
			
		||||
		data->param = param;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Change DTLS */
 | 
			
		||||
void capwap_crypt_change_dtls(struct capwap_dtls* dtls, struct capwap_dtls* newdtls) {
 | 
			
		||||
	BIO* bio;
 | 
			
		||||
 | 
			
		||||
	ASSERT(dtls != NULL);
 | 
			
		||||
	ASSERT(dtls->enable != 0);
 | 
			
		||||
	ASSERT(newdtls != NULL);
 | 
			
		||||
 | 
			
		||||
	memcpy(newdtls, dtls, sizeof(struct capwap_dtls));
 | 
			
		||||
 | 
			
		||||
	/* Update DTLS into BIO */
 | 
			
		||||
	bio = SSL_get_rbio(dtls->sslsession);
 | 
			
		||||
	if ((bio != NULL) && (bio->ptr != NULL)) {
 | 
			
		||||
		struct bio_capwap_data* data = (struct bio_capwap_data*)bio->ptr;
 | 
			
		||||
 | 
			
		||||
		data->dtls = newdtls;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_crypt_freesession(struct capwap_dtls* dtls) {
 | 
			
		||||
	ASSERT(dtls != NULL);
 | 
			
		||||
	
 | 
			
		||||
	/* Free SSL session */
 | 
			
		||||
	if (dtls->sslsession) {
 | 
			
		||||
		struct capwap_app_data* appdata = (struct capwap_app_data*)SSL_get_app_data(dtls->sslsession);
 | 
			
		||||
		if (appdata) {
 | 
			
		||||
			capwap_free(appdata);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		SSL_free(dtls->sslsession);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	memset(dtls, 0, sizeof(struct capwap_dtls));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* TODO: con SSL vengono utilizzati gli indirizzi predefiniti invece quelli specificati nella funzione. Reingegnerizzarla basandosi sul concetto di connessione */
 | 
			
		||||
int capwap_crypt_sendto(struct capwap_dtls* dtls, int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr) {
 | 
			
		||||
	ASSERT(sock >= 0);
 | 
			
		||||
	ASSERT(buffer != NULL);
 | 
			
		||||
	ASSERT(size > 0);
 | 
			
		||||
	ASSERT(sendtoaddr != NULL);
 | 
			
		||||
 | 
			
		||||
	if (!dtls || !dtls->enable) {
 | 
			
		||||
		return capwap_sendto(sock, buffer, size, sendfromaddr, sendtoaddr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Valid DTLS status */
 | 
			
		||||
	if (dtls->action != CAPWAP_DTLS_ACTION_DATA) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ERR_clear_error();
 | 
			
		||||
	return SSL_write(dtls->sslsession, buffer, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize) {
 | 
			
		||||
	int sslerror;
 | 
			
		||||
	int result = -1;
 | 
			
		||||
	char* clone = NULL;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(dtls != NULL);
 | 
			
		||||
	ASSERT(dtls->enable != 0);
 | 
			
		||||
	ASSERT((dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE) || (dtls->action == CAPWAP_DTLS_ACTION_DATA));
 | 
			
		||||
	ASSERT(dtls->buffer == NULL);
 | 
			
		||||
	ASSERT(dtls->length == 0);
 | 
			
		||||
	ASSERT(encrybuffer != NULL);
 | 
			
		||||
	ASSERT(size > 0);
 | 
			
		||||
	ASSERT(maxsize > 0);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	if (!plainbuffer) {
 | 
			
		||||
		clone = capwap_clone(encrybuffer, size);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	dtls->buffer = (clone ? clone : encrybuffer);
 | 
			
		||||
	dtls->length = size;
 | 
			
		||||
 | 
			
		||||
	/* */	
 | 
			
		||||
	if (dtls->action == CAPWAP_DTLS_ACTION_HANDSHAKE) {
 | 
			
		||||
		if (capwap_crypt_handshake(dtls) == CAPWAP_HANDSHAKE_ERROR) {
 | 
			
		||||
			capwap_logging_debug("Error in DTLS handshake");
 | 
			
		||||
			result = CAPWAP_ERROR_CLOSE;			/* Error handshake */
 | 
			
		||||
		} else {
 | 
			
		||||
			result = CAPWAP_ERROR_AGAIN;			/* Don't parsing DTLS packet */
 | 
			
		||||
		}
 | 
			
		||||
	} else if (dtls->action == CAPWAP_DTLS_ACTION_DATA) {
 | 
			
		||||
		ERR_clear_error();
 | 
			
		||||
		result = SSL_read(dtls->sslsession, (plainbuffer ? plainbuffer : encrybuffer), maxsize);
 | 
			
		||||
		if (!result) {
 | 
			
		||||
			int shutdown;
 | 
			
		||||
 | 
			
		||||
			/* Check shutdown status */
 | 
			
		||||
			shutdown = SSL_get_shutdown(dtls->sslsession);
 | 
			
		||||
			if (shutdown & SSL_RECEIVED_SHUTDOWN) {
 | 
			
		||||
				dtls->action = CAPWAP_DTLS_ACTION_SHUTDOWN;
 | 
			
		||||
				result = CAPWAP_ERROR_SHUTDOWN;
 | 
			
		||||
			} else {
 | 
			
		||||
				result = CAPWAP_ERROR_AGAIN;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (result < 0) {
 | 
			
		||||
			/* Check error */
 | 
			
		||||
			sslerror = SSL_get_error(dtls->sslsession, result);
 | 
			
		||||
			if ((sslerror == SSL_ERROR_WANT_READ) || (sslerror == SSL_ERROR_WANT_WRITE)) {
 | 
			
		||||
				result = CAPWAP_ERROR_AGAIN;			/* DTLS Renegotiation */
 | 
			
		||||
			} else {
 | 
			
		||||
				result = CAPWAP_ERROR_CLOSE;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Verify BIO read */
 | 
			
		||||
	ASSERT(dtls->buffer == NULL);
 | 
			
		||||
	ASSERT(dtls->length == 0);
 | 
			
		||||
 | 
			
		||||
	/* Free clone */
 | 
			
		||||
	if (clone) {
 | 
			
		||||
		capwap_free(clone);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								src/common/capwap_dtls.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/common/capwap_dtls.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,108 @@
 | 
			
		||||
#ifndef __CAPWAP_DTLS_HEADER__
 | 
			
		||||
#define __CAPWAP_DTLS_HEADER__
 | 
			
		||||
 | 
			
		||||
#include <openssl/ssl.h>
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_DTLS_CLIENT						0
 | 
			
		||||
#define CAPWAP_DTLS_SERVER						1
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_DTLS_MODE_NONE					0
 | 
			
		||||
#define CAPWAP_DTLS_MODE_CERTIFICATE			1
 | 
			
		||||
#define CAPWAP_DTLS_MODE_PRESHAREDKEY			2
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_DTLS_ACTION_NONE					0
 | 
			
		||||
#define CAPWAP_DTLS_ACTION_HANDSHAKE			1
 | 
			
		||||
#define CAPWAP_DTLS_ACTION_DATA					2
 | 
			
		||||
#define CAPWAP_DTLS_ACTION_SHUTDOWN				3
 | 
			
		||||
#define CAPWAP_DTLS_ACTION_ERROR				4
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_HANDSHAKE_ERROR					-1
 | 
			
		||||
#define CAPWAP_HANDSHAKE_CONTINUE				0
 | 
			
		||||
#define CAPWAP_HANDSHAKE_COMPLETE				1
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_DTLS_CONTROL_SESSION				0
 | 
			
		||||
#define CAPWAP_DTLS_DATA_SESSION				1
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_COOKIE_SECRET_LENGTH				16
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ERROR_AGAIN						0
 | 
			
		||||
#define CAPWAP_ERROR_SHUTDOWN					-1
 | 
			
		||||
#define CAPWAP_ERROR_CLOSE						-2
 | 
			
		||||
 | 
			
		||||
struct capwap_dtls_param {
 | 
			
		||||
	int type;
 | 
			
		||||
	int mode;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			int dummy;							/* TODO */
 | 
			
		||||
		} presharedkey;
 | 
			
		||||
	
 | 
			
		||||
		struct {
 | 
			
		||||
			/* Certificate files */
 | 
			
		||||
			char* filecert;
 | 
			
		||||
			char* filekey;
 | 
			
		||||
			char* fileca;
 | 
			
		||||
 | 
			
		||||
			/* Password for private key */
 | 
			
		||||
			char* pwdprivatekey;
 | 
			
		||||
		} cert;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_dtls_context {
 | 
			
		||||
	int type;
 | 
			
		||||
	int mode;
 | 
			
		||||
 | 
			
		||||
	SSL_CTX* sslcontext;
 | 
			
		||||
 | 
			
		||||
	/* Cookie */
 | 
			
		||||
	unsigned char cookie[CAPWAP_COOKIE_SECRET_LENGTH];
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			int dummy;							/* TODO */
 | 
			
		||||
		} presharedkey;
 | 
			
		||||
 | 
			
		||||
		struct {
 | 
			
		||||
			char* pwdprivatekey;				/* Password for private key */
 | 
			
		||||
		} cert;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_dtls {
 | 
			
		||||
	int enable;
 | 
			
		||||
	int action;
 | 
			
		||||
	int session;
 | 
			
		||||
 | 
			
		||||
	SSL* sslsession;
 | 
			
		||||
 | 
			
		||||
	/* Buffer read */
 | 
			
		||||
	void* buffer;
 | 
			
		||||
	int length;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_app_data {
 | 
			
		||||
	unsigned char* cookie;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef int(*capwap_bio_send)(struct capwap_dtls* dtls, char* buffer, int length, void* param);
 | 
			
		||||
 | 
			
		||||
int capwap_crypt_init();
 | 
			
		||||
void capwap_crypt_free();
 | 
			
		||||
 | 
			
		||||
int capwap_crypt_createcontext(struct capwap_dtls_context* dtlscontext, struct capwap_dtls_param* param);
 | 
			
		||||
void capwap_crypt_freecontext(struct capwap_dtls_context* dtlscontext);
 | 
			
		||||
 | 
			
		||||
int capwap_crypt_createsession(struct capwap_dtls* dtls, int sessiontype, struct capwap_dtls_context* dtlscontext, capwap_bio_send biosend, void* param);
 | 
			
		||||
void capwap_crypt_freesession(struct capwap_dtls* dtls);
 | 
			
		||||
 | 
			
		||||
int capwap_crypt_open(struct capwap_dtls* dtls, struct sockaddr_storage* peeraddr);
 | 
			
		||||
void capwap_crypt_close(struct capwap_dtls* dtls);
 | 
			
		||||
void capwap_crypt_change_bio_send(struct capwap_dtls* dtls, capwap_bio_send biosend, void* param);
 | 
			
		||||
void capwap_crypt_change_dtls(struct capwap_dtls* dtls, struct capwap_dtls* newdtls);
 | 
			
		||||
 | 
			
		||||
int capwap_crypt_sendto(struct capwap_dtls* dtls, int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
 | 
			
		||||
int capwap_decrypt_packet(struct capwap_dtls* dtls, void* encrybuffer, int size, void* plainbuffer, int maxsize);
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_DTLS_HEADER__ */
 | 
			
		||||
							
								
								
									
										1373
									
								
								src/common/capwap_element.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1373
									
								
								src/common/capwap_element.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										288
									
								
								src/common/capwap_element.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								src/common/capwap_element.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,288 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_HEADER__
 | 
			
		||||
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "capwap_list.h"
 | 
			
		||||
 | 
			
		||||
/* Standard message elements 1 -> 52 (1 - 1023) */
 | 
			
		||||
#define CAPWAP_MESSAGE_ELEMENTS_START				1
 | 
			
		||||
#define CAPWAP_MESSAGE_ELEMENTS_STOP				53
 | 
			
		||||
#define CAPWAP_MESSAGE_ELEMENTS_COUNT				((CAPWAP_MESSAGE_ELEMENTS_STOP - CAPWAP_MESSAGE_ELEMENTS_START) + 1)
 | 
			
		||||
#define IS_MESSAGE_ELEMENTS(x)						(((x >= CAPWAP_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
 | 
			
		||||
 | 
			
		||||
/* 802.11 message elements 1024 -> 1024 (1024 - 2047) */
 | 
			
		||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_START			1024
 | 
			
		||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_STOP			1048
 | 
			
		||||
#define CAPWAP_80211_MESSAGE_ELEMENTS_COUNT			((CAPWAP_80211_MESSAGE_ELEMENTS_STOP - CAPWAP_80211_MESSAGE_ELEMENTS_START) + 1)
 | 
			
		||||
#define IS_80211_MESSAGE_ELEMENTS(x)				(((x >= CAPWAP_80211_MESSAGE_ELEMENTS_START) && (x <= CAPWAP_80211_MESSAGE_ELEMENTS_STOP)) ? 1 : 0)
 | 
			
		||||
 | 
			
		||||
/* Message element */
 | 
			
		||||
struct capwap_message_element {
 | 
			
		||||
	unsigned short type;
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	char data[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
typedef struct capwap_message_element*(*capwap_create_message_element)(void* data, unsigned long length);
 | 
			
		||||
typedef int(*capwap_validate_message_element)(struct capwap_message_element* element);
 | 
			
		||||
typedef void*(*capwap_parsing_message_element)(struct capwap_message_element* element);
 | 
			
		||||
typedef void(*capwap_free_message_element)(void*);
 | 
			
		||||
 | 
			
		||||
struct capwap_message_elements_func {
 | 
			
		||||
	capwap_create_message_element create;
 | 
			
		||||
	capwap_validate_message_element check;
 | 
			
		||||
	capwap_parsing_message_element parsing;
 | 
			
		||||
	capwap_free_message_element free;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_elements_func* capwap_get_message_element(unsigned long code);
 | 
			
		||||
 | 
			
		||||
/*********************************************************************************************************************/
 | 
			
		||||
/* Standard message elements */
 | 
			
		||||
#include "capwap_element_acdescriptor.h"				/* 00001 */
 | 
			
		||||
#include "capwap_element_acipv4list.h"					/* 00002 */
 | 
			
		||||
#include "capwap_element_acipv6list.h"					/* 00003 */
 | 
			
		||||
#include "capwap_element_acname.h"						/* 00004 */
 | 
			
		||||
#include "capwap_element_acnamepriority.h" 				/* 00005 */
 | 
			
		||||
/* 00006 */
 | 
			
		||||
/* 00007 */
 | 
			
		||||
/* 00008 */
 | 
			
		||||
/* Reserved */											/* 00009 */
 | 
			
		||||
#include "capwap_element_controlipv4.h"					/* 00010 */
 | 
			
		||||
#include "capwap_element_controlipv6.h"					/* 00011 */
 | 
			
		||||
#include "capwap_element_timers.h"						/* 00012 */
 | 
			
		||||
/* 00013 */
 | 
			
		||||
/* 00014 */
 | 
			
		||||
/* 00015 */
 | 
			
		||||
#include "capwap_element_decrypterrorreportperiod.h"	/* 00016 */
 | 
			
		||||
/* 00017 */
 | 
			
		||||
/* 00018 */
 | 
			
		||||
/* Reserved */											/* 00019 */
 | 
			
		||||
#include "capwap_element_discoverytype.h"				/* 00020 */
 | 
			
		||||
/* 00021 */
 | 
			
		||||
/* 00022 */
 | 
			
		||||
#include "capwap_element_idletimeout.h"					/* 00023 */
 | 
			
		||||
/* 00024 */
 | 
			
		||||
#include "capwap_element_imageidentifier.h"				/* 00025 */
 | 
			
		||||
/* 00026 */
 | 
			
		||||
/* 00027 */
 | 
			
		||||
#include "capwap_element_location.h"					/* 00028 */
 | 
			
		||||
#include "capwap_element_maximumlength.h"				/* 00029 */
 | 
			
		||||
#include "capwap_element_localipv4.h"					/* 00030 */
 | 
			
		||||
#include "capwap_element_radioadmstate.h"				/* 00031 */
 | 
			
		||||
#include "capwap_element_radiooprstate.h"				/* 00032 */
 | 
			
		||||
#include "capwap_element_resultcode.h"					/* 00033 */
 | 
			
		||||
#include "capwap_element_returnedmessage.h"				/* 00034 */
 | 
			
		||||
#include "capwap_element_sessionid.h"					/* 00035 */
 | 
			
		||||
#include "capwap_element_statisticstimer.h"				/* 00036 */
 | 
			
		||||
#include "capwap_element_vendorpayload.h"				/* 00037 */
 | 
			
		||||
#include "capwap_element_wtpboarddata.h"				/* 00038 */
 | 
			
		||||
#include "capwap_element_wtpdescriptor.h"				/* 00039 */
 | 
			
		||||
#include "capwap_element_wtpfallback.h"					/* 00040 */
 | 
			
		||||
#include "capwap_element_wtpframetunnelmode.h"			/* 00041 */
 | 
			
		||||
/* Reserved */											/* 00042 */
 | 
			
		||||
/* Reserved */											/* 00043 */
 | 
			
		||||
#include "capwap_element_wtpmactype.h"					/* 00044 */
 | 
			
		||||
#include "capwap_element_wtpname.h"						/* 00045 */
 | 
			
		||||
/* Reserved */											/* 00046 */
 | 
			
		||||
/* 00047 */
 | 
			
		||||
#include "capwap_element_wtprebootstat.h"				/* 00048 */
 | 
			
		||||
#include "capwap_element_wtpstaticipaddress.h"			/* 00049 */
 | 
			
		||||
#include "capwap_element_localipv6.h"					/* 00050 */
 | 
			
		||||
#include "capwap_element_transport.h"					/* 00051 */
 | 
			
		||||
#include "capwap_element_mtudiscovery.h"				/* 00052 */
 | 
			
		||||
#include "capwap_element_ecnsupport.h"					/* 00053 */
 | 
			
		||||
 | 
			
		||||
/* IEEE 802.11 message elements */
 | 
			
		||||
#include "capwap_element_80211_wtpradioinformation.h"	/* 01048 */
 | 
			
		||||
 | 
			
		||||
/*********************************************************************************************************************/
 | 
			
		||||
struct capwap_element_discovery_request {
 | 
			
		||||
	struct capwap_discoverytype_element* discoverytype;
 | 
			
		||||
	struct capwap_wtpboarddata_element* wtpboarddata;
 | 
			
		||||
	struct capwap_wtpdescriptor_element* wtpdescriptor;
 | 
			
		||||
	struct capwap_wtpframetunnelmode_element* wtpframetunnel;
 | 
			
		||||
	struct capwap_wtpmactype_element* wtpmactype;
 | 
			
		||||
	struct capwap_mtudiscovery_element* mtudiscovery;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
	
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			struct capwap_array* wtpradioinformation;
 | 
			
		||||
		} ieee80211;
 | 
			
		||||
	} binding;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_discovery_request(struct capwap_element_discovery_request* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_discovery_request(struct capwap_element_discovery_request* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_discovery_response {
 | 
			
		||||
	struct capwap_acdescriptor_element* acdescriptor;
 | 
			
		||||
	struct capwap_acname_element* acname;
 | 
			
		||||
	struct capwap_array* controlipv4;
 | 
			
		||||
	struct capwap_array* controlipv6;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
	
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			struct capwap_array* wtpradioinformation;
 | 
			
		||||
		} ieee80211;
 | 
			
		||||
	} binding;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_discovery_response(struct capwap_element_discovery_response* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_discovery_response(struct capwap_element_discovery_response* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_join_request {
 | 
			
		||||
	struct capwap_location_element* locationdata;
 | 
			
		||||
	struct capwap_wtpboarddata_element* wtpboarddata;
 | 
			
		||||
	struct capwap_wtpdescriptor_element* wtpdescriptor;
 | 
			
		||||
	struct capwap_wtpname_element* wtpname;
 | 
			
		||||
	struct capwap_sessionid_element* sessionid;
 | 
			
		||||
	struct capwap_wtpframetunnelmode_element* wtpframetunnel;
 | 
			
		||||
	struct capwap_wtpmactype_element* wtpmactype;
 | 
			
		||||
	struct capwap_ecnsupport_element* ecnsupport;
 | 
			
		||||
	struct capwap_localipv4_element* localipv4;
 | 
			
		||||
	struct capwap_localipv6_element* localipv6;
 | 
			
		||||
	struct capwap_transport_element* trasport;
 | 
			
		||||
	struct capwap_maximumlength_element* maxiumlength;
 | 
			
		||||
	struct capwap_wtprebootstat_element* wtprebootstat;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
	
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			struct capwap_array* wtpradioinformation;
 | 
			
		||||
		} ieee80211;
 | 
			
		||||
	} binding;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_join_request(struct capwap_element_join_request* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_join_request(struct capwap_element_join_request* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_join_request(struct capwap_element_join_request* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_join_response {
 | 
			
		||||
	struct capwap_resultcode_element* resultcode;
 | 
			
		||||
	struct capwap_array* returnedmessage;
 | 
			
		||||
	struct capwap_acdescriptor_element* acdescriptor;
 | 
			
		||||
	struct capwap_acname_element* acname;
 | 
			
		||||
	struct capwap_ecnsupport_element* ecnsupport;
 | 
			
		||||
	struct capwap_array* controlipv4;
 | 
			
		||||
	struct capwap_array* controlipv6;
 | 
			
		||||
	struct capwap_localipv4_element* localipv4;
 | 
			
		||||
	struct capwap_localipv6_element* localipv6;
 | 
			
		||||
	capwap_acipv4list_element_array* acipv4list;
 | 
			
		||||
	capwap_acipv6list_element_array* acipv6list;
 | 
			
		||||
	struct capwap_transport_element* trasport;
 | 
			
		||||
	struct capwap_imageidentifier_element* imageidentifier;
 | 
			
		||||
	struct capwap_maximumlength_element* maxiumlength;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			struct capwap_array* wtpradioinformation;
 | 
			
		||||
		} ieee80211;
 | 
			
		||||
	} binding;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_join_response(struct capwap_element_join_response* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_join_response(struct capwap_element_join_response* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_join_response(struct capwap_element_join_response* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_configurationstatus_request {
 | 
			
		||||
	struct capwap_acname_element* acname;
 | 
			
		||||
	struct capwap_array* radioadmstatus;
 | 
			
		||||
	struct capwap_statisticstimer_element* statisticstimer;
 | 
			
		||||
	struct capwap_wtprebootstat_element* wtprebootstat;
 | 
			
		||||
	struct capwap_array* acnamepriority;
 | 
			
		||||
	struct capwap_transport_element* trasport;
 | 
			
		||||
	struct capwap_wtpstaticipaddress_element* wtpstaticipaddress;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_configurationstatus_request(struct capwap_element_configurationstatus_request* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_configurationstatus_response {
 | 
			
		||||
	struct capwap_timers_element* timers;
 | 
			
		||||
	struct capwap_array* decrypterrorresultperiod;
 | 
			
		||||
	struct capwap_idletimeout_element* idletimeout;
 | 
			
		||||
	struct capwap_wtpfallback_element* wtpfallback;
 | 
			
		||||
	capwap_acipv4list_element_array* acipv4list;
 | 
			
		||||
	capwap_acipv6list_element_array* acipv6list;
 | 
			
		||||
	struct capwap_array* radiooprstatus;
 | 
			
		||||
	struct capwap_wtpstaticipaddress_element* wtpstaticipaddress;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_configurationstatus_response(struct capwap_element_configurationstatus_response* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_changestateevent_request {
 | 
			
		||||
	struct capwap_array* radiooprstatus;
 | 
			
		||||
	struct capwap_resultcode_element* resultcode;
 | 
			
		||||
	struct capwap_array* returnedmessage;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_changestateevent_request(struct capwap_element_changestateevent_request* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_changestateevent_request(struct capwap_element_changestateevent_request* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_changestateevent_response {
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_changestateevent_response(struct capwap_element_changestateevent_response* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_changestateevent_response(struct capwap_element_changestateevent_response* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_echo_request {
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_echo_request(struct capwap_element_echo_request* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_echo_request(struct capwap_element_echo_request* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_echo_response {
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_echo_response(struct capwap_element_echo_response* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_echo_response(struct capwap_element_echo_response* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_reset_request {
 | 
			
		||||
	struct capwap_imageidentifier_element* imageidentifier;
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_reset_request(struct capwap_element_reset_request* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_reset_request(struct capwap_element_reset_request* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_element_reset_response {
 | 
			
		||||
	struct capwap_resultcode_element* resultcode;	
 | 
			
		||||
	struct capwap_vendorpayload_element* vendorpayload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void capwap_init_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding);
 | 
			
		||||
int capwap_parsing_element_reset_response(struct capwap_element_reset_response* element, struct capwap_list_item* item);
 | 
			
		||||
void capwap_free_element_reset_response(struct capwap_element_reset_response* element, unsigned short binding);
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_HEADER__ */
 | 
			
		||||
							
								
								
									
										88
									
								
								src/common/capwap_element_80211_wtpradioinformation.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/common/capwap_element_80211_wtpradioinformation.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Radio ID    |                  Radio Type                   |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|  Radio Type   |
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   1048 for IEEE 802.11 WTP Radio Information
 | 
			
		||||
 | 
			
		||||
Length:   5
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_80211_wtpradioinformation_raw_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned long radiotype;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_80211_wtpradioinformation_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_80211_wtpradioinformation_raw_element* dataraw;
 | 
			
		||||
	struct capwap_80211_wtpradioinformation_element* dataelement = (struct capwap_80211_wtpradioinformation_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_80211_wtpradioinformation_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_wtpradioinformation_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_80211_wtpradioinformation_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_80211_wtpradioinformation_raw_element));
 | 
			
		||||
	dataraw = (struct capwap_80211_wtpradioinformation_raw_element*)element->data;
 | 
			
		||||
	
 | 
			
		||||
	dataraw->radioid = dataelement->radioid;
 | 
			
		||||
	dataraw->radiotype = htonl(dataelement->radiotype);
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_80211_wtpradioinformation_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_80211_wtpradioinformation_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_80211_wtpradioinformation_element* data;
 | 
			
		||||
	struct capwap_80211_wtpradioinformation_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != 5) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dataraw = (struct capwap_80211_wtpradioinformation_raw_element*)element->data;
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_80211_wtpradioinformation_element*)capwap_alloc(sizeof(struct capwap_80211_wtpradioinformation_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->radioid = dataraw->radioid;
 | 
			
		||||
	data->radiotype = ntohl(dataraw->radiotype);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_80211_wtpradioinformation_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								src/common/capwap_element_80211_wtpradioinformation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/common/capwap_element_80211_wtpradioinformation.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION			1048
 | 
			
		||||
 | 
			
		||||
struct capwap_80211_wtpradioinformation_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned long radiotype;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_RADIO_TYPE_80211N			0x08
 | 
			
		||||
#define CAPWAP_RADIO_TYPE_80211G			0x04
 | 
			
		||||
#define CAPWAP_RADIO_TYPE_80211A			0x02
 | 
			
		||||
#define CAPWAP_RADIO_TYPE_80211B			0x01
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_80211_wtpradioinformation_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_80211_wtpradioinformation_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_80211_wtpradioinformation_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_80211_wtpradioinformation_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_80211_WTPRADIOINFORMATION_ELEMENT(x)			({	\
 | 
			
		||||
																		struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION);	\
 | 
			
		||||
																		f->create(x, sizeof(struct capwap_80211_wtpradioinformation_element));	\
 | 
			
		||||
																	})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_80211_WTPRADIOINFORMATION_HEADER__ */
 | 
			
		||||
							
								
								
									
										199
									
								
								src/common/capwap_element_acdescriptor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								src/common/capwap_element_acdescriptor.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,199 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_array.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|            Stations           |             Limit             |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|          Active WTPs          |            Max WTPs           |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|    Security   |  R-MAC Field  |   Reserved1   |  DTLS Policy  |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                  AC Information Sub-Element...
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
	
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                AC Information Vendor Identifier               |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|      AC Information Type      |     AC Information Length     |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                     AC Information Data...
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   1 for AC Descriptor
 | 
			
		||||
Length:   >= 12
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_acdescriptor_raw_element {
 | 
			
		||||
	unsigned short stations;
 | 
			
		||||
	unsigned short limit;
 | 
			
		||||
	unsigned short activewtp;
 | 
			
		||||
	unsigned short maxwtp;
 | 
			
		||||
	unsigned char security;
 | 
			
		||||
	unsigned char rmacfield;
 | 
			
		||||
	unsigned char reserved;
 | 
			
		||||
	unsigned char dtlspolicy;
 | 
			
		||||
	char data[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
struct capwap_acdescriptor_raw_desc_subelement {
 | 
			
		||||
	unsigned long vendor;
 | 
			
		||||
	unsigned short type;
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	char data[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_acdescriptor_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	char* pos;
 | 
			
		||||
	unsigned long i;
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_acdescriptor_raw_element* dataraw;
 | 
			
		||||
	struct capwap_acdescriptor_element* dataelement = (struct capwap_acdescriptor_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_acdescriptor_element));
 | 
			
		||||
	ASSERT(dataelement->descsubelement != NULL);
 | 
			
		||||
	
 | 
			
		||||
	/* Calc length packet */
 | 
			
		||||
	length = sizeof(struct capwap_acdescriptor_raw_element);
 | 
			
		||||
	for (i = 0; i < dataelement->descsubelement->count; i++) {
 | 
			
		||||
		struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i);
 | 
			
		||||
		length += sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desc->length;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + length);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + length);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_ACDESCRIPTION);
 | 
			
		||||
	element->length = htons(length);
 | 
			
		||||
 | 
			
		||||
	/* Descriptor */
 | 
			
		||||
	dataraw = (struct capwap_acdescriptor_raw_element*)element->data;
 | 
			
		||||
	dataraw->stations = htons(dataelement->station);
 | 
			
		||||
	dataraw->limit = htons(dataelement->stationlimit);
 | 
			
		||||
	dataraw->activewtp = htons(dataelement->wtp);
 | 
			
		||||
	dataraw->maxwtp = htons(dataelement->wtplimit);
 | 
			
		||||
	dataraw->security = dataelement->security;
 | 
			
		||||
	dataraw->rmacfield = dataelement->rmacfield;
 | 
			
		||||
	dataraw->dtlspolicy = dataelement->dtlspolicy;
 | 
			
		||||
	
 | 
			
		||||
	/* Descriptor Sub-Element */
 | 
			
		||||
	pos = dataraw->data;
 | 
			
		||||
	for (i = 0; i < dataelement->descsubelement->count; i++) {
 | 
			
		||||
		struct capwap_acdescriptor_raw_desc_subelement* descraw = (struct capwap_acdescriptor_raw_desc_subelement*)pos;
 | 
			
		||||
		struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(dataelement->descsubelement, i);
 | 
			
		||||
		
 | 
			
		||||
		descraw->vendor = htonl(desc->vendor);
 | 
			
		||||
		descraw->type = htons(desc->type);
 | 
			
		||||
		descraw->length = htons(desc->length);
 | 
			
		||||
		memcpy(descraw->data, desc->data, desc->length);
 | 
			
		||||
		
 | 
			
		||||
		pos += sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desc->length;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_acdescriptor_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_acdescriptor_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	unsigned char i;
 | 
			
		||||
	long length;
 | 
			
		||||
	char* pos;
 | 
			
		||||
	struct capwap_acdescriptor_element* data;
 | 
			
		||||
	struct capwap_acdescriptor_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACDESCRIPTION);
 | 
			
		||||
	
 | 
			
		||||
	length = (long)ntohs(element->length);
 | 
			
		||||
	if (length < 12) {
 | 
			
		||||
		capwap_logging_debug("Invalid AC Descriptor element");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_acdescriptor_raw_element*)element->data;
 | 
			
		||||
	if ((dataraw->stations > dataraw->limit) || (dataraw->activewtp > dataraw->maxwtp)) {
 | 
			
		||||
		capwap_logging_debug("Invalid AC Descriptor element");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_acdescriptor_element*)capwap_alloc(sizeof(struct capwap_acdescriptor_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	data->descsubelement = capwap_array_create(sizeof(struct capwap_acdescriptor_desc_subelement), 0);
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	data->station = htons(dataraw->stations);
 | 
			
		||||
	data->stationlimit = htons(dataraw->limit);
 | 
			
		||||
	data->wtp = htons(dataraw->activewtp);
 | 
			
		||||
	data->wtplimit = htons(dataraw->maxwtp);
 | 
			
		||||
	data->security = dataraw->security;
 | 
			
		||||
	data->rmacfield = dataraw->rmacfield;
 | 
			
		||||
	data->dtlspolicy = dataraw->dtlspolicy;
 | 
			
		||||
	
 | 
			
		||||
	pos = dataraw->data;
 | 
			
		||||
	length -= sizeof(struct capwap_acdescriptor_raw_element);
 | 
			
		||||
	
 | 
			
		||||
	/* Description Subelement */
 | 
			
		||||
	i = 0;
 | 
			
		||||
	while (length > 0) {
 | 
			
		||||
		struct capwap_acdescriptor_desc_subelement* desc = (struct capwap_acdescriptor_desc_subelement*)capwap_array_get_item_pointer(data->descsubelement, i);
 | 
			
		||||
		struct capwap_acdescriptor_raw_desc_subelement* descraw = (struct capwap_acdescriptor_raw_desc_subelement*)pos;
 | 
			
		||||
		unsigned short desclength = ntohs(descraw->length);
 | 
			
		||||
		unsigned short descrawlength = sizeof(struct capwap_acdescriptor_raw_desc_subelement) + desclength;
 | 
			
		||||
		
 | 
			
		||||
		if ((desclength > CAPWAP_ACDESC_SUBELEMENT_MAXDATA) || (length < descrawlength)) {
 | 
			
		||||
			capwap_logging_debug("Invalid AC Descriptor element");
 | 
			
		||||
			capwap_acdescriptor_element_free(data);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		/* */
 | 
			
		||||
		desc->vendor = ntohl(descraw->vendor);
 | 
			
		||||
		desc->type = ntohs(descraw->type);
 | 
			
		||||
		desc->length = desclength;
 | 
			
		||||
		memcpy(desc->data, descraw->data, desclength);
 | 
			
		||||
 | 
			
		||||
		/* */
 | 
			
		||||
		i++;
 | 
			
		||||
		pos += descrawlength;
 | 
			
		||||
		length -= descrawlength;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_acdescriptor_element_free(void* data) {
 | 
			
		||||
	struct capwap_acdescriptor_element* dataelement = (struct capwap_acdescriptor_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(dataelement != NULL);
 | 
			
		||||
	ASSERT(dataelement->descsubelement != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_array_free(dataelement->descsubelement);
 | 
			
		||||
	capwap_free(dataelement);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								src/common/capwap_element_acdescriptor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/common/capwap_element_acdescriptor.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_ACDESCRIPTION				1
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACDESC_SECURITY_PRESHARED_KEY		0x04
 | 
			
		||||
#define CAPWAP_ACDESC_SECURITY_X509_CERT			0x02
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACDESC_RMACFIELD_SUPPORTED			1
 | 
			
		||||
#define CAPWAP_ACDESC_RMACFIELD_NOTSUPPORTED		2
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACDESC_DTLS_DATA_CHANNEL_ENABLED		0x04
 | 
			
		||||
#define CAPWAP_ACDESC_CLEAR_DATA_CHANNEL_ENABLED	0x02
 | 
			
		||||
 | 
			
		||||
struct capwap_acdescriptor_element {
 | 
			
		||||
	unsigned short station;
 | 
			
		||||
	unsigned short stationlimit;
 | 
			
		||||
	unsigned short wtp;
 | 
			
		||||
	unsigned short wtplimit;
 | 
			
		||||
	unsigned char security;
 | 
			
		||||
	unsigned char rmacfield;
 | 
			
		||||
	unsigned char dtlspolicy;
 | 
			
		||||
	struct capwap_array* descsubelement;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACDESC_SUBELEMENT_HARDWAREVERSION			4
 | 
			
		||||
#define CAPWAP_ACDESC_SUBELEMENT_SOFTWAREVERSION			5
 | 
			
		||||
#define CAPWAP_ACDESC_SUBELEMENT_MAXDATA					1024
 | 
			
		||||
 | 
			
		||||
struct capwap_acdescriptor_desc_subelement {
 | 
			
		||||
	unsigned long vendor;
 | 
			
		||||
	unsigned short type;
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	char data[CAPWAP_ACDESC_SUBELEMENT_MAXDATA];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_acdescriptor_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_acdescriptor_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_acdescriptor_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_acdescriptor_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_ACDESCRIPTOR_ELEMENT(x)			({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACDESCRIPTION);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_acdescriptor_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_ACDESCRIPTOR_HEADER__ */
 | 
			
		||||
							
								
								
									
										103
									
								
								src/common/capwap_element_acipv4list.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/common/capwap_element_acipv4list.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address[]                        |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   2 for AC IPv4 List
 | 
			
		||||
Length:   >= 4
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_acipv4list_raw_element {
 | 
			
		||||
	unsigned long address;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_acipv4list_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	int i;
 | 
			
		||||
	int items;
 | 
			
		||||
	unsigned short sizeitems;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	capwap_acipv4list_element_array* dataarray = (capwap_acipv4list_element_array*)data;
 | 
			
		||||
	struct capwap_acipv4list_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(capwap_acipv4list_element_array));
 | 
			
		||||
	
 | 
			
		||||
	items = min(dataarray->count, CAPWAP_ACIPV4LIST_MAX_ELEMENTS);
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	sizeitems = sizeof(struct capwap_acipv4list_raw_element) * items;
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeitems);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeitems);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_ACIPV4LIST);
 | 
			
		||||
	element->length = htons(sizeitems);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_acipv4list_raw_element*)element->data;
 | 
			
		||||
	for (i = 0; i < items; i++) {
 | 
			
		||||
		struct capwap_acipv4list_element* dataelement = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(dataarray, i);
 | 
			
		||||
		dataraw->address = dataelement->address.s_addr;
 | 
			
		||||
 | 
			
		||||
		/* Next raw item */
 | 
			
		||||
		dataraw++;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_acipv4list_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_acipv4list_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	int i;
 | 
			
		||||
	int items;
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	capwap_acipv4list_element_array* data;
 | 
			
		||||
	struct capwap_acipv4list_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACIPV4LIST);
 | 
			
		||||
	
 | 
			
		||||
	length = ntohs(element->length);
 | 
			
		||||
	if ((length > 0) && ((length % sizeof(struct capwap_acipv4list_raw_element)) != 0)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	items = length / sizeof(struct capwap_acipv4list_raw_element);
 | 
			
		||||
	data = (capwap_acipv4list_element_array*)capwap_array_create(sizeof(struct capwap_acipv4list_element), items);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_acipv4list_raw_element*)element->data;
 | 
			
		||||
	for (i = 0; i < items; i++) {
 | 
			
		||||
		struct capwap_acipv4list_element* dataelement = (struct capwap_acipv4list_element*)capwap_array_get_item_pointer(data, i);
 | 
			
		||||
		dataelement->address.s_addr = dataraw->address;
 | 
			
		||||
 | 
			
		||||
		/* Next raw item */
 | 
			
		||||
		dataraw++;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_acipv4list_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_array_free((capwap_acipv4list_element_array*)data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/common/capwap_element_acipv4list.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/common/capwap_element_acipv4list.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_ACIPV4LIST							2
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACIPV4LIST_MAX_ELEMENTS						1024
 | 
			
		||||
 | 
			
		||||
typedef struct capwap_array capwap_acipv4list_element_array;
 | 
			
		||||
struct capwap_acipv4list_element {
 | 
			
		||||
	struct in_addr address;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_acipv4list_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_acipv4list_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_acipv4list_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_acipv4list_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_ACIPV4LIST_ELEMENT(x)				({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACIPV4LIST);	\
 | 
			
		||||
															f->create(x, sizeof(capwap_acipv4list_element_array));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_ACIPV4LIST_HEADER__ */
 | 
			
		||||
							
								
								
									
										109
									
								
								src/common/capwap_element_acipv6list.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/common/capwap_element_acipv6list.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   3 for AC IPV6 List
 | 
			
		||||
Length:   >= 16
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_acipv6list_raw_element {
 | 
			
		||||
	unsigned long address[4];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_acipv6list_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	int i;
 | 
			
		||||
	int items;
 | 
			
		||||
	unsigned short sizeitems;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	capwap_acipv6list_element_array* dataarray = (capwap_acipv6list_element_array*)data;
 | 
			
		||||
	struct capwap_acipv6list_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(capwap_acipv6list_element_array));
 | 
			
		||||
	
 | 
			
		||||
	items = min(dataarray->count, CAPWAP_ACIPV6LIST_MAX_ELEMENTS);
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	sizeitems = sizeof(struct capwap_acipv6list_raw_element) * items;
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeitems);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeitems);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_ACIPV6LIST);
 | 
			
		||||
	element->length = htons(sizeitems);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_acipv6list_raw_element*)element->data;
 | 
			
		||||
	for (i = 0; i < items; i++) {
 | 
			
		||||
		struct capwap_acipv6list_element* dataelement = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(dataarray, i);
 | 
			
		||||
		memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4);
 | 
			
		||||
 | 
			
		||||
		/* Next raw item */
 | 
			
		||||
		dataraw++;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_acipv6list_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_acipv6list_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	int i;
 | 
			
		||||
	int items;
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	capwap_acipv6list_element_array* data;
 | 
			
		||||
	struct capwap_acipv6list_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACIPV6LIST);
 | 
			
		||||
	
 | 
			
		||||
	length = ntohs(element->length);
 | 
			
		||||
	if ((length > 0) && ((length % sizeof(struct capwap_acipv6list_raw_element)) != 0)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	items = length / sizeof(struct capwap_acipv6list_raw_element);
 | 
			
		||||
	data = (capwap_acipv6list_element_array*)capwap_array_create(sizeof(struct capwap_acipv6list_element), items);
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_acipv6list_raw_element*)element->data;
 | 
			
		||||
	for (i = 0; i < items; i++) {
 | 
			
		||||
		struct capwap_acipv6list_element* dataelement = (struct capwap_acipv6list_element*)capwap_array_get_item_pointer(data, i);
 | 
			
		||||
		memcpy(dataelement->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4);
 | 
			
		||||
 | 
			
		||||
		/* Next raw item */
 | 
			
		||||
		dataraw++;		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_acipv6list_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_array_free((capwap_acipv6list_element_array*)data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/common/capwap_element_acipv6list.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/common/capwap_element_acipv6list.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_ACIPV6LIST							3
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACIPV6LIST_MAX_ELEMENTS						1024
 | 
			
		||||
 | 
			
		||||
typedef struct capwap_array capwap_acipv6list_element_array;
 | 
			
		||||
struct capwap_acipv6list_element {
 | 
			
		||||
	struct in6_addr address;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_acipv6list_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_acipv6list_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_acipv6list_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_acipv6list_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_ACIPV6LIST_ELEMENT(x)				({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACIPV6LIST);	\
 | 
			
		||||
															f->create(x, sizeof(capwap_acipv6list_element_array));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_ACIPV6LIST_HEADER__ */
 | 
			
		||||
							
								
								
									
										86
									
								
								src/common/capwap_element_acname.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/common/capwap_element_acname.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0
 | 
			
		||||
 0 1 2 3 4 5 6 7
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Name ...
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   4 for AC Name
 | 
			
		||||
Length:   >= 1
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_acname_raw_element {
 | 
			
		||||
	char name[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_acname_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_acname_raw_element* dataraw;
 | 
			
		||||
	struct capwap_acname_element* dataelement = (struct capwap_acname_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_acname_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	namelength = strlen(dataelement->name);
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + namelength);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + namelength);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_ACNAME);
 | 
			
		||||
	element->length = htons(namelength);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_acname_raw_element*)element->data;
 | 
			
		||||
	memcpy(&dataraw->name[0], &dataelement->name[0], namelength);
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_acname_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_acname_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_acname_element* data;
 | 
			
		||||
	struct capwap_acname_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACNAME);
 | 
			
		||||
 | 
			
		||||
	namelength = ntohs(element->length);
 | 
			
		||||
	if (!namelength  || (namelength > CAPWAP_ACNAME_MAXLENGTH))  {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_acname_raw_element*)element->data;
 | 
			
		||||
	data = (struct capwap_acname_element*)capwap_alloc(sizeof(struct capwap_acname_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	memcpy(&data->name[0], &dataraw->name[0], namelength);
 | 
			
		||||
	data->name[namelength] = 0;
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_acname_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/common/capwap_element_acname.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/common/capwap_element_acname.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_ACNAME_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_ACNAME_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_ACNAME			4
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACNAME_MAXLENGTH			512
 | 
			
		||||
 | 
			
		||||
struct capwap_acname_element {
 | 
			
		||||
	char name[CAPWAP_ACNAME_MAXLENGTH + 1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_acname_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_acname_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_acname_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_acname_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_ACNAME_ELEMENT(x)					({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACNAME);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_acname_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_ACNAME_HEADER__ */
 | 
			
		||||
							
								
								
									
										91
									
								
								src/common/capwap_element_acnamepriority.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/common/capwap_element_acnamepriority.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Priority  |   AC Name...
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   5 for AC Name with Priority
 | 
			
		||||
Length:   >= 2
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_acnamepriority_raw_element {
 | 
			
		||||
	unsigned char priority;
 | 
			
		||||
	char name[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_acnamepriority_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_acnamepriority_raw_element* dataraw;
 | 
			
		||||
	struct capwap_acnamepriority_element* dataelement = (struct capwap_acnamepriority_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_acnamepriority_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	namelength = strlen(dataelement->name);
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_acnamepriority_raw_element) + namelength);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_acnamepriority_raw_element) + namelength);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_ACNAMEPRIORITY);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_acnamepriority_raw_element) + namelength);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_acnamepriority_raw_element*)element->data;
 | 
			
		||||
	dataraw->priority = dataelement->priority;
 | 
			
		||||
	memcpy(&dataraw->name[0], &dataelement->name[0], namelength);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_acnamepriority_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_acnamepriority_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_acnamepriority_element* data;
 | 
			
		||||
	struct capwap_acnamepriority_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ACNAMEPRIORITY);
 | 
			
		||||
 | 
			
		||||
	namelength = ntohs(element->length) - sizeof(struct capwap_acnamepriority_raw_element);
 | 
			
		||||
	if (!namelength  || (namelength > CAPWAP_ACNAMEPRIORITY_MAXLENGTH))  {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_acnamepriority_raw_element*)element->data;
 | 
			
		||||
	data = (struct capwap_acnamepriority_element*)capwap_alloc(sizeof(struct capwap_acnamepriority_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->priority = dataraw->priority;
 | 
			
		||||
	memcpy(&data->name[0], &dataraw->name[0], namelength);
 | 
			
		||||
	data->name[namelength] = 0;
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_acnamepriority_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/common/capwap_element_acnamepriority.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/common/capwap_element_acnamepriority.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_ACNAMEPRIORITY			5
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ACNAMEPRIORITY_MAXLENGTH			512
 | 
			
		||||
 | 
			
		||||
struct capwap_acnamepriority_element {
 | 
			
		||||
	unsigned char priority;
 | 
			
		||||
	char name[CAPWAP_ACNAMEPRIORITY_MAXLENGTH + 1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_acnamepriority_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_acnamepriority_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_acnamepriority_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_acnamepriority_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_ACNAMEPRIORITY_ELEMENT(x)			({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ACNAMEPRIORITY);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_acnamepriority_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_ACNAMEPRIORITY_HEADER__ */
 | 
			
		||||
							
								
								
									
										88
									
								
								src/common/capwap_element_controlipv4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/common/capwap_element_controlipv4.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|           WTP Count           |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   10 for CAPWAP Control IPv4 Address
 | 
			
		||||
Length:   6
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_controlipv4_raw_element {
 | 
			
		||||
	unsigned long address;
 | 
			
		||||
	unsigned short wtpcount;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_controlipv4_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_controlipv4_element* dataelement = (struct capwap_controlipv4_element*)data;
 | 
			
		||||
	struct capwap_controlipv4_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_controlipv4_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv4_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv4_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_CONTROLIPV4);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_controlipv4_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_controlipv4_raw_element*)element->data;
 | 
			
		||||
	dataraw->address = dataelement->address.s_addr;
 | 
			
		||||
	dataraw->wtpcount = htons(dataelement->wtpcount);
 | 
			
		||||
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_controlipv4_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_controlipv4_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_controlipv4_element* data;
 | 
			
		||||
	struct capwap_controlipv4_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_CONTROLIPV4);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_controlipv4_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_controlipv4_element*)capwap_alloc(sizeof(struct capwap_controlipv4_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_controlipv4_raw_element*)element->data;
 | 
			
		||||
	data->address.s_addr = dataraw->address;
 | 
			
		||||
	data->wtpcount = ntohs(dataraw->wtpcount);
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_controlipv4_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/common/capwap_element_controlipv4.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/common/capwap_element_controlipv4.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_CONTROLIPV4							10
 | 
			
		||||
 | 
			
		||||
struct capwap_controlipv4_element {
 | 
			
		||||
	struct in_addr address;
 | 
			
		||||
	unsigned short wtpcount;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_controlipv4_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_controlipv4_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_controlipv4_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_controlipv4_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_CONTROLIPV4_ELEMENT(x)			({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV4);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_controlipv4_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */
 | 
			
		||||
							
								
								
									
										94
									
								
								src/common/capwap_element_controlipv6.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/common/capwap_element_controlipv6.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|           WTP Count           |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   11 for CAPWAP Control IPv6 Address
 | 
			
		||||
Length:   18
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_controlipv6_raw_element {
 | 
			
		||||
	unsigned long address[4];
 | 
			
		||||
	unsigned short wtpcount;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_controlipv6_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_controlipv6_element* dataelement = (struct capwap_controlipv6_element*)data;
 | 
			
		||||
	struct capwap_controlipv6_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_controlipv6_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv6_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_controlipv6_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_CONTROLIPV6);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_controlipv6_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_controlipv6_raw_element*)element->data;
 | 
			
		||||
	memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4);
 | 
			
		||||
	dataraw->wtpcount = htons(dataelement->wtpcount);
 | 
			
		||||
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_controlipv6_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_controlipv6_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_controlipv6_element* data;
 | 
			
		||||
	struct capwap_controlipv6_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_CONTROLIPV6);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_controlipv6_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_controlipv6_element*)capwap_alloc(sizeof(struct capwap_controlipv6_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_controlipv6_raw_element*)element->data;
 | 
			
		||||
	memcpy(data->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4);
 | 
			
		||||
	data->wtpcount = ntohs(dataraw->wtpcount);
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_controlipv6_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/common/capwap_element_controlipv6.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/common/capwap_element_controlipv6.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_CONTROLIPV6_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_CONTROLIPV6_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_CONTROLIPV6							11
 | 
			
		||||
 | 
			
		||||
struct capwap_controlipv6_element {
 | 
			
		||||
	struct in6_addr address;
 | 
			
		||||
	unsigned short wtpcount;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_controlipv6_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_controlipv6_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_controlipv6_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_controlipv6_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_CONTROLIPV6_ELEMENT(x)			({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_CONTROLIPV6);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_controlipv6_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */
 | 
			
		||||
							
								
								
									
										86
									
								
								src/common/capwap_element_decrypterrorreportperiod.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/common/capwap_element_decrypterrorreportperiod.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Radio ID    |        Report Interval        |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   16 for Decryption Error Report Period
 | 
			
		||||
Length:  3
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_decrypterrorreportperiod_raw_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned short interval;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_decrypterrorreportperiod_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_decrypterrorreportperiod_element* dataelement = (struct capwap_decrypterrorreportperiod_element*)data;
 | 
			
		||||
	struct capwap_decrypterrorreportperiod_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_decrypterrorreportperiod_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_decrypterrorreportperiod_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_decrypterrorreportperiod_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_decrypterrorreportperiod_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_decrypterrorreportperiod_raw_element*)element->data;
 | 
			
		||||
	dataraw->radioid = dataelement->radioid;
 | 
			
		||||
	dataraw->interval = htons(dataelement->interval);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_decrypterrorreportperiod_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_decrypterrorreportperiod_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_decrypterrorreportperiod_element* data;
 | 
			
		||||
	struct capwap_decrypterrorreportperiod_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_decrypterrorreportperiod_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_decrypterrorreportperiod_element*)capwap_alloc(sizeof(struct capwap_decrypterrorreportperiod_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_decrypterrorreportperiod_raw_element*)element->data;
 | 
			
		||||
	data->radioid = dataraw->radioid;
 | 
			
		||||
	data->interval = ntohs(dataraw->interval);
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_decrypterrorreportperiod_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/common/capwap_element_decrypterrorreportperiod.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/common/capwap_element_decrypterrorreportperiod.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD			16
 | 
			
		||||
 | 
			
		||||
struct capwap_decrypterrorreportperiod_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned short interval;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_decrypterrorreportperiod_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_decrypterrorreportperiod_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_decrypterrorreportperiod_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_decrypterrorreportperiod_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_DECRYPTERRORREPORTPERIOD_ELEMENT(x)		({	\
 | 
			
		||||
																	struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD);	\
 | 
			
		||||
																	f->create(x, sizeof(struct capwap_decrypterrorreportperiod_element));	\
 | 
			
		||||
																})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_DECRYPTERRORREPORTPERIOD_HEADER__ */
 | 
			
		||||
							
								
								
									
										75
									
								
								src/common/capwap_element_discoverytype.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/common/capwap_element_discoverytype.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0
 | 
			
		||||
 0 1 2 3 4 5 6 7
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
| Discovery Type|
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   20 for Discovery Type
 | 
			
		||||
Length:   1
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_discoverytype_raw_element {
 | 
			
		||||
	unsigned char type;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_discoverytype_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_discoverytype_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_discoverytype_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_discoverytype_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_DISCOVERYTYPE);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_discoverytype_raw_element));
 | 
			
		||||
	((struct capwap_discoverytype_raw_element*)element->data)->type = ((struct capwap_discoverytype_element*)data)->type;
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_discoverytype_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_discoverytype_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_discoverytype_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_DISCOVERYTYPE);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_discoverytype_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_discoverytype_element*)capwap_alloc(sizeof(struct capwap_discoverytype_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->type = ((struct capwap_discoverytype_raw_element*)element->data)->type;
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_discoverytype_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/common/capwap_element_discoverytype.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/common/capwap_element_discoverytype.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_DISCOVERYTYPE_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_DISCOVERYTYPE_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE			20
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_UNKNOWN			0
 | 
			
		||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_STATIC			1
 | 
			
		||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_DHCP				2
 | 
			
		||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_DNS				3
 | 
			
		||||
#define CAPWAP_ELEMENT_DISCOVERYTYPE_TYPE_ACREFERRAL		4
 | 
			
		||||
 | 
			
		||||
struct capwap_discoverytype_element {
 | 
			
		||||
	unsigned char type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_discoverytype_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_discoverytype_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_discoverytype_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_discoverytype_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_DISCOVERYTYPE_ELEMENT(x)			({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_DISCOVERYTYPE);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_discoverytype_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_DISCOVERYTYPE_HEADER__ */
 | 
			
		||||
							
								
								
									
										77
									
								
								src/common/capwap_element_ecnsupport.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/common/capwap_element_ecnsupport.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0
 | 
			
		||||
 0 1 2 3 4 5 6 7
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
|  ECN Support  |
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   53 for ECN Support
 | 
			
		||||
Length:  1
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_ecnsupport_raw_element {
 | 
			
		||||
	char flag;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_ecnsupport_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_ecnsupport_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_ecnsupport_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_ecnsupport_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_ECNSUPPORT);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_ecnsupport_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	((struct capwap_ecnsupport_raw_element*)element->data)->flag = ((struct capwap_ecnsupport_element*)data)->flag;
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_ecnsupport_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_ecnsupport_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_ecnsupport_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_ECNSUPPORT);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_ecnsupport_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_ecnsupport_element*)capwap_alloc(sizeof(struct capwap_ecnsupport_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->flag = ((struct capwap_ecnsupport_raw_element*)element->data)->flag;
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_ecnsupport_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/common/capwap_element_ecnsupport.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/common/capwap_element_ecnsupport.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_ECNSUPPORT_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_ECNSUPPORT_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_ECNSUPPORT			53
 | 
			
		||||
 | 
			
		||||
struct capwap_ecnsupport_element {
 | 
			
		||||
	char flag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_LIMITED_ECN_SUPPORT			0
 | 
			
		||||
#define CAPWAP_FULL_ECN_SUPPORT				1
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_ecnsupport_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_ecnsupport_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_ecnsupport_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_ecnsupport_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_ECNSUPPORT_ELEMENT(x)			({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_ECNSUPPORT);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_ecnsupport_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_ECNSUPPORT_HEADER__ */
 | 
			
		||||
							
								
								
									
										77
									
								
								src/common/capwap_element_idletimeout.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/common/capwap_element_idletimeout.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                            Timeout                            |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   23 for Idle Timeout
 | 
			
		||||
Length:  4
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_idletimeout_raw_element {
 | 
			
		||||
	unsigned long timeout;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_idletimeout_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_idletimeout_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_idletimeout_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_idletimeout_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_IDLETIMEOUT);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_idletimeout_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	((struct capwap_idletimeout_raw_element*)element->data)->timeout = htonl(((struct capwap_idletimeout_element*)data)->timeout);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_idletimeout_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_idletimeout_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_idletimeout_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_IDLETIMEOUT);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_idletimeout_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_idletimeout_element*)capwap_alloc(sizeof(struct capwap_idletimeout_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->timeout = ntohl(((struct capwap_idletimeout_raw_element*)element->data)->timeout);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_idletimeout_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/common/capwap_element_idletimeout.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/common/capwap_element_idletimeout.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_IDLETIMEOUT_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_IDLETIMEOUT_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_IDLETIMEOUT			23
 | 
			
		||||
 | 
			
		||||
struct capwap_idletimeout_element {
 | 
			
		||||
	unsigned long timeout;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_idletimeout_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_idletimeout_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_idletimeout_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_idletimeout_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_IDLETIMEOUT_ELEMENT(x)		({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_IDLETIMEOUT);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_idletimeout_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_IDLETIMEOUT_HEADER__ */
 | 
			
		||||
							
								
								
									
										93
									
								
								src/common/capwap_element_imageidentifier.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/common/capwap_element_imageidentifier.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                       Vendor Identifier                       |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                             Data...
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   25 for Image Identifier
 | 
			
		||||
Length:   >= 5
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_imageidentifier_raw_element {
 | 
			
		||||
	unsigned long vendor;
 | 
			
		||||
	char name[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_imageidentifier_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_imageidentifier_raw_element* dataraw;
 | 
			
		||||
	struct capwap_imageidentifier_element* dataelement = (struct capwap_imageidentifier_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_imageidentifier_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	namelength = strlen(dataelement->name);
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_imageidentifier_raw_element) + namelength);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_imageidentifier_raw_element) + namelength);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_IMAGEIDENTIFIER);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_imageidentifier_raw_element) + namelength);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_imageidentifier_raw_element*)element->data;
 | 
			
		||||
	dataraw->vendor = htonl(dataelement->vendor);
 | 
			
		||||
	memcpy(&dataraw->name[0], &dataelement->name[0], namelength);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_imageidentifier_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_imageidentifier_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_imageidentifier_element* data;
 | 
			
		||||
	struct capwap_imageidentifier_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_IMAGEIDENTIFIER);
 | 
			
		||||
 | 
			
		||||
	namelength = ntohs(element->length) - sizeof(struct capwap_imageidentifier_raw_element);
 | 
			
		||||
	if (!namelength  || (namelength > CAPWAP_IMAGEIDENTIFIER_MAXLENGTH))  {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_imageidentifier_raw_element*)element->data;
 | 
			
		||||
	data = (struct capwap_imageidentifier_element*)capwap_alloc(sizeof(struct capwap_imageidentifier_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->vendor = ntohl(dataraw->vendor);
 | 
			
		||||
	memcpy(&data->name[0], &dataraw->name[0], namelength);
 | 
			
		||||
	data->name[namelength] = 0;
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_imageidentifier_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/common/capwap_element_imageidentifier.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/common/capwap_element_imageidentifier.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_IMAGEIDENTIFIER_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_IMAGEIDENTIFIER_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_IMAGEIDENTIFIER			25
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_IMAGEIDENTIFIER_MAXLENGTH		1024
 | 
			
		||||
 | 
			
		||||
struct capwap_imageidentifier_element {
 | 
			
		||||
	unsigned long vendor;
 | 
			
		||||
	char name[CAPWAP_IMAGEIDENTIFIER_MAXLENGTH + 1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_imageidentifier_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_imageidentifier_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_imageidentifier_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_imageidentifier_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_IMAGEIDENTIFIER_ELEMENT(x)		({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_IMAGEIDENTIFIER);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_imageidentifier_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_IMAGEIDENTIFIER_HEADER__ */
 | 
			
		||||
							
								
								
									
										83
									
								
								src/common/capwap_element_localipv4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/common/capwap_element_localipv4.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   30 for CAPWAP Local IPv4 Address
 | 
			
		||||
Length:   4
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_localipv4_raw_element {
 | 
			
		||||
	unsigned long address;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_localipv4_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_localipv4_element* dataelement = (struct capwap_localipv4_element*)data;
 | 
			
		||||
	struct capwap_localipv4_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_localipv4_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv4_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv4_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_LOCALIPV4);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_localipv4_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_localipv4_raw_element*)element->data;
 | 
			
		||||
	dataraw->address = dataelement->address.s_addr;
 | 
			
		||||
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_localipv4_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_localipv4_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_localipv4_element* data;
 | 
			
		||||
	struct capwap_localipv4_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCALIPV4);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_localipv4_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_localipv4_element*)capwap_alloc(sizeof(struct capwap_localipv4_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_localipv4_raw_element*)element->data;
 | 
			
		||||
	data->address.s_addr = dataraw->address;
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_localipv4_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/common/capwap_element_localipv4.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/common/capwap_element_localipv4.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_LOCALIPV4_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_LOCALIPV4_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_LOCALIPV4							30
 | 
			
		||||
 | 
			
		||||
struct capwap_localipv4_element {
 | 
			
		||||
	struct in_addr address;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_localipv4_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_localipv4_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_localipv4_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_localipv4_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_LOCALIPV4_ELEMENT(x)				({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV4);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_localipv4_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_LOCALIPV4_HEADER__ */
 | 
			
		||||
							
								
								
									
										89
									
								
								src/common/capwap_element_localipv6.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/common/capwap_element_localipv6.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           IP Address                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   50 for CAPWAP Local IPv6 Address
 | 
			
		||||
Length:   16
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_localipv6_raw_element {
 | 
			
		||||
	unsigned long address[4];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_localipv6_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_localipv6_element* dataelement = (struct capwap_localipv6_element*)data;
 | 
			
		||||
	struct capwap_localipv6_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_localipv6_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv6_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_localipv6_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_LOCALIPV6);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_localipv6_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_localipv6_raw_element*)element->data;
 | 
			
		||||
	memcpy(dataraw->address, dataelement->address.s6_addr32, sizeof(unsigned long) * 4);
 | 
			
		||||
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_localipv6_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_localipv6_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_localipv6_element* data;
 | 
			
		||||
	struct capwap_localipv6_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCALIPV6);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_localipv6_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_localipv6_element*)capwap_alloc(sizeof(struct capwap_localipv6_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_localipv6_raw_element*)element->data;
 | 
			
		||||
	memcpy(data->address.s6_addr32, dataraw->address, sizeof(unsigned long) * 4);
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_localipv6_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/common/capwap_element_localipv6.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/common/capwap_element_localipv6.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_LOCALIPV6_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_LOCALIPV6_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_LOCALIPV6						50
 | 
			
		||||
 | 
			
		||||
struct capwap_localipv6_element {
 | 
			
		||||
	struct in6_addr address;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_localipv6_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_localipv6_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_localipv6_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_localipv6_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_LOCALIPV6_ELEMENT(x)				({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCALIPV6);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_localipv6_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_CONTROLIPV4_HEADER__ */
 | 
			
		||||
							
								
								
									
										86
									
								
								src/common/capwap_element_location.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/common/capwap_element_location.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0
 | 
			
		||||
 0 1 2 3 4 5 6 7
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Location ...
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   28 for Location Data
 | 
			
		||||
Length:   >= 1
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_location_raw_element {
 | 
			
		||||
	char value[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_location_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_location_raw_element* dataraw;
 | 
			
		||||
	struct capwap_location_element* dataelement = (struct capwap_location_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength >= sizeof(struct capwap_location_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	namelength = strlen(dataelement->value);
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + namelength);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + namelength);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_LOCATION);
 | 
			
		||||
	element->length = htons(namelength);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_location_raw_element*)element->data;
 | 
			
		||||
	memcpy(&dataraw->value[0], &dataelement->value[0], namelength);
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_location_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_location_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	unsigned short namelength;
 | 
			
		||||
	struct capwap_location_element* data;
 | 
			
		||||
	struct capwap_location_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_LOCATION);
 | 
			
		||||
 | 
			
		||||
	namelength = ntohs(element->length);
 | 
			
		||||
	if (!namelength  || (namelength > CAPWAP_LOCATION_MAXLENGTH))  {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_location_raw_element*)element->data;
 | 
			
		||||
	data = (struct capwap_location_element*)capwap_alloc(sizeof(struct capwap_location_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	memcpy(&data->value[0], &dataraw->value[0], namelength);
 | 
			
		||||
	data->value[namelength] = 0;
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_location_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/common/capwap_element_location.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/common/capwap_element_location.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_LOCATION_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_LOCATION_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_LOCATION			28
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_LOCATION_MAXLENGTH		1024
 | 
			
		||||
 | 
			
		||||
struct capwap_location_element {
 | 
			
		||||
	char value[CAPWAP_LOCATION_MAXLENGTH + 1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_location_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_location_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_location_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_location_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_LOCATION_ELEMENT(x)				({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_LOCATION);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_location_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_LOCATION_HEADER__ */
 | 
			
		||||
							
								
								
									
										77
									
								
								src/common/capwap_element_maximumlength.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/common/capwap_element_maximumlength.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0              1
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|    Maximum Message Length     |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   29 for Maximum Message Length
 | 
			
		||||
Length:  2
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_maximumlength_raw_element {
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_maximumlength_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_maximumlength_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_maximumlength_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_maximumlength_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_MAXIMUMLENGTH);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_maximumlength_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	((struct capwap_maximumlength_raw_element*)element->data)->length = htons(((struct capwap_maximumlength_element*)data)->length);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_maximumlength_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_maximumlength_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_maximumlength_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_MAXIMUMLENGTH);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_maximumlength_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_maximumlength_element*)capwap_alloc(sizeof(struct capwap_maximumlength_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->length = ntohs(((struct capwap_maximumlength_raw_element*)element->data)->length);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_maximumlength_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/common/capwap_element_maximumlength.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/common/capwap_element_maximumlength.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_MAXIMUMLENGTH_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_MAXIMUMLENGTH_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_MAXIMUMLENGTH			29
 | 
			
		||||
 | 
			
		||||
struct capwap_maximumlength_element {
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_maximumlength_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_maximumlength_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_maximumlength_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_maximumlength_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_MAXIMUMLENGTH_ELEMENT(x)		({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_MAXIMUMLENGTH);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_maximumlength_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_MAXIMUMLENGTH_HEADER__ */
 | 
			
		||||
							
								
								
									
										72
									
								
								src/common/capwap_element_mtudiscovery.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/common/capwap_element_mtudiscovery.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0
 | 
			
		||||
 0 1 2 3 4 5 6 7
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
|  Padding...
 | 
			
		||||
+-+-+-+-+-+-+-+-
 | 
			
		||||
 | 
			
		||||
Type:   52 for MTU Discovery Padding
 | 
			
		||||
Length:  variable
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_mtudiscovery_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_mtudiscovery_element* dataelement = (struct capwap_mtudiscovery_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_mtudiscovery_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + dataelement->length);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_MTUDISCOVERY);
 | 
			
		||||
	element->length = htons(dataelement->length);
 | 
			
		||||
	
 | 
			
		||||
	if (dataelement->length > 0) {
 | 
			
		||||
		memset(element->data, 0xff, dataelement->length);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_mtudiscovery_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_mtudiscovery_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_mtudiscovery_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_MTUDISCOVERY);
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_mtudiscovery_element*)capwap_alloc(sizeof(struct capwap_mtudiscovery_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->length = ntohs(element->length);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_mtudiscovery_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/common/capwap_element_mtudiscovery.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/common/capwap_element_mtudiscovery.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_MTUDISCOVERY_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_MTUDISCOVERY_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_MTUDISCOVERY			52
 | 
			
		||||
 | 
			
		||||
struct capwap_mtudiscovery_element {
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_mtudiscovery_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_mtudiscovery_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_mtudiscovery_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_mtudiscovery_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_MTUDISCOVERY_ELEMENT(x)		({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_MTUDISCOVERY);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_mtudiscovery_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_MTUDISCOVERY_HEADER__ */
 | 
			
		||||
							
								
								
									
										86
									
								
								src/common/capwap_element_radioadmstate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/common/capwap_element_radioadmstate.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Radio ID    |  Admin State  |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   31 for Radio Administrative State
 | 
			
		||||
Length:  2
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_radioadmstate_raw_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned char state;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_radioadmstate_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_radioadmstate_element* dataelement = (struct capwap_radioadmstate_element*)data;
 | 
			
		||||
	struct capwap_radioadmstate_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_radioadmstate_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_radioadmstate_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_radioadmstate_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_RADIOADMSTATE);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_radioadmstate_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_radioadmstate_raw_element*)element->data;
 | 
			
		||||
	dataraw->radioid = dataelement->radioid;
 | 
			
		||||
	dataraw->state = dataelement->state;
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_radioadmstate_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_radioadmstate_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_radioadmstate_element* data;
 | 
			
		||||
	struct capwap_radioadmstate_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RADIOADMSTATE);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_radioadmstate_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_radioadmstate_element*)capwap_alloc(sizeof(struct capwap_radioadmstate_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_radioadmstate_raw_element*)element->data;
 | 
			
		||||
	data->radioid = dataraw->radioid;
 | 
			
		||||
	data->state = dataraw->state;
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_radioadmstate_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/common/capwap_element_radioadmstate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/common/capwap_element_radioadmstate.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_RADIOADMSTATE_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_RADIOADMSTATE_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_RADIOADMSTATE		31
 | 
			
		||||
 | 
			
		||||
struct capwap_radioadmstate_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned char state;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_RADIO_ADMIN_STATE_ENABLED		1
 | 
			
		||||
#define CAPWAP_RADIO_ADMIN_STATE_DISABLED		2
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_radioadmstate_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_radioadmstate_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_radioadmstate_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_radioadmstate_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_RADIOADMSTATE_ELEMENT(x)		({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOADMSTATE);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_radioadmstate_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_RADIOADMSTATE_HEADER__ */
 | 
			
		||||
							
								
								
									
										89
									
								
								src/common/capwap_element_radiooprstate.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/common/capwap_element_radiooprstate.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Radio ID    |     State     |     Cause     |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   32 for Radio Operational State
 | 
			
		||||
Length:  3
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_radiooprstate_raw_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned char state;
 | 
			
		||||
	unsigned char cause;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_radiooprstate_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_radiooprstate_element* dataelement = (struct capwap_radiooprstate_element*)data;
 | 
			
		||||
	struct capwap_radiooprstate_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_radiooprstate_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_radiooprstate_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_radiooprstate_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_RADIOOPRSTATE);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_radiooprstate_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_radiooprstate_raw_element*)element->data;
 | 
			
		||||
	dataraw->radioid = dataelement->radioid;
 | 
			
		||||
	dataraw->state = dataelement->state;
 | 
			
		||||
	dataraw->cause = dataelement->cause;
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_radiooprstate_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_radiooprstate_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_radiooprstate_element* data;
 | 
			
		||||
	struct capwap_radiooprstate_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RADIOOPRSTATE);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_radiooprstate_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_radiooprstate_element*)capwap_alloc(sizeof(struct capwap_radiooprstate_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_radiooprstate_raw_element*)element->data;
 | 
			
		||||
	data->radioid = dataraw->radioid;
 | 
			
		||||
	data->state = dataraw->state;
 | 
			
		||||
	data->cause = dataraw->cause;
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_radiooprstate_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								src/common/capwap_element_radiooprstate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/common/capwap_element_radiooprstate.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_RADIOOPRSTATE_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_RADIOOPRSTATE_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_RADIOOPRSTATE		32
 | 
			
		||||
 | 
			
		||||
struct capwap_radiooprstate_element {
 | 
			
		||||
	unsigned char radioid;
 | 
			
		||||
	unsigned char state;
 | 
			
		||||
	unsigned char cause;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_RADIO_OPERATIONAL_STATE_ENABLED				1
 | 
			
		||||
#define CAPWAP_RADIO_OPERATIONAL_STATE_DISABLED				2
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_NORMAL				0
 | 
			
		||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_RADIOFAILURE			1
 | 
			
		||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_SOFTWAREFAILURE		2
 | 
			
		||||
#define CAPWAP_RADIO_OPERATIONAL_CAUSE_ADMINSET				3
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_radiooprstate_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_radiooprstate_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_radiooprstate_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_radiooprstate_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_RADIOOPRSTATE_ELEMENT(x)		({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RADIOOPRSTATE);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_radiooprstate_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_RADIOOPRSTATE_HEADER__ */
 | 
			
		||||
							
								
								
									
										77
									
								
								src/common/capwap_element_resultcode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/common/capwap_element_resultcode.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                         Result Code                           |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   33 for Result Code
 | 
			
		||||
Length:  4
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_resultcode_raw_element {
 | 
			
		||||
	unsigned long code;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_resultcode_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_resultcode_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_resultcode_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_resultcode_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_RESULTCODE);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_resultcode_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	((struct capwap_resultcode_raw_element*)element->data)->code = htonl(((struct capwap_resultcode_element*)data)->code);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_resultcode_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_resultcode_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_resultcode_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RESULTCODE);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_resultcode_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_resultcode_element*)capwap_alloc(sizeof(struct capwap_resultcode_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->code = ntohl(((struct capwap_resultcode_raw_element*)element->data)->code);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_resultcode_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								src/common/capwap_element_resultcode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/common/capwap_element_resultcode.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_RESULTCODE_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_RESULTCODE_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_RESULTCODE			33
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_RESULTCODE_SUCCESS									0
 | 
			
		||||
#define CAPWAP_RESULTCODE_FAILURE									1
 | 
			
		||||
#define CAPWAP_RESULTCODE_SUCCESS_NAT_DETECTED						2
 | 
			
		||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_UNSPECIFIED					3
 | 
			
		||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_RESOURCE_DEPLETION			4
 | 
			
		||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_UNKNOWN_SOURCE				5
 | 
			
		||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_INCORRECT_DATA				6
 | 
			
		||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_ID_ALREADY_IN_USE			7
 | 
			
		||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_WTP_HARDWARE_NOT_SUPPORTED	8
 | 
			
		||||
#define CAPWAP_RESULTCODE_JOIN_FAILURE_BINDING_NOT_SUPPORTED		9
 | 
			
		||||
#define CAPWAP_RESULTCODE_RESET_FAILURE_UNABLE_TO_RESET				10
 | 
			
		||||
#define CAPWAP_RESULTCODE_RESET_FAILURE_FIRMWARE_WRITE_ERROR		11
 | 
			
		||||
#define CAPWAP_RESULTCODE_CONF_FAILURE_SERVICE_PROVIDED_ANYHOW		12
 | 
			
		||||
#define CAPWAP_RESULTCODE_CONF_FAILURE_SERVICE_NOT_PROVIDED			13
 | 
			
		||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_INVALID_CHECKSUM				14
 | 
			
		||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_INVALID_DATA_LENGTH			15
 | 
			
		||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_OTHER_ERROR					16
 | 
			
		||||
#define CAPWAP_RESULTCODE_IMAGE_ERROR_IMAGE_ALREADY_PRESENT			17
 | 
			
		||||
#define CAPWAP_RESULTCODE_MSG_UNEXPECTED_INVALID_CURRENT_STATE		18
 | 
			
		||||
#define CAPWAP_RESULTCODE_MSG_UNEXPECTED_UNRECOGNIZED_REQUEST		19
 | 
			
		||||
#define CAPWAP_RESULTCODE_FAILURE_MISSING_MANDATORY_MSG_ELEMENT		20
 | 
			
		||||
#define CAPWAP_RESULTCODE_FAILURE_UNRECOGNIZED_MESSAGE_ELEMENT		21
 | 
			
		||||
#define CAPWAP_RESULTCODE_DATA_TRANSFER_ERROR						22
 | 
			
		||||
      
 | 
			
		||||
struct capwap_resultcode_element {
 | 
			
		||||
	unsigned long code;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_resultcode_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_resultcode_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_resultcode_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_resultcode_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_RESULTCODE_ELEMENT(x)			({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RESULTCODE);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_resultcode_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_RESULTCODE_HEADER__ */
 | 
			
		||||
							
								
								
									
										93
									
								
								src/common/capwap_element_returnedmessage.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/common/capwap_element_returnedmessage.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|    Reason     |    Length     |       Message Element...
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   34 for Returned Message Element
 | 
			
		||||
Length:  >= 6
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_returnedmessage_raw_element {
 | 
			
		||||
	unsigned char reason;
 | 
			
		||||
	unsigned char length;
 | 
			
		||||
	char message[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_returnedmessage_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_returnedmessage_raw_element* dataraw;
 | 
			
		||||
	struct capwap_returnedmessage_element* dataelement = (struct capwap_returnedmessage_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_returnedmessage_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	length = sizeof(struct capwap_returnedmessage_raw_element) + dataelement->length;
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + length);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_RETURNEDMESSAGE);
 | 
			
		||||
	element->length = htons(length);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_returnedmessage_raw_element*)element->data;
 | 
			
		||||
	dataraw->reason = dataelement->reason;
 | 
			
		||||
	dataraw->length = dataelement->length;
 | 
			
		||||
	memcpy(&dataraw->message[0], &dataelement->message[0], dataelement->length);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_returnedmessage_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_returnedmessage_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	unsigned short length;
 | 
			
		||||
	struct capwap_returnedmessage_element* data;
 | 
			
		||||
	struct capwap_returnedmessage_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_RETURNEDMESSAGE);
 | 
			
		||||
 | 
			
		||||
	length = ntohs(element->length) - sizeof(struct capwap_returnedmessage_raw_element);
 | 
			
		||||
	if (length > CAPWAP_RETURNED_MESSAGE_MAX_LENGTH)  {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_returnedmessage_raw_element*)element->data;
 | 
			
		||||
	data = (struct capwap_returnedmessage_element*)capwap_alloc(sizeof(struct capwap_returnedmessage_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->reason = dataraw->reason;
 | 
			
		||||
	data->length = dataraw->length;
 | 
			
		||||
	memcpy(&data->message[0], &dataraw->message[0], dataraw->length);
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_returnedmessage_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								src/common/capwap_element_returnedmessage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/common/capwap_element_returnedmessage.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_RETURNEDMESSAGE_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_RETURNEDMESSAGE_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_RETURNEDMESSAGE			34
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_REASON_UNKNOWN_MESSAGE_ELEMENT					1
 | 
			
		||||
#define CAPWAP_REASON_UNSUPPORTED_MESSAGE_ELEMENT				2
 | 
			
		||||
#define CAPWAP_REASON_UNKNOWN_MESSAGE_ELEMENT_VALUE				3
 | 
			
		||||
#define CAPWAP_REASON_UNSUPPORTED_MESSAGE_ELEMENT_VALUE			4
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_RETURNED_MESSAGE_MAX_LENGTH						255
 | 
			
		||||
     
 | 
			
		||||
struct capwap_returnedmessage_element {
 | 
			
		||||
	unsigned char reason;
 | 
			
		||||
	unsigned char length;
 | 
			
		||||
	char message[CAPWAP_RETURNED_MESSAGE_MAX_LENGTH];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_returnedmessage_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_returnedmessage_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_returnedmessage_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_returnedmessage_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_RETURNEDMESSAGE_ELEMENT(x)	({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_RETURNEDMESSAGE);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_returnedmessage_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_RETURNEDMESSAGE_HEADER__ */
 | 
			
		||||
							
								
								
									
										115
									
								
								src/common/capwap_element_sessionid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/common/capwap_element_sessionid.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,115 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           Session ID                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           Session ID                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           Session ID                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                           Session ID                          |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Type:   35 for Session ID
 | 
			
		||||
Length:   16
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_sessionid_raw_element {
 | 
			
		||||
	unsigned char id[16];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_sessionid_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_sessionid_raw_element* dataraw;
 | 
			
		||||
	struct capwap_sessionid_element* dataelement = (struct capwap_sessionid_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_sessionid_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_sessionid_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_sessionid_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_SESSIONID);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_sessionid_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_sessionid_raw_element*)element->data;
 | 
			
		||||
	memcpy(&dataraw->id[0], &dataelement->id[0], sizeof(unsigned char) * 16);
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_sessionid_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_sessionid_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_sessionid_element* data;
 | 
			
		||||
	struct capwap_sessionid_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_SESSIONID);
 | 
			
		||||
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_sessionid_raw_element))  {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_sessionid_raw_element*)element->data;
 | 
			
		||||
	data = (struct capwap_sessionid_element*)capwap_alloc(sizeof(struct capwap_sessionid_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	memcpy(&data->id[0], &dataraw->id[0], sizeof(unsigned char) * 16);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_sessionid_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_sessionid_generate(struct capwap_sessionid_element* session) {
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 16; i++) {
 | 
			
		||||
		session->id[i] = (unsigned char)capwap_get_rand(256);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_sessionid_printf(struct capwap_sessionid_element* session, char* string) {
 | 
			
		||||
	int i;
 | 
			
		||||
	char* pos = string;
 | 
			
		||||
 | 
			
		||||
	ASSERT(session != NULL);
 | 
			
		||||
	ASSERT(string != NULL);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < 16; i++) {
 | 
			
		||||
		sprintf(pos, "%02x", session->id[i]);
 | 
			
		||||
		pos += 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*pos = 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/common/capwap_element_sessionid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/common/capwap_element_sessionid.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_SESSIONID_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_SESSIONID_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_SESSIONID		35
 | 
			
		||||
 | 
			
		||||
struct capwap_sessionid_element {
 | 
			
		||||
	unsigned char id[16];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_sessionid_element_create(void* data, unsigned long datalength);
 | 
			
		||||
int capwap_sessionid_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_sessionid_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_sessionid_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
void capwap_sessionid_generate(struct capwap_sessionid_element* session);
 | 
			
		||||
void capwap_sessionid_printf(struct capwap_sessionid_element* session, char* string);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_SESSIONID_ELEMENT(x)				({	\
 | 
			
		||||
															struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_SESSIONID);	\
 | 
			
		||||
															f->create(x, sizeof(struct capwap_sessionid_element));	\
 | 
			
		||||
														})
 | 
			
		||||
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_SESSIONID_HEADER__ */
 | 
			
		||||
							
								
								
									
										77
									
								
								src/common/capwap_element_statisticstimer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/common/capwap_element_statisticstimer.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|        Statistics Timer       |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   36 for Statistics Timer
 | 
			
		||||
Length:  2
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_statisticstimer_raw_element {
 | 
			
		||||
	unsigned short timer;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_statisticstimer_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_statisticstimer_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_statisticstimer_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_statisticstimer_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_STATISTICSTIMER);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_statisticstimer_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	((struct capwap_statisticstimer_raw_element*)element->data)->timer = htons(((struct capwap_statisticstimer_element*)data)->timer);
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_statisticstimer_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_statisticstimer_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_statisticstimer_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_STATISTICSTIMER);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_statisticstimer_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_statisticstimer_element*)capwap_alloc(sizeof(struct capwap_statisticstimer_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->timer = ntohs(((struct capwap_statisticstimer_raw_element*)element->data)->timer);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_statisticstimer_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								src/common/capwap_element_statisticstimer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/common/capwap_element_statisticstimer.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_STATISTICSTIMER_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_STATISTICSTIMER_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_STATISTICSTIMER			36
 | 
			
		||||
 | 
			
		||||
struct capwap_statisticstimer_element {
 | 
			
		||||
	unsigned short timer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_statisticstimer_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_statisticstimer_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_statisticstimer_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_statisticstimer_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_STATISTICSTIMER_ELEMENT(x)	({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_STATISTICSTIMER);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_statisticstimer_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_STATISTICSTIMER_HEADER__ */
 | 
			
		||||
							
								
								
									
										86
									
								
								src/common/capwap_element_timers.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/common/capwap_element_timers.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Discovery   | Echo Request  |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   12 for CAPWAP Timers
 | 
			
		||||
Length:  2
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_timers_raw_element {
 | 
			
		||||
	unsigned char discovery;
 | 
			
		||||
	unsigned char echorequest;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_timers_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_timers_element* dataelement = (struct capwap_timers_element*)data;
 | 
			
		||||
	struct capwap_timers_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_timers_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_timers_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_timers_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_TIMERS);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_timers_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_timers_raw_element*)element->data;
 | 
			
		||||
	dataraw->discovery = dataelement->discovery;
 | 
			
		||||
	dataraw->echorequest = dataelement->echorequest;
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_timers_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_timers_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_timers_element* data;
 | 
			
		||||
	struct capwap_timers_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_TIMERS);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_timers_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_timers_element*)capwap_alloc(sizeof(struct capwap_timers_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_timers_raw_element*)element->data;
 | 
			
		||||
	data->discovery = dataraw->discovery;
 | 
			
		||||
	data->echorequest = dataraw->echorequest;
 | 
			
		||||
	
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_timers_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								src/common/capwap_element_timers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/common/capwap_element_timers.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_TIMERS_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_TIMERS_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_TIMERS				12
 | 
			
		||||
 | 
			
		||||
struct capwap_timers_element {
 | 
			
		||||
	unsigned char discovery;
 | 
			
		||||
	unsigned char echorequest;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_timers_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_timers_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_timers_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_timers_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_TIMERS_ELEMENT(x)				({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_TIMERS);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_timers_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_TIMERS_HEADER__ */
 | 
			
		||||
							
								
								
									
										77
									
								
								src/common/capwap_element_transport.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/common/capwap_element_transport.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0
 | 
			
		||||
 0 1 2 3 4 5 6 7
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
|   Transport   |
 | 
			
		||||
+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   51 for CAPWAP Transport Protocol
 | 
			
		||||
Length:  1
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_transport_raw_element {
 | 
			
		||||
	char type;
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_transport_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_transport_element));
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + sizeof(struct capwap_transport_raw_element));
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + sizeof(struct capwap_transport_raw_element));
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_TRANSPORT);
 | 
			
		||||
	element->length = htons(sizeof(struct capwap_transport_raw_element));
 | 
			
		||||
	
 | 
			
		||||
	((struct capwap_transport_raw_element*)element->data)->type = ((struct capwap_transport_element*)data)->type;
 | 
			
		||||
	
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_transport_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_transport_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	struct capwap_transport_element* data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_TRANSPORT);
 | 
			
		||||
	
 | 
			
		||||
	if (ntohs(element->length) != sizeof(struct capwap_transport_raw_element)) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data = (struct capwap_transport_element*)capwap_alloc(sizeof(struct capwap_transport_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->type = ((struct capwap_transport_raw_element*)element->data)->type;
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_transport_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/common/capwap_element_transport.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/common/capwap_element_transport.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
#ifndef __CAPWAP_ELEMENT_TRANSPORT_HEADER__
 | 
			
		||||
#define __CAPWAP_ELEMENT_TRANSPORT_HEADER__
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_ELEMENT_TRANSPORT			51
 | 
			
		||||
 | 
			
		||||
struct capwap_transport_element {
 | 
			
		||||
	char type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define CAPWAP_UDPLITE_TRANSPORT		1
 | 
			
		||||
#define CAPWAP_UDP_TRANSPORT			2
 | 
			
		||||
 | 
			
		||||
struct capwap_message_element* capwap_transport_element_create(void* data, unsigned long length);
 | 
			
		||||
int capwap_transport_element_validate(struct capwap_message_element* element);
 | 
			
		||||
void* capwap_transport_element_parsing(struct capwap_message_element* element);
 | 
			
		||||
void capwap_transport_element_free(void* data);
 | 
			
		||||
 | 
			
		||||
/* Helper */
 | 
			
		||||
#define CAPWAP_CREATE_TRANSPORT_ELEMENT(x)			({	\
 | 
			
		||||
														struct capwap_message_elements_func* f = capwap_get_message_element(CAPWAP_ELEMENT_TRANSPORT);	\
 | 
			
		||||
														f->create(x, sizeof(struct capwap_transport_element));	\
 | 
			
		||||
													})
 | 
			
		||||
														
 | 
			
		||||
#endif /* __CAPWAP_ELEMENT_TRANSPORT_HEADER__ */
 | 
			
		||||
							
								
								
									
										99
									
								
								src/common/capwap_element_vendorpayload.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/common/capwap_element_vendorpayload.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,99 @@
 | 
			
		||||
#include "capwap.h"
 | 
			
		||||
#include "capwap_element.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************************
 | 
			
		||||
 | 
			
		||||
 0                   1                   2                   3
 | 
			
		||||
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|                       Vendor Identifier                       |
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
|          Element ID           |    Data...
 | 
			
		||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 | 
			
		||||
 | 
			
		||||
Type:   37 for Vendor Specific Payload
 | 
			
		||||
Length:   >= 7
 | 
			
		||||
 | 
			
		||||
********************************************************************/
 | 
			
		||||
 | 
			
		||||
struct capwap_vendorpayload_raw_element {
 | 
			
		||||
	unsigned long vendorid;
 | 
			
		||||
	unsigned short elementid;
 | 
			
		||||
	char data[0];
 | 
			
		||||
} __attribute__((__packed__));
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
struct capwap_message_element* capwap_vendorpayload_element_create(void* data, unsigned long datalength) {
 | 
			
		||||
	unsigned short elementlength;
 | 
			
		||||
	struct capwap_message_element* element;
 | 
			
		||||
	struct capwap_vendorpayload_raw_element* dataraw;
 | 
			
		||||
	struct capwap_vendorpayload_element* dataelement = (struct capwap_vendorpayload_element*)data;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	ASSERT(datalength == sizeof(struct capwap_vendorpayload_element));
 | 
			
		||||
	
 | 
			
		||||
	/* */
 | 
			
		||||
	if (!dataelement->datalength || (dataelement->datalength > CAPWAP_VENDORPAYLOAD_MAXLENGTH)) {
 | 
			
		||||
		return NULL; 
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Alloc block of memory */
 | 
			
		||||
	elementlength = sizeof(struct capwap_vendorpayload_raw_element) + dataelement->datalength;
 | 
			
		||||
	element = capwap_alloc(sizeof(struct capwap_message_element) + elementlength);
 | 
			
		||||
	if (!element) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Create message element */
 | 
			
		||||
	memset(element, 0, sizeof(struct capwap_message_element) + elementlength);
 | 
			
		||||
	element->type = htons(CAPWAP_ELEMENT_VENDORPAYLOAD);
 | 
			
		||||
	element->length = htons(elementlength);
 | 
			
		||||
	
 | 
			
		||||
	dataraw = (struct capwap_vendorpayload_raw_element*)element->data;
 | 
			
		||||
	dataraw->vendorid = htonl(dataelement->vendorid);
 | 
			
		||||
	dataraw->elementid = htons(dataelement->elementid);
 | 
			
		||||
	memcpy(&dataraw->data[0], &dataelement->data[0], dataelement->datalength);
 | 
			
		||||
	return element;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
int capwap_vendorpayload_element_validate(struct capwap_message_element* element) {
 | 
			
		||||
	/* TODO */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void* capwap_vendorpayload_element_parsing(struct capwap_message_element* element) {
 | 
			
		||||
	unsigned short elementlength;
 | 
			
		||||
	struct capwap_vendorpayload_element* data;
 | 
			
		||||
	struct capwap_vendorpayload_raw_element* dataraw;
 | 
			
		||||
	
 | 
			
		||||
	ASSERT(element);
 | 
			
		||||
	ASSERT(ntohs(element->type) == CAPWAP_ELEMENT_VENDORPAYLOAD);
 | 
			
		||||
 | 
			
		||||
	elementlength = ntohs(element->length);
 | 
			
		||||
	if (elementlength > sizeof(struct capwap_vendorpayload_raw_element))  {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	dataraw = (struct capwap_vendorpayload_raw_element*)element->data;
 | 
			
		||||
	data = (struct capwap_vendorpayload_element*)capwap_alloc(sizeof(struct capwap_vendorpayload_element));
 | 
			
		||||
	if (!data) {
 | 
			
		||||
		capwap_outofmemory();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* */
 | 
			
		||||
	data->vendorid = ntohl(dataraw->vendorid);
 | 
			
		||||
	data->elementid = ntohs(dataraw->elementid);
 | 
			
		||||
	data->datalength = elementlength - sizeof(struct capwap_vendorpayload_element);
 | 
			
		||||
	memcpy(&data->data[0], &dataraw->data[0], data->datalength);
 | 
			
		||||
	return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* */
 | 
			
		||||
void capwap_vendorpayload_element_free(void* data) {
 | 
			
		||||
	ASSERT(data != NULL);
 | 
			
		||||
	
 | 
			
		||||
	capwap_free(data);
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user