init
This commit is contained in:
18
BUGREPORTS
Normal file
18
BUGREPORTS
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
* If you have found a bug, i.e. socat SIGSEGV'ed, terminated abnormally without
|
||||
error message, did not comply to the documentation, or behaves different from
|
||||
your expectations, please send the following infos to socat@dest-unreach.org,
|
||||
as available:
|
||||
. output of "make info" in socat.out (you may remove the hostname in the first
|
||||
line to keep your privacy)
|
||||
. config.log
|
||||
. run your example with "socat -d -d -d -d -D ..." options, and include the log
|
||||
output
|
||||
. describe what you've done, and why you think socat did wrong
|
||||
|
||||
* If you fixed a bug:
|
||||
Please do as described in the above paragraph, and include the modified files
|
||||
(or a patch file)
|
||||
|
||||
* If you have contributions, problems etc: send available info and a
|
||||
description to the above address.
|
||||
339
COPYING
Normal file
339
COPYING
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.
|
||||
127
COPYING.OpenSSL
Normal file
127
COPYING.OpenSSL
Normal file
@@ -0,0 +1,127 @@
|
||||
|
||||
LICENSE ISSUES
|
||||
==============
|
||||
|
||||
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.
|
||||
|
||||
OpenSSL License
|
||||
---------------
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2002 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.]
|
||||
*/
|
||||
|
||||
242
DEVELOPMENT
Normal file
242
DEVELOPMENT
Normal file
@@ -0,0 +1,242 @@
|
||||
|
||||
This file should help you to add new address types and address options to
|
||||
socat.
|
||||
|
||||
NOTE:
|
||||
socat will in future releases be split into a library "libxio" containing all
|
||||
the address stuff, useful also for many other purposes, and the socat main()
|
||||
and data shuffler. If you intend to perform major changes to the xio part and
|
||||
to publish them, please contact me before!
|
||||
|
||||
|
||||
ADDING A NEW ADDRESS TYPE:
|
||||
|
||||
* Create new files xio-newaddr.c and xio-newaddr.h
|
||||
|
||||
* Create a new record of struct addrdesc in xio-newaddr.c, with declaration in xio-newaddr.h.
|
||||
|
||||
* Make a new entry to addressnames[] in xioopen.c with the addresses main name
|
||||
and maybe with alias names. Keep this array ASCII sorted, without uppercase
|
||||
chars.
|
||||
|
||||
* config.h.in: #undef WITH_NEWADDR
|
||||
|
||||
* configure.in: Copy the disable part of, e.g., WITH_SOCKS4 and adapt it to
|
||||
NEWADDR
|
||||
|
||||
* In socat.c, add to socat_version
|
||||
|
||||
* Write a function xioopen_newaddr() in xio-newaddr.c, declaration in
|
||||
xio-newaddr.h
|
||||
Do not forget the following option processing calls:
|
||||
All groups: _xio_openlate()
|
||||
Group FD: applyopts_cloexec()
|
||||
Group NAMED: applyopts_file() for phases PREOPEN, OPEN, and FD
|
||||
|
||||
* Describe a tested example in file EXAMPLES, and maybe in the socat manpage
|
||||
source.
|
||||
|
||||
* Try to define a test for this address type in test.sh
|
||||
|
||||
* Update file CHANGES
|
||||
|
||||
|
||||
ADDING A NEW ADDRESS OPTION:
|
||||
|
||||
xioopen.c:
|
||||
|
||||
* If this option depends on a #define that is probably not available on all
|
||||
platforms, make all new code for this option dependent on the existence of this
|
||||
C header define:
|
||||
#ifdef PREFIX_NEWOPTION
|
||||
...
|
||||
#endif
|
||||
|
||||
* Add an OPT_NEWOPTION to enum e_optcode in xioopts.h, preferably keeping
|
||||
alphabetic order
|
||||
|
||||
* Add a struct optdesc opt_newoption record in xio-newaddr.c and its
|
||||
declaration in xio-newaddr.h. The complete structure definition must be in one
|
||||
line without breaks for automatic docu extraction.
|
||||
Build the record from the following components:
|
||||
. A canonical default name (e.g. "newoption")
|
||||
. A short, preferable name (e.g. "newopt") or NULL
|
||||
. OPT_NEWOPTION (from enum e_optcode, see above)
|
||||
. A group membership that restricts appliance of the new option to matching
|
||||
address types (e.g., one of GROUP_ANY, GROUP_IP_TCP, GROUP_EXEC)
|
||||
. A phase specification that positions this option within address processing.
|
||||
Note that the function code can override this value.
|
||||
. A representation type for option arguments (e.g., TYPE_INT, TYPE_STRING etc.;
|
||||
use TYPE_BOOL if this option just triggers an action)
|
||||
. A function or action definition for applying this option. If it does not use
|
||||
one of the standard functions (open(), ioctl(), setsockopt()...), then use
|
||||
OFUNC_SPEC (specific).
|
||||
|
||||
* For the canonical name and all its aliases and abbreviations, add entries to
|
||||
the array optionnames in xioopts.c. KEEP STRICT ALPHABETIC (ASCII) ORDER!
|
||||
The entries must be embedded in an IF_... macro of their group for conditional
|
||||
compiling.
|
||||
|
||||
* For options using some predefined action (see OFUNC above), this might be
|
||||
enough - test the option and document it in doc/socat.yo!
|
||||
For OFUNC_SPEC, it might suffice to add another "case" to the OFUNC_SPEC branch
|
||||
in applyopts() in xioopts.c. If you need more special handling, you should try
|
||||
to understand the address specific functions and add your code there.
|
||||
|
||||
* If you use system or low level C library calls or library calls that might
|
||||
hang or induce problems, please invoke them with capitalized name; if no such
|
||||
name is defined, add an appropriate debug function to sycls.c, and a header
|
||||
entry and a wrapper "define" to sycls.h
|
||||
|
||||
* Update file CHANGES
|
||||
|
||||
|
||||
INFO ABOUT ADDRESS PHASES:
|
||||
|
||||
Each option entry has a field specifying a default phase for its application.
|
||||
Of course, the code that analyses and applies an address may override this
|
||||
default phase.
|
||||
|
||||
Depending on the type of address there are several major phase sequences:
|
||||
|
||||
|
||||
OPEN addresses:
|
||||
|
||||
PH_INIT retrieving info from original state
|
||||
PH_EARLY before any other processing
|
||||
PH_PREOPEN before file creation/opening (not UNIX sockets)
|
||||
PH_OPEN during file creation/opening (not UNIX sockets)
|
||||
PH_PASTOPEN past file creation/opening (not UNIX sockets)
|
||||
PH_FD soon after FD creation or identification
|
||||
PH_LATE FD is ready, before start of data loop
|
||||
PH_LATE2 FD is ready, dropping privileges
|
||||
|
||||
|
||||
SOCKET addresses:
|
||||
|
||||
PH_INIT retrieving info from original state
|
||||
PH_EARLY before any other processing
|
||||
PH_PRESOCKET before socket call
|
||||
PH_SOCKET for socket call
|
||||
PH_PASTSOCKET after socket call
|
||||
PH_FD soon after FD creation or identification
|
||||
PH_PREBIND before socket bind()
|
||||
PH_BIND during socket bind()
|
||||
PH_PASTBIND past socket bind()
|
||||
PH_PRECONNECT before connect()
|
||||
PH_CONNECT during connect()
|
||||
PH_PASTCONNECT after connect()
|
||||
PH_CONNECTED phase common with listen
|
||||
PH_LATE FD is ready, before start of data loop
|
||||
PH_LATE2 FD is ready, dropping privileges
|
||||
|
||||
|
||||
SOCKET with LISTEN and ACCEPT:
|
||||
|
||||
PH_INIT retrieving info from original state
|
||||
PH_EARLY before any other processing
|
||||
PH_PRESOCKET before socket call
|
||||
PH_SOCKET for socket call
|
||||
PH_PREBIND before socket bind()
|
||||
PH_BIND during socket bind()
|
||||
PH_PASTBIND past socket bind()
|
||||
PH_PRELISTEN before listen()
|
||||
PH_LISTEN during listen()
|
||||
PH_PASTLISTEN after listen()
|
||||
PH_PREACCEPT before accept()
|
||||
PH_ACCEPT during accept()
|
||||
PH_PASTACCEPT after accept()
|
||||
# and the following on the new FD:
|
||||
PH_FD soon after FD creation or identification
|
||||
PH_PASTSOCKET after socket call
|
||||
PH_CONNECTED phase common with connect
|
||||
PH_PREFORK before forking
|
||||
PH_FORK during fork()
|
||||
PH_PASTFORK after fork()
|
||||
PH_LATE FD is ready, before start of data loop
|
||||
PH_LATE2 FD is ready, dropping privileges
|
||||
|
||||
|
||||
Passive UNIX socket addresses; this is a mix of socket phases and file system phases:
|
||||
PH_INIT retrieving info from original state
|
||||
PH_EARLY before any other processing
|
||||
PH_PRESOCKET before socket call
|
||||
PH_SOCKET for socket call
|
||||
PH_PASTSOCKET after socket call
|
||||
PH_FD soon after FD creation or identification
|
||||
PH_PREOPEN before file creation/opening
|
||||
PH_PREBIND before socket bind()
|
||||
PH_BIND during socket bind()
|
||||
PH_PASTOPEN past file creation/opening
|
||||
PH_PASTBIND past socket bind(), not used up to 1.7.3.4
|
||||
PH_PRECONNECT before connect()
|
||||
PH_CONNECT during connect()
|
||||
PH_PASTCONNECT after connect()
|
||||
PH_CONNECTED phase common with listen
|
||||
PH_LATE FD is ready, before start of data loop
|
||||
PH_LATE2 FD is ready, dropping privileges
|
||||
|
||||
|
||||
FD addresses:
|
||||
|
||||
PH_INIT retrieving info from original state
|
||||
PH_EARLY before any other processing
|
||||
PH_FD soon after FD identification
|
||||
PH_LATE FD is ready, before start of data loop
|
||||
PH_LATE2 FD is ready, dropping privileges
|
||||
|
||||
|
||||
EXEC addresses:
|
||||
|
||||
PH_INIT retrieving info from original state
|
||||
PH_EARLY before any other processing
|
||||
PH_PREBIGEN before socketpair() pipe() openpty()
|
||||
PH_BIGEN during socketpair() pipe() openpty()
|
||||
PH_PASTBIGEN past socketpair() pipe() openpty()
|
||||
PH_PASTSOCKET for socketpair()
|
||||
PH_FD soon after FD creation or identification
|
||||
PH_PREFORK before forking
|
||||
PH_FORK during fork()
|
||||
PH_PASTFORK after fork()
|
||||
PH_LATE FD is ready, before start of data loop
|
||||
PH_LATE2 FD is ready, dropping privileges
|
||||
PH_PREEXEC before exec() or system()
|
||||
PH_EXEC during exec() or system()
|
||||
|
||||
|
||||
There are lots of semantic relations between group, phase, and func fields of
|
||||
an option.
|
||||
|
||||
|
||||
There exists something like an overall phase sequence:
|
||||
PH_INIT # su-d.1
|
||||
PH_EARLY # chroot-early
|
||||
PH_PREOPEN, PH_OPEN, PH_PASTOPEN # (chroot before/after?)
|
||||
PH_PRESOCKET, PH_SOCKET, PH_PASTSOCKET # (su after (root for raw)?)
|
||||
PH_PREBIGEN, PH_BIGEN, PH_PASTBIGEN # (chroot before/after (/dev..)?)
|
||||
PH_FD
|
||||
PH_PREBIND, PH_BIND, PH_PASTBIND # (su after(before?))
|
||||
PH_PRELISTEN, PH_LISTEN, PH_PASTLISTEN
|
||||
PH_PRECONNECT, PH_CONNECT, PH_PASTCONNECT # (chroot before/after (AF_UNIX)?)
|
||||
PH_PREACCEPT, PH_ACCEPT, PH_PASTACCEPT
|
||||
PH_CONNECTED
|
||||
PH_PREFORK, PH_FORK, PH_PASTFORK # (all before/after?)
|
||||
PH_LATE # chroot
|
||||
PH_LATE2 # su, su-d.2
|
||||
PH_PREEXEC, PH_EXEC # (all before)
|
||||
|
||||
===============================================================================
|
||||
// Up to 1.7.2.4 socat used non async signal safe system and library calls in signal handlers, mostly for logging purposes. This problem was fixed in release 1.7.3.0 with the following concepts:
|
||||
|
||||
Signal handlers set on entry and unset on return the diag_in_handler global variable. The logging system, when this variable is set, queues the text message together with errno and exit info in a UNIX datagram socket. When invoked with unset diag_in_handler it first checks if there are messages in that queue and prints them first.
|
||||
|
||||
A async signal safe but minimal version of vsnprintf, named vsnprintf_r, was written so no value arguments need to be queued.
|
||||
|
||||
Because strerror is not async signal safe a new function snprinterr was written that replaces the (glibc compatible) %m format with strerror output. The original errno is passed in the message queue, snprinterr is called when dequeuing messages outside of signal handler.
|
||||
|
||||
// List of signal handlers in socat
|
||||
socat.c:socat_signal (generic, just logs and maybe exits)
|
||||
xioshutdown.c:signal_kill_pid (SIGALRM, kill child process)
|
||||
xiosigchld.c:childdied (SIGCHLD: get info, log; possibly close channel)
|
||||
xiosignal.c:socatsignalpass: cascades signal to channel child processes; w/ options sighup,sigint,sigquit
|
||||
xio-socket.c:xiosigaction_hasread: SIGUSR1,SIGCHLD, tells parent that datagram has been consumed
|
||||
456
EXAMPLES
Normal file
456
EXAMPLES
Normal file
@@ -0,0 +1,456 @@
|
||||
|
||||
// Examples for using socat (and filan)
|
||||
|
||||
|
||||
//"$" means normal user, "#" requires privileges, "//" starts a comment
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Similar to netcat
|
||||
|
||||
// Connect to 10.1.1.1 on port 80 and relay to and from stdio
|
||||
$ socat - TCP:10.1.1.1:80 # similar to "netcat 10.1.1.1 80"
|
||||
|
||||
// Listen on port 25, wait for an incoming connection, use CR+NL on this
|
||||
// connection, relay data to and from stdio;
|
||||
// then emulate a mailserver by hand :-)
|
||||
# socat - TCP-LISTEN:25,crlf
|
||||
|
||||
// Listen on port 25, wait for an incoming connection, use CR+NL on this
|
||||
// connection, relay data to and from stdio, but have line editing and history;
|
||||
// then emulate a mailserver by hand :-)
|
||||
# socat READLINE TCP-LISTEN:25,crlf
|
||||
|
||||
// Provide a transient history enabled front end to stupid line based
|
||||
// interactive programs
|
||||
$ socat \
|
||||
READLINE \
|
||||
EXEC:"nslookup",pty,ctty,setsid,echo=0
|
||||
// Same works for ftp (but password is not hidden)
|
||||
|
||||
// You may also use a file based history list
|
||||
$ socat \
|
||||
READLINE,history=.nslookup_hist \
|
||||
EXEC:"nslookup",pty,ctty,setsid,echo=0
|
||||
// Using ~ as abbreviation for $HOME does not work!
|
||||
|
||||
// Poor mans 'telnetd' replacement
|
||||
# socat \
|
||||
TCP-L:2023,reuseaddr,fork \
|
||||
EXEC:/bin/login,pty,setsid,setpgid,stderr,ctty
|
||||
// and here an appropriate client:
|
||||
$ socat \
|
||||
-,raw,echo=0 \
|
||||
TCP:172.16.181.130:2023
|
||||
// Use ssl with client and server certificate for improved security;
|
||||
// replace /bin/login by /bin/bash when using SSL client authentication, can be
|
||||
// run without root then
|
||||
|
||||
// This is a cool trick, proposed by Christophe Lohr, to dump communications to
|
||||
// two files; it would also work for other manipulations (recode, compress...)
|
||||
// and it might also work with netcat ;-)
|
||||
$ socat \
|
||||
TCP-LISTEN:5555 \
|
||||
SYSTEM:'tee l2r | socat - "TCP:remote:5555" | tee r2l'
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Emergence solution because usleep(1) is not always available
|
||||
// this will "sleep" for 0.1s
|
||||
$ socat -T 0.1 PIPE PIPE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// A very primitive HTTP/1.0 echo server (problems: sends reply headers before
|
||||
// request; hangs if client does not shutdown - HTTP keep-alive)
|
||||
// wait for a connection on port 8000; do not wait for request, but immediately
|
||||
// start a shell that sends reply headers and an empty line; then echo all
|
||||
// incoming data back to client
|
||||
$ socat \
|
||||
TCP-LISTEN:8000,crlf \
|
||||
SYSTEM:"echo HTTP/1.0 200; echo Content-Type\: text/plain; echo; cat"
|
||||
|
||||
// A less primitive HTTP echo server that sends back not only the reqest but
|
||||
// also server and client address and port. Might have portability issues with
|
||||
// echo
|
||||
$ socat -T 1 -d -d \
|
||||
TCP-L:10081,reuseaddr,fork,crlf \
|
||||
SYSTEM:"echo -e \"\\\"HTTP/1.0 200 OK\\\nDocumentType: text/html\\\n\\\n<html>date: \$\(date\)<br>server:\$SOCAT_SOCKADDR:\$SOCAT_SOCKPORT<br>client: \$SOCAT_PEERADDR:\$SOCAT_PEERPORT\\\n<pre>\\\"\"; cat; echo -e \"\\\"\\\n</pre></html>\\\"\""
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For communicating with an attached modem, I had reasonable results with
|
||||
// following command line. Required privileges depend on device mode.
|
||||
// After leaving socat, type "sane".
|
||||
// Replace /dev/ttyS0 by the correct serial line or with /dev/modem
|
||||
$ socat \
|
||||
READLINE \
|
||||
/dev/ttyS0,raw,echo=0,crlf
|
||||
// or
|
||||
$ socat \
|
||||
READLINE \
|
||||
/dev/ttyS0,raw,echo=0,crlf,nonblock
|
||||
// then enter "at$"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Relay TCP port 80 from everywhere (internet, intranet, dmz) through your
|
||||
// firewall to your DMZ webserver (like plug-gw)
|
||||
// Listen on port 80; whenever a connection is made, fork a new process (parent
|
||||
// Process keeps accepting connections), su to nobody, and connect to
|
||||
// www.dmz.mydomain.org on port 80.
|
||||
// Attention: this is a substitute for a reverse proxy without providing
|
||||
// application level security.
|
||||
# socat \
|
||||
TCP-LISTEN:80,reuseaddr,fork,su=nobody \
|
||||
TCP:www.dmz.mydomain.org:80
|
||||
// Note: parent process keeps running as root, su after forking
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Relay mail from your DMZ server through your firewall.
|
||||
// accept connections only on dmz interface and allow connections only from
|
||||
// smtp.dmz.mydomain.org.
|
||||
// the advantages over plug-gw and other relays are:
|
||||
// * you can bind to an IP address (even an alias), therefore enhance security
|
||||
// * in your OS you can create several IP aliases and bind another socat daemon
|
||||
// to each, making several application servers addressable
|
||||
// * lots of options, like switching user, chroot, IP performance tuning
|
||||
// * no need for inetd
|
||||
# socat -lm -d -d \
|
||||
TCP-LISTEN:25,bind=fw.dmz.mydomain.org,fork,su=nobody,range=smtp.dmz.mydomain.org/32 \
|
||||
TCP:smtp.intra.mydomain.org:25
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Convert line terminator in ascii streams, stdin to stdout
|
||||
// use unidirectional mode, convert nl to crnl
|
||||
$ socat -u - -,crlf
|
||||
// or cr to nl
|
||||
$ socat -u -,cr -
|
||||
|
||||
// Save piped data similar to 'tee':
|
||||
// copies stdin to stdout, but writes everything to the file too
|
||||
$ socat \
|
||||
-,echo=0 \
|
||||
OPEN:/tmp/myfile,create,trunc,ignoreeof!!/tmp/myfile
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Intrusion testing
|
||||
|
||||
// Found an XWindow Server behind IP filters with FTP data hole? (you are
|
||||
// lucky!)
|
||||
// prepare your host:
|
||||
# rm -f /tmp/.X11-unix/X1
|
||||
// relay a pseudo display :1 on your machine to victim:0
|
||||
# socat \
|
||||
UNIX-LISTEN:/tmp/.X11-unix/X1,fork \
|
||||
TCP:host.victim.org:6000,sp=20 &
|
||||
// and try to take a screendump (must be very lucky - when server has not even
|
||||
// host based authentication!)
|
||||
# xwd -root -display :1 -silent >victim.xwd
|
||||
|
||||
// You sit behind a socks firewall that has IP filters but lazily allows socks
|
||||
// connections to loopback and has only host based X11 security.
|
||||
// like above, but from your inside client:
|
||||
# socat \
|
||||
UNIX-LISTEN:/tmp/.X11-unix/X1,fork \
|
||||
SOCKS4:firewall:loopback:6000
|
||||
// or for the HTTP proxy:
|
||||
# socat \
|
||||
UNIX-LISTEN:/tmp/.X11-unix/X1,fork \
|
||||
PROXY:firewall:loopback:6000
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// forms of stdin with stdout, all equivalent
|
||||
$ socat PIPE -
|
||||
$ socat PIPE STDIO
|
||||
$ socat PIPE STDIN!!STDOUT
|
||||
$ socat PIPE STDIO!!STDIO
|
||||
$ socat PIPE -!!-
|
||||
$ socat PIPE FD:0!!FD:1
|
||||
$ socat PIPE 0!!1
|
||||
$ socat PIPE /dev/stdin!!/dev/stdout // when your OS provides these
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// some echo address examples
|
||||
$ socat - PIPE
|
||||
$ socat - PIPE:/tmp/pipi // other version of echo
|
||||
$ socat - PIPE:/tmp/pipi,nonblock!!/tmp/pipi // other version of echo
|
||||
$ socat - EXEC:/bin/cat // another echo
|
||||
$ socat - SYSTEM:/bin/cat // another echo
|
||||
$ socat - TCP:loopback:7 // if inetd echo/TCP service activated
|
||||
$ socat - UDP:loopback:7 // if inetd echo/UDP service activated
|
||||
$ socat - /tmp/hugo,trunc,ignoreeof!!/tmp/hugo // with delay
|
||||
$ socat - UDP:loopback:2000,bind=:2000 // self "connection"
|
||||
$ socat - TCP:loopback:2000,bind=:2000 // Linux bug?
|
||||
# socat - IP:loopback:222 // raw protocol, self "connected" (attention,
|
||||
// Linux might drop packets with less than 8 bytes payload)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// unidirectional data transfer
|
||||
$ socat -u - -
|
||||
// like "tail -f", but start with showing all file contents:
|
||||
$ socat -u FILE:/var/log/syslog.debug,ignoreeof -
|
||||
// like "tail -f", but do not show existing file contents:
|
||||
$ socat -u FILE:/var/log/syslog.debug,ignoreeof,seek-end -
|
||||
// write to new file, create with given permission and group (must be member) - race condition with group!!!
|
||||
$ socat -u - CREATE:/tmp/outfile1,group=floppy,perm=0640
|
||||
//
|
||||
// for an existing file /tmp/outfile1
|
||||
# socat -u - FILE:/tmp/outfile1,group=floppy,perm=0700,user=4321
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// File handling
|
||||
$ socat - FILE:/tmp/outfile1,ignoreeof!!FILE:/tmp/outfile1,append // prints outfile1, then echoes input and protocols into file (appends to old data)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UNIX socket handling
|
||||
|
||||
// Create a listening unix socket
|
||||
$ rm -f /tmp/mysocket; socat UNIX-LISTEN:/tmp/mysocket -
|
||||
// From another terminal, connect to this socket
|
||||
$ socat UNIX:/tmp/mysocket -
|
||||
// then transfer data bidirectionally
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Transport examples
|
||||
|
||||
// Socks relay (externally socksify applications);
|
||||
// your ssh client and OS are not socksified, but you want to pass a socks
|
||||
// server with ssh:
|
||||
$ socat \
|
||||
TCP-LISTEN:10022,fork \
|
||||
SOCKS4:socks.mydomain.org:ssh-serv:22
|
||||
$ ssh -p 10022 loopback
|
||||
// or better define a ProxyCommand in ~/.ssh/config:
|
||||
ProxyCommand socat - SOCKS:socks.mydomain.org:%h:%p
|
||||
// and with proxy:
|
||||
ProxyCommand socat - PROXY:proxy.mydomain.org:%h:%p,proxyport=8000
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Application examples
|
||||
|
||||
// run sendmail daemon with your favorite network options
|
||||
# socat \
|
||||
TCP-LISTEN:25,fork,ip-ttl=4,ip-tos=7,tcp-maxseg=576 \
|
||||
EXEC:"/usr/sbin/sendmail -bs",nofork
|
||||
|
||||
// Local mail delivery over UNIX socket - no SUID program required
|
||||
# socat \
|
||||
UNIX-LISTEN:/tmp/postoffice,fork,perm-early=0666 \
|
||||
EXEC:"/usr/sbin/sendmail -bs"
|
||||
$ socat - /tmp/postoffice
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uses of filan
|
||||
// See what your operating system opens for you
|
||||
$ filan
|
||||
// or if that was too detailled
|
||||
$ filan -s
|
||||
// See what file descriptors are passed via exec function
|
||||
$ socat - EXEC:"filan -s",nofork
|
||||
$ socat - EXEC:"filan -s"
|
||||
$ socat - EXEC:"filan -s",pipes,stderr
|
||||
$ socat - EXEC:"filan -s",pipes
|
||||
$ socat - EXEC:"filan -s",pty
|
||||
// see what's done by your shell and with option "pipes"
|
||||
$ socat - SYSTEM:"filan -s",pipes
|
||||
// see if gdb gives you an equivalent environment or opens some files for your program
|
||||
$ gdb ./filan
|
||||
(gdb) r -s
|
||||
(gdb) r
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Want to use chat from the ppp package?
|
||||
// Note: some OS's do not need "-e" for echo to print control characters
|
||||
// Note: chat might send bytes one by one
|
||||
// With AIX, a similar program is available under the name "pppdial"
|
||||
$ socat -d -d \
|
||||
TCP:localhost:25,crlf,nodelay \
|
||||
EXEC:'/usr/sbin/chat -v -s "\"220 \"" "\"HELO loopback\"" "\"250 \"" "\"MAIL FROM: <hugo@localhost>\"" "\"250 \"" "\"RCPT TO: root\"" "\"250 \"" "\"DATA\"" "\"354 \"" "\"test1'$(echo -e "\r.")'\"" "\"250 \"" "\"QUIT\"" "\"221 \""',pty,echo=0,cr
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// IP6
|
||||
|
||||
# socat \
|
||||
READLINE \
|
||||
TCP6:[::1]:21 # if your inetd/ftp is listening on ip6
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// VSOCK
|
||||
# Start a linux VM with cid=21
|
||||
# qemu-system-x86_64 -m 1G -smp 2 -cpu host -M accel=kvm \
|
||||
# -drive if=virtio,file=/path/to/fedora.img,format=qcow2 \
|
||||
# -device vhost-vsock-pci,guest-cid=21
|
||||
|
||||
# guest listens on port 1234 and host connects to it
|
||||
guest$ socat - VSOCK-LISTEN:1234
|
||||
host$ socat - VSOCK-CONNECT:21:1234
|
||||
|
||||
# Host (well know CID_HOST = 2) listens on port 4321 and guest connects to it
|
||||
host$ socat - VSOCK-LISTEN:4321
|
||||
guest$ socat - VSOCK-CONNECT:2:4321
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Application server solutions
|
||||
// Run a program (here: /bin/sh) chrooted, unprivileged;
|
||||
// parent process stays in real / running as root
|
||||
# socat -d -d - EXEC:/bin/sh,chroot=/home/sandbox,su=sandbox,pty
|
||||
|
||||
// Make a program available on the network chrooted, unprivileged;
|
||||
// parent process stays in / running as root
|
||||
// script path is already chrooted
|
||||
# ./socat -lm -d -d \
|
||||
TCP-LISTEN:5555,fork \
|
||||
EXEC:/bin/myscript,chroot=/home/sandbox,su=sandbox,pty,stderr
|
||||
// To avoid terminal problems, you might - instead of telnet - connect using
|
||||
$ socat \
|
||||
-,icanon=0,echo=0 \
|
||||
TCP:target:5555; reset
|
||||
|
||||
|
||||
// Access local display from ssh server, when ssh port forwarding is disabled
|
||||
// Socat must be installed on ssh server host
|
||||
// Might have to use xauth...
|
||||
// This example is one-shot because ssh can handle only one channel
|
||||
xterm1$ socat -d -d \
|
||||
EXEC:"ssh www.dest-unreach.org rm -f /tmp/.X11-unix/X9; ~/bin/socat -d -d unix-l\:/tmp/.X11-unix/X9\,fork -" \
|
||||
UNIX:/tmp/.X11-unix/X0
|
||||
xterm2$ ssh target
|
||||
target$ DISPLAY=:9 myxapplication
|
||||
|
||||
// Touch with perms:
|
||||
// no race condition for perms (applied with creat() call)
|
||||
$ socat -u \
|
||||
/dev/null \
|
||||
CREAT:/tmp/tempfile,perm=0600
|
||||
|
||||
// Touch with owner and perms:
|
||||
// race condition before changing owner, but who cares - only root may access
|
||||
# socat -u \
|
||||
/dev/null \
|
||||
CREAT:/tmp/tempfile,user=user1,perm=0600
|
||||
|
||||
// Invoke an interactive ssh with EXEC
|
||||
// First example passes control chars (^C etc.) to remote server as usual
|
||||
socat \
|
||||
-,echo=0,raw \
|
||||
EXEC:'ssh server',pty,setsid,ctty
|
||||
// Second example interprets control chars on local command line
|
||||
socat \
|
||||
-,echo=0,icanon=0 \
|
||||
EXEC:'ssh server',pty,setsid,ctty
|
||||
// afterwards, type "reset"!
|
||||
|
||||
// Convince ssh to provide an "interactive" shell to your script
|
||||
// three main versions for entering password:
|
||||
// 1) from your TTY; have 10 seconds to enter password:
|
||||
(sleep 10; echo "ls"; sleep 1) |socat - EXEC:'ssh server',pty
|
||||
// 2) from XWindows (DISPLAY !); again 10 seconds
|
||||
(sleep 10; echo "ls"; sleep 1) |socat - EXEC:'ssh server',pty,setsid
|
||||
// 3) from script
|
||||
(sleep 5; echo PASSWORD; echo ls; sleep 1) |./socat - EXEC:'ssh server',pty,setsid,ctty
|
||||
|
||||
|
||||
// Download with proxy CONNECT
|
||||
// use echo -e if required for \n
|
||||
$ (echo -e "CONNECT 128.129.130.131:80 HTTP/1.0\n"; sleep 5; echo -e "GET /download/file HTTP/1.0\n"; sleep 10) |
|
||||
socat -d -d -t 3600 - tcp:proxy:8080,crlf
|
||||
|
||||
// Retrieve a file from an sshd site with sourceforge style entry menu;
|
||||
// fill in your personal values; cat lets you enter your password (will be
|
||||
// visible on screen)
|
||||
$ (sleep 10; read pass; echo $pass; sleep 10; echo M; sleep 5; echo cat FILENAME; sleep 10) |
|
||||
./socat -d -d -ly - EXEC:'ssh -c 3des -l USER cf.sourceforge.net',pty,setsid,ctty |
|
||||
tee FILENAME
|
||||
|
||||
// Multicast community on local network: start the following command on all
|
||||
// participating hosts; like a conference call:
|
||||
# socat -d -d -d -d - \
|
||||
UDP-DATAGRAM:224.0.0.2:6666,bind=:6666,ip-add-membership=224.0.0.2:eth0,bindtodevice=eth0
|
||||
// or
|
||||
$ socat -d -d -d -d - \
|
||||
UDP-DATAGRAM:224.0.0.2:6666,bind=:6666,ip-add-membership=224.0.0.2:eth0
|
||||
// Possible reasons for failure:
|
||||
// iptables or other filters (open your filters as required)
|
||||
// Packets leave via wrong interface (set route: ...)
|
||||
// Socket bound to specific address
|
||||
|
||||
//=============================================================================
|
||||
// GENERIC FUNCTION CALLS
|
||||
|
||||
// ioctl(): open CD drive (given value valid on Linux)
|
||||
// on my Linux system I find in /usr/include/linux/cdrom.h the define:
|
||||
// #define CDROMEJECT 0x5309 /* Ejects the cdrom media */
|
||||
// The following command makes something like ioctl(fd, CDROMEJECT, NULL)
|
||||
// (don't care about the read error):
|
||||
$ socat /dev/cdrom,o-nonblock,ioctl-void=0x5309 -
|
||||
|
||||
// setsockopt(): SO_REUSEADDR
|
||||
// The following command performs - beyond lots of overhead - something like:
|
||||
// myint=1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &myint, sizeof(myint))
|
||||
$ socat -u UDP-RECV:7777,setsockopt-int=1:2:1 -
|
||||
// setsockopt(): SO_BINDTODEVICE
|
||||
|
||||
// Ways to apply SO_BINDTODEVICE without using the special socat address option
|
||||
// so-bindtodevice:
|
||||
// with string argument:
|
||||
$ sudo socat TCP-L:7777,setsockopt-string=1:25:eth0 PIPE
|
||||
// with binary argument:
|
||||
$ sudo socat TCP-L:7777,setsockopt-bin=1:25:x6574683000 PIPE
|
||||
|
||||
===============================================================================
|
||||
|
||||
// Not tested, just ideas, or have problems
|
||||
|
||||
|
||||
// Traverse firewall for making internal telnet server accessible for outside
|
||||
// telnet client, when only outbound traffic (syn-filter) is allowed:
|
||||
// on external client run "double server". this process waits for a
|
||||
// connection from localhost on port 10023, and, when it is established, waits
|
||||
// for a connection from anywhere to port 20023:
|
||||
ext$ socat -d \
|
||||
TCP-LISTEN:10023,range=localhost \
|
||||
TCP-LISTEN:20023
|
||||
// on internal server run double client:
|
||||
int$ socat -d \
|
||||
TCP:localhost:23 \
|
||||
TCP:extclient:10023
|
||||
// or, with socks firewall:
|
||||
int$ socat -d \
|
||||
TCP:localhost:23 \
|
||||
SOCKS:socksserver:extclient:10023
|
||||
// login with:
|
||||
ext$ telnet localhost 20023
|
||||
|
||||
// YOU can make a double server capable of handling multiple instances:
|
||||
ext$ socat -d \
|
||||
TCP-LISTEN:10023,range=localhost,fork \
|
||||
TCP-LISTEN:20023,reuseaddr
|
||||
|
||||
// Access remote display via ssh, when ssh port forwarding is disabled
|
||||
$ socat -d -d \
|
||||
EXEC:"ssh target socat - UNIX:/tmp/.X11-unix/X0" \
|
||||
TCP-LISTEN:6030
|
||||
$ xclock -display localhost:30
|
||||
|
||||
// Relay multiple webserver addresses through your firewall into your DMZ:
|
||||
// Make IP aliases on your firewall, and then:
|
||||
# socat -d -d \
|
||||
TCP-L:80,bind=fw-addr1,fork \
|
||||
TCP:dmz-www1:80
|
||||
# socat -d -d \
|
||||
TCP-L:80,bind=fw-addr2,fork \
|
||||
TCP:dmz-www2:80
|
||||
// and for improved security:
|
||||
# socat -d -d \
|
||||
TCP-L:80,bind=fw-addr3,su=nobody,fork \
|
||||
TCP:dmz-www3:80
|
||||
|
||||
// Proxy an arbitrary IP protocol over your firewall (answers won't work)
|
||||
# socat -d -d \
|
||||
IP:0.0.0.0:150,bind=fwnonsec \
|
||||
IP:sec-host:150,bind=fwsec
|
||||
|
||||
// Proxy an unsupported IP protocol over your firewall, point to point
|
||||
// end points see firewall interfaces as IP peers!
|
||||
# socat -d -d \
|
||||
IP:nonsec-host:150,bind=fwnonsec \
|
||||
IP:sec-host:150,bind=fwsec
|
||||
// note that, for IPsec, you might face problems that are known with NAT
|
||||
96
FAQ
Normal file
96
FAQ
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
Q: What is the clue of socat?
|
||||
|
||||
A: socat probably doesn't have any clue. It is more an attempt to smoothly
|
||||
integrate similar I/O features that are usually handled differently under
|
||||
UNIX.
|
||||
|
||||
|
||||
Q: What does the prefix XIO mean?
|
||||
|
||||
A: XIO means "extended input/output". It is a library/API that provides a
|
||||
common way for handling files, sockets and other forms of I/O. Its advantage is
|
||||
that the application may reduce its I/O to open / read+write / close calls,
|
||||
while the user controls all I/O details (and even basic process properties) by
|
||||
packing options into the filename string. This is the basic part of socat.
|
||||
|
||||
|
||||
Q: Is there a Windows port of socat available?
|
||||
|
||||
A: Try with Cygwin from http://www.cygwin.com/, or upgrade to Linux.
|
||||
|
||||
|
||||
Q: I succeeded to configure and make socat, but ./test.sh says something
|
||||
like:
|
||||
./test.sh: No such file or directory
|
||||
|
||||
A: You need a bash shell in your executable path (locations in $PATH)
|
||||
|
||||
|
||||
Q: configure disables readline / openssl / libwrap support because it does not
|
||||
find an include file / the library. How can I tell configure where these files
|
||||
are?
|
||||
|
||||
A: For include locations, use the environment variable CPPFLAGS, for library
|
||||
locations use LIBS, e.g.:
|
||||
export CPPFLAGS="-I/home/user/ssl/include"
|
||||
export LIBS="-L/home/user/ssl/lib"
|
||||
On some systems (SunOS), you might also need to set LD_LIBRARY_PATH:
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/user/ssl/lib"
|
||||
Then try again:
|
||||
make distclean; ./configure; make
|
||||
|
||||
|
||||
Q: I succeeded to make socat, but the test.sh script fails for many tests.
|
||||
Is my socat build corrupt?
|
||||
|
||||
A: Probably your socat program is ok; the tests have been developed on Linux
|
||||
2.4, and there they usually succeed.
|
||||
But the following OS differences result in errors on non Linux systems:
|
||||
* Linux allows to bind a socket to any address of range 127.0.0.0/8, not
|
||||
only 127.0.0.1. Some tests are built on this feature, but they might fail on
|
||||
other systems.
|
||||
* Your OS might have no IP6 implementation
|
||||
* MacOS X has some difficulties, e.g. distinguishing sockets and pipes.
|
||||
* the OpenSSL tests require OpenSSL support by socat, must have openssl in
|
||||
$PATH, and "openssl s_server ..." needs enough entropy to generate a key.
|
||||
|
||||
|
||||
Q: When I specify a dual address (two partial addresses linked with "!!") on
|
||||
the command line, I get some message "event not found", and my shell history
|
||||
has the line truncated. Not even protecting the '!'s with '\' helps.
|
||||
|
||||
A: '!' is appearently used by your shell as history expansion character. Say
|
||||
"set +H" and add this line to your (bash) profile.
|
||||
|
||||
|
||||
Q: On Solaris, socat was built successfully, but when started, it gets killed
|
||||
with something like "ld.so.1: ./socat: fatal: libreadline.so.4: open failed: no
|
||||
such file or directory"
|
||||
|
||||
A: The configure script finds your libreadline, but the runtime loader
|
||||
doesn't. Add the directory where the library resides to your LD_LIBRARY_PATH
|
||||
variable, e.g.:
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/sfw/lib/
|
||||
make distclean; ./configure; make
|
||||
|
||||
|
||||
Q: On Solaris, socat was built successfully, but when started, an assertion
|
||||
fails: "xioinitialize.c:25: failed assertion `3 << opt_crdly.arg3 == CRDLY'
|
||||
|
||||
A: Probably, in a second attempt you set the correct LD_LIBARY_PATH for socat,
|
||||
but it had not been set during the ./configure run, or you did not "make clean"
|
||||
before running configure. Try it again:
|
||||
make distclean; ./configure; make
|
||||
|
||||
|
||||
Q: A socat process, run in background from an interactive shell, is always
|
||||
stopped with all its child processes after about 5 minutes. killall -9 socat is
|
||||
required to clean the system and allow socat to be started again.
|
||||
|
||||
A: The terminal (window) might have the TOSTOP flag set and one of the socat
|
||||
processes wants to write to the terminal. Clear this flag in your shell:
|
||||
stty -tostop
|
||||
and start socat again.
|
||||
Thanks to Philippe Teuwen for reporting this situation.
|
||||
|
||||
81
FILES
Normal file
81
FILES
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
The socat distribution contains the following files:
|
||||
|
||||
* README: an introduction to socat
|
||||
|
||||
* FILES: a navigator through the socat distribution (this file)
|
||||
|
||||
* EXAMPLES: a collection of simple examples how to use socat.
|
||||
|
||||
* COPYING: what you and others are allowed to do with socat.
|
||||
|
||||
* PORTING: instructions and tips if you want to try socat on a new platform.
|
||||
|
||||
* BUGREPORTS: instructions what to do with problems and contributions.
|
||||
|
||||
* SECURITY: tips if you want to use socat in a security relevant environment.
|
||||
|
||||
* DEVELOPMENT: infos for programmers
|
||||
|
||||
* VERSION: the version of the socat distribution, for inclusion during
|
||||
compilation
|
||||
|
||||
* CHANGES: what happened since first public release
|
||||
|
||||
* socat.1: man page of socat
|
||||
* socat.html: html version of man page
|
||||
|
||||
* daemon.sh: example shell script for running socat as TCP relay daemon
|
||||
* ftp.sh: example shell based ftp client, using socat for transport
|
||||
* mail.sh: example shell based smtp client, for execution by socat
|
||||
|
||||
* gatherinfo.sh: shell script for gathering info about platform and socat
|
||||
implementation
|
||||
|
||||
* server.pem: a self signed test cerificate, for self test only
|
||||
|
||||
|
||||
The source code system:
|
||||
|
||||
* configure: the autoconf generated configurator script
|
||||
|
||||
* Makefile.in: the Makefile source input to configure
|
||||
|
||||
* config.h.in: the config.h source input to configure
|
||||
|
||||
* Config/config.<platform>.h: sample config.h for platform.
|
||||
* Config/Makefile.<platform>: sample Makefile for platform.
|
||||
Copy the appropriate files to ./config.h and ./Makefile if configure fails
|
||||
|
||||
* socat.c: the main C source, including option parsing, general control, and
|
||||
the data shuffler
|
||||
|
||||
* xio-*.c, xio-*.h: the source of the different address type implementations
|
||||
with all their modes and options
|
||||
|
||||
* xio*.c, xio*.h: the source of the xio API and xio utilities
|
||||
|
||||
* filan.c, filan.h: file descriptor analyzer function
|
||||
|
||||
* dalan.c, dalan.h: data language, a most primitive subset of what should
|
||||
become a language for describing/generating all kinds of binary data.
|
||||
|
||||
* error.c, error.h: the logging subsystem
|
||||
|
||||
* sycls.c, sycls.h: explicit system call and C library trace functions
|
||||
* sslcls.c, sslcls.h: explicit openssl call trace functions
|
||||
|
||||
* xioconfig.h: ensures some dependencies between configure WITH defines; to be
|
||||
included immediately after config.h
|
||||
|
||||
* sysutils.c, sysutils.h: some more general system (socket, IP) related
|
||||
functions, e.g. converting socket addresses to human readable form
|
||||
|
||||
* utils.c, utils.h: useful additions to C library; currently memdup, binary
|
||||
search, and setenv.
|
||||
|
||||
* mytypes.h: some types and macros I miss in C89
|
||||
|
||||
* test.sh: an incomplete attempt to automate tests of socat
|
||||
|
||||
* compat.h: ensure some features that might be missing on some platforms
|
||||
208
Makefile.in
Normal file
208
Makefile.in
Normal file
@@ -0,0 +1,208 @@
|
||||
# source: Makefile.in
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# note: @...@ forms are filled in by configure script
|
||||
|
||||
SHELL = /bin/sh
|
||||
AR = @AR@
|
||||
RANLIB = @RANLIB@
|
||||
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
BINDEST = @bindir@
|
||||
|
||||
datarootdir = @datarootdir@
|
||||
MANDEST = @mandir@
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
CC = @CC@
|
||||
#CCOPT1=-no-pie -fstack-protector
|
||||
#CCOPT=$(CCOPT1) -fcf-protection=none # for gdb on Ubuntu-20.04
|
||||
CCOPTS = $(CCOPT)
|
||||
|
||||
SYSDEFS = @SYSDEFS@
|
||||
CPPFLAGS = -I. @CPPFLAGS@
|
||||
#0 INCLS = -I. @V_INCL@
|
||||
DEFS = @DEFS@
|
||||
LIBS = @LIBS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
|
||||
#OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) @LIBOBJS@
|
||||
|
||||
|
||||
#0 CFLAGS = @CFLAGS@ $(CCOPTS) $(DEFS) $(INCLS)
|
||||
CFLAGS = @CFLAGS@ $(CCOPTS) $(DEFS) $(CPPFLAGS)
|
||||
CLIBS = $(LIBS)
|
||||
#CLIBS = $(LIBS) -lm -lefence
|
||||
XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
|
||||
xiosignal.c xiosigchld.c xioread.c xiowrite.c \
|
||||
xiolayer.c xioshutdown.c xioclose.c xioexit.c \
|
||||
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
|
||||
xio-socketpair.c xio-gopen.c xio-creat.c xio-file.c xio-named.c \
|
||||
xio-socket.c xio-interface.c xio-listen.c xio-unix.c xio-vsock.c \
|
||||
xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c \
|
||||
xio-sctp.c xio-dccp.c xio-rawip.c xio-posixmq.c \
|
||||
xio-socks.c xio-socks5.c xio-proxy.c xio-udp.c xio-udplite.c \
|
||||
xio-progcall.c xio-exec.c xio-system.c xio-shell.c \
|
||||
xio-termios.c xio-readline.c \
|
||||
xio-pty.c xio-openssl.c xio-streams.c xio-namespaces.c \
|
||||
xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-fs.c xio-tun.c
|
||||
XIOOBJS = $(XIOSRCS:.c=.o)
|
||||
UTLSRCS = error.c dalan.c procan.c procan-cdefs.c hostan.c fdname.c sysutils.c utils.c nestlex.c vsnprintf_r.c snprinterr.c @FILAN@ sycls.c @SSLCLS@
|
||||
UTLOBJS = $(UTLSRCS:.c=.o)
|
||||
CFILES = $(XIOSRCS) $(UTLSRCS) socat.c procan_main.c filan_main.c
|
||||
OFILES = $(CFILES:.c=.o)
|
||||
PROGS = socat procan filan
|
||||
|
||||
HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.h xio.h xioopen.h sysutils.h utils.h nestlex.h vsnprintf_r.h snprinterr.h compat.h \
|
||||
xioconfig.h mytypes.h xioopts.h xiodiag.h xiohelp.h xiosysincludes.h \
|
||||
xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
|
||||
xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h \
|
||||
xio-socketpair.h xio-socket.h xio-interface.h xio-listen.h xio-unix.h xio-vsock.h \
|
||||
xio-ip.h xio-ip4.h xio-ip6.h xio-rawip.h xio-posixmq.h \
|
||||
xio-ipapp.h xio-tcp.h xio-udp.h xio-sctp.h xio-dccp.h xio-udplite.h \
|
||||
xio-socks.h xio-socks5.h xio-proxy.h xio-progcall.h xio-exec.h \
|
||||
xio-system.h xio-shell.h xio-termios.h xio-readline.h \
|
||||
xio-pty.h xio-openssl.h xio-streams.h xio-namespaces.h \
|
||||
xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-fs.h xio-tun.h
|
||||
|
||||
|
||||
DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.yo doc/socat.1 doc/socat.html FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html doc/socat-genericsocket.html
|
||||
SHFILES = socat-chain.sh socat-mux.sh socat-broker.sh \
|
||||
daemon.sh mail.sh ftp.sh readline.sh \
|
||||
socat_buildscript_for_android.sh
|
||||
TESTFILES = test.sh socks4echo.sh proxyecho.sh readline-test.sh \
|
||||
proxy.sh socks4a-echo.sh
|
||||
|
||||
all: progs doc
|
||||
|
||||
scmclean: gitclean
|
||||
|
||||
gitclean: distclean docclean
|
||||
rm -f Makefile.bak configure
|
||||
|
||||
doc: doc/socat.1 doc/socat.html
|
||||
|
||||
docclean:
|
||||
rm -f doc/socat.1 doc/socat.html
|
||||
|
||||
doc/socat.1: doc/socat.yo
|
||||
-mkdir -p $(@D); yodl2man -o $@ $+
|
||||
|
||||
doc/socat.html: doc/socat.yo
|
||||
# care for refs in html
|
||||
-mkdir -p $(@D); cd $(@D); yodl2html -o socat.html ../$+; cd ..
|
||||
|
||||
progs: $(PROGS)
|
||||
|
||||
depend: $(CFILES) $(HFILES)
|
||||
makedepend $(SYSDEFS) $(CFILES)
|
||||
|
||||
socat: socat.o libxio.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ socat.o libxio.a $(CLIBS)
|
||||
|
||||
procan.o: procan.c
|
||||
$(CC) $(CFLAGS) -c -D CC=\"$(CC)\" -o $@ procan.c
|
||||
|
||||
PROCAN_OBJS=procan_main.o procan.o procan-cdefs.o hostan.o error.o sycls.o sysutils.o utils.o vsnprintf_r.o snprinterr.o
|
||||
procan: $(PROCAN_OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(PROCAN_OBJS) $(CLIBS)
|
||||
|
||||
FILAN_OBJS=filan_main.o filan.o fdname.o error.o sycls.o sysutils.o utils.o vsnprintf_r.o snprinterr.o
|
||||
filan: $(FILAN_OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(FILAN_OBJS) $(CLIBS)
|
||||
|
||||
libxio.a: $(XIOOBJS) $(UTLOBJS)
|
||||
$(AR) r $@ $(XIOOBJS) $(UTLOBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
|
||||
strip: progs
|
||||
strip $(PROGS)
|
||||
|
||||
install: progs $(srcdir)/doc/socat.1
|
||||
mkdir -p $(DESTDIR)$(BINDEST)
|
||||
$(INSTALL) -m 755 socat $(DESTDIR)$(BINDEST)/socat1
|
||||
ln -sf socat1 $(DESTDIR)$(BINDEST)/socat
|
||||
$(INSTALL) -m 755 socat-chain.sh $(DESTDIR)$(BINDEST)
|
||||
$(INSTALL) -m 755 socat-mux.sh $(DESTDIR)$(BINDEST)
|
||||
$(INSTALL) -m 755 socat-broker.sh $(DESTDIR)$(BINDEST)
|
||||
$(INSTALL) -m 755 procan $(DESTDIR)$(BINDEST)
|
||||
$(INSTALL) -m 755 filan $(DESTDIR)$(BINDEST)
|
||||
mkdir -p $(DESTDIR)$(MANDEST)/man1
|
||||
$(INSTALL) -m 644 $(srcdir)/doc/socat.1 $(DESTDIR)$(MANDEST)/man1/socat1.1
|
||||
ln -sf socat1.1 $(DESTDIR)$(MANDEST)/man1/socat.1
|
||||
|
||||
uninstall:
|
||||
rm -f $(DESTDIR)$(BINDEST)/socat
|
||||
rm -f $(DESTDIR)$(BINDEST)/socat1
|
||||
rm -f $(DESTDIR)$(BINDEST)/socat-chain.sh
|
||||
rm -f $(DESTDIR)$(BINDEST)/socat-mux.sh
|
||||
rm -f $(DESTDIR)$(BINDEST)/socat-broker.sh
|
||||
rm -f $(DESTDIR)$(BINDEST)/procan
|
||||
rm -f $(DESTDIR)$(BINDEST)/filan
|
||||
rm -f $(DESTDIR)$(MANDEST)/man1/socat.1
|
||||
rm -f $(DESTDIR)$(MANDEST)/man1/socat1.1
|
||||
|
||||
# make a GNU-zipped tar ball of the source files
|
||||
dist: socat.tar.gz socat.tar.bz2
|
||||
|
||||
socat.tar.gz: socat.tar
|
||||
gzip -9 <socat.tar >socat.tar.gz
|
||||
|
||||
socat.tar.bz2: socat.tar
|
||||
bzip2 -9 <socat.tar >socat.tar.bz2
|
||||
|
||||
VERSION = `sed 's/"//g' VERSION`
|
||||
TARDIR = socat-$(VERSION)
|
||||
socat.tar: configure.in configure Makefile.in config.h.in install-sh VERSION $(CFILES) $(HFILES) $(DOCFILES) $(SHFILES) $(TESTFILES) socat.spec \
|
||||
configure.ac
|
||||
if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi
|
||||
tar cf - $+ |(cd $(TARDIR); tar xf -)
|
||||
tar cvf socat.tar $(TARDIR)
|
||||
rm -f $(TARDIR)/COPYING # write protected
|
||||
rm -r $(TARDIR)
|
||||
|
||||
clean:
|
||||
rm -f *.o libxio.a socat procan filan \
|
||||
socat.tar socat.tar.Z socat.tar.gz socat.tar.bz2 \
|
||||
socat.out compile.log test.log
|
||||
|
||||
# remove all files that are generated from the original socat distribution
|
||||
# note that Makefile is also removed, so you have to start with ./configure
|
||||
# again
|
||||
distclean: clean
|
||||
rm -f config.status config.cache config.log config.h Makefile
|
||||
rm -rf autom4te.cache
|
||||
|
||||
info: socat
|
||||
uname -a >socat.out
|
||||
./socat -V >>socat.out
|
||||
./socat -hh >>socat.out
|
||||
|
||||
# perform some tests on socat
|
||||
test: progs
|
||||
./test.sh
|
||||
|
||||
cert:
|
||||
# prepare critical files with correct permissions to avoid race cond
|
||||
>cert.key
|
||||
>cert.pem
|
||||
chmod 600 cert.key cert.pem
|
||||
# generate a private key
|
||||
openssl genrsa -out cert.key 1024
|
||||
# generate a self signed cert
|
||||
openssl req -new -key cert.key -x509 -days 3653 -out cert.crt
|
||||
# ...enter fields
|
||||
# generate the pem file
|
||||
cat cert.key cert.crt >cert.pem
|
||||
#echo use cert.pem on requestors side, i.e. with option cert=cert.pem
|
||||
#echo use cert.crt on checkers side, i.e. with option cafile=cert.crt
|
||||
72
PORTING
Normal file
72
PORTING
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
DEVELOPMENT PLATFORMS
|
||||
|
||||
Primary development platform for socat is currently SuSE Linux 8.2 with
|
||||
a 2.4.20 kernel. New features are then ported to the non-Linux platforms on the
|
||||
Sourceforge compile farm (per July 2003: SunOS 5.8 with gcc, and MacOS X 10.2),
|
||||
and AIX 5.1 with gcc. But due to limited time resources and restricted
|
||||
(non-root) access to these systems I cannot extensively test socat there.
|
||||
|
||||
|
||||
PORTING STEPS
|
||||
|
||||
If you want to port socat to another operating system you will typically go
|
||||
through two phases: First, you might just try to compile and run the actual
|
||||
socat distribution (passive phase). Then, you should see if your platform
|
||||
has some nice features that are not yet used in socat, and add code for
|
||||
supporting them (active phase). At last, I encourage you to send me your
|
||||
changes so I can integrate them into the main socat distribution.
|
||||
|
||||
|
||||
PASSIVE PHASE:
|
||||
|
||||
* Generate Makefile and config.h:
|
||||
. If you have gcc, then just invoke "./configure".
|
||||
. If you use another C compiler, configure might not work properly;
|
||||
You will have to adapt config.h and Makefile manually.
|
||||
Change compiler options or defines to use all features of the operating
|
||||
system (not only ANSI-C; e.g. HP-UX: -Ae!)
|
||||
Some practical config.<platform>.h examples have been included in the
|
||||
Config directory of the source that might serve as starting point.
|
||||
|
||||
* Try to "make" socat; correct the errors. If some constants are undefined,
|
||||
please disable these parts option-dependent, not platform-dependent (use
|
||||
#ifdef TCP_OPTION instead of #if MY_OS)
|
||||
|
||||
* If you have big troubles compiling socat then try configure with options
|
||||
--disable-filan --disable-sycls; this excludes some of the most system
|
||||
dependent parts.
|
||||
|
||||
* After successful compilation and linking, run "make test" and try some
|
||||
examples.
|
||||
|
||||
|
||||
ACTIVE PHASE:
|
||||
|
||||
* Check the man pages of your operating system for open(2), fcntl(2),
|
||||
setsockopt(2), ioctl(2), socket(7), ip(7), tcp(7), termios etc. and the
|
||||
include files where you find the definitions of existing options, for new
|
||||
options and implement them - again option-dependent.
|
||||
Places to add code for the new options:
|
||||
. xioopts.h: enum e_optcode (sorted numerically/alphabetically by name)
|
||||
. xio-*.c: select the appropriate address file (e.g., xio-tcp.c for
|
||||
TCP-options) and make a record of type struct optdesc: opt_newoption
|
||||
. xio-*.h: the declation of struct optdesc
|
||||
. xioopts.c: add records to struct optname optionnames for all appropriate
|
||||
names (sorted strictly ASCII for binary search)
|
||||
. filan.c: add the option to the appropriate array (sockopts, ipopts,
|
||||
tcpopts)
|
||||
. socat.html, socat.1: write a short documentation and tell which
|
||||
platform and version implements this option
|
||||
|
||||
* problems may occur especially:
|
||||
. with 16 or 64 bit systems
|
||||
. if snprintf() etc. is missing
|
||||
. on UNIX emulations, e.g. Cygwin
|
||||
|
||||
|
||||
INTEGRATION
|
||||
|
||||
* If you ported socat to another platform:
|
||||
To let other people participate please send the modified files or a patch
|
||||
file and the files generated by ./gatherinfo.sh to socat@dest-unreach.org.
|
||||
287
README
Normal file
287
README
Normal file
@@ -0,0 +1,287 @@
|
||||
|
||||
about
|
||||
-----
|
||||
|
||||
socat is a relay for bidirectional data transfer between two independent data
|
||||
channels. Each of these data channels may be a file, pipe, device (serial line
|
||||
etc. or a pseudo terminal), a socket (UNIX, IP4, IP6 - raw, UDP, TCP), an
|
||||
SSL socket, proxy CONNECT connection, a file descriptor (stdin etc.), the GNU
|
||||
line editor (readline), a program, or a combination of two of these.
|
||||
These modes include generation of "listening" sockets, named pipes, and pseudo
|
||||
terminals.
|
||||
|
||||
socat can be used, e.g., as TCP port forwarder (one-shot or daemon), as an
|
||||
external socksifier, for attacking weak firewalls, as a shell interface to UNIX
|
||||
sockets, IP6 relay, for redirecting TCP oriented programs to a serial line, to
|
||||
logically connect serial lines on different computers, or to establish a
|
||||
relatively secure environment (su and chroot) for running client or server
|
||||
shell scripts with network connections.
|
||||
|
||||
Many options are available to refine socats behaviour:
|
||||
terminal parameters, open() options, file permissions, file and process owners,
|
||||
basic socket options like bind address, advanced socket options like IP source
|
||||
routing, linger, TTL, TOS (type of service), or TCP performance tuning.
|
||||
|
||||
More capabilities, like daemon mode with forking, client address check,
|
||||
"tail -f" mode, some stream data processing (line terminator conversion),
|
||||
choosing sockets, pipes, or ptys for interprocess communication, debug and
|
||||
trace options, logging to syslog, stderr or file, and last but not least
|
||||
precise error messages make it a versatile tool for many different purposes.
|
||||
|
||||
In fact, many of these features already exist in specialized tools; but until
|
||||
now, there does not seem to exists another tool that provides such a generic,
|
||||
flexible, simple and almost comprehensive (UNIX) byte stream connector.
|
||||
|
||||
|
||||
packages
|
||||
--------
|
||||
|
||||
before bothering with compilers, dependencies and include files, you might
|
||||
try to get a binary distribution that matches your platform. Have a look at
|
||||
the projects home page for actual information regarding socat binary
|
||||
distributions.
|
||||
|
||||
|
||||
platforms
|
||||
---------
|
||||
|
||||
socat 1.8.0 was compiled and more or less successfully tested under the
|
||||
following operating systems:
|
||||
|
||||
Debian 4 on x86_64
|
||||
FreeBSD 10 on amd64
|
||||
OpenBSD 7.2 on amd64
|
||||
OpenIndiana 2021-04 on i386 with gcc
|
||||
Ubuntu 10.04 on i386
|
||||
Ubuntu 12..22
|
||||
Rocky 9
|
||||
Cygwin 10.0
|
||||
|
||||
|
||||
install
|
||||
-------
|
||||
|
||||
Get the tarball and extract it:
|
||||
tar xzf socat.tar.gz
|
||||
cd socat-1.8.0.0
|
||||
./configure
|
||||
make
|
||||
su
|
||||
make install # installs socat, filan, and procan in /usr/local/bin
|
||||
|
||||
For compiling socat, gcc (or clang) is recommended.
|
||||
If gcc (or a compiler with similar front end) is not available, the configure
|
||||
script might fail to determine some features
|
||||
|
||||
If you have problems with the OpenSSL library, you can apply the option
|
||||
"--disable-openssl" to configure.
|
||||
|
||||
If you have problems with the readline library or (n)curses, you can apply the
|
||||
option "--disable-readline" to configure.
|
||||
|
||||
If you have problems with the tcp wrappers library, you can apply the option
|
||||
"--disable-libwrap" to configure.
|
||||
|
||||
If you still get errors or a tremendous amount of warnings you can exclude
|
||||
the features for system call tracing and file descriptor analyzing by
|
||||
applying the options "--disable-sycls --disable-filan" to configure.
|
||||
|
||||
You still need the functions vsnprintf and snprintf that are in the GNU libc,
|
||||
but might not be available with some proprietary libc's.
|
||||
|
||||
The configure script looks for headers and libraries of openssl, readline, and
|
||||
tcp wrappers in the OS'es standard places and in the subdirectories include/
|
||||
and lib/ of the following places:
|
||||
/sw/
|
||||
/usr/local/
|
||||
/opt/freeware/
|
||||
/usr/sfw/
|
||||
and for openssl also in:
|
||||
/usr/local/ssl/
|
||||
In case of unexpected behaviour it is important to understand that configure
|
||||
first searches for the appropriate include file and then expects to find the
|
||||
library in the associated lib directory. That means, when e.g. a OpenSSL
|
||||
installation resides under /usr/local and there is a symbolic link from
|
||||
/usr/include/ssl/ssl.h to /usr/local/ssl/include/ssl/ssl.h, configure will find
|
||||
the /usr/include/... header and will therefore expect libssl in /usr/lib
|
||||
instead of /usr/local/...
|
||||
|
||||
If configure does not find a header file or library but you know where it is,
|
||||
you can specify additional search locations, e.g.:
|
||||
export LIBS="-L$HOME/lib"
|
||||
export CPPFLAGS="-I$HOME/include"
|
||||
before running configure and make.
|
||||
|
||||
For other operating systems, if socat does not compile without errors, refer to
|
||||
the file PORTING.
|
||||
|
||||
|
||||
platform specifics - Debian (Ubuntu, ...)
|
||||
-----------------------------------------
|
||||
|
||||
libssl-dev
|
||||
|
||||
|
||||
platform specifics - redhat
|
||||
---------------------------
|
||||
|
||||
Install the following packages before building socat:
|
||||
tcp_wrappers-devel
|
||||
readline-devel
|
||||
openssl-devel
|
||||
|
||||
On RedHat Linux 9.0, including openssl/ssl.h might fail due to problems with
|
||||
the krb5-devel package. configure reacts with disabling openssl integration.
|
||||
To solve this issue, help cpp to find the krb5.h include file:
|
||||
CPPFLAGS="-I/usr/kerberos/include" ./configure
|
||||
|
||||
|
||||
platform specifics - aix
|
||||
------------------------
|
||||
|
||||
The flock() prototype is not available but the function is. Thus, to enable the
|
||||
socat flock options, run configure and then change in config.h the line
|
||||
/* #undef HAVE_FLOCK */
|
||||
to
|
||||
#define HAVE_FLOCK 1
|
||||
and continue the build process.
|
||||
|
||||
When using the OpenSSL rpm provided by IBM, configure might need the
|
||||
environment variable setting:
|
||||
LIBS="-L/opt/freeware/lib"
|
||||
|
||||
When using the OpenSSL bundle provided by IBM, egd needs to be installed too
|
||||
to get enough entropy.
|
||||
|
||||
socat compiles not only with gcc, but also with xlc. Just adapt the Makefile:
|
||||
replace gcc by /usr/vac/bin/xlc and remove gcc specific options
|
||||
"-Wall -Wno-parentheses".
|
||||
|
||||
When linking with the OpenSSL library provided by IBM, errors may occur:
|
||||
ld: 0711-317 ERROR: Undefined symbol: .__umoddi3
|
||||
In this case, you need to link with libgcc or compile libcrypt yourself using
|
||||
xlc, or disable SSL (in config.h, undefine WITH_OPENSSL and recompile)
|
||||
|
||||
The score of test.sh can be improved by uncommenting MISCDELAY=1 in this
|
||||
script.
|
||||
|
||||
|
||||
platform specifics - solaris
|
||||
----------------------------
|
||||
|
||||
If libreadline or libssl are in a directory not searched by the loader per
|
||||
default, e.g. /opt/sfw/lib, you must add this directory to $LD_LIBRARY_PATH,
|
||||
for running both configure and the socat executables, e.g.:
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/sfw/lib
|
||||
|
||||
For some shell scripts, it is preferable to have /usr/xpg4/bin at a prominent
|
||||
position in $PATH.
|
||||
|
||||
With the default compiler define _GNU_SOURCE, the CMSG_* macros are not
|
||||
available, and therefore ancillary messages cannot be used. To enable these try
|
||||
the following:
|
||||
After running ./configure, edit Makefile and replace "-D_GNU_SOURCE" with
|
||||
"-D_XPG4_2 -D__EXTENSIONS__" and run make
|
||||
|
||||
|
||||
platform specifics - hp-ux
|
||||
--------------------------
|
||||
|
||||
Ancillary messages cannot be compiled in with socat: both struct msghdr and
|
||||
struct cmsghdr are required. Compiling with -D_XOPEN_SOURCE_EXTENDED provides
|
||||
struct msghdr but disables struct cmsghdr while -D_OPEN_SOURCE disables struct
|
||||
msghdr but disables struct cmsghdr. Please contact socat development if you
|
||||
know a solution.
|
||||
|
||||
Shutting down the write channel of a UNIX domain socket does not seem to
|
||||
trigger an EOF on the peer socket. This makes problems with the exec and
|
||||
system addresses.
|
||||
|
||||
This OS provides the type "long long", but not the strtoll() function to read
|
||||
data into a long long variable.
|
||||
|
||||
UNIX domain sockets are only supported with SOCK_STREAM, not with datagrams
|
||||
(see man 7 unix).
|
||||
|
||||
With UDP sockets it seems to happen that the select() call reports available
|
||||
data (or EOF) but a subsequent read() call hangs.
|
||||
|
||||
|
||||
platform specifics - tru64
|
||||
--------------------------
|
||||
|
||||
When the use of the readline address fails with an error like:
|
||||
socat: /sbin/loader: Fatal Error: Reference to unresolvable symbol "tgetent" in ".../libreadline.so.4"
|
||||
and you still want to use shared libraries, try the following workaround:
|
||||
$ make distclean; LIBS="-static" ./configure
|
||||
remove the "-static" occurrence in Makefile
|
||||
$ make
|
||||
|
||||
|
||||
documentation
|
||||
-------------
|
||||
|
||||
These files reside in the doc subdirectory:
|
||||
|
||||
socat.1 is the man page, socat.html is the HTML based man page. It is actual,
|
||||
but describes only the more useful options.
|
||||
|
||||
doc/socat-openssltunnel.html is a simple tutorial for a private SSL connection.
|
||||
doc/socat-multicast.html is a short tutorial for multicast and broadcast
|
||||
communications.
|
||||
doc/socat-tun shows how to build a virtual network between two hosts.
|
||||
|
||||
socat.1 and socat.html can be generated from socat.yo (which is released with
|
||||
socat 1.6.0.1 and later) using the yodl document language package. Maintenance
|
||||
of yodl had been discontinued by its author
|
||||
(http://www.xs4all.nl/~jantien/yodl/) (there seems to be a revival at
|
||||
http://yodl.sourceforge.net/ though). For socat, the revival version 3.03 is used,
|
||||
|
||||
|
||||
license
|
||||
-------
|
||||
|
||||
socat is distributed under the terms of the GNU GPLv2;
|
||||
except for install-sh, which is copyright MIT, with its own license;
|
||||
|
||||
In addition, as a special exception, the copyright holder
|
||||
gives permission to link the code of this program with
|
||||
any version of the OpenSSL library which is distributed
|
||||
under a license identical to that listed in the included
|
||||
COPYING.OpenSSL file, and distribute linked combinations
|
||||
including the two. You must obey the GNU General Public
|
||||
License in all respects for all of the code used other
|
||||
than OpenSSL. If you modify this file, you may extend this
|
||||
exception to your version of the file, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete
|
||||
this exception statement from your version.
|
||||
|
||||
|
||||
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, version 2 of the License
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
contact
|
||||
-------
|
||||
|
||||
For questions, bug reports, ideas, contributions etc. please contact
|
||||
socat@dest-unreach.org
|
||||
|
||||
For socat source distribution, bug fixes, and latest news see
|
||||
http://www.dest-unreach.org/socat/
|
||||
|
||||
www.socat.org is an alternate site providing the same contents.
|
||||
|
||||
public git repository:
|
||||
git://repo.or.cz/socat.git
|
||||
http://repo.or.cz/socat.git
|
||||
67
README.FIPS
Normal file
67
README.FIPS
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
David Acker has patched socat to add OpenSSL FIPS.
|
||||
See http://oss-institute.org/fips-faq.html and
|
||||
http://linuxdevices.com/news/NS4742716157.html for more information.
|
||||
|
||||
The patch that is integrated into socat 1.5 does the following:
|
||||
|
||||
Add support for LDFLAGS in Makefile. LDFLAGS can be specified on the
|
||||
configure command line and then will be carried over into the make.
|
||||
|
||||
Add fips support. Requires OpenSSL 0.9.7j-fips-dev from
|
||||
http://www.openssl.org/source/OpenSSL-fips-1.0.tar.gz built with fips
|
||||
support turned on. use ./Configure fips [os-arc], for example
|
||||
./Configure fips linux-pentium
|
||||
|
||||
The LDFLAGS is needed to point a build against a library
|
||||
located in a non-standard location. For example, if you download and
|
||||
build openssl manually, it gets installed in /usr/local/ssl by default.
|
||||
|
||||
The FIPS support patches involve adding an option to enable/disable fips
|
||||
in configure (enabled by default), checking the system for FIPS support
|
||||
during configure, and then adding a fips option to socats openssl address
|
||||
to turn on fips mode. The openssl binary uses an environment variable
|
||||
instead of a command line flag.
|
||||
FIPS mode requires both a compile time flag of OPENSSL_FIPS and a
|
||||
runtime call of FIPS_mode_set(1). Fips mode requires building with the
|
||||
fipsld script provided by OpenSSL. FIPS tracks the pid of the process that
|
||||
initializes things so after a fork, the child must reinitialize. When the
|
||||
ssl code detects a forks occur and if FIPS mode was enabled, it reinitializes
|
||||
FIPS by disabling and then enabling it again.
|
||||
|
||||
To produce Davids enviroment, do the following:
|
||||
To build openssl
|
||||
download OpenSSL 0.9.7j-fips-dev from
|
||||
http://www.openssl.org/source/OpenSSL-fips-1.0.tar.gz
|
||||
tar xzf OpenSSL-fips-1.0.tar.gz
|
||||
cd openssl
|
||||
./Configure fips linux-pentium
|
||||
make
|
||||
make test
|
||||
(become root)
|
||||
make install
|
||||
This leaves an install in /usr/local/ssl
|
||||
|
||||
To build socat:
|
||||
setup directory with socat 1.5 or higher.
|
||||
cd socat-1.5.0.0
|
||||
./configure CPPFLAGS=-I/usr/local/ssl/include/ LDFLAGS=-L/usr/local/ssl/lib/ FIPSLD=/usr/local/ssl/bin/fipsld
|
||||
make
|
||||
(become root)
|
||||
make install
|
||||
|
||||
To run tests we make sure the new openssl is used:
|
||||
|
||||
export PATH=/usr/local/ssl/bin:$PATH
|
||||
./test.sh fips
|
||||
|
||||
There are two tests in test.sh that depend on fips:
|
||||
|
||||
OPENSSL_FIPS_BOTHAUTH performs a SSL client to server connection with
|
||||
certificate based authentication in both directions. If it works FIPS mode
|
||||
seems to be ok.
|
||||
|
||||
OPENSSL_FIPS_SECURITY generates a certificaet/key pair without fips support. It
|
||||
then tries a SSL connection in "normal" mode which is expected to work. In the
|
||||
second phase it uses fips mode with these credentials which is expected to
|
||||
fail. If so, the test succeeded.
|
||||
41
SECURITY
Normal file
41
SECURITY
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
Tips for using socat in secured environments:
|
||||
|
||||
* Configure socat to only enable the required features, e.g. to protect your
|
||||
filesystem from any accesses through socat:
|
||||
make distclean
|
||||
./configure --disable-file --disable-creat --disable-gopen \
|
||||
--disable-pipe --disable-unix --disable-exec --disable-system
|
||||
use "socat -V" to see what features are still enabled; see
|
||||
./configure --help for more options to disable
|
||||
|
||||
* Do NOT install socat SUID root or so when you have untrusted users or
|
||||
unprivileged daemons on your machine, because the full install of socat can
|
||||
override arbitrary files and execute arbitrary programs!
|
||||
|
||||
* Set logging to "-d -d" (in special cases even higher)
|
||||
|
||||
* With files, protect against symlink attacks with nofollow (Linux), and
|
||||
avoid accessing files in world-writable directories like /tmp
|
||||
|
||||
* When listening, use bind option (except UNIX domain sockets)
|
||||
|
||||
* When listening, use range option (currently only for IP4 sockets)
|
||||
|
||||
* When using socat with system, exec, or in a shell script, know what you do
|
||||
|
||||
* With system and exec, use absolute pathes or set the path option
|
||||
|
||||
* When starting programs with socat, consider using the chroot option (this
|
||||
requires root, so use the substuser option too).
|
||||
|
||||
* Start socat as root only if required; if so, use substuser option
|
||||
Note: starting a SUID program after applying substuser or setuid gives the
|
||||
process the SUID owner, which might give root privileges again.
|
||||
|
||||
* Socat, like netcat, is what intruders like to have on their victims machine:
|
||||
once they have gained a toehold they try to establish a versatile connection
|
||||
back to their attack base, and they want to attack other systems. For both
|
||||
purposes, socat could be helpful. Therefore, it might be useful to install
|
||||
socat with owner/permissions root:socatgrp/750, and to make all trusted users
|
||||
members of group socatgrp.
|
||||
869
compat.h
Normal file
869
compat.h
Normal file
@@ -0,0 +1,869 @@
|
||||
/* source: compat.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __compat_h_included
|
||||
#define __compat_h_included 1
|
||||
|
||||
#if !HAVE_DECL_ENVIRON && HAVE_VAR_ENVIRON
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* I dont like this system dependent part, but it would be quite a challenge
|
||||
for configure */
|
||||
|
||||
/* define if the following does not work:
|
||||
socket()
|
||||
connect() -> Connection refused
|
||||
connect() -> ok
|
||||
instead, it needs close() and socket() between the two connect() attmpts: */
|
||||
#if __FreeBSD__ || __APPLE__ || _AIX || __hpux__ || __osf__
|
||||
# undef SOCKET_CAN_RECOVER
|
||||
#else
|
||||
# define SOCKET_CAN_RECOVER 1
|
||||
#endif
|
||||
|
||||
/* define if stat() says that pipes are sockets */
|
||||
#if __APPLE__
|
||||
# define PIPE_STATES_SOCKET 1
|
||||
#else
|
||||
# undef PIPE_STATES_SOCKET
|
||||
#endif
|
||||
|
||||
#if defined(__sun) || defined(__sun__) || defined(__SunOS)
|
||||
# define XIO_ANCILLARY_TYPE_SOLARIS 1
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* substitute some features that might be missing on some platforms */
|
||||
|
||||
#if !HAVE_TYPE_SIG_ATOMIC_T
|
||||
typedef int sig_atomic_t;
|
||||
#endif
|
||||
|
||||
#ifndef SHUT_RD
|
||||
# define SHUT_RD 0
|
||||
#endif
|
||||
#ifndef SHUT_WR
|
||||
# define SHUT_WR 1
|
||||
#endif
|
||||
#ifndef SHUT_RDWR
|
||||
# define SHUT_RDWR 2
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(x,y) ((x)<=(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
# define MAX(x,y) ((x)>=(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
/* O_ASYNC: Linux 2.2.10 */
|
||||
#if !defined(O_ASYNC) && defined(FASYNC)
|
||||
# define O_ASYNC FASYNC
|
||||
#endif
|
||||
|
||||
/* NGROUPS not defined on Solaris */
|
||||
#if !defined(NGROUPS) && defined(NGROUPS_MAX)
|
||||
# define NGROUPS NGROUPS_MAX
|
||||
#endif
|
||||
|
||||
/* UNIX_PATH_MAX: AIX 4.3.3 */
|
||||
#ifndef UNIX_PATH_MAX
|
||||
# define UNIX_PATH_MAX 104 /*! why 104? Linux: 108 ! */
|
||||
#endif
|
||||
|
||||
|
||||
/* SOL_IP: AIX 4.3.3 */
|
||||
#ifndef SOL_IP
|
||||
# define SOL_IP 0
|
||||
#endif
|
||||
|
||||
/* SOL_TCP: AIX 4.3.3 */
|
||||
#ifndef SOL_TCP
|
||||
# ifdef IPPROTO_TCP
|
||||
# define SOL_TCP IPPROTO_TCP
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* POSIX.1 doesn't seem to know sockets */
|
||||
#ifndef S_ISSOCK
|
||||
# define S_ISSOCK(fmode) 0
|
||||
#endif
|
||||
|
||||
#if defined(IPPROTO_IPV6) && !defined(SOL_IPV6)
|
||||
# define SOL_IPV6 IPPROTO_IPV6
|
||||
#endif
|
||||
|
||||
#define F_uint8_t "%hu"
|
||||
#define F_uint8_x "%02hx"
|
||||
#define F_int8_t "%hd"
|
||||
|
||||
#ifndef F_uint16_t
|
||||
# if HAVE_BASIC_UINT16_T==0
|
||||
# define F_uint16_t "%hu"
|
||||
# define F_uint16_x "%04hx"
|
||||
# elif HAVE_BASIC_UINT16_T==2
|
||||
# define F_uint16_t "%hu"
|
||||
# define F_uint16_x "%04hx"
|
||||
# elif HAVE_BASIC_UINT16_T==4
|
||||
# define F_uint16_t "%u"
|
||||
# define F_uint16_x "%04x"
|
||||
# elif HAVE_BASIC_UINT16_T==6
|
||||
# define F_uint16_t "%lu"
|
||||
# define F_uint16_x "%04lx"
|
||||
# else
|
||||
# error "HAVE_BASIC_UINT16_T is out of range:" HAVE_BASIC_UINT16_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef F_uint32_t
|
||||
# if HAVE_BASIC_UINT32_T==0
|
||||
# define F_uint32_t "%hu"
|
||||
# define F_uint32_x "%08hx"
|
||||
# elif HAVE_BASIC_UINT32_T==2
|
||||
# define F_uint32_t "%hu"
|
||||
# define F_uint32_x "%08hx"
|
||||
# elif HAVE_BASIC_UINT32_T==4
|
||||
# define F_uint32_t "%u"
|
||||
# define F_uint32_x "%08x"
|
||||
# elif HAVE_BASIC_UINT32_T==6
|
||||
# define F_uint32_t "%lu"
|
||||
# define F_uint32_x "%08lx"
|
||||
# else
|
||||
# error "HAVE_BASIC_UINT32_T is out of range:" HAVE_BASIC_UINT32_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef F_uint64_t
|
||||
# if HAVE_BASIC_UINT64_T==0
|
||||
# define F_uint64_t "%hu"
|
||||
# define F_uint64_x "%016hx"
|
||||
# elif HAVE_BASIC_UINT64_T==2
|
||||
# define F_uint64_t "%hu"
|
||||
# define F_uint64_x "%016hx"
|
||||
# elif HAVE_BASIC_UINT64_T==4
|
||||
# define F_uint64_t "%u"
|
||||
# define F_uint64_x "%016x"
|
||||
# elif HAVE_BASIC_UINT64_T==6
|
||||
# define F_uint64_t "%lu"
|
||||
# define F_uint64_x "%016lx"
|
||||
# elif HAVE_BASIC_UINT64_T==8
|
||||
# define F_uint64_t "%llu"
|
||||
# define F_uint64_x "%016llx"
|
||||
# else
|
||||
# error "HAVE_BASIC_UINT64_T is out of range:" HAVE_BASIC_UINT64_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef F_int16_t
|
||||
# if HAVE_BASIC_INT16_T==0
|
||||
# define F_int16_t "%hd"
|
||||
# elif HAVE_BASIC_INT16_T==1
|
||||
# define F_int16_t "%hd"
|
||||
# elif HAVE_BASIC_INT16_T==3
|
||||
# define F_int16_t "%d"
|
||||
# elif HAVE_BASIC_INT16_T==5
|
||||
# define F_int16_t "%ld"
|
||||
# else
|
||||
# error "HAVE_BASIC_INT16_T is out of range:" HAVE_BASIC_INT16_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef F_int32_t
|
||||
# if HAVE_BASIC_INT32_T==0
|
||||
# define F_int32_t "%hd"
|
||||
# elif HAVE_BASIC_INT32_T==1
|
||||
# define F_int32_t "%hd"
|
||||
# elif HAVE_BASIC_INT32_T==3
|
||||
# define F_int32_t "%d"
|
||||
# elif HAVE_BASIC_INT32_T==5
|
||||
# define F_int32_t "%ld"
|
||||
# else
|
||||
# error "HAVE_BASIC_INT32_T is out of range:" HAVE_BASIC_INT32_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef F_int64_t
|
||||
# if HAVE_BASIC_INT64_T==0
|
||||
# define F_int64_t "%hd"
|
||||
# elif HAVE_BASIC_INT64_T==1
|
||||
# define F_int64_t "%hd"
|
||||
# elif HAVE_BASIC_INT64_T==3
|
||||
# define F_int64_t "%d"
|
||||
# elif HAVE_BASIC_INT64_T==5
|
||||
# define F_int64_t "%ld"
|
||||
# elif HAVE_BASIC_INT64_T==7
|
||||
# define F_int64_t "%lld"
|
||||
# else
|
||||
# error "HAVE_BASIC_INT64_T is out of range:" HAVE_BASIC_INT64_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* all unsigned */
|
||||
#if !defined(HAVE_BASIC_SIZE_T) || !HAVE_BASIC_SIZE_T
|
||||
# undef HAVE_BASIC_SIZE_T
|
||||
# define HAVE_BASIC_SIZE_T 6
|
||||
#endif
|
||||
#if HAVE_BASIC_SIZE_T==2
|
||||
# define SIZET_MAX USHRT_MAX
|
||||
# define SSIZET_MIN SHRT_MIN
|
||||
# define SSIZET_MAX SHRT_MAX
|
||||
# define F_Zd "%hd"
|
||||
# define F_Zu "%hu"
|
||||
#elif HAVE_BASIC_SIZE_T==4
|
||||
# define SIZET_MAX UINT_MAX
|
||||
# define SSIZET_MIN INT_MIN
|
||||
# define SSIZET_MAX INT_MAX
|
||||
# define F_Zd "%""d"
|
||||
# define F_Zu "%u"
|
||||
#elif HAVE_BASIC_SIZE_T==6
|
||||
# define SIZET_MAX ULONG_MAX
|
||||
# define SSIZET_MIN LONG_MIN
|
||||
# define SSIZET_MAX LONG_MAX
|
||||
# define F_Zd "%ld"
|
||||
# define F_Zu "%lu"
|
||||
#elif HAVE_BASIC_SIZE_T==8
|
||||
# define SIZET_MAX ULLONG_MAX
|
||||
# define SSIZET_MIN LLONG_MIN
|
||||
# define SSIZET_MAX LLONG_MAX
|
||||
# define F_Zd "%Ld"
|
||||
# define F_Zu "%Lu"
|
||||
#else
|
||||
# error "HAVE_BASIC_SIZE_T is out of range:" HAVE_BASIC_SIZE_T
|
||||
#endif
|
||||
#if HAVE_FORMAT_Z
|
||||
# undef F_Zd
|
||||
# undef F_Zu
|
||||
# define F_Zd "%Zd"
|
||||
# define F_Zu "%Zu"
|
||||
#endif
|
||||
|
||||
|
||||
/* mode_t is always unsigned; default: unsigned int */
|
||||
#if !defined(HAVE_BASIC_MODE_T) || !HAVE_BASIC_MODE_T
|
||||
# undef HAVE_BASIC_MODE_T
|
||||
# define HAVE_BASIC_MODE_T 4
|
||||
#endif
|
||||
#ifndef F_mode
|
||||
# if HAVE_BASIC_MODE_T==1 || HAVE_BASIC_MODE_T==2
|
||||
#define F_mode "0%03ho"
|
||||
# elif HAVE_BASIC_MODE_T==3 || HAVE_BASIC_MODE_T==4
|
||||
#define F_mode "0%03o"
|
||||
# elif HAVE_BASIC_MODE_T==5 || HAVE_BASIC_MODE_T==6
|
||||
#define F_mode "0%03lo"
|
||||
# else
|
||||
#error "HAVE_BASIC_MODE_T is out of range:" HAVE_BASIC_MODE_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* default: unsigned int */
|
||||
#if !defined(HAVE_BASIC_PID_T) || !HAVE_BASIC_PID_T
|
||||
# undef HAVE_BASIC_PID_T
|
||||
# define HAVE_BASIC_PID_T 4
|
||||
#endif
|
||||
#ifndef F_pid
|
||||
# if HAVE_BASIC_PID_T==1
|
||||
#define F_pid "%hd"
|
||||
# elif HAVE_BASIC_PID_T==2
|
||||
#define F_pid "%hu"
|
||||
# elif HAVE_BASIC_PID_T==3
|
||||
#define F_pid "%""d"
|
||||
# elif HAVE_BASIC_PID_T==4
|
||||
#define F_pid "%u"
|
||||
# elif HAVE_BASIC_PID_T==5
|
||||
#define F_pid "%ld"
|
||||
# elif HAVE_BASIC_PID_T==6
|
||||
#define F_pid "%lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_PID_T is out of range:" HAVE_BASIC_PID_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* default: unsigned int */
|
||||
#if !defined(HAVE_BASIC_UID_T) || !HAVE_BASIC_UID_T
|
||||
# undef HAVE_BASIC_UID_T
|
||||
# define HAVE_BASIC_UID_T 4
|
||||
#endif
|
||||
#ifndef F_uid
|
||||
# if HAVE_BASIC_UID_T==1
|
||||
#define F_uid "%hd"
|
||||
# elif HAVE_BASIC_UID_T==2
|
||||
#define F_uid "%hu"
|
||||
# elif HAVE_BASIC_UID_T==3
|
||||
#define F_uid "%""d"
|
||||
# elif HAVE_BASIC_UID_T==4
|
||||
#define F_uid "%u"
|
||||
# elif HAVE_BASIC_UID_T==5
|
||||
#define F_uid "%ld"
|
||||
# elif HAVE_BASIC_UID_T==6
|
||||
#define F_uid "%lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_UID_T is out of range:" HAVE_BASIC_UID_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* default: unsigned int */
|
||||
#if !defined(HAVE_BASIC_GID_T) || !HAVE_BASIC_GID_T
|
||||
# undef HAVE_BASIC_GID_T
|
||||
# define HAVE_BASIC_GID_T 4
|
||||
#endif
|
||||
#ifndef F_gid
|
||||
# if HAVE_BASIC_GID_T==1
|
||||
#define F_gid "%hd"
|
||||
# elif HAVE_BASIC_GID_T==2
|
||||
#define F_gid "%hu"
|
||||
# elif HAVE_BASIC_GID_T==3
|
||||
#define F_gid "%""d"
|
||||
# elif HAVE_BASIC_GID_T==4
|
||||
#define F_gid "%u"
|
||||
# elif HAVE_BASIC_GID_T==5
|
||||
#define F_gid "%ld"
|
||||
# elif HAVE_BASIC_GID_T==6
|
||||
#define F_gid "%lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_GID_T is out of range:" HAVE_BASIC_GID_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* all signed; default: long */
|
||||
#if !defined(HAVE_BASIC_TIME_T) || !HAVE_BASIC_TIME_T
|
||||
# undef HAVE_BASIC_TIME_T
|
||||
# define HAVE_BASIC_TIME_T 5
|
||||
#endif
|
||||
#ifndef F_time
|
||||
# if HAVE_BASIC_TIME_T==1
|
||||
#define F_time "%hd"
|
||||
# elif HAVE_BASIC_TIME_T==2
|
||||
#define F_time "%hu"
|
||||
# elif HAVE_BASIC_TIME_T==3
|
||||
#define F_time "%""d"
|
||||
# elif HAVE_BASIC_TIME_T==4
|
||||
#define F_time "%u"
|
||||
# elif HAVE_BASIC_TIME_T==5
|
||||
#define F_time "%ld"
|
||||
# elif HAVE_BASIC_TIME_T==6
|
||||
#define F_time "%lu"
|
||||
# elif HAVE_BASIC_TIME_T==7
|
||||
#define F_time "%Ld"
|
||||
# elif HAVE_BASIC_TIME_T==8
|
||||
#define F_time "%Lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_TIME_T is out of range:" HAVE_BASIC_TIME_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* default: int */
|
||||
#if !defined(HAVE_BASIC_SOCKLEN_T) || !HAVE_BASIC_SOCKLEN_T
|
||||
# undef HAVE_BASIC_SOCKLEN_T
|
||||
# define HAVE_BASIC_SOCKLEN_T 3
|
||||
#endif
|
||||
#ifndef F_socklen
|
||||
# if HAVE_BASIC_SOCKLEN_T==1
|
||||
#define F_socklen "%hd"
|
||||
# elif HAVE_BASIC_SOCKLEN_T==2
|
||||
#define F_socklen "%hu"
|
||||
# elif HAVE_BASIC_SOCKLEN_T==3
|
||||
#define F_socklen "%""d"
|
||||
# elif HAVE_BASIC_SOCKLEN_T==4
|
||||
#define F_socklen "%u"
|
||||
# elif HAVE_BASIC_SOCKLEN_T==5
|
||||
#define F_socklen "%ld"
|
||||
# elif HAVE_BASIC_SOCKLEN_T==6
|
||||
#define F_socklen "%lu"
|
||||
# elif HAVE_BASIC_SOCKLEN_T==7
|
||||
#define F_socklen "%Ld"
|
||||
# elif HAVE_BASIC_SOCKLEN_T==8
|
||||
#define F_socklen "%Lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_SOCKLEN_T is out of range:" HAVE_BASIC_SOCKLEN_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_BASIC_OFF_T) || !HAVE_BASIC_OFF_T
|
||||
# undef HAVE_BASIC_OFF_T
|
||||
# define HAVE_BASIC_OFF_T 5 /*long*/
|
||||
#endif
|
||||
#ifndef F_off
|
||||
# if HAVE_BASIC_OFF_T==3
|
||||
# define F_off "%""d"
|
||||
# elif HAVE_BASIC_OFF_T==5
|
||||
# define F_off "%ld"
|
||||
# elif HAVE_BASIC_OFF_T==7
|
||||
# define F_off "%Ld"
|
||||
# else
|
||||
#error "HAVE_BASIC_OFF_T is out of range:" HAVE_BASIC_OFF_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* default: long long */
|
||||
#if !defined(HAVE_BASIC_OFF64_T) || !HAVE_BASIC_OFF64_T
|
||||
# undef HAVE_BASIC_OFF64_T
|
||||
# define HAVE_BASIC_OFF64_T 7
|
||||
#endif
|
||||
#ifndef F_off64
|
||||
# if HAVE_BASIC_OFF64_T==1
|
||||
#define F_off64 "%hd"
|
||||
# elif HAVE_BASIC_OFF64_T==2
|
||||
#define F_off64 "%hu"
|
||||
# elif HAVE_BASIC_OFF64_T==3
|
||||
#define F_off64 "%""d"
|
||||
# elif HAVE_BASIC_OFF64_T==4
|
||||
#define F_off64 "%u"
|
||||
# elif HAVE_BASIC_OFF64_T==5
|
||||
#define F_off64 "%ld"
|
||||
# elif HAVE_BASIC_OFF64_T==6
|
||||
#define F_off64 "%lu"
|
||||
# elif HAVE_BASIC_OFF64_T==7
|
||||
#define F_off64 "%Ld"
|
||||
# elif HAVE_BASIC_OFF64_T==8
|
||||
#define F_off64 "%Lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_OFF64_T is out of range:" HAVE_BASIC_OFF64_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* all unsigned; default: unsigned long */
|
||||
#if !defined(HAVE_BASIC_DEV_T) || !HAVE_BASIC_DEV_T
|
||||
# undef HAVE_BASIC_DEV_T
|
||||
# define HAVE_BASIC_DEV_T 6
|
||||
#endif
|
||||
#ifndef F_dev
|
||||
# if HAVE_BASIC_DEV_T==1
|
||||
#define F_dev "%hd"
|
||||
# elif HAVE_BASIC_DEV_T==2
|
||||
#define F_dev "%hu"
|
||||
# elif HAVE_BASIC_DEV_T==3
|
||||
#define F_dev "%""d"
|
||||
# elif HAVE_BASIC_DEV_T==4
|
||||
#define F_dev "%u"
|
||||
# elif HAVE_BASIC_DEV_T==5
|
||||
#define F_dev "%ld"
|
||||
# elif HAVE_BASIC_DEV_T==6
|
||||
#define F_dev "%lu"
|
||||
# elif HAVE_BASIC_DEV_T==7
|
||||
#define F_dev "%Ld"
|
||||
# elif HAVE_BASIC_DEV_T==8
|
||||
#define F_dev "%Lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_DEV_T is out of range:" HAVE_BASIC_DEV_T
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if _WITH_TERMIOS
|
||||
#if !defined(HAVE_BASIC_SPEED_T) || !HAVE_BASIC_SPEED_T
|
||||
# undef HAVE_BASIC_SPEED_T
|
||||
# define HAVE_BASIC_SPEED_T 4
|
||||
#endif
|
||||
#ifndef F_speed
|
||||
# if HAVE_BASIC_SPEED_T==1
|
||||
#define F_speed "%hd"
|
||||
# elif HAVE_BASIC_SPEED_T==2
|
||||
#define F_speed "%hu"
|
||||
# elif HAVE_BASIC_SPEED_T==3
|
||||
#define F_speed "%""d"
|
||||
# elif HAVE_BASIC_SPEED_T==4
|
||||
#define F_speed "%u"
|
||||
# elif HAVE_BASIC_SPEED_T==5
|
||||
#define F_speed "%ld"
|
||||
# elif HAVE_BASIC_SPEED_T==6
|
||||
#define F_speed "%lu"
|
||||
# elif HAVE_BASIC_SPEED_T==7
|
||||
#define F_speed "%Ld"
|
||||
# elif HAVE_BASIC_SPEED_T==8
|
||||
#define F_speed "%Lu"
|
||||
# else
|
||||
#error "HAVE_BASIC_SPEED_T is out of range:" HAVE_BASIC_SPEED_T
|
||||
# endif
|
||||
#endif
|
||||
#endif /* _WITH_TERMIOS */
|
||||
|
||||
/* all unsigned; default; unsigned long */
|
||||
#if !defined(HAVE_TYPEOF_ST_INO) || !HAVE_TYPEOF_ST_INO
|
||||
# undef HAVE_TYPEOF_ST_INO
|
||||
# define HAVE_TYPEOF_ST_INO 6
|
||||
#endif
|
||||
#ifndef F_st_ino
|
||||
# if HAVE_TYPEOF_ST_INO==1
|
||||
#define F_st_ino "%hd"
|
||||
# elif HAVE_TYPEOF_ST_INO==2
|
||||
#define F_st_ino "%hu"
|
||||
# elif HAVE_TYPEOF_ST_INO==3
|
||||
#define F_st_ino "%""d"
|
||||
# elif HAVE_TYPEOF_ST_INO==4
|
||||
#define F_st_ino "%u"
|
||||
# elif HAVE_TYPEOF_ST_INO==5
|
||||
#define F_st_ino "%ld"
|
||||
# elif HAVE_TYPEOF_ST_INO==6
|
||||
#define F_st_ino "%lu"
|
||||
# elif HAVE_TYPEOF_ST_INO==7 /* Cygwin 1.5 */
|
||||
#define F_st_ino "%Ld"
|
||||
# elif HAVE_TYPEOF_ST_INO==8
|
||||
#define F_st_ino "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST_INO is out of range:" HAVE_TYPEOF_ST_INO
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* all unsigned; default; unsigned long long */
|
||||
#if !defined(HAVE_TYPEOF_ST64_INO) || !HAVE_TYPEOF_ST64_INO
|
||||
# undef HAVE_TYPEOF_ST64_INO
|
||||
# define HAVE_TYPEOF_ST64_INO 8
|
||||
#endif
|
||||
#ifndef F_st64_ino
|
||||
# if HAVE_TYPEOF_ST64_INO==1
|
||||
#define F_st64_ino "%hd"
|
||||
# elif HAVE_TYPEOF_ST64_INO==2
|
||||
#define F_st64_ino "%hu"
|
||||
# elif HAVE_TYPEOF_ST64_INO==3
|
||||
#define F_st64_ino "%""d"
|
||||
# elif HAVE_TYPEOF_ST64_INO==4
|
||||
#define F_st64_ino "%u"
|
||||
# elif HAVE_TYPEOF_ST64_INO==5
|
||||
#define F_st64_ino "%ld"
|
||||
# elif HAVE_TYPEOF_ST64_INO==6
|
||||
#define F_st64_ino "%lu"
|
||||
# elif HAVE_TYPEOF_ST64_INO==7
|
||||
#define F_st64_ino "%Ld"
|
||||
# elif HAVE_TYPEOF_ST64_INO==8
|
||||
#define F_st64_ino "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST64_INO is out of range:" HAVE_TYPEOF_ST64_INO
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* default: unsigned short */
|
||||
#if !defined(HAVE_TYPEOF_ST_NLINK) || !HAVE_TYPEOF_ST_NLINK
|
||||
# undef HAVE_TYPEOF_ST_NLINK
|
||||
# define HAVE_TYPEOF_ST_NLINK 2
|
||||
#endif
|
||||
#ifndef F_st_nlink
|
||||
# if HAVE_TYPEOF_ST_NLINK==1
|
||||
#define F_st_nlink "%hd"
|
||||
# elif HAVE_TYPEOF_ST_NLINK==2
|
||||
#define F_st_nlink "%hu"
|
||||
# elif HAVE_TYPEOF_ST_NLINK==3
|
||||
#define F_st_nlink "%""d"
|
||||
# elif HAVE_TYPEOF_ST_NLINK==4
|
||||
#define F_st_nlink "%u"
|
||||
# elif HAVE_TYPEOF_ST_NLINK==5
|
||||
#define F_st_nlink "%ld"
|
||||
# elif HAVE_TYPEOF_ST_NLINK==6
|
||||
#define F_st_nlink "%lu"
|
||||
# elif HAVE_TYPEOF_ST_NLINK==7
|
||||
#define F_st_nlink "%Ld"
|
||||
# elif HAVE_TYPEOF_ST_NLINK==8
|
||||
#define F_st_nlink "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST_NLINK is out of range:" HAVE_TYPEOF_ST_NLINK
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* all signed; default: long */
|
||||
#if !defined(HAVE_TYPEOF_ST_SIZE) || !HAVE_TYPEOF_ST_SIZE
|
||||
# undef HAVE_TYPEOF_ST_SIZE
|
||||
# define HAVE_TYPEOF_ST_SIZE 5
|
||||
#endif
|
||||
#ifndef F_st_size
|
||||
# if HAVE_TYPEOF_ST_SIZE==1
|
||||
#define F_st_size "%hd"
|
||||
# elif HAVE_TYPEOF_ST_SIZE==2
|
||||
#define F_st_size "%hu"
|
||||
# elif HAVE_TYPEOF_ST_SIZE==3
|
||||
#define F_st_size "%""d"
|
||||
# elif HAVE_TYPEOF_ST_SIZE==4
|
||||
#define F_st_size "%u"
|
||||
# elif HAVE_TYPEOF_ST_SIZE==5
|
||||
#define F_st_size "%ld"
|
||||
# elif HAVE_TYPEOF_ST_SIZE==6
|
||||
#define F_st_size "%lu"
|
||||
# elif HAVE_TYPEOF_ST_SIZE==7
|
||||
#define F_st_size "%Ld"
|
||||
# elif HAVE_TYPEOF_ST_SIZE==8
|
||||
#define F_st_size "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST_SIZE is out of range:" HAVE_TYPEOF_ST_SIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* all signed; default: long long */
|
||||
#if !defined(HAVE_TYPEOF_ST64_SIZE) || !HAVE_TYPEOF_ST64_SIZE
|
||||
# undef HAVE_TYPEOF_ST64_SIZE
|
||||
# define HAVE_TYPEOF_ST64_SIZE 7
|
||||
#endif
|
||||
#ifndef F_st64_size
|
||||
# if HAVE_TYPEOF_ST64_SIZE==1
|
||||
#define F_st64_size "%hd"
|
||||
# elif HAVE_TYPEOF_ST64_SIZE==2
|
||||
#define F_st64_size "%hu"
|
||||
# elif HAVE_TYPEOF_ST64_SIZE==3
|
||||
#define F_st64_size "%""d"
|
||||
# elif HAVE_TYPEOF_ST64_SIZE==4
|
||||
#define F_st64_size "%u"
|
||||
# elif HAVE_TYPEOF_ST64_SIZE==5
|
||||
#define F_st64_size "%ld"
|
||||
# elif HAVE_TYPEOF_ST64_SIZE==6
|
||||
#define F_st64_size "%lu"
|
||||
# elif HAVE_TYPEOF_ST64_SIZE==7
|
||||
#define F_st64_size "%Ld"
|
||||
# elif HAVE_TYPEOF_ST64_SIZE==8
|
||||
#define F_st64_size "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST64_SIZE is out of range:" HAVE_TYPEOF_ST64_SIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* very different results; default: long */
|
||||
#if !defined(HAVE_TYPEOF_ST_BLKSIZE) || !HAVE_TYPEOF_ST_BLKSIZE
|
||||
# undef HAVE_TYPEOF_ST_BLKSIZE
|
||||
# define HAVE_TYPEOF_ST_BLKSIZE 5
|
||||
#endif
|
||||
#ifndef F_st_blksize
|
||||
# if HAVE_TYPEOF_ST_BLKSIZE==1
|
||||
#define F_st_blksize "%hd"
|
||||
# elif HAVE_TYPEOF_ST_BLKSIZE==2
|
||||
#define F_st_blksize "%hu"
|
||||
# elif HAVE_TYPEOF_ST_BLKSIZE==3
|
||||
#define F_st_blksize "%""d"
|
||||
# elif HAVE_TYPEOF_ST_BLKSIZE==4
|
||||
#define F_st_blksize "%u"
|
||||
# elif HAVE_TYPEOF_ST_BLKSIZE==5
|
||||
#define F_st_blksize "%ld"
|
||||
# elif HAVE_TYPEOF_ST_BLKSIZE==6
|
||||
#define F_st_blksize "%lu"
|
||||
# elif HAVE_TYPEOF_ST_BLKSIZE==7
|
||||
#define F_st_blksize "%Ld"
|
||||
# elif HAVE_TYPEOF_ST_BLKSIZE==8
|
||||
#define F_st_blksize "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST_BLKSIZE is out of range:" HAVE_TYPEOF_ST_BLKSIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* default: long */
|
||||
#if !defined(HAVE_TYPEOF_ST_BLOCKS) || !HAVE_TYPEOF_ST_BLOCKS
|
||||
# undef HAVE_TYPEOF_ST_BLOCKS
|
||||
# define HAVE_TYPEOF_ST_BLOCKS 5
|
||||
#endif
|
||||
#ifndef F_st_blocks
|
||||
# if HAVE_TYPEOF_ST_BLOCKS==1
|
||||
#define F_st_blocks "%hd"
|
||||
# elif HAVE_TYPEOF_ST_BLOCKS==2
|
||||
#define F_st_blocks "%hu"
|
||||
# elif HAVE_TYPEOF_ST_BLOCKS==3
|
||||
#define F_st_blocks "%""d"
|
||||
# elif HAVE_TYPEOF_ST_BLOCKS==4
|
||||
#define F_st_blocks "%u"
|
||||
# elif HAVE_TYPEOF_ST_BLOCKS==5
|
||||
#define F_st_blocks "%ld"
|
||||
# elif HAVE_TYPEOF_ST_BLOCKS==6
|
||||
#define F_st_blocks "%lu"
|
||||
# elif HAVE_TYPEOF_ST_BLOCKS==7
|
||||
#define F_st_blocks "%Ld"
|
||||
# elif HAVE_TYPEOF_ST_BLOCKS==8
|
||||
#define F_st_blocks "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST_BLOCKS is out of range:" HAVE_TYPEOF_ST_BLOCKS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* default: long long */
|
||||
#if !defined(HAVE_TYPEOF_ST64_BLOCKS) || !HAVE_TYPEOF_ST64_BLOCKS
|
||||
# undef HAVE_TYPEOF_ST64_BLOCKS
|
||||
# define HAVE_TYPEOF_ST64_BLOCKS 7
|
||||
#endif
|
||||
#ifndef F_st64_blocks
|
||||
# if HAVE_TYPEOF_ST64_BLOCKS==1
|
||||
#define F_st64_blocks "%hd"
|
||||
# elif HAVE_TYPEOF_ST64_BLOCKS==2
|
||||
#define F_st64_blocks "%hu"
|
||||
# elif HAVE_TYPEOF_ST64_BLOCKS==3
|
||||
#define F_st64_blocks "%""d"
|
||||
# elif HAVE_TYPEOF_ST64_BLOCKS==4
|
||||
#define F_st64_blocks "%u"
|
||||
# elif HAVE_TYPEOF_ST64_BLOCKS==5
|
||||
#define F_st64_blocks "%ld"
|
||||
# elif HAVE_TYPEOF_ST64_BLOCKS==6
|
||||
#define F_st64_blocks "%lu"
|
||||
# elif HAVE_TYPEOF_ST64_BLOCKS==7
|
||||
#define F_st64_blocks "%Ld"
|
||||
# elif HAVE_TYPEOF_ST64_BLOCKS==8
|
||||
#define F_st64_blocks "%Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_ST64_BLOCKS is out of range:" HAVE_TYPEOF_ST64_BLOCKS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* at least for Linux */
|
||||
#define F_tv_sec "%ld"
|
||||
|
||||
/* default: long */
|
||||
#if !defined(HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC) || !HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
|
||||
# undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
|
||||
# define HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC 5
|
||||
#endif
|
||||
#ifndef F_tv_usec
|
||||
# if HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==1
|
||||
#define F_tv_usec "%06hd"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==2
|
||||
#define F_tv_usec "%06hu"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==3
|
||||
#define F_tv_usec "%06d"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==4
|
||||
#define F_tv_usec "%06u"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==5
|
||||
#define F_tv_usec "%06ld"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==6
|
||||
#define F_tv_usec "%06lu"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==7
|
||||
#define F_tv_usec "%06Ld"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC==8
|
||||
#define F_tv_usec "%06Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC is out of range:" HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* default: long */
|
||||
#if !defined(HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC) || !HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC
|
||||
# undef HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC
|
||||
# define HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC 5
|
||||
#endif
|
||||
#ifndef F_tv_nsec
|
||||
# if HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==1
|
||||
#define F_tv_nsec "%09hd"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==2
|
||||
#define F_tv_nsec "%09hu"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==3
|
||||
#define F_tv_nsec "%09d"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==4
|
||||
#define F_tv_nsec "%09u"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==5
|
||||
#define F_tv_nsec "%09ld"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==6
|
||||
#define F_tv_nsec "%09lu"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==7
|
||||
#define F_tv_nsec "%09Ld"
|
||||
# elif HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC==8
|
||||
#define F_tv_nsec "%09Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC is out of range:" HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* default: long */
|
||||
#if !defined(HAVE_TYPEOF_RLIM_MAX) || !HAVE_TYPEOF_RLIM_MAX
|
||||
# undef HAVE_TYPEOF_RLIM_MAX
|
||||
# define HAVE_TYPEOF_RLIM_MAX 5
|
||||
#endif
|
||||
#ifndef F_rlim_max
|
||||
# if HAVE_TYPEOF_RLIM_MAX==1
|
||||
#define F_rlim_max "hd"
|
||||
# elif HAVE_TYPEOF_RLIM_MAX==2
|
||||
#define F_rlim_max "hu"
|
||||
# elif HAVE_TYPEOF_RLIM_MAX==3
|
||||
#define F_rlim_max "d"
|
||||
# elif HAVE_TYPEOF_RLIM_MAX==4
|
||||
#define F_rlim_max "u"
|
||||
# elif HAVE_TYPEOF_RLIM_MAX==5
|
||||
#define F_rlim_max "ld"
|
||||
# elif HAVE_TYPEOF_RLIM_MAX==6
|
||||
#define F_rlim_max "lu"
|
||||
# elif HAVE_TYPEOF_RLIM_MAX==7
|
||||
#define F_rlim_max "Ld"
|
||||
# elif HAVE_TYPEOF_RLIM_MAX==8
|
||||
#define F_rlim_max "Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_RLIM_MAX is out of range:" HAVE_TYPEOF_RLIM_MAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* sigset_t printing - not an exact solution yet */
|
||||
#define F_sigset "0x%06lx"
|
||||
typedef unsigned long T_sigset;
|
||||
|
||||
/* default: socklen_t */
|
||||
#if !defined(HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN) || !HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
|
||||
# undef HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
|
||||
# define HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN HAVE_BASIC_SOCKLEN_T
|
||||
#endif
|
||||
#ifndef F_cmsg_len
|
||||
# if HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==1
|
||||
#define F_cmsg_len "%""hd"
|
||||
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==2
|
||||
#define F_cmsg_len "%""hu"
|
||||
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==3
|
||||
#define F_cmsg_len "%""d"
|
||||
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==4
|
||||
#define F_cmsg_len "%""u"
|
||||
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==5
|
||||
#define F_cmsg_len "%""ld"
|
||||
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==6
|
||||
#define F_cmsg_len "%""lu"
|
||||
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==7
|
||||
#define F_cmsg_len "%""Ld"
|
||||
# elif HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN==8
|
||||
#define F_cmsg_len "%""Lu"
|
||||
# else
|
||||
#error "HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN is out of range:" HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* basic type of struct timeval tv_usec */
|
||||
#ifndef F_tv_usec
|
||||
# if TYPEOF_STRUCT_TIMEVAL_TV_USEC==1
|
||||
# define F_tv_usec "%hu"
|
||||
# elif TYPEOF_STRUCT_TIMEVAL_TV_USEC==3
|
||||
# define F_tv_usec "%u"
|
||||
# elif TYPEOF_STRUCT_TIMEVAL_TV_USEC==5
|
||||
# define F_tv_usec "%lu"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* OpenBSD (at least 7.2) does better with this special setting */
|
||||
#if __FreeBSD__ || __OpenBSD__
|
||||
# define UNIX_TIGHTSOCKLEN false
|
||||
#else
|
||||
# define UNIX_TIGHTSOCKLEN true
|
||||
#endif
|
||||
|
||||
/* Cygwin 1.3.22 has the prototypes, but not the type... */
|
||||
#ifndef HAVE_TYPE_STAT64
|
||||
# undef HAVE_STAT64
|
||||
# undef HAVE_FSTAT64
|
||||
# undef HAVE_LSTAT64
|
||||
#endif
|
||||
#ifndef HAVE_TYPE_OFF64
|
||||
# undef HAVE_LSEEK64
|
||||
# undef HAVE_FTRUNCATE64
|
||||
#endif
|
||||
|
||||
#if !defined(NETDB_INTERNAL) && defined(h_NETDB_INTERNAL)
|
||||
# define NETDB_INTERNAL h_NETDB_INTERNAL
|
||||
#endif
|
||||
|
||||
#ifndef INET_ADDRSTRLEN
|
||||
# define INET_ADDRSTRLEN sizeof(struct sockaddr_in)
|
||||
#endif
|
||||
|
||||
#if !HAVE_PROTOTYPE_HSTRERROR
|
||||
/* with MacOSX this is char * */
|
||||
extern const char *hstrerror(int);
|
||||
#endif
|
||||
|
||||
#if !HAVE_PROTOTYPE_LIB_strndup
|
||||
extern char *strndup (const char *s, size_t n);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__compat_h_included) */
|
||||
762
config.h.in
Normal file
762
config.h.in
Normal file
@@ -0,0 +1,762 @@
|
||||
/* source: config.h.in */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __config_h_included
|
||||
#define __config_h_included 1
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef gid_t
|
||||
|
||||
/* Define if your struct stat has st_blksize. */
|
||||
#undef HAVE_ST_BLKSIZE
|
||||
|
||||
/* Define if your struct stat has st_blocks. */
|
||||
#undef HAVE_ST_BLOCKS
|
||||
|
||||
/* Define if your struct stat has st_rdev. */
|
||||
#undef HAVE_ST_RDEV
|
||||
|
||||
/* Define if you have the strftime function. */
|
||||
#undef HAVE_STRFTIME
|
||||
|
||||
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef mode_t
|
||||
|
||||
/* Define to `long' if <sys/types.h> doesn't define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define as the return type of signal handlers (int or void). */
|
||||
#undef RETSIGTYPE
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> doesn't define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef uid_t
|
||||
|
||||
/* Define if you have the putenv function. */
|
||||
#undef HAVE_PUTENV
|
||||
|
||||
/* Define if your cc provides char **environ declaration.
|
||||
This implies HAVE_VAR_ENVIRON */
|
||||
#undef HAVE_DECL_ENVIRON
|
||||
|
||||
/* Define if you have the char **environ variable */
|
||||
#undef HAVE_VAR_ENVIRON
|
||||
|
||||
/* Define if you have the select function. */
|
||||
#undef HAVE_SELECT
|
||||
|
||||
/* Define if you have the pselect function. */
|
||||
#undef HAVE_PSELECT
|
||||
|
||||
/* Define if you have the poll function. */
|
||||
#undef HAVE_POLL
|
||||
|
||||
/* Define if you have the socket function. */
|
||||
#undef HAVE_SOCKET
|
||||
|
||||
/* Define if you have the posix_memalign function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_posix_memalign
|
||||
|
||||
/* Define if you have the strdup function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_strdup
|
||||
|
||||
/* Define if you have the strerror function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_strerror
|
||||
|
||||
/* Define if you have the strstr function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_strstr
|
||||
|
||||
/* Define if you have the strtod function. */
|
||||
#undef HAVE_STRTOD
|
||||
|
||||
/* Define if you have the strtol function. */
|
||||
#undef HAVE_STRTOL
|
||||
|
||||
/* Define if you have the strtoul function. */
|
||||
#undef HAVE_STRTOUL
|
||||
|
||||
/* Define if you have the uname function. */
|
||||
#undef HAVE_UNAME
|
||||
|
||||
/* Define if you have the getpgid function. */
|
||||
#undef HAVE_GETPGID
|
||||
|
||||
/* Define if you have the getsid function. */
|
||||
#undef HAVE_GETSID
|
||||
|
||||
/* Define if you have the nanosleep function. */
|
||||
#undef HAVE_NANOSLEEP
|
||||
|
||||
/* Define if you have the gethostbyname function. */
|
||||
#undef HAVE_GETHOSTBYNAME
|
||||
|
||||
/* Define if you have the getaddrinfo function. */
|
||||
#undef HAVE_GETADDRINFO
|
||||
|
||||
/* Define if you have the getipnodebyname function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_getipnodebyname
|
||||
|
||||
/* Define if you have the getprotobynumber_r function. */
|
||||
#undef HAVE_GETPROTOBYNUMBER_R
|
||||
|
||||
/* Define if you have the getprotobynumber function. */
|
||||
#undef HAVE_GETPROTOBYNUMBER
|
||||
|
||||
/* Define if you have the setgroups function. */
|
||||
#undef HAVE_SETGROUPS
|
||||
|
||||
/* Define if you have the inet_aton function. */
|
||||
#undef HAVE_INET_ATON
|
||||
|
||||
/* Define if you have the strndup function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_strndup
|
||||
|
||||
/* Define if you have the memrchr function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_memrchr
|
||||
|
||||
/* Define if you have the if_indextoname function. */
|
||||
#undef HAVE_PROTOTYPE_LIB_if_indextoname
|
||||
|
||||
/* Define if you have the sigaction function */
|
||||
#undef HAVE_SIGACTION
|
||||
|
||||
/* Define if you have the stat64 function */
|
||||
#undef HAVE_STAT64
|
||||
|
||||
/* Define if you have the fstat64 function */
|
||||
#undef HAVE_FSTAT64
|
||||
|
||||
/* Define if you have the lstat64 function */
|
||||
#undef HAVE_LSTAT64
|
||||
|
||||
/* Define if you have the lseek64 function */
|
||||
#undef HAVE_LSEEK64
|
||||
|
||||
/* Define if you have the truncate64 function */
|
||||
#undef HAVE_TRUNCATE64
|
||||
|
||||
/* Define if you have the ftruncate64 function */
|
||||
#undef HAVE_FTRUNCATE64
|
||||
|
||||
/* Define if you have the gettimeofday function */
|
||||
#undef HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
|
||||
/* Define if you have the clock_gettime function */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define if you have the strtoll function */
|
||||
#undef HAVE_STRTOLL
|
||||
|
||||
/* Define if you have the hstrerror function */
|
||||
#undef HAVE_HSTRERROR
|
||||
|
||||
/* Define if you have the inet_ntop function */
|
||||
#undef HAVE_INET_NTOP
|
||||
|
||||
/* Define if you have the hstrerror prototype */
|
||||
#undef HAVE_PROTOTYPE_HSTRERROR
|
||||
|
||||
/* Define if you have the <stdbool.h> header file. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
|
||||
/* Define if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
/* Define if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define if you have the <syslog.h> header file. */
|
||||
#undef HAVE_SYSLOG_H
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if you have the <pwd.h> header file. */
|
||||
#undef HAVE_PWD_H
|
||||
|
||||
/* Define if you have the <grp.h> header file. */
|
||||
#undef HAVE_GRP_H
|
||||
|
||||
/* Define if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define if you have the <poll.h> header file. */
|
||||
#undef HAVE_POLL_H
|
||||
|
||||
/* Define if you have the <sys/poll.h> header file. */
|
||||
#undef HAVE_SYS_POLL_H
|
||||
|
||||
/* Define if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define if you have the <sys/uio.h> header file. */
|
||||
#undef HAVE_SYS_UIO_H
|
||||
|
||||
/* Define if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
|
||||
/* Define if you have the <sys/un.h> header file. */
|
||||
#undef HAVE_SYS_UN_H
|
||||
|
||||
/* Define if you have the <pty.h> header file. */
|
||||
#undef HAVE_PTY_H
|
||||
|
||||
/* Define if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Define if you have the <netinet/in_systm.h> header file. */
|
||||
#undef HAVE_NETINET_IN_SYSTM_H
|
||||
|
||||
/* Define if you have the <netinet/ip.h> header file. */
|
||||
#undef HAVE_NETINET_IP_H
|
||||
|
||||
/* Define if you have the <netinet/tcp.h> header file. */
|
||||
#undef HAVE_NETINET_TCP_H
|
||||
|
||||
/* Define if you have the <netinet/ip6.h> header file. */
|
||||
#undef HAVE_NETINET_IP6_H
|
||||
|
||||
/* Define if you have the <netinet6/in6.h> header file. */
|
||||
#undef HAVE_NETINET6_IN6_H
|
||||
|
||||
/* Define if you have the <arpa/nameser.h> header file. */
|
||||
#undef HAVE_ARPA_NAMESER_H
|
||||
|
||||
/* Define if you have the <resolv.h> header file. */
|
||||
#undef HAVE_RESOLV_H
|
||||
|
||||
/* Define if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define if you have the <net/if.h> header file. */
|
||||
#undef HAVE_NET_IF_H
|
||||
|
||||
/* Define if you have the <net/if_dl.h> header file. */
|
||||
#undef HAVE_NET_IF_DL_H
|
||||
|
||||
/* Define if you have the <linux/types.h> header file. */
|
||||
#undef HAVE_LINUX_TYPES_H
|
||||
|
||||
/* Define if you have the <linux/errqueue.h> header file. */
|
||||
#undef HAVE_LINUX_ERRQUEUE_H
|
||||
|
||||
/* Define if you have the <linux/if_tun.h> header file. */
|
||||
#undef HAVE_LINUX_IF_TUN_H
|
||||
|
||||
/* Define if you have the <linux/dccp.h> header file. */
|
||||
#undef HAVE_LINUX_DCCP_H
|
||||
|
||||
/* Define if you have the <linux/vm_sockets.h> header file. */
|
||||
#undef HAVE_LINUX_VM_SOCKETS_H
|
||||
|
||||
/* Define if you have the <sched.h> header file. */
|
||||
#undef HAVE_SCHED_H
|
||||
|
||||
/* Define if you have the <linux/if_packet.h> header file. */
|
||||
#undef HAVE_LINUX_IF_PACKET_H
|
||||
|
||||
/* Define if you have the <netinet/if_ether.h> header file. */
|
||||
#undef HAVE_NETINET_IF_ETHER_H
|
||||
|
||||
/* Define if you have the <sys/utsname.h> header file. */
|
||||
#undef HAVE_SYS_UTSNAME_H
|
||||
|
||||
/* Define if you have the <sys/select.h> header file. (AIX) */
|
||||
#undef HAVE_SYS_SELECT_H
|
||||
|
||||
/* Define if you have the <sys/file.h> header file. (AIX) */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define if you have the <util.h> header file. (NetBSD, OpenBSD: openpty()) */
|
||||
#undef HAVE_UTIL_H
|
||||
|
||||
/* Define if you have the <bsd/libutil.h> header file. */
|
||||
#undef HAVE_BSD_LIBUTIL_H
|
||||
|
||||
/* Define if you have the <libutil.h> header file. (FreeBSD: openpty()) */
|
||||
#undef HAVE_LIBUTIL_H
|
||||
|
||||
/* Define if you have the <sys/stropts.h> header file. (stream opts on SunOS)*/
|
||||
#undef HAVE_SYS_STROPTS_H
|
||||
|
||||
/* Define if you have the <regex.h> header file. */
|
||||
#undef HAVE_REGEX_H
|
||||
|
||||
/* Define if you have the <linux/fs.h> header file. */
|
||||
#undef HAVE_LINUX_FS_H
|
||||
|
||||
/* Define if you have the <linux/ext2_fs.h> header file. */
|
||||
#undef HAVE_LINUX_EXT2_FS_H
|
||||
|
||||
/* Define if you have the <readline/readline.h> header file. */
|
||||
#undef HAVE_READLINE_READLINE_H
|
||||
|
||||
/* Define if you have the <readline/history.h> header file. */
|
||||
#undef HAVE_READLINE_HISTORY_H
|
||||
|
||||
/* Define if you have the readline library. */
|
||||
#undef HAVE_LIBREADLINE
|
||||
|
||||
/* Define if you have the m library (-lm). */
|
||||
#undef HAVE_LIBM
|
||||
|
||||
/* Define if you have the floor function */
|
||||
#undef HAVE_FLOOR
|
||||
|
||||
/* some platforms need _XOPEN_EXTENDED_SOURCE to get syslog headers (AIX4.1) */
|
||||
#undef _XOPEN_EXTENDED_SOURCE
|
||||
|
||||
/* fdset may have component fds_bits or __fds_bits */
|
||||
#undef HAVE_FDS_BITS
|
||||
|
||||
/* struct termios may have components c_ispeed,c_ospeed */
|
||||
#undef HAVE_STRUCT_TERMIOS_C_ISPEED
|
||||
#undef HAVE_STRUCT_TERMIOS_C_OSPEED
|
||||
|
||||
/* Define if you have the sa_family_t */
|
||||
#undef HAVE_TYPE_SA_FAMILY_T
|
||||
|
||||
/* define if your struct sigaction has sa_sigaction */
|
||||
#undef HAVE_STRUCT_SIGACTION_SA_SIGACTION
|
||||
|
||||
/* define if you have struct sock_extended_err */
|
||||
#undef HAVE_STRUCT_SOCK_EXTENDED_ERR
|
||||
|
||||
/* Define if your termios.h likes _SVID3 defined */
|
||||
#undef _SVID3
|
||||
|
||||
/* Define if your sys/socket.h likes _XPG4_2 defined */
|
||||
#undef _XPG4_2
|
||||
|
||||
/* Define if your ctime_r() choices need _POSIX_PTHREAD_SEMANTICS */
|
||||
#undef _POSIX_PTHREAD_SEMANTICS
|
||||
|
||||
/* Define if you need __EXTENSIONS__ */
|
||||
#undef __EXTENSIONS__
|
||||
|
||||
/* Define if you have struct timespec (e.g. for nanosleep) */
|
||||
#undef HAVE_STRUCT_TIMESPEC
|
||||
|
||||
/* Define if you have struct linger */
|
||||
#undef HAVE_STRUCT_LINGER
|
||||
|
||||
/* Define if you have struct ip */
|
||||
#undef HAVE_STRUCT_IP
|
||||
|
||||
/* Define if you have struct ip_mreq */
|
||||
#undef HAVE_STRUCT_IP_MREQ
|
||||
|
||||
/* Define if you have struct ip_mreqn */
|
||||
#undef HAVE_STRUCT_IP_MREQN
|
||||
|
||||
/* Define if you have struct ipv6_mreq */
|
||||
#undef HAVE_STRUCT_IPV6_MREQ
|
||||
|
||||
/* Define if you have struct ip_mreq_source */
|
||||
#undef HAVE_STRUCT_IP_MREQ_SOURCE
|
||||
|
||||
/* Define if you have struct group_source_req */
|
||||
#undef HAVE_STRUCT_GROUP_SOURCE_REQ
|
||||
|
||||
/* Define if you have struct ifreq */
|
||||
#undef HAVE_STRUCT_IFREQ
|
||||
|
||||
/* Define if you have struct ifreq.ifr_index */
|
||||
#undef HAVE_STRUCT_IFREQ_IFR_INDEX
|
||||
|
||||
/* Define if you have struct ifreq.ifr_ifindex; not on HPUX */
|
||||
#undef HAVE_STRUCT_IFREQ_IFR_IFINDEX
|
||||
|
||||
/* Define if your struct sockaddr has sa_len */
|
||||
#undef HAVE_STRUCT_SOCKADDR_SALEN
|
||||
|
||||
/* there are several implementations of sockaddr_in6 */
|
||||
#undef HAVE_IP6_SOCKADDR
|
||||
|
||||
/* Define if you have struct iovec */
|
||||
#undef HAVE_STRUCT_IOVEC
|
||||
|
||||
/* define if your struct msghdr has msg_control */
|
||||
#undef HAVE_STRUCT_MSGHDR_MSGCONTROL
|
||||
|
||||
/* define if your struct msghdr has msg_controllen */
|
||||
#undef HAVE_STRUCT_MSGHDR_MSGCONTROLLEN
|
||||
|
||||
/* define if your struct msghdr has msg_flag */
|
||||
#undef HAVE_STRUCT_MSGHDR_MSGFLAGS
|
||||
|
||||
/* define if you have struct cmsghdr */
|
||||
#undef HAVE_STRUCT_CMSGHDR
|
||||
|
||||
/* define if you have struct in_pktinfo */
|
||||
#undef HAVE_STRUCT_IN_PKTINFO
|
||||
|
||||
/* define if your struct in_pktinfo has component ipi_spec_dst */
|
||||
#undef HAVE_PKTINFO_IPI_SPEC_DST
|
||||
|
||||
/* define if you have struct in6_pktinfo */
|
||||
#undef HAVE_STRUCT_IN6_PKTINFO
|
||||
|
||||
/* define if you have struct tpacket_auxdata */
|
||||
#undef HAVE_STRUCT_TPACKET_AUXDATA
|
||||
|
||||
/* define if you have struct tpacket_auxdata and it has tp_vlan_tpid */
|
||||
#undef HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TPID
|
||||
|
||||
/* define if your struct ip has ip_hl; otherwise assume ip_vhl */
|
||||
#undef HAVE_STRUCT_IP_IP_HL
|
||||
|
||||
/* Define if you have the setns function */
|
||||
#undef HAVE_SETNS
|
||||
|
||||
/* Define if you have the setenv function */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define if you have the unsetenv function. not on HP-UX */
|
||||
#undef HAVE_UNSETENV
|
||||
|
||||
/* Define if you have the cfsetispeed,cfgetispeed,cfsetspeed,cfgetospeed function */
|
||||
#undef HAVE_CFSETISPEED
|
||||
#undef HAVE_CFSETOSPEED
|
||||
|
||||
#if HAVE_CFSETISPEED
|
||||
# define HAVE_TERMIOS_ISPEED 1
|
||||
#endif
|
||||
#if HAVE_CFSETOSPEED
|
||||
# define HAVE_TERMIOS_OSPEED 1
|
||||
#endif
|
||||
#if defined(HAVE_TERMIOS_ISPEED) && defined(HAVE_TERMIOS_OSPEED)
|
||||
# define HAVE_TERMIOS_SPEED 1
|
||||
#endif
|
||||
|
||||
/* Define if you have the OPENSSL_init_ssl function */
|
||||
#undef HAVE_OPENSSL_INIT_SSL
|
||||
|
||||
/* Define if you have the OPENSSL_INIT_SETTINGS type (guarded for OpenBSD) */
|
||||
#undef HAVE_OPENSSL_INIT_SETTINGS
|
||||
|
||||
/* Define if you have the SSL_library_init function */
|
||||
#undef HAVE_SSL_library_init
|
||||
|
||||
/* Define if you have the OPENSSL_INIT_new function */
|
||||
#undef HAVE_OPENSSL_INIT_new
|
||||
|
||||
/* Define if you have the SSLv2 client and server method functions. not in new openssl */
|
||||
#undef HAVE_SSLv2_client_method
|
||||
#undef HAVE_SSLv2_server_method
|
||||
|
||||
/* Define if you have the HAVE_SSL_CTX_set_default_verify_paths function */
|
||||
#undef HAVE_SSL_CTX_set_default_verify_paths
|
||||
|
||||
/* Define if you have the TLS client and server method functions. not in old openssl? */
|
||||
#undef HAVE_TLS_client_method
|
||||
#undef HAVE_TLS_server_method
|
||||
|
||||
/* Define if you have the SSLv3 client and server method functions. not in new openssl */
|
||||
#undef HAVE_SSLv3_client_method
|
||||
#undef HAVE_SSLv3_server_method
|
||||
|
||||
/* Define if you have the SSLv3 client and server method functions with rollback to v2 */
|
||||
#undef HAVE_SSLv23_client_method
|
||||
#undef HAVE_SSLv23_server_method
|
||||
|
||||
/* Define if you have the TLSv1.0 client and server method functions */
|
||||
#undef HAVE_TLSv1_client_method
|
||||
#undef HAVE_TLSv1_server_method
|
||||
|
||||
/* Define if you have the TLSv1.1 client and server method functions */
|
||||
#undef HAVE_TLSv1_1_client_method
|
||||
#undef HAVE_TLSv1_1_server_method
|
||||
|
||||
/* Define if you have the TLSv1.2 client and server method functions */
|
||||
#undef HAVE_TLSv1_2_client_method
|
||||
#undef HAVE_TLSv1_2_server_method
|
||||
|
||||
/* Define if you have the DTLS client and server method functions */
|
||||
#undef HAVE_DTLS_client_method
|
||||
#undef HAVE_DTLS_server_method
|
||||
|
||||
/* Define if you have the DTLSv1 client and server method functions */
|
||||
#undef HAVE_DTLSv1_client_method
|
||||
#undef HAVE_DTLSv1_server_method
|
||||
|
||||
/* Define if you have the SSL CTX_set_min_proto_version function/macro */
|
||||
#undef HAVE_SSL_CTX_set_min_proto_version
|
||||
|
||||
/* Define if you have the SSL_CTX_set_max_proto_version function/macro */
|
||||
#undef HAVE_SSL_CTX_set_max_proto_version
|
||||
|
||||
/* Define if you have the DTLSv1_2 client and server method functions */
|
||||
#undef HAVE_DTLSv1_2_client_method
|
||||
#undef HAVE_DTLSv1_2_server_method
|
||||
|
||||
/* Define if you have the EC_KEY type */
|
||||
#undef HAVE_TYPE_EC_KEY
|
||||
|
||||
/* Define if you have the OpenSSL RAND_egd function */
|
||||
#undef HAVE_RAND_egd
|
||||
|
||||
/* Define if you have the OpenSSL RAND_status function */
|
||||
#undef HAVE_RAND_status
|
||||
|
||||
/* Define if you have the OpenSSL DH_set0_pqg function */
|
||||
#undef HAVE_DH_set0_pqg
|
||||
|
||||
/* Define if you have the OpenSSL ASN1_STRING_get0_data function */
|
||||
#undef HAVE_ASN1_STRING_get0_data
|
||||
|
||||
/* Define if you have the OpenSSL SSL_CTX_clear_mode macro or function */
|
||||
#undef HAVE_SSL_CTX_clear_mode
|
||||
|
||||
/* Define if you have the OpenSSL SSL_set_tlsext_host_name define/function */
|
||||
#undef HAVE_SSL_set_tlsext_host_name
|
||||
|
||||
/* Define if you have the OpenSSL SSL_CTX_set_tlsext_max_fragment_length define/function */
|
||||
#undef HAVE_SSL_CTX_set_tlsext_max_fragment_length
|
||||
|
||||
/* Define if you have the OpenSSL SSL_CTX_set_max_send_fragment define/function */
|
||||
#undef HAVE_SSL_CTX_set_max_send_fragment
|
||||
|
||||
/* Define if you have the flock function */
|
||||
#undef HAVE_FLOCK
|
||||
|
||||
/* Define if you have the openpty function */
|
||||
#undef HAVE_OPENPTY
|
||||
|
||||
/* Define if you have the grantpt function */
|
||||
#undef HAVE_GRANTPT
|
||||
|
||||
/* Define if you have the unlockpt function */
|
||||
#undef HAVE_UNLOCKPT
|
||||
|
||||
/* Define if you have the ptsname function */
|
||||
#undef HAVE_PROTOTYPE_LIB_ptsname
|
||||
|
||||
/* Define if you have the /dev/ptmx pseudo terminal multiplexer */
|
||||
#undef HAVE_DEV_PTMX
|
||||
|
||||
/* Define if you have the /dev/ptc pseudo terminal multiplexer */
|
||||
#undef HAVE_DEV_PTC
|
||||
|
||||
/* Define if you have the cfmakeraw() function */
|
||||
#undef HAVE_CFMAKERAW
|
||||
|
||||
/* Define if you have the long long type */
|
||||
#undef HAVE_TYPE_LONGLONG
|
||||
|
||||
/* is sig_atomic_t declared */
|
||||
#undef HAVE_TYPE_SIG_ATOMIC_T
|
||||
|
||||
/* is bool already typedef'd? */
|
||||
#undef HAVE_TYPE_BOOL
|
||||
|
||||
/* is socklen_t already typedef'd? */
|
||||
#undef HAVE_TYPE_SOCKLEN
|
||||
|
||||
/* Define if you have the struct stat64 type */
|
||||
#undef HAVE_TYPE_STAT64
|
||||
|
||||
/* Define if you have the struct off64_t type */
|
||||
#undef HAVE_TYPE_OFF64
|
||||
|
||||
/* is sighandler_t already typedef'd? */
|
||||
#undef HAVE_TYPE_SIGHANDLER
|
||||
|
||||
/* is uint8_t already defined? */
|
||||
#undef HAVE_TYPE_UINT8
|
||||
|
||||
/* is uint16_t already defined? */
|
||||
#undef HAVE_TYPE_UINT16
|
||||
|
||||
/* is uint32_t already defined? */
|
||||
#undef HAVE_TYPE_UINT32
|
||||
|
||||
/* is uint64_t already defined? */
|
||||
#undef HAVE_TYPE_UINT64
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define if snprintf() returns required len on truncation (C-99 conform) */
|
||||
#undef HAVE_C99_SNPRINTF
|
||||
|
||||
/* Define if you have the printf "Z" modifier */
|
||||
#undef HAVE_FORMAT_Z
|
||||
|
||||
/* Define the shift offset of the CRDLY mask */
|
||||
#undef CRDLY_SHIFT
|
||||
|
||||
/* Define the shift offset of the TABDLY mask */
|
||||
#undef TABDLY_SHIFT
|
||||
|
||||
/* Define the shift offset of the CSIZE mask */
|
||||
#undef CSIZE_SHIFT
|
||||
|
||||
/* Define if you have tcpwrappers (libwrap, tcpd) and it declares hosts_allow_table */
|
||||
#undef HAVE_HOSTS_ALLOW_TABLE
|
||||
#if defined(HAVE_HOSTS_ALLOW_TABLE) && HAVE_HOSTS_ALLOW_TABLE
|
||||
# define HAVE_HOSTS_DENY_TABLE 1
|
||||
#else
|
||||
# undef HAVE_HOSTS_DENY_TABLE
|
||||
#endif
|
||||
|
||||
/* 1..short, 3..int, 5..long; 2,4,6..unsigned */
|
||||
#undef HAVE_BASIC_UINT16_T
|
||||
#undef HAVE_BASIC_UINT32_T
|
||||
#undef HAVE_BASIC_UINT64_T
|
||||
#undef HAVE_BASIC_INT16_T
|
||||
#undef HAVE_BASIC_INT32_T
|
||||
#undef HAVE_BASIC_INT64_T
|
||||
|
||||
#undef HAVE_BASIC_SIZE_T
|
||||
#undef HAVE_BASIC_MODE_T
|
||||
#undef HAVE_BASIC_PID_T
|
||||
#undef HAVE_BASIC_UID_T
|
||||
#undef HAVE_BASIC_GID_T
|
||||
#undef HAVE_BASIC_TIME_T
|
||||
#undef HAVE_BASIC_OFF_T
|
||||
#undef HAVE_BASIC_OFF64_T
|
||||
#undef HAVE_BASIC_DEV_T
|
||||
#undef HAVE_BASIC_SPEED_T
|
||||
|
||||
#undef HAVE_BASIC_SOCKLEN_T
|
||||
|
||||
#undef HAVE_TYPEOF_ST_INO
|
||||
#undef HAVE_TYPEOF_ST_NLINK
|
||||
#undef HAVE_TYPEOF_ST_SIZE
|
||||
#undef HAVE_TYPEOF_ST_BLKSIZE
|
||||
#undef HAVE_TYPEOF_ST_BLOCKS
|
||||
|
||||
#undef HAVE_TYPEOF_ST64_DEV
|
||||
#undef HAVE_TYPEOF_ST64_INO
|
||||
#undef HAVE_TYPEOF_ST64_NLINK
|
||||
#undef HAVE_TYPEOF_ST64_SIZE
|
||||
#undef HAVE_TYPEOF_ST64_BLKSIZE
|
||||
#undef HAVE_TYPEOF_ST64_BLOCKS
|
||||
|
||||
#undef HAVE_TYPEOF_STRUCT_TIMEVAL_TV_USEC
|
||||
#undef HAVE_TYPEOF_STRUCT_TIMESPEC_TV_NSEC
|
||||
|
||||
#undef HAVE_TYPEOF_RLIM_MAX
|
||||
|
||||
#undef HAVE_TYPEOF_STRUCT_CMSGHDR_CMSG_LEN
|
||||
|
||||
/* Define if you have the /proc filesystem */
|
||||
#undef HAVE_PROC_DIR
|
||||
|
||||
/* Define if you have the /proc/$$/fd directories */
|
||||
#undef HAVE_PROC_DIR_FD
|
||||
#undef HAVE_PROC_DIR_PATH
|
||||
|
||||
#undef HAVE_DIRENT_D_TYPE
|
||||
|
||||
#undef HAVE_RES_RETRANS
|
||||
#undef HAVE_RES_RETRY
|
||||
#undef HAVE_RES_NSADDR_LIST
|
||||
|
||||
#undef HAVE_SETGRENT
|
||||
#undef HAVE_GETGRENT
|
||||
#undef HAVE_ENDGRENT
|
||||
#undef HAVE_GETGROUPLIST
|
||||
|
||||
#undef WITH_HELP
|
||||
#undef WITH_STATS
|
||||
#undef WITH_STDIO
|
||||
#undef WITH_FDNUM
|
||||
#undef WITH_FILE
|
||||
#undef WITH_CREAT
|
||||
#undef WITH_GOPEN
|
||||
#undef WITH_TERMIOS
|
||||
#undef WITH_PIPE
|
||||
#undef WITH_SOCKETPAIR
|
||||
#undef WITH_UNIX
|
||||
#undef WITH_ABSTRACT_UNIXSOCKET
|
||||
#undef WITH_IP4
|
||||
#undef WITH_IP6
|
||||
#undef WITH_RAWIP
|
||||
#undef WITH_GENERICSOCKET
|
||||
#undef WITH_INTERFACE
|
||||
#undef WITH_TCP
|
||||
#undef WITH_UDP
|
||||
#undef WITH_UDPLITE
|
||||
#undef WITH_SCTP
|
||||
#undef WITH_DCCP
|
||||
#undef WITH_LISTEN
|
||||
#undef WITH_POSIXMQ
|
||||
#undef WITH_SOCKS4
|
||||
#undef WITH_SOCKS4A
|
||||
#undef WITH_SOCKS5
|
||||
#undef WITH_VSOCK
|
||||
#undef WITH_NAMESPACES
|
||||
#undef WITH_PROXY
|
||||
#undef WITH_EXEC
|
||||
#undef WITH_SYSTEM
|
||||
#undef WITH_SHELL
|
||||
#undef WITH_READLINE
|
||||
#undef WITH_TUN
|
||||
#undef WITH_PTY
|
||||
#undef WITH_FS
|
||||
#undef WITH_OPENSSL
|
||||
#undef WITH_OPENSSL_METHOD
|
||||
#undef WITH_RESOLVE
|
||||
#undef WITH_RES_DEPRECATED /* AAONLY,PRIMARY */
|
||||
#define WITH_STREAMS 1
|
||||
#undef WITH_FIPS
|
||||
#undef OPENSSL_FIPS
|
||||
#undef WITH_LIBWRAP
|
||||
#undef HAVE_TCPD_H
|
||||
#undef HAVE_LIBWRAP
|
||||
|
||||
#undef WITH_SYCLS
|
||||
#undef WITH_FILAN
|
||||
#undef WITH_RETRY
|
||||
|
||||
#undef WITH_MSGLEVEL
|
||||
|
||||
#undef WITH_DEFAULT_IPV /* default IP version: "0", "4", "6" */
|
||||
|
||||
#define BUILD_DATE __DATE__ " " __TIME__
|
||||
|
||||
#endif /* !defined(__config_h_included) */
|
||||
2376
configure.ac
Normal file
2376
configure.ac
Normal file
File diff suppressed because it is too large
Load Diff
1
configure.in
Symbolic link
1
configure.in
Symbolic link
@@ -0,0 +1 @@
|
||||
configure.ac
|
||||
34
daemon.sh
Executable file
34
daemon.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#! /bin/sh
|
||||
# source: daemon.sh
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# This script assumes that you create group daemon1 and user daemon1 before.
|
||||
# they need only the right to exist (no login etc.)
|
||||
|
||||
# Note: this pid file mechanism is not robust!
|
||||
|
||||
# You will adapt these variables
|
||||
USER=daemon1
|
||||
GROUP=daemon1
|
||||
INIF=fwnonsec.domain.org
|
||||
OUTIF=fwsec.domain.org
|
||||
TARGET=w3.intra.domain.org
|
||||
INPORT=80
|
||||
DSTPORT=80
|
||||
#
|
||||
INOPTS="fork,setgid=$GROUP,setuid=$USER"
|
||||
OUTOPTS=
|
||||
PIDFILE=/var/run/socat-$INPORT.pid
|
||||
OPTS="-d -d -lm" # notice to stderr, then to syslog
|
||||
SOCAT=/usr/local/bin/socat
|
||||
|
||||
if [ "$1" = "start" -o -z "$1" ]; then
|
||||
|
||||
$SOCAT $OPTS tcp-l:$INPORT,bind=$INIF,$INOPTS tcp:$TARGET:$DSTPORT,bind=$OUTIF,$OUTOPTS </dev/null &
|
||||
echo $! >$PIDFILE
|
||||
|
||||
elif [ "$1" = "stop" ]; then
|
||||
|
||||
/bin/kill $(/bin/cat $PIDFILE)
|
||||
fi
|
||||
330
dalan.c
Normal file
330
dalan.c
Normal file
@@ -0,0 +1,330 @@
|
||||
/* source: dalan.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* idea of a low level data description language. currently only a most
|
||||
primitive subset exists. */
|
||||
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include "dalan.h"
|
||||
|
||||
/* test structure to find maximal alignment */
|
||||
static struct {
|
||||
char a;
|
||||
long double b;
|
||||
} maxalign;
|
||||
|
||||
/* test structure to find minimal alignment */
|
||||
static struct {
|
||||
char a;
|
||||
char b;
|
||||
} minalign;
|
||||
|
||||
/* test union to find kind of byte ordering */
|
||||
static union {
|
||||
char a[2];
|
||||
short b;
|
||||
} byteorder = { "01" };
|
||||
|
||||
struct dalan_opts_s dalan_opts = {
|
||||
sizeof(int),
|
||||
sizeof(short),
|
||||
sizeof(long),
|
||||
sizeof(char),
|
||||
sizeof(float),
|
||||
sizeof(double)
|
||||
} ;
|
||||
|
||||
/* fill the dalan_opts structure with machine dependent defaults values. */
|
||||
static void _dalan_dflts(struct dalan_opts_s *dlo) {
|
||||
dlo->c_int = sizeof(int);
|
||||
dlo->c_short = sizeof(short);
|
||||
dlo->c_long = sizeof(long);
|
||||
dlo->c_char = sizeof(char);
|
||||
dlo->c_float = sizeof(float);
|
||||
dlo->c_double = sizeof(double);
|
||||
dlo->maxalign = (char *)&maxalign.b-&maxalign.a;
|
||||
dlo->minalign = &minalign.b-&minalign.a;
|
||||
dlo->byteorder = (byteorder.b!=7711);
|
||||
}
|
||||
|
||||
/* allocate a new dalan_opts structure, fills it with machine dependent
|
||||
defaults values, and returns the pointer. */
|
||||
struct dalan_opts_s *dalan_props(void) {
|
||||
struct dalan_opts_s *dlo;
|
||||
dlo = malloc(sizeof(struct dalan_opts_s));
|
||||
if (dlo == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
_dalan_dflts(dlo);
|
||||
return dlo;
|
||||
}
|
||||
|
||||
void dalan_init(void) {
|
||||
_dalan_dflts(&dalan_opts);
|
||||
}
|
||||
|
||||
/* Parses and coverts a data item.
|
||||
Returns 0 on success,
|
||||
-1 if the data was cut due to n limit,
|
||||
1 if a syntax error occurred
|
||||
2 if the actual character is white space
|
||||
3 if the first character is not a type specifier
|
||||
*/
|
||||
static int dalan_item(int c, const char **line0, uint8_t *data, size_t *p, size_t n) {
|
||||
const char *line = *line0;
|
||||
size_t p1 = *p;
|
||||
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
return 2;
|
||||
case '"':
|
||||
while (1) {
|
||||
switch (c = *line++) {
|
||||
case '\0': fputs("unterminated string\n", stderr);
|
||||
*line0 = line;
|
||||
return 1;
|
||||
case '"':
|
||||
break;
|
||||
case '\\':
|
||||
if (!(c = *line++)) {
|
||||
fputs("continuation line not implemented\n", stderr);
|
||||
*line0 = line;
|
||||
return 1;
|
||||
}
|
||||
switch (c) {
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'a': c = '\a'; break;
|
||||
#if 0
|
||||
case 'e': c = '\e'; break;
|
||||
#else
|
||||
case 'e': c = '\033'; break;
|
||||
#endif
|
||||
case '0': c = '\0'; break;
|
||||
}
|
||||
/* PASSTHROUGH */
|
||||
default:
|
||||
if (p1 >= n) {
|
||||
*p = p1;
|
||||
*line0 = line;
|
||||
return -1;
|
||||
}
|
||||
data[p1++] = c;
|
||||
continue;
|
||||
}
|
||||
if (c == '"')
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '\'':
|
||||
switch (c = *line++) {
|
||||
case '\0': fputs("unterminated character\n", stderr);
|
||||
*line0 = line;
|
||||
return 1;
|
||||
case '\'': fputs("error in character\n", stderr);
|
||||
*line0 = line;
|
||||
return 1;
|
||||
case '\\':
|
||||
if (!(c = *line++)) {
|
||||
fputs("continuation line not implemented\n", stderr);
|
||||
*line0 = line;
|
||||
return 1;
|
||||
}
|
||||
switch (c) {
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'a': c = '\a'; break;
|
||||
#if 0
|
||||
case 'e': c = '\e'; break;
|
||||
#else
|
||||
case 'e': c = '\033'; break;
|
||||
#endif
|
||||
}
|
||||
/* PASSTHROUGH */
|
||||
default:
|
||||
if (p1 >= n) { *p = p1; return -1; }
|
||||
data[p1++] = c;
|
||||
break;
|
||||
}
|
||||
if (*line != '\'') {
|
||||
fputs("error in character termination\n", stderr);
|
||||
*p = p1;
|
||||
*line0 = line;
|
||||
return 1;
|
||||
}
|
||||
++line;
|
||||
break;
|
||||
case 'x':
|
||||
/* expecting hex data, must be an even number of digits!! */
|
||||
while (true) {
|
||||
int x;
|
||||
c = *line;
|
||||
if (isdigit(c&0xff)) {
|
||||
x = (c-'0') << 4;
|
||||
} else if (isxdigit(c&0xff)) {
|
||||
x = ((c&0x07) + 9) << 4;
|
||||
} else
|
||||
break;
|
||||
++line;
|
||||
c = *line;
|
||||
if (isdigit(c&0xff)) {
|
||||
x |= (c-'0');
|
||||
} else if (isxdigit(c&0xff)) {
|
||||
x |= (c&0x07) + 9;
|
||||
} else {
|
||||
fputs("odd number of hexadecimal digits\n", stderr);
|
||||
*p = p1;
|
||||
*line0 = line;
|
||||
return 1;
|
||||
}
|
||||
++line;
|
||||
if (p1 >= n) {
|
||||
*p = p1;
|
||||
*line0 = line;
|
||||
return -1;
|
||||
}
|
||||
data[p1++] = x;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
/* expecting decimal number, with target type long */
|
||||
{
|
||||
char *endptr;
|
||||
*(long *)&data[p1] = strtol(line, &endptr, 10);
|
||||
p1 += sizeof(long);
|
||||
line = endptr;
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
/* expecting decimal number, with target type unsigned long */
|
||||
{
|
||||
char *endptr;
|
||||
*(unsigned long *)&data[p1] = strtol(line, &endptr, 10);
|
||||
p1 += sizeof(unsigned long);
|
||||
line = endptr;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
/* expecting decimal number, with target type int */
|
||||
{
|
||||
char *endptr;
|
||||
*(int *)&data[p1] = strtol(line, &endptr, 10);
|
||||
p1 += sizeof(int);
|
||||
line = endptr;
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
/* expecting decimal number, with target type unsigned int */
|
||||
{
|
||||
char *endptr;
|
||||
*(unsigned int *)&data[p1] = strtol(line, &endptr, 10);
|
||||
p1 += sizeof(unsigned int);
|
||||
line = endptr;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
/* expecting decimal number, with target type short */
|
||||
{
|
||||
char *endptr;
|
||||
*(short *)&data[p1] = strtol(line, &endptr, 10);
|
||||
p1 += sizeof(short);
|
||||
line = endptr;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
/* expecting decimal number, with target type unsigned short */
|
||||
{
|
||||
char *endptr;
|
||||
*(unsigned short *)&data[p1] = strtol(line, &endptr, 10);
|
||||
p1 += sizeof(unsigned short);
|
||||
line = endptr;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
/* expecting decimal number, with target type byte (int8_t) */
|
||||
{
|
||||
char *endptr;
|
||||
*(int8_t *)&data[p1] = strtoul(line, &endptr, 10);
|
||||
p1 += sizeof(uint8_t);
|
||||
line = endptr;
|
||||
}
|
||||
case 'B':
|
||||
/* expecting decimal number, with target type byte (uint8_t) */
|
||||
{
|
||||
char *endptr;
|
||||
*(uint8_t *)&data[p1] = strtoul(line, &endptr, 10);
|
||||
p1 += sizeof(uint8_t);
|
||||
line = endptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*line0 = line;
|
||||
return 3;
|
||||
}
|
||||
*p = p1;
|
||||
*line0 = line;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read data description from line (\0-terminated), write result to data; do
|
||||
not write so much data that *p exceeds n !
|
||||
*p must be initialized.
|
||||
return 0 on success,
|
||||
-1 if the data was cut due to n limit,
|
||||
1 if a syntax error occurred
|
||||
*p is a global data counter; especially it must be used when calculating
|
||||
alignment. On successful return from the function *p must be actual!
|
||||
*/
|
||||
int dalan(const char *line, uint8_t *data, size_t *p, size_t n, char deflt) {
|
||||
size_t p0;
|
||||
char c;
|
||||
int rc;
|
||||
|
||||
while (1) {
|
||||
/* assume there is a type specifier on beginning of rest of line */
|
||||
c = *line++;
|
||||
if (c == '\0')
|
||||
break;
|
||||
p0 = *p;
|
||||
rc = dalan_item(c, &line, data, p, n);
|
||||
if (rc == 0) {
|
||||
deflt = c; /* continue with this type as default */
|
||||
} else if (rc == 2) {
|
||||
/* white space */
|
||||
continue;
|
||||
} else if (rc == 3) {
|
||||
const char *line0;
|
||||
--line;
|
||||
line0 = line;
|
||||
/* No, we did not recognize c as type specifier, try default type */
|
||||
rc = dalan_item(deflt, &line, data, p, n);
|
||||
if (line == line0) {
|
||||
/* Nothing was parsed */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
/* rc == 0 */
|
||||
n -= (*p-p0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
30
dalan.h
Normal file
30
dalan.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* source: dalan.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __dalan_h_included
|
||||
#define __dalan_h_included 1
|
||||
|
||||
#include "mytypes.h"
|
||||
|
||||
/* machine properties and command line options */
|
||||
struct dalan_opts_s {
|
||||
int c_int; /* natural int size / C int size */
|
||||
int c_short; /* C short size */
|
||||
int c_long; /* C long size */
|
||||
int c_char; /* C char size */
|
||||
int c_float; /* C float size */
|
||||
int c_double; /* C double size */
|
||||
int maxalign; /* maximal alignment (double after char) */
|
||||
int minalign; /* minimal alignment (char after char) */
|
||||
int byteorder; /* 0: Motorola, network, big endian; 1: Intel, little
|
||||
endian */
|
||||
} ;
|
||||
|
||||
extern struct dalan_opts_s dalan_opts;
|
||||
|
||||
extern void dalan_init(void);
|
||||
extern struct dalan_opts_s *dalan_props(void);
|
||||
extern int dalan(const char *line, uint8_t *data, size_t *p, size_t n, char deflt);
|
||||
|
||||
#endif /* !defined(__dalan_h_included) */
|
||||
28
doc/dest-unreach.css
Normal file
28
doc/dest-unreach.css
Normal file
@@ -0,0 +1,28 @@
|
||||
table {
|
||||
empty-cells: show;
|
||||
}
|
||||
|
||||
.shell {
|
||||
display: block;
|
||||
font-family: Courier;
|
||||
padding: 6px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 4px;
|
||||
border: 3px solid grey;
|
||||
color: lightgreen;
|
||||
background-color: black;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.error {
|
||||
display: inline;
|
||||
block-size: auto;
|
||||
font-family: monospace;
|
||||
background-color: #e08080;
|
||||
border: 4px;
|
||||
padding: 2px;
|
||||
padding-right: 4px;
|
||||
border-style: ridge;
|
||||
border-color: #e08080;
|
||||
}
|
||||
328
doc/socat-genericsocket.html
Normal file
328
doc/socat-genericsocket.html
Normal file
@@ -0,0 +1,328 @@
|
||||
<html><head>
|
||||
<title>Generic sockets with Socat</title>
|
||||
<link rel="stylesheet" type="text/css" href="dest-unreach.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Generic sockets with Socat</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>Beginning with version 1.7.0 socat provides means to freely control
|
||||
important aspects of socket handling. This allows to experiment with socket
|
||||
types and protocols that are not explicitely implemented in socat.
|
||||
</p>
|
||||
|
||||
<p>The related socat features fall into three major categories:<p>
|
||||
|
||||
<ul>
|
||||
<li>address options for changing socket parameters while using common
|
||||
socket types:
|
||||
<tt>pf (protocol-family), so-type (socktype), so-prototype (protocol)</tt>
|
||||
</li>
|
||||
<li>address options for setting arbitrary socket options:
|
||||
<tt>setsockopt-int, setsockopt-string, setsockopt-bin</tt></li>
|
||||
<li>address types for passing almost arbitrary parameters and address data to
|
||||
the standard system calls:
|
||||
<tt>socket-connect, socket-listen, socket-sendto, socket-recv,
|
||||
socket-recvfrom, socket-datagram</tt></li>
|
||||
</ul>
|
||||
|
||||
<p>In practice this gives you two possibilities:</p>
|
||||
|
||||
<p>If you want to cope with sockets staying within the usual domains ( =
|
||||
protocol families = address families) which are IPv4, IPv6, UNIX/local, and
|
||||
raw interface for socat 1.7.0, it is sufficient to learn about a couple of
|
||||
<a href="#GENERIC_OPTIONS">address options</a> that allow to change default
|
||||
parameters, and to apply generic socket options.</p>
|
||||
|
||||
<p>For other address families socat provides <a
|
||||
href="#GENERIC_ADDRESSES">generic socket addresses</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<a name="GENERIC_OPTIONS"></a>
|
||||
<h2>Generic socket options</h2>
|
||||
|
||||
<h3>Example 1: DCCP communication</h3>
|
||||
|
||||
<p>A relatively new communication protocol has been introduced in the Internet
|
||||
community for which no socat address type has been implemented up to version
|
||||
1.7.0
|
||||
(see <a href="http://www.ietf.org/html.charters/dccp-charter.html">IETF's
|
||||
Datagram Congestion Control Protocol</a>
|
||||
and <a href="http://www.linuxfoundation.org/en/Net:DCCP#python_support">Linux
|
||||
foundation Net:DCCP</a> for more info). Taken that the
|
||||
operating system implements DCCP, it is possible to use this protocol
|
||||
with socat while just employing standard socket addresses and some options.
|
||||
</p>
|
||||
|
||||
<p>A simple server that accepts a DCCP connection, passes the arriving data to a
|
||||
subprocess for converting upper case to lower case characters, and then
|
||||
returns it to the client:
|
||||
</p>
|
||||
|
||||
<span class="shell">socat \
|
||||
TCP4-LISTEN:4096,reuseaddr,type=6,prototype=33 \
|
||||
EXEC:'tr A-Z a-z',pty,raw,echo=0
|
||||
</span>
|
||||
|
||||
<p>A simple client that sends some upper case characters to the server via DCCP
|
||||
and prints what the server returns:
|
||||
</p>
|
||||
|
||||
<span class="shell">echo ABCD | \
|
||||
socat - \
|
||||
TCP4-CONNECT:localhost:4096,type=6,prototype=33
|
||||
</span>
|
||||
|
||||
<p>We choose the TCP4 addresses as base because it best matches the DCCP
|
||||
requirements:
|
||||
<ol>
|
||||
<li>DCCP is (here) based on IPv4</li>
|
||||
<li>DCCP is stream oriented and uses <tt>connect()</tt> and <tt>listen();
|
||||
accept()</tt> calls</li>
|
||||
<li>DCCP protocol uses ports</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
<p>Option <tt><a href="socat.html#OPTION_SO_TYPE">type</a>=6</tt> changes TCP's
|
||||
<tt>SOCK_STREAM</tt> parameter to <tt>SOCK_DCCP</tt>, and <tt>
|
||||
<a href="socat.html#OPTION_SO_PROTOTYPE">prototype</a>=33</tt> replaces the
|
||||
default <tt>IPPROTO_TCP</tt> with <tt>IPPROTO_DCCP</tt>.
|
||||
</p>
|
||||
|
||||
<p>DCCP has an important parameter, the service code. It provides another
|
||||
multiplexing layer beyond the protocol ports. The Linux implementation of DCCP
|
||||
allows to set this parameter with code like <tt>setsocktopt(fd, SOL_DCCP,
|
||||
DCCP_SOCKOPT_SERVICE, {1}, sizeof(int))</tt>. The equivalent generic socat
|
||||
option is: <tt><a href="socat.html#OPTION_SETSOCKOPT_INT">setsockopt-int</a>=269:2:1</tt> for service code 1.
|
||||
If the service codes on server and client do not match the <tt>connect()</tt>
|
||||
operation fails with error:<p>
|
||||
|
||||
<span class="error">... E connect(3, AF=2 127.0.0.1:4096, 16): Invalid request code</span>
|
||||
|
||||
<p>Please note that this examples works with IPv6 as well, you just need to
|
||||
replace the TCP4 words with TCP6, and the IPv4 socket address with an
|
||||
appropriate IPv6 socket address, e.g. <tt>[::1]</tt>!
|
||||
</p>
|
||||
|
||||
<a name="GENERIC_ADDRESSES"></a>
|
||||
<h2>Generic socket addresses</h2>
|
||||
|
||||
<p>socat's generic socket addresses are a more comprehensive mechanism that
|
||||
allows to deal with protocol families whose socket addresses are not supported
|
||||
by socat - no semantical parsing, no structured assignment to the struct
|
||||
components are available. Instead, the socket address records for binding and
|
||||
connecting/sending are specified in unstructured hexadecimal form. The
|
||||
following example demonstrates this by performing simple data transfer over
|
||||
raw AppleTalk protocol.
|
||||
</p>
|
||||
|
||||
<p>Note: I do not have any knowledge about AppleTalk. I just managed to
|
||||
configure my Linux host to tolerate the creation of a receiving and a sending
|
||||
socket. Don't blame me nor ask me for support if it does not work for you.
|
||||
</p>
|
||||
|
||||
<a name="EXAMPLE_APPLETALK"></a>
|
||||
<h3>Enabling AppleTalk protocol</h3>
|
||||
|
||||
<p>Install the <tt>netatalk</tt> package. Check that <tt>/etc/netatalk/atalkd.conf</tt>
|
||||
has an entry like <tt>eth0 -phase 2 -net 0-65534 -addr 65280.243</tt>. The
|
||||
last part is an arbitrary (?) host address, some of the following values must
|
||||
fit it. Make sure the <tt>atalkd</tt> daemon is running. Run the AppleTalk
|
||||
ping command:
|
||||
</p>
|
||||
|
||||
<span class="shell">aecho 65280.243
|
||||
</span>
|
||||
|
||||
<p>If you get an error like:
|
||||
</p>
|
||||
|
||||
<span class="error">Device or resource busy</span>
|
||||
|
||||
<p>then try to restart <tt>atalkd</tt>:</p>
|
||||
|
||||
<span class="shell">/etc/init.d/atalkd restart
|
||||
</span>
|
||||
|
||||
<p>When <tt>aecho</tt> works like <tt>ping</tt> you are ready for the next step.
|
||||
</p>
|
||||
|
||||
<h3>Example 2: AppleTalk datagram communication</h3>
|
||||
|
||||
<p>We start a socat process with a receiver and echo service:
|
||||
</p>
|
||||
|
||||
<span class="shell">socat \
|
||||
SOCKET-RECVFROM:5:2:0:x40x00x0000x00x00x0000000000000000 \
|
||||
PIPE
|
||||
</span>
|
||||
|
||||
<p>Then, in another shell on the same host, we start a client socket process
|
||||
that sends data to the server and gets the answer:
|
||||
</p>
|
||||
|
||||
<span class="shell">echo ABCD | \
|
||||
socat - \
|
||||
SOCKET-DATAGRAM:5:2:0:x40x00xff00xf3x00x0000000000000000
|
||||
</span>
|
||||
|
||||
<p>The client process should print the data.
|
||||
</p>
|
||||
|
||||
<p>How did this work? The generic socat address has just used the system call
|
||||
parameters that were provided on command line, without knowing anything about
|
||||
AppleTalk sockets and protocol. The values 5, 2, and 0 are directly used for
|
||||
the <tt>socket()</tt> call: they specify the domain (<tt>PF_APPLETALK=5</tt>),
|
||||
socket type (<tt>SOCK_DGRAM=2</tt>), and no protocol (0) - values for Linux.
|
||||
The long hex strings define the socket addresses. They can only be constructed
|
||||
with knowledge of the underlying structure. In
|
||||
<tt>/usr/include/linux/atalk.h</tt> we find the following declarations:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
struct atalk_addr {
|
||||
__be16 s_net;
|
||||
__u8 s_node;
|
||||
};
|
||||
|
||||
struct sockaddr_at {
|
||||
sa_family_t sat_family;
|
||||
__u8 sat_port;
|
||||
struct atalk_addr sat_addr;
|
||||
char sat_zero[8];
|
||||
</pre>
|
||||
|
||||
<p>After rolling out <tt>atalk_addr</tt> and considering implicit padding by the
|
||||
C programming language we get the following byte map:
|
||||
</p>
|
||||
|
||||
<table border="1">
|
||||
<tr><th>component</th><th>offset</th><th>length</th><th>value</th><th>meaning</th></tr>
|
||||
<tr><td>sat_family</td><td>0</td><td>2</td><td>x0005</td><td>address family</td></tr>
|
||||
<tr><td>sat_port</td><td>2</td><td>1</td><td>x40</td><td>port</td></tr>
|
||||
<tr><td>-</td><td>3</td><td>1</td><td>x00</td><td>padding</td></tr>
|
||||
<tr><td>sat_addr.s_net</td><td>4</td><td>2</td><td>xff00</td><td>network address</td></tr>
|
||||
<tr><td>sat_addr.s_node</td><td>6</td><td>1</td><td>xf3</td><td>node address</td></tr>
|
||||
<tr><td>-</td><td>7</td><td>1</td><td>x00</td><td>padding</td></tr>
|
||||
<tr><td>sat_zero</td><td>8</td><td>8</td><td>x0000000000000000</td><td>padding</td></tr>
|
||||
</table>
|
||||
|
||||
<p>Note that hexadecimal ff00 is the same as decimal 65280, and hexadecimal xf3
|
||||
is the same as decimal 243 - these are the numbers specified in
|
||||
<tt>atalkd.conf</tt>.
|
||||
</p>
|
||||
|
||||
<p>The address family component must be omitted from the socket address because
|
||||
it is added by socat implicitely. The resulting hexadecimal representation of
|
||||
the target socket address is therefore:
|
||||
</p>
|
||||
<tt>x40x00xff00xf3x00x0000000000000000</tt>
|
||||
|
||||
<p>The receiver just has to specify the port, so its bind address data is:
|
||||
</p>
|
||||
<tt>x40x00x0000x00x00x0000000000000000</tt>
|
||||
|
||||
<h2>Parameters for well known socket types</h2>
|
||||
|
||||
<p>Finding the correct parameters and socket addresses is not always trivial.
|
||||
Therefore this section provides tables with the parameters of common socket
|
||||
types. Some of these types are directly implemented by socat (and other
|
||||
programs). Establishing interoperability between a directly implemented
|
||||
socket and a generic socket might be your first step before entering unknown
|
||||
ground.</p>
|
||||
|
||||
<h3>Socket parameters</h3>
|
||||
|
||||
<h4>Table: parameter names for "well known" sockets:</h4>
|
||||
|
||||
<table border=1>
|
||||
<tr><th>name</th><th>domain</th><th>socktype</th><th>protocol</th><th> </th><th>level</th><th>remark</th></tr>
|
||||
<tr><td>UDP4</td><td>PF_INET</td><td>SOCK_DGRAM</td><td>IPPROTO_UDP</td><td> </td><td>SOL_UDP</td><td></td></tr>
|
||||
<tr><td>UDP6</td><td>PF_INET6</td><td>SOCK_DGRAM</td><td>IPPROTO_UDP</td><td> </td><td>SOL_UDP</td><td></td></tr>
|
||||
<tr><td>raw IPv4</td><td>PF_INET</td><td>SOCK_RAW</td><td>IPPROTO_RAW</td><td> </td><td>SOL_IP</td><td></td></tr>
|
||||
<tr><td>raw IPv6</td><td>PF_INET6</td><td>SOCK_RAW</td><td>IPPROTO_RAW</td><td> </td><td>SOL_IPV6</td><td></td></tr>
|
||||
<tr><td>UNIX</td><td>PF_LOCAL</td><td>SOCK_DGRAM</td><td>0</td><td> </td><td>SOL_SOCKET</td><td> </td></tr>
|
||||
<tr><td>PACKET</td><td>PF_PACKET</td><td>SOCK_RAW</td><td>768</td><td></td><td>SOL_PACKET</td><td>tcpdump (include layer 2 header)</td></tr>
|
||||
<tr><td>PACKET</td><td>PF_PACKET</td><td>SOCK_DGRAM</td><td>768</td><td></td><td>SOL_PACKET</td><td>no level 2 header</td></tr>
|
||||
<tr><td>SCTP4</td><td>PF_INET</td><td>SOCK_SEQPACKET</td><td>IPPROTO_SCTP</td><td> </td><td>SOL_SCTP</td><td> </td></tr>
|
||||
</table>
|
||||
|
||||
<h4>Table: parameter values:</h4>
|
||||
|
||||
<table border=1>
|
||||
<tr><th>name</th><th>Linux</th><th>FreeBSD</th><th>NetBSD</th><th>OpenBSD</th><th>Solaris</th><th>AIX</th><th>Cygwin</th><th>Mac OS X</th><th>HP-UX</th></tr>
|
||||
<tr><td>PF_LOCAL</td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
|
||||
<tr><td>PF_INET</td><td>2</td><td>2</td><td>2</td><td>2</td><td>2</td><td>2</td><td>2</td><td>2</td><td>2</td></tr>
|
||||
<tr><td>PF_APPLETALK</td><td>5</td><td>16</td><td>16</td><td>16</td><td>16</td><td>16</td><td>16</td><td>16</td><td>16</td></tr>
|
||||
<tr><td>PF_INET6</td><td>10</td><td>28</td><td>24</td><td>24</td><td>26</td><td>24</td><td>-</td><td>30</td><td>22</td></tr>
|
||||
<tr><td>PF_PACKET</td><td>17</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>SOCK_STREAM</td><td>1</td><td>1</td><td>1</td><td>1</td><td>2</td><td>1</td><td>1</td><td>1</td><td>1</td></tr>
|
||||
<tr><td>SOCK_DGRAM</td><td>2</td><td>2</td><td>2</td><td>2</td><td>1</td><td>2</td><td>2</td><td>2</td><td>2</td></tr>
|
||||
<tr><td>SOCK_RAW</td><td>3</td><td>3</td><td>3</td><td>3</td><td>4</td><td>3</td><td>3</td><td>3</td><td>3</td></tr>
|
||||
<tr><td>SOCK_SEQPACKET</td><td>5</td><td>5</td><td>5</td><td>5</td><td>6</td><td>5</td><td>5</td><td>5</td><td>5</td></tr>
|
||||
<tr><td>SOCK_DCCP</td><td>(6)</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>SOCK_PACKET</td><td>10</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>IPPROTO_IP</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
|
||||
<tr><td>IPPROTO_TCP</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td></tr>
|
||||
<tr><td>IPPROTO_UDP</td><td>17</td><td>17</td><td>17</td><td>17</td><td>17</td><td>17</td><td>17</td><td>17</td><td>17</td></tr>
|
||||
<tr><td>IPPROTO_DCCP</td><td>33</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>IPPROTO_SCTP</td><td>132</td><td>132</td><td>-</td><td>-</td><td>132</td><td>132</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>IPPROTO_RAW</td><td>255</td><td>255</td><td>255</td><td>255</td><td>255</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>SOL_SOCKET</td><td>1</td><td>65535</td><td>65535</td><td>65535</td><td>65535</td><td>65535</td><td>65535</td><td>65535</td><td>65535</td></tr>
|
||||
<tr><td>SOL_IP</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td><td>0</td></tr>
|
||||
<tr><td>SOL_TCP</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td><td>6</td></tr>
|
||||
<tr><td>SOL_UDP</td><td>17</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>17</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>SOL_IPV6</td><td>41</td><td>41</td><td>41</td><td>41</td><td>41</td><td>41</td><td>-</td><td>41</td><td>41</td></tr>
|
||||
<tr><td>SOL_PACKET</td><td>263</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
<tr><td>SOL_DCCP</td><td>269</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h3>Socket address specifications</h3>
|
||||
|
||||
<p>These hexadecimal data define socket addresses for local and remote sockets,
|
||||
and for bind and range options. The basis is the <tt>struct sockaddr_*</tt> for
|
||||
the respective address family that should be declared in the C include files.
|
||||
Please keep in mind that their first two bytes (<tt>sa_family</tt> and - on BSD
|
||||
- <tt>sa_len</tt>) are implicitely prepended by socat.</p>
|
||||
|
||||
<h4>Linux on 32bit Intel:</h4>
|
||||
|
||||
<table border=1>
|
||||
<tr><th>name</th><th>socket address type (without leading address family)</th><th>binary specification</th></tr>
|
||||
<tr><td>IPv4</td><td>2 bytes port, 4 bytes IPv4 addr, 8 bytes 0</td><td>x0016
|
||||
x7f000001 x0000000000000000</td></tr>
|
||||
<tr><td>IPv6</td><td>2 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4 bytes scope-id</td><td>x0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000</td></tr>
|
||||
<tr><td>UNIX</td><td>variable length path name, 0 terminated</td><td>x2f746d702f736f636b00</td></tr>
|
||||
<tr><td>PACKET</td><td>2 bytes protocol (0x0003), interface index as int in host byte order, 8 bytes 0</td><td>x0003 x02000000 x0000000000000000</td></tr>
|
||||
</table>
|
||||
|
||||
<p>For AppleTalk see above <a href="#EXAMPLE_APPLETALK">example</a>.</p>
|
||||
|
||||
<h4>Solaris on 32bit Intel:</h4>
|
||||
|
||||
<table border=1>
|
||||
<tr><th>name</th><th>socket address type (without leading address family)</th><th>binary specification</th></tr>
|
||||
<tr><td>IPv6</td><td>2 bytes port, 4 bytes flowinfo, 16 bytes IPv6 addr, 4
|
||||
bytes scope-id, 4 bytes src-id</td><td>x0016 x00000000 x0102030405060708090a0b0c0d0e0f x00000000 x00000000</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>Forever - play on...</h3>
|
||||
|
||||
<p>Eager to experiment with exotic socket types? Run nmap's protocol scan and
|
||||
see what is available on your system:
|
||||
</p>
|
||||
|
||||
<span class="shell">nmap -sO localhost
|
||||
</span>
|
||||
|
||||
<p>
|
||||
<small>Copyright: Gerhard Rieger 2008</small><br>
|
||||
<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
400
doc/socat-multicast.html
Normal file
400
doc/socat-multicast.html
Normal file
@@ -0,0 +1,400 @@
|
||||
<!-- source: doc/socat-multicast.html -->
|
||||
<html><head>
|
||||
<title>IP Multicasting with Socat</title>
|
||||
<link rel="stylesheet" type="text/css" href="dest-unreach.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>IP Multicasting with Socat</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
Multicasting (and broadcasting which is also discussed in this article)
|
||||
provides a means to direct a single packet to more than one host. Special
|
||||
addresses are defined for this purpose and are handled specially by network
|
||||
adapters, networking hardware, and IP stacks.
|
||||
</p>
|
||||
<p>
|
||||
IPv4 specifications provide broadcasting and multicasting; IPv6 provides
|
||||
multicasting but replaces broadcasting by special multicast modes. UNIX domain
|
||||
sockets do not know broadcasting or multicasting.
|
||||
</p>
|
||||
<p>
|
||||
The following examples use UDP/IPv4 only. However, they can easily be
|
||||
adapted for raw IPv4 sockets. IPv6 multicasting has not yet been successfully
|
||||
used with socat; please contact the author if you have positive experiences or
|
||||
ideas that go beyond <tt>IPV6_ADD_MEMBERSHIP</tt>.
|
||||
</p>
|
||||
<p>
|
||||
All multicast examples presented in this document use multicast address
|
||||
224.1.0.1; it can be replaced by any valid IPv4 multicast address (except
|
||||
<a href="#ALLSYSTEMS">all-systems</a>).
|
||||
</p>
|
||||
<p>
|
||||
We assume a local network with address 192.168.10.0 and mask 255.255.255.0; an
|
||||
eventual "client" has 192.168.10.1, example "server" and example peer have
|
||||
192.168.10.2 in all examples. Change these addresses and mask to your own
|
||||
requirements.
|
||||
</p>
|
||||
<p>
|
||||
All the following examples work bidirectionally except when otherwise noticed.
|
||||
For "clients" we just use <tt>STDIO</tt>, and for "servers" we use <tt>EXEC:hostname</tt> which
|
||||
ingores its input but shows us which host the reply comes from. Replace these
|
||||
socat addresses with what is appropriate for your needs (e.g. shell script
|
||||
invocations). Port 6666 can be replaced with any other port (but for ports <
|
||||
1024 root privilege might be required).
|
||||
</p>
|
||||
<p>
|
||||
Different kinds of broadcast addresses exist: 255.255.255.255 is local network
|
||||
only; for the IPv4 network 192.168.10.0/24 the "official" broadcast address
|
||||
is 192.168.10.255; the network address 192.168.10.0 is also interpreted as
|
||||
broadcast by some hosts. The two latter forms are routed by gateways. In the
|
||||
following examples we only use broadcast address 192.168.10.255.
|
||||
</p>
|
||||
|
||||
<h2>Example 1: Multicast client and servers</h2>
|
||||
|
||||
<p>This example builds something like a "supervisor" or "client" that
|
||||
communicates with a set of "servers". The supervisor may send packets to the
|
||||
multicast address, and the servers may send response packets. Note that the
|
||||
servers would also respond to other clients' requests.</p>
|
||||
|
||||
<p>Multicast server:</p>
|
||||
<div class="shell">socat \
|
||||
UDP4-RECVFROM:6666,ip-add-membership=224.1.0.1:192.168.10.2,fork \
|
||||
EXEC:hostname
|
||||
</div>
|
||||
<p>
|
||||
This command receives multicast packets addressed to 224.1.0.1 and forks a
|
||||
child process for each. The child processes may each send one or more reply
|
||||
packets back to the particular sender. 192.168.10.2 means the address of the
|
||||
interface where multicasts should be received.
|
||||
Run this command on a number of hosts, and they will all respond in
|
||||
parallel.</p>
|
||||
|
||||
<p>Multicast client:</p>
|
||||
|
||||
<span class="shell">socat \
|
||||
STDIO \
|
||||
UDP4-DATAGRAM:224.1.0.1:6666,range=192.168.10.0/24
|
||||
</span>
|
||||
<p>
|
||||
This process transfers data from stdin to the multicast address, and transfers
|
||||
packets received from the local network to stdout. It does not matter in which
|
||||
direction the first data is passed.
|
||||
A packet from the network is accepted by the IP stack for our socket if:
|
||||
<ul>
|
||||
<li>it is an incoming UDP/IPv4 packet</li>
|
||||
<li>its target port matches the local port assigned to the socket (random)</li>
|
||||
<li>its target address matches one of the hosts local addresses or the any-host
|
||||
multicast address</li>
|
||||
</ul>
|
||||
Of these packets, socat handles only those matching the following criteria:
|
||||
<ul>
|
||||
<li>the source address is within the given range</li>
|
||||
<li>the source port is 6666</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<h2>Example 2: Broadcast client and servers</h2>
|
||||
|
||||
<p>Broadcast server:</p>
|
||||
|
||||
<span class="shell">socat \
|
||||
UDP4-RECVFROM:6666,broadcast,fork \
|
||||
EXEC:hostname
|
||||
</span>
|
||||
<p>
|
||||
This command receives packets addressed to a local broadcast address and forks
|
||||
a child process for each. The child processes may each send one or more reply
|
||||
packets back to the particular sender.
|
||||
Run this command on a number of hosts, and they will all respond in
|
||||
parallel.</p>
|
||||
|
||||
<p>Broadcast client:</p>
|
||||
|
||||
<span class="shell">socat \
|
||||
STDIO \
|
||||
UDP4-DATAGRAM:192.168.10.255:6666,broadcast,range=192.168.10.0/24
|
||||
</span>
|
||||
<p>
|
||||
This process transfers data from stdin to the broadcast address, and transfers
|
||||
packets received from the local network to stdout. It does not matter in which
|
||||
direction the first data is passed.
|
||||
A packet from the network is accepted by the IP stack for our socket if:
|
||||
<ul>
|
||||
<li>it is an incoming UDP/IPv4 packet</li>
|
||||
<li>its target port matches the local port assigned to the socket (6666)</li>
|
||||
<li>its target address matches one of the hosts local addresses or the any-host
|
||||
multicast address, or a local broadcast address</li>
|
||||
</ul>
|
||||
Of these packets, socat handles only those matching the following criteria:
|
||||
<ul>
|
||||
<li>the source address is within the given range</li>
|
||||
<li>the source port is 6666</li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>The <tt>broadcast</tt> option is only required for sending or receiving
|
||||
local broadcasts.</p>
|
||||
|
||||
<h2>Example 3: Multicast peers</h2>
|
||||
|
||||
<p>It is possible to combine multicast sender and receiver in one socat
|
||||
address. This allows to start processes on different hosts on the local network
|
||||
that will communicate symmetrically, so each process can send messages that are
|
||||
received by all the other ones.</p>
|
||||
|
||||
<span class="shell">socat \
|
||||
STDIO \
|
||||
UDP4-DATAGRAM:224.1.0.1:6666,bind=:6666,range=192.168.10.0/24,ip-add-membership=224.1.0.1:192.168.10.2
|
||||
</span>
|
||||
<p>
|
||||
This command is valid for host 192.168.10.2; adapt this address to the
|
||||
particular interface addresses of the hosts.
|
||||
</p>
|
||||
<p>
|
||||
Starting this process opens a socket on port 6666 that will receive packets
|
||||
directed to multicast address 224.1.0.1. Only packets with matching source
|
||||
address and source port 6666 will be handled though. When this process sends
|
||||
data to the network the packets will be addressed to 224.1.0.1:6666 and have a
|
||||
source address of 192.168.10.2:6666, matching the accept criteria of the peers
|
||||
on the local network.
|
||||
</p>
|
||||
|
||||
<p>Note: this command receives the packets it just has sent; add option
|
||||
<tt>ip-multicast-loop=0</tt> if this in undesired.</p>
|
||||
|
||||
<h2>Example 4: Broadcast peers</h2>
|
||||
|
||||
<p>Just as with multicast, it is possible to combine broadcast sender and
|
||||
receiver in one socat address.</p>
|
||||
|
||||
<span class="shell">socat \
|
||||
STDIO \
|
||||
UDP4-DATAGRAM:255.255.255.255:6666,bind=:6666,range=192.168.10.0/24,broadcast
|
||||
</span>
|
||||
<p>
|
||||
Starting this process opens a socket on port 6666 that will receive packets
|
||||
directed to a local broadcast addresses. Only packets with matching source
|
||||
address and source port 6666 will be handled though. When this process sends
|
||||
data to the network the packets will be addressed to 255.255.255.255:6666 and
|
||||
have a source address of 192.168.10.2:6666, matching the accept criteria of
|
||||
the peers on the local network.
|
||||
</p>
|
||||
|
||||
<p>Note: this command receives the packets it just has sent; there does not
|
||||
seem to exist a simple way to prevent this.</p>
|
||||
|
||||
|
||||
<h2>Troubleshooting</h2>
|
||||
|
||||
<p>
|
||||
If you do not get an error message during operation, but the packets do not
|
||||
reach the target processes, use <tt>tcpdump</tt> to see if the packets have the
|
||||
correct source and destination addresses and ports, and if they leave and enter
|
||||
the hosts as expected.
|
||||
</p>
|
||||
<p>
|
||||
The following subsections discuss some typical sources of trouble.
|
||||
</p>
|
||||
|
||||
<h3>IP filters</h3>
|
||||
<p>
|
||||
If you do not succeed in receiving multicast or broadcast packets, check if
|
||||
iptables are activated on the receiving or sending host. They might be
|
||||
configured to disallow this traffic.
|
||||
</p>
|
||||
|
||||
<h3>Do not bind()</h3>
|
||||
<p>
|
||||
When using multicast communications, you should not bind the sockets to a
|
||||
specific IP address. It seems that the (Linux) IP stack compares the
|
||||
destination address with the bind address, not taking care of the multicast
|
||||
property of the incoming packet.
|
||||
</p>
|
||||
|
||||
<h3>Routing</h3>
|
||||
<p>
|
||||
When you receive an error like:</p>
|
||||
<span class="error">
|
||||
... E sendto(3, 0x80c2e44, 4, 0, AF=2 224.1.0.1:6666, 16): Network is unreachable
|
||||
</span>
|
||||
<p>you have a routing problem. The (Linux) IP stack seems to handle multicast
|
||||
addresses just like unicast addresses when determining their route (interface
|
||||
and gateway), i.e. the routing table needs an entry that somehow matches the
|
||||
target address. </p>
|
||||
<p>
|
||||
For the same reason, multicast packets will probably leave your host on the
|
||||
interface with the default route if it is specified.</p>
|
||||
<p>
|
||||
Set a multicast/broadcast route with the following command (Linux):</p>
|
||||
<span class="shell">route add -net 224.0.0.0/3 gw 192.168.10.2
|
||||
</span>
|
||||
|
||||
<a name="ALLSYSTEMS"></a>
|
||||
<h3>ALL-SYSTEMS multicast address</h3>
|
||||
<p>
|
||||
<tt>224.0.0.1</tt> is the all-systems multicast address: all
|
||||
datagram sockets appear to be automatically member of this group on all
|
||||
interfaces. This membership cannot be dropped on Linux (you need iptables to
|
||||
filter packets).
|
||||
</p>
|
||||
|
||||
|
||||
<h2>(In)Security</h2>
|
||||
|
||||
<p>When you use the above examples you should understand that all datagram
|
||||
sockets without exception accept all packets that are directly addressed to
|
||||
them;
|
||||
the multi- and broadcast receiving features are just extensions to this
|
||||
functionality. socat currently has no means to handle incoming packets
|
||||
differently whether they are addressed to unicast, multicast, or broadcast
|
||||
addresses. However, for EXEC'd scripts socat can provide this info in
|
||||
environment variables.
|
||||
</p>
|
||||
|
||||
<p>Authentication or encryption are not available.</p>
|
||||
|
||||
<p>It is very easy to fake the source address of UDP (or raw IP) packets. You
|
||||
should understand whether your network is protected from address spoofing
|
||||
attacks.</p>
|
||||
|
||||
<p>Broadcast and multicast traffic can trivially be received by <em>any</em>
|
||||
host on the local network.</p>
|
||||
|
||||
|
||||
<h2>History</h2>
|
||||
|
||||
Starting with version 1.5.0, socat provides a set of address types that
|
||||
allow various operations on datagram oriented sockets:
|
||||
<dl>
|
||||
<dt>SENDTO</dt><dd>send packets to a remote socket and receive packet from this
|
||||
remote socket only</dd>
|
||||
<dt>RECV</dt><dd>receive all packets that arrive on the local socket, but do
|
||||
not reply</dd>
|
||||
<dt>RECVFROM</dt><dd>receive all packets that arrive on the local socket, and
|
||||
reply using child processes</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
These modes already enable several different client/server oriented operations.
|
||||
Moreover, the SENDTO addresses can send to multicast and broadcast addresses
|
||||
(the latter requires the <tt>broadcast</tt> option though). RECV and RECVFROM
|
||||
also would accept packets addressed to a local broadcast address (with option
|
||||
<tt>broadcast</tt>) or the all-systems multicast address.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These address types had, however, two major caveats:
|
||||
<ul>
|
||||
<li>Missing control of multicast group membership in the RECV and RECVFROM
|
||||
addresses</li>
|
||||
<li>The SENDTO address would never accept a reply to a broadcast or multicast
|
||||
addressed packet because the source address of incoming replies would not match
|
||||
the target address of the sent packet.
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h3>New Features in socat 1.6.0</h3>
|
||||
|
||||
<p>
|
||||
socat version 1.6.0 addresses these problems and provides a new more generic
|
||||
datagram address type (*-DATAGRAM) and the new address option IP-ADD-MEMBERSHIP.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Please note that the new features could not be successfully tested on IPv6;
|
||||
these sections thus apply to IPv4 only.
|
||||
</p>
|
||||
|
||||
<h3>New Features in socat 1.7.0</h3>
|
||||
|
||||
<p>
|
||||
socat version 1.7.0 helps to find more information about incoming packets in
|
||||
environment variables that can be used in scripts or programs invoked by
|
||||
socat. The option <tt>ip-pktinfo</tt> (on non-BSD systems)
|
||||
or <tt>ip-recvdstaddr</tt> (on BSD systems) is required to get basic
|
||||
information about incoming packets.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Example: Start a receiver of the following form (tried on Linux):
|
||||
</p>
|
||||
|
||||
<span class="shell">socat -u \
|
||||
UDP-RECVFROM:8888,reuseaddr,ip-add-membership=224.1.0.1:192.168.10.2,ip-pktinfo,fork \
|
||||
SYSTEM:export
|
||||
</span>
|
||||
|
||||
<p>
|
||||
Then send a multicast packet from the client:
|
||||
</p>
|
||||
|
||||
<span class="shell">echo | \
|
||||
socat -u \
|
||||
STDIO \
|
||||
UDP-DATAGRAM:224.1.0.1:8888
|
||||
</span>
|
||||
|
||||
<p>
|
||||
On the server the following text should appear (only interesting lines shown):
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
export SOCAT_IP_DSTADDR="224.1.0.1"
|
||||
export SOCAT_IP_IF="eth0"
|
||||
export SOCAT_IP_LOCADDR="192.168.10.2"
|
||||
export SOCAT_PEERADDR="192.168.10.1"
|
||||
export SOCAT_PEERPORT="41159"
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<tt>SOCAT_IP_IF</tt> shows the interface where the packet entered the server;
|
||||
<tt>SOCAT_IP_LOCADDR</tt> shows the IP address of this interface;
|
||||
<tt>SOCAT_IP_DSTADDR</tt> shows the target address of the packet;
|
||||
<tt>SOCAT_PEERADDR</tt> and <tt>SOCAT_PEERPORT</tt> are the client socket
|
||||
values.
|
||||
</p>
|
||||
|
||||
<h2>More info about socat datagrams</h2>
|
||||
|
||||
<h3>Links regarding this tutorial</h3>
|
||||
<a href="socat.html#ADDRESS_UDP4_DATAGRAM">address UDP4-DATAGRAM</a><br>
|
||||
<a href="socat.html#ADDRESS_UDP4_RECVFROM">address UDP4-RECVFROM</a><br>
|
||||
<a href="socat.html#OPTION_RANGE">option range</a><br>
|
||||
<a href="socat.html#OPTION_SO_BROADCAST">option broadcast</a><br>
|
||||
<a href="socat.html#OPTION_IP_ADD_MEMBERSHIP">option ip-add-membership</a><br>
|
||||
<a href="socat.html#OPTION_FORK">option fork</a><br>
|
||||
<a href="socat.html#OPTION_BIND">option bind</a><br>
|
||||
|
||||
<h3>Other datagram addresses</h3>
|
||||
<a href="socat.html#ADDRESS_UDP4_RECV">address UDP4-RECV</a>: pure datagram receiver<br>
|
||||
<a href="socat.html#ADDRESS_UDP4_SENDTO">address UDP4-SENDTO</a>: communicate
|
||||
with one peer address<br>
|
||||
<a href="socat.html#ADDRESS_UDP4_LISTEN">address UDP4-LISTEN</a>: pseudo stream server<br>
|
||||
<a href="socat.html#ADDRESS_UDP4_CONNECT">address UDP4-CONNECT</a>: pseudo stream client<br>
|
||||
|
||||
<h3>Related socat option groups</h3>
|
||||
<a href="socat.html#GROUP_IP">IP options</a><br>
|
||||
<a href="socat.html#GROUP_SOCKET">socket options</a><br>
|
||||
<a href="socat.html#GROUP_FD">file descriptor options</a><br>
|
||||
<a href="socat.html#GROUP_RANGE">range options</a><br>
|
||||
<a href="socat.html#GROUP_CHILD">child process options</a><br>
|
||||
|
||||
|
||||
<h2>References</h2>
|
||||
<a href="http://www.dest-unreach.org/socat">socat home page</a><br>
|
||||
<a href="socat.html">socat man page</a><br>
|
||||
<a href="http://en.wikipedia.org/wiki/Multicast">multicasting on Wikipedia</a><br>
|
||||
<a href="http://en.wikipedia.org/wiki/Broadcast_address">broadcasting on Wikipedia</a><br>
|
||||
|
||||
<p>
|
||||
<small>This document was last modified in May 2009.</small><br>
|
||||
<small>Copyright: Gerhard Rieger 2007-2009</small><br>
|
||||
<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
199
doc/socat-openssltunnel.html
Normal file
199
doc/socat-openssltunnel.html
Normal file
@@ -0,0 +1,199 @@
|
||||
<!-- $Revision: 1.1 $ $Date: 2007/03/06 20:54:43 $ -->
|
||||
<html><head>
|
||||
<title>Securing Traffic Between two Socat Instances Using SSL</title>
|
||||
<link rel="stylesheet" type="text/css" href="dest-unreach.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Securing Traffic Between two Socat Instances Using SSL</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
When you want to connect two socat processes running on different machines and
|
||||
feel that you need to protect the connection against unauthorized access,
|
||||
sniffing, data manipulation etc., you might want to encrypt the communications.
|
||||
</p>
|
||||
<p>
|
||||
For this purpose socat integrates the OpenSSL library and provides SSL client
|
||||
and server features.
|
||||
</p>
|
||||
<p>
|
||||
SSL is a complex protocol that provides much more features than required for
|
||||
protecting a single connection; in this document we present only a simple
|
||||
scenario that provides just the basic security requirements.
|
||||
</p>
|
||||
|
||||
<!-- discussion -->
|
||||
<h2>Configuring OpenSSL in socat</h2>
|
||||
<p>
|
||||
This section shows how the SSL addresses can be configured in socat.
|
||||
In this docu we only use self signed certificates for the sake of simplicity.
|
||||
</p>
|
||||
<p>We assume that the server host is called <tt>server.domain.org</tt> and the
|
||||
server process uses port 4433. To keep it simple, we use a very simple server
|
||||
funtionality that just echos data (<tt>echo</tt>), and <tt>stdio</tt> on the
|
||||
client.</p>
|
||||
<h3>Generate a server certificate</h3>
|
||||
|
||||
<p>Perform the following steps on a trusted host where OpenSSL is
|
||||
installed. It might as well be the client or server host themselves.</p>
|
||||
<p>Prepare a basename for the files related to the server certificate:</p>
|
||||
<span class="shell">FILENAME=server</span>
|
||||
|
||||
<p>Generate a public/private key pair:</p>
|
||||
<span class="shell">openssl genrsa -out $FILENAME.key 2048</span>
|
||||
|
||||
<p>Generate a self signed certificate:</p>
|
||||
<span class="shell">openssl req -new -key $FILENAME.key -x509 -days 3653 -out $FILENAME.crt</span>
|
||||
<p>You will be prompted for your country code, name etc.; you may quit all prompts
|
||||
with the ENTER key, except for the Common Name which must be exactly the name or IP address of the server that the client will use.</p>
|
||||
<p>Generate the PEM file by just appending the key and certificate files:<p>
|
||||
<span class="shell">cat $FILENAME.key $FILENAME.crt >$FILENAME.pem</span>
|
||||
|
||||
<p>The files that contain the private key should be kept secret, thus adapt
|
||||
their permissions:<p>
|
||||
<span class="shell">chmod 600 $FILENAME.key $FILENAME.pem</span>
|
||||
|
||||
<p>Now bring the file <tt>server.pem</tt> to the SSL server, e.g. to directory
|
||||
<tt>$HOME/etc/</tt>, using a secure channel like USB memory stick or SSH. Keep
|
||||
tight permissions on the file even on the target host, and remove all other
|
||||
instances of <tt>server.key</tt> and <tt>server.pem</tt>.
|
||||
</p>
|
||||
<p>Copy the trust certificate server.crt to the SSL client host, e.g. to directory
|
||||
<tt>$HOME/etc/</tt>; a secure channel is not required here, and the permissions
|
||||
are not critical.
|
||||
</p>
|
||||
|
||||
<h3>Generate a client certificate</h3>
|
||||
<p>First prepare a different basename for the files related to the client certificate:</p>
|
||||
<span class="shell">FILENAME=client</span>
|
||||
|
||||
<p>Repeat the procedure for certificate generation described above. A special common name is not required.
|
||||
Copy <tt>client.pem</tt> to the SSL client, and <tt>client.crt</tt> to the
|
||||
server.</p>
|
||||
|
||||
<h3>OpenSSL Server</h3>
|
||||
|
||||
<p>Instead of using a tcp-listen (tcp-l) address, we use openssl-listen (ssl-l)
|
||||
for the server, <tt>cert=...</tt> tells the program to the file containing its
|
||||
ceritificate and private key, and <tt>cafile=...</tt> points to the file
|
||||
containing the certificate of the peer; we trust clients only if they can proof
|
||||
that they have the related private key (OpenSSL handles this for us):<p>
|
||||
<span class="shell">socat \
|
||||
OPENSSL-LISTEN:4433,reuseaddr,cert=$HOME/etc/server.pem,cafile=$HOME/etc/client.crt \
|
||||
PIPE</span>
|
||||
<p>After starting this command, socat should be listening on port 4433, but
|
||||
will require client authentication.</p>
|
||||
|
||||
<h3>OpenSSL Client</h3>
|
||||
<p>Substitute your <tt>tcp-connect</tt> or <tt>tcp</tt> address keyword with
|
||||
<tt>openssl-connect</tt> or just <tt>ssl</tt> and here too add the
|
||||
<tt>cert</tt> and <tt>cafile</tt> options:<p>
|
||||
<span class="shell">socat STDIO \
|
||||
OPENSSL-CONNECT:server.domain.org:4433,cert=$HOME/etc/client.pem,cafile=$HOME/etc/server.crt</span>
|
||||
<p>This command should establish a secured connection to the server
|
||||
process.</p>
|
||||
|
||||
<h3>TCP/IP version 6</h3>
|
||||
|
||||
<p>If the communication is to go over IPv6, the above described commands have
|
||||
to be adapted; <tt>ip6name.domain.org</tt> is assumed to resolve to the IPv6
|
||||
address of the server:</p>
|
||||
<p>Server:</p>
|
||||
<span class="shell">socat \
|
||||
OPENSSL-LISTEN:4433,<b style="color:yellow">pf=ip6</b>,reuseaddr,cert=$HOME/etc/server.pem,cafile=$HOME/etc/client.crt \
|
||||
PIPE</span>
|
||||
|
||||
<p>Client:</p>
|
||||
<span class="shell">socat STDIO \
|
||||
OPENSSL-CONNECT:<b style="color:yellow">ip6name</b>.domain.org:4433,cert=$HOME/etc/client.pem,cafile=$HOME/etc/server.crt</span>
|
||||
|
||||
<h2>Troubleshooting</h2>
|
||||
|
||||
<h3>Test OpenSSL Integration</h3>
|
||||
<p>
|
||||
If you get error messages like this:</p>
|
||||
<span class="error">... E unknown device/address "OPENSSL-LISTEN"</span>
|
||||
<p>your socat executable probably does not have the OpenSSL library linked in.
|
||||
Check socat's compile time configuration with the following command:</p>
|
||||
<span class="shell">socat -V |grep SSL</span>
|
||||
<p>Positive output:
|
||||
<tt>#define WITH_OPENSSL 1</tt><br>
|
||||
Negative output:
|
||||
<tt>#undef WITH_OPENSSL</tt><br>
|
||||
</p>
|
||||
<p>
|
||||
In the latter case, make sure you have OpenSSL and its development package
|
||||
(include files) installed, and check the run of the configure script.
|
||||
</p>
|
||||
|
||||
|
||||
<h2>History</h2>
|
||||
<p>
|
||||
A first OpenSSL client was implemented in socat 1.2.0; it did not support
|
||||
client certificates and could not verify server certificates. It was rather
|
||||
considered as a tool for probing typical SSL secured Internet services.
|
||||
</p>
|
||||
<p>
|
||||
From version 1.4.0 on, socat provided experimental support for SSL client and
|
||||
SSL server, implemented using the OpenSSL libraries. Only TCP/IPv4 transport
|
||||
was supported. With both SSL client and server, trust certificates for checking
|
||||
the peers authentication, and certificates for authentication could be
|
||||
specified. This allowed for non interactive secure connection establishing.
|
||||
The features were considered experimental; like most Internet sites, socat
|
||||
server did not require the client to present a certificate per default, but the
|
||||
client required a server certificate.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
DSA certificate support is implemented since version 1.4.2.
|
||||
</p>
|
||||
<p>
|
||||
Socat version 1.5.0 extended SSL to TCP/IPv6 transports.
|
||||
</p>
|
||||
<p>
|
||||
With socat version 1.6.0, the SSL server per default requires the client to
|
||||
present a trusted certificate. socat's OpenSSL implementation still does not
|
||||
check the contents of a certificate like host name or host address.
|
||||
</p>
|
||||
<p>
|
||||
Socat 1.7.3.0 introduces check of servers commonname by the client, and optionally check of clients commonname by the server.
|
||||
</p>
|
||||
|
||||
<p>This document was last modified in Oct. 2023.</p>
|
||||
|
||||
<h2>More info about socat OpenSSL</h2>
|
||||
|
||||
<h3>Links regarding this tutorial</h3>
|
||||
<a href="socat.html#ADDRESS_OPENSSL_CONNECT">address openssl-connect</a><br>
|
||||
<a href="socat.html#ADDRESS_OPENSSL_LISTEN">address openssl-listen</a><br>
|
||||
<a href="socat.html#OPTION_OPENSSL_CERTIFICATE">option cert</a><br>
|
||||
<a href="socat.html#OPTION_OPENSSL_CAFILE">option cafile</a><br>
|
||||
|
||||
<h3>More socat options for OpenSSL addresses</h3>
|
||||
<a href="socat.html#GROUP_OPENSSL">OpenSSL options</a><br>
|
||||
<a href="socat.html#GROUP_TCP">TCP options</a><br>
|
||||
<a href="socat.html#GROUP_IP">IP options</a><br>
|
||||
<a href="socat.html#GROUP_SOCKET">socket options</a><br>
|
||||
<a href="socat.html#GROUP_FD">file descriptor options</a><br>
|
||||
<a href="socat.html#GROUP_RETRY">retry options</a><br>
|
||||
<p>For openssl-listen only:</p>
|
||||
<a href="socat.html#GROUP_LISTEN">listen options</a><br>
|
||||
<a href="socat.html#GROUP_CHILD">child options</a><br>
|
||||
<a href="socat.html#GROUP_RANGE">range options</a><br>
|
||||
|
||||
<h2>References</h2>
|
||||
<a href="http://www.dest-unreach.org/socat">socat home page</a><br>
|
||||
<a href="socat.html">socat man page</a><br>
|
||||
<a href="http://www.openssl.org/">OpenSSL home page</a><br>
|
||||
<a href="http://www.stunnel.org/">stunnel home page</a><br>
|
||||
<a href="http://en.wikipedia.org/wiki/Secure_Sockets_Layer">secure sockets layer on Wikipedia</a><br>
|
||||
|
||||
<p>
|
||||
<small>Copyright: Gerhard Rieger 2007</small><br>
|
||||
<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
175
doc/socat-tun.html
Normal file
175
doc/socat-tun.html
Normal file
@@ -0,0 +1,175 @@
|
||||
<!-- source: doc/socat-tun.html -->
|
||||
<html><head>
|
||||
<title>Building TUN based virtual networks with socat</title>
|
||||
<link rel="stylesheet" type="text/css" href="dest-unreach.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Building TUN based virtual networks with socat</h1>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
Some operating systems allow the generation of virtual network interfaces that
|
||||
do not connect to a wire but to a process that simulates the network. Often
|
||||
these devices are called TUN or TAP.
|
||||
</p>
|
||||
<p>
|
||||
socat provides an address type that creates a TUN device on Linux; the other
|
||||
socat address can be any type; it transfers the "wire" data as desired.
|
||||
</p>
|
||||
<p>
|
||||
This document shows how a simple virtual network can be created between
|
||||
two hosts that may be far (many network hops) apart. On both hosts a socat
|
||||
instance is started that connects to the other host using TCP and creates a TUN
|
||||
device. See <a href="socat-openssltunnel.html">socat-openssltunnel.html</a> for
|
||||
a guide on securing the connection using SSL.
|
||||
</p>
|
||||
<p>
|
||||
The following IP addresses are used in the example; replace them in the
|
||||
following commands with the requirements of your situation:</p>
|
||||
<table border="1">
|
||||
<tr><th>host</th><th>address</th><th>mask</th></tr>
|
||||
<tr><td>physical "server" address</td><td>1.2.3.4</td><td>n/a</td></tr>
|
||||
<tr><td>physical "client" address</td><td>n/a</td><td>n/a</td></tr>
|
||||
<tr><td>TUN on "server"</td><td>192.168.255.1</td><td>255.255.255.0</td></tr>
|
||||
<tr><td>TUN on "client"</td><td>192.168.255.2</td><td>255.255.255.0</td></tr>
|
||||
</table>
|
||||
<p>The TCP connection uses port 11443.</p>
|
||||
|
||||
<p>On "default" Linux installations, creating TUN/TAP devices might require
|
||||
root privilege.</p>
|
||||
|
||||
<!-- discussion -->
|
||||
<h2>Generate TUN devices with socat</h2>
|
||||
<p>In this section two instances of socat are used to generate TUN devices on
|
||||
different hosts and connect the "wire" sides, providing a simple virtual
|
||||
network.
|
||||
</p>
|
||||
<p>
|
||||
We distinguish server and client only with respect to the connection between
|
||||
the two socat instances; the TUN interfaces both have the same quality.
|
||||
</p>
|
||||
|
||||
<h3>TUN Server</h3>
|
||||
|
||||
<span class="shell">socat -d -d \
|
||||
UDP-LISTEN:11443 \
|
||||
TUN:192.168.255.1/24,up
|
||||
</span>
|
||||
<p>After starting this command, socat will wait for a connection and then
|
||||
create a TUN pseudo network device with address 192.168.255.1; the bit number
|
||||
specifies the mask of the network that is pretended to be connected on this
|
||||
interface.</p>
|
||||
|
||||
<h3>TUN Client</h3>
|
||||
<span class="shell">socat \
|
||||
UDP:1.2.3.4:11443 \
|
||||
TUN:192.168.255.2/24,up
|
||||
</span>
|
||||
<p>This command should establish a connection to the server and create the TUN
|
||||
device on the client.</p>
|
||||
|
||||
<h3>Seeing it work</h3>
|
||||
|
||||
<p>
|
||||
After successful connection both TUN interfaces should be active and transfer
|
||||
data between each other using the TCP connection. Try this by pinging
|
||||
192.168.255.1 from the client and 192.168.255.2 from the server.
|
||||
</p>
|
||||
|
||||
<h3>TCP/IP version 6</h3>
|
||||
|
||||
<p>IPv6 as transport should work just like any TCP/IPv6 connection.</p>
|
||||
|
||||
<p>Creation of an IPv6 virtual interface is not directly possible, but you can
|
||||
generate an IPv4 interface as described above, and add IPv6 addresses using
|
||||
the <tt>ifconfig</tt> command.
|
||||
|
||||
<h2>Troubleshooting</h2>
|
||||
|
||||
<h3>Test TUN integration</h3>
|
||||
<p>
|
||||
If you get error messages like this:</p>
|
||||
<span class="error">... E unknown device/address "tun"</span>
|
||||
<p>your socat executable probably does not provide TUN/TAP support. Potential
|
||||
reasons: you are not on Linux or are using an older version of socat.
|
||||
</p>
|
||||
|
||||
<h3>Missing kernel support</h3>
|
||||
<p>An error message like:</p>
|
||||
<span class="error">... E open("/dev/net/tun", 02, 0666): No such file or directory</span>
|
||||
<p>indicates that your kernel either needs to load the tun module or does not
|
||||
have TUN/TAP support compiled in. Try to load the module:</p>
|
||||
<span class="shell">modprobe tun</span>
|
||||
<p>and check
|
||||
for /dev/net/tun. If that does not succeed you need to
|
||||
rebuild your kernel with the appropriate configuration (probably under
|
||||
<b>Device driver / Network device support / Network device / Universal TUN/TAP</b>).
|
||||
</p>
|
||||
|
||||
<h3>TUN cloning device permissions</h3>
|
||||
<p>An error message like:</p>
|
||||
<span class="error">... E open("/dev/net/tun", 02, 0666): Permission denied</span>
|
||||
<p>indicates that you do not have permission to read or write the TUN cloning
|
||||
device. Check its permission and ownership.</p>
|
||||
|
||||
<h3>Interface down</h3>
|
||||
<p>If no error occurs but the pings do not work check if the network devices
|
||||
have been created:</p>
|
||||
<span class="shell">ifconfig tun0</span>
|
||||
<p>The output should look like:</p>
|
||||
<pre>
|
||||
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
|
||||
inet addr:192.168.255.1 P-t-P:192.168.255.1 Mask:255.255.255.0
|
||||
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
|
||||
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
|
||||
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
|
||||
collisions:0 txqueuelen:500
|
||||
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
|
||||
</pre>
|
||||
<p>Check the "UP" keyword; you forget the "up" option in the socat command if
|
||||
it is missing.<p>
|
||||
<p>Check if the correct IP address and network mask are displayed.</p>
|
||||
|
||||
<h3>Routing</h3>
|
||||
<p></p>
|
||||
<span class="shell">netstat -an |fgrep 192.168.255</span>
|
||||
<p>The output should look like:</p>
|
||||
<pre>
|
||||
192.168.255.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0
|
||||
</pre>
|
||||
|
||||
<h3>Other problems</h3>
|
||||
<p>Another reason for failure might be iptables.</p>
|
||||
<p>Run socat with options <tt>-d -d -d</tt>, this will show every data transfer
|
||||
between the two processes. Each ping probe should cause a forth and a back
|
||||
transfer.<p>
|
||||
|
||||
<h2>History</h2>
|
||||
<p>
|
||||
Linux TUN/TAP support was added to socat in version 1.6.0.</p>
|
||||
|
||||
<p>This document was last modified in February 2010.</p>
|
||||
|
||||
<h2>More info about socat TUN/TAP support</h2>
|
||||
|
||||
<h3>Links regarding this tutorial</h3>
|
||||
<a href="socat.html#ADDRESS_TUN">socat address tun</a><br>
|
||||
|
||||
<h3>socat options for TUN/TAP addresses</h3>
|
||||
<a href="socat.html#GROUP_TUN">TUN/TAP options</a><br>
|
||||
|
||||
<h2>References</h2>
|
||||
<a href="http://www.dest-unreach.org/socat">socat home page</a><br>
|
||||
<a href="socat.html">socat man page</a><br>
|
||||
<a href="http://openvpn.net/">OpenVPN home page</a><br>
|
||||
<a href="http://en.wikipedia.org/wiki/TUN/TAP">TUN/TAP on Wikipedia</a><br>
|
||||
|
||||
<p>
|
||||
<small>Copyright: Gerhard Rieger 2007-2010</small><br>
|
||||
<small>License: <a href="http://www.fsf.org/licensing/licenses/fdl.html">GNU Free Documentation License (FDL)</a></small>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
4960
doc/socat.1
Normal file
4960
doc/socat.1
Normal file
File diff suppressed because it is too large
Load Diff
4803
doc/socat.html
Normal file
4803
doc/socat.html
Normal file
File diff suppressed because it is too large
Load Diff
4810
doc/socat.yo
Normal file
4810
doc/socat.yo
Normal file
File diff suppressed because it is too large
Load Diff
564
error.c
Normal file
564
error.c
Normal file
@@ -0,0 +1,564 @@
|
||||
/* source: error.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* the logging subsystem */
|
||||
|
||||
#include "config.h"
|
||||
#include "sysincludes.h"
|
||||
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "utils.h"
|
||||
#include "vsnprintf_r.h"
|
||||
#include "snprinterr.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "sycls.h"
|
||||
|
||||
|
||||
/* translate MSG level to SYSLOG level */
|
||||
int syslevel[] = {
|
||||
LOG_DEBUG,
|
||||
LOG_INFO,
|
||||
LOG_NOTICE,
|
||||
LOG_WARNING,
|
||||
LOG_ERR,
|
||||
LOG_CRIT };
|
||||
|
||||
struct diag_opts {
|
||||
const char *progname;
|
||||
int msglevel;
|
||||
int shutup; /* decrease msglevel by this value */
|
||||
int exitlevel;
|
||||
int syslog;
|
||||
FILE *logfile;
|
||||
int logfacility;
|
||||
bool micros;
|
||||
int exitstatus; /* pass signal number to error exit */
|
||||
bool withhostname; /* in custom logs add hostname */
|
||||
char *hostname;
|
||||
bool signalsafe;
|
||||
} ;
|
||||
|
||||
|
||||
static void _diag_exit(int status);
|
||||
|
||||
|
||||
struct diag_opts diagopts =
|
||||
{ NULL, E_WARN, 0, E_ERROR, 0, NULL, LOG_DAEMON, false, 0, false, NULL, true } ;
|
||||
|
||||
static void msg2(
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
struct timespec *now,
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
struct timeval *now,
|
||||
#else
|
||||
time_t *now,
|
||||
#endif
|
||||
int level, int exitcode, int handler, const char *text);
|
||||
static void _msg(int level, const char *buff, const char *syslp);
|
||||
|
||||
volatile sig_atomic_t diag_in_handler; /* !=0 indicates to msg() that in signal handler */
|
||||
volatile sig_atomic_t diag_immediate_msg; /* !=0 prints messages even from within signal handler instead of deferring them */
|
||||
volatile sig_atomic_t diag_immediate_exit; /* !=0 calls exit() from diag_exit() even when in signal handler. For system() */
|
||||
|
||||
static struct wordent facilitynames[] = {
|
||||
{"auth", (void *)LOG_AUTH},
|
||||
#ifdef LOG_AUTHPRIV
|
||||
{"authpriv", (void *)LOG_AUTHPRIV},
|
||||
#endif
|
||||
#ifdef LOG_CONSOLE
|
||||
{"console", (void *)LOG_CONSOLE},
|
||||
#endif
|
||||
{"cron", (void *)LOG_CRON},
|
||||
{"daemon", (void *)LOG_DAEMON},
|
||||
#ifdef LOG_FTP
|
||||
{"ftp", (void *)LOG_FTP},
|
||||
#endif
|
||||
{"kern", (void *)LOG_KERN},
|
||||
{"local0", (void *)LOG_LOCAL0},
|
||||
{"local1", (void *)LOG_LOCAL1},
|
||||
{"local2", (void *)LOG_LOCAL2},
|
||||
{"local3", (void *)LOG_LOCAL3},
|
||||
{"local4", (void *)LOG_LOCAL4},
|
||||
{"local5", (void *)LOG_LOCAL5},
|
||||
{"local6", (void *)LOG_LOCAL6},
|
||||
{"local7", (void *)LOG_LOCAL7},
|
||||
{"lpr", (void *)LOG_LPR},
|
||||
{"mail", (void *)LOG_MAIL},
|
||||
{"news", (void *)LOG_NEWS},
|
||||
#ifdef LOG_SECURITY
|
||||
{"security", (void *)LOG_SECURITY},
|
||||
#endif
|
||||
{"syslog", (void *)LOG_SYSLOG},
|
||||
{"user", (void *)LOG_USER},
|
||||
{"uucp", (void *)LOG_UUCP}
|
||||
} ;
|
||||
|
||||
/* serialize message for sending from signal handlers */
|
||||
struct sermsg {
|
||||
int severity;
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
struct timespec ts;
|
||||
#else
|
||||
struct timeval tv;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
static int diaginitialized;
|
||||
static int diag_sock_send = -1;
|
||||
static int diag_sock_recv = -1;
|
||||
static volatile sig_atomic_t diag_msg_avail = 0; /* !=0: messages from within signal handler may be waiting */
|
||||
|
||||
|
||||
static int diag_sock_pair(void) {
|
||||
int handlersocks[2];
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, handlersocks) < 0) {
|
||||
diag_sock_send = -1;
|
||||
diag_sock_recv = -1;
|
||||
return -1;
|
||||
}
|
||||
fcntl(handlersocks[0], F_SETFD, FD_CLOEXEC);
|
||||
fcntl(handlersocks[1], F_SETFD, FD_CLOEXEC);
|
||||
diag_sock_send = handlersocks[1];
|
||||
diag_sock_recv = handlersocks[0];
|
||||
#if !defined(MSG_DONTWAIT)
|
||||
fcntl(diag_sock_send, F_SETFL, O_NONBLOCK);
|
||||
fcntl(diag_sock_recv, F_SETFL, O_NONBLOCK);
|
||||
#endif
|
||||
fcntl(diag_sock_send, F_SETFD, FD_CLOEXEC);
|
||||
fcntl(diag_sock_recv, F_SETFD, FD_CLOEXEC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int diag_init(void) {
|
||||
if (diaginitialized) {
|
||||
return 0;
|
||||
}
|
||||
diaginitialized = 1;
|
||||
/* gcc with GNU libc refuses to set this in the initializer */
|
||||
diagopts.logfile = stderr;
|
||||
if (diagopts.signalsafe) {
|
||||
if (diag_sock_pair() < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#define DIAG_INIT ((void)(diaginitialized || diag_init()))
|
||||
|
||||
|
||||
void diag_set(char what, const char *arg) {
|
||||
switch (what) {
|
||||
case 'I':
|
||||
if (diagopts.signalsafe) {
|
||||
if (diag_sock_send >= 0) { Close(diag_sock_send); diag_sock_send = -1; }
|
||||
if (diag_sock_recv >= 0) { Close(diag_sock_recv); diag_sock_recv = -1; }
|
||||
}
|
||||
diagopts.signalsafe = false;
|
||||
return;
|
||||
}
|
||||
|
||||
DIAG_INIT;
|
||||
switch (what) {
|
||||
const struct wordent *keywd;
|
||||
|
||||
case 'y': diagopts.syslog = true;
|
||||
if (arg && arg[0]) {
|
||||
if ((keywd =
|
||||
keyw(facilitynames, arg,
|
||||
sizeof(facilitynames)/sizeof(struct wordent))) == NULL) {
|
||||
Error1("unknown syslog facility \"%s\"", arg);
|
||||
} else {
|
||||
diagopts.logfacility = (int)(size_t)keywd->desc;
|
||||
}
|
||||
}
|
||||
openlog(diagopts.progname, LOG_PID, diagopts.logfacility);
|
||||
if (diagopts.logfile != NULL && diagopts.logfile != stderr) {
|
||||
fclose(diagopts.logfile);
|
||||
}
|
||||
diagopts.logfile = NULL;
|
||||
break;
|
||||
case 'f':
|
||||
if (diagopts.logfile != NULL && diagopts.logfile != stderr) {
|
||||
fclose(diagopts.logfile);
|
||||
}
|
||||
if ((diagopts.logfile = fopen(arg, "a")) == NULL) {
|
||||
Error2("cannot open log file \"%s\": %s", arg, strerror(errno));
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (diagopts.logfile != NULL && diagopts.logfile != stderr) {
|
||||
fclose(diagopts.logfile);
|
||||
}
|
||||
diagopts.logfile = stderr; break; /* logging to stderr is default */
|
||||
case 'p': diagopts.progname = arg;
|
||||
openlog(diagopts.progname, LOG_PID, diagopts.logfacility);
|
||||
break;
|
||||
case 'u': diagopts.micros = true; break;
|
||||
default: msg(E_ERROR, "unknown diagnostic option %c", what);
|
||||
}
|
||||
}
|
||||
|
||||
void diag_set_int(char what, int arg) {
|
||||
DIAG_INIT;
|
||||
switch (what) {
|
||||
case 'D': diagopts.msglevel = arg; break;
|
||||
case 'e': diagopts.exitlevel = arg; break;
|
||||
case 'x': diagopts.exitstatus = arg; break;
|
||||
case 'd':
|
||||
diagopts.msglevel = arg;
|
||||
break;
|
||||
case 'h': diagopts.withhostname = arg;
|
||||
if ((diagopts.hostname = getenv("HOSTNAME")) == NULL) {
|
||||
struct utsname ubuf;
|
||||
uname(&ubuf);
|
||||
diagopts.hostname = strdup(ubuf.nodename);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
diagopts.shutup = arg;
|
||||
diagopts.exitlevel -= arg;
|
||||
break;
|
||||
default: msg(E_ERROR, "unknown diagnostic option %c", what);
|
||||
}
|
||||
}
|
||||
|
||||
int diag_get_int(char what) {
|
||||
DIAG_INIT;
|
||||
switch (what) {
|
||||
case 'y': return diagopts.syslog;
|
||||
case 's': return diagopts.logfile == stderr;
|
||||
case 'd': case 'D': return diagopts.msglevel;
|
||||
case 'e': return diagopts.exitlevel;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *diag_get_string(char what) {
|
||||
DIAG_INIT;
|
||||
switch (what) {
|
||||
case 'p': return diagopts.progname;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* make sure that the diag_sock fds do not have this num */
|
||||
int diag_reserve_fd(int fd) {
|
||||
DIAG_INIT;
|
||||
if (diag_sock_send == fd) {
|
||||
diag_sock_send = Dup(fd);
|
||||
Close(fd);
|
||||
}
|
||||
if (diag_sock_recv == fd) {
|
||||
diag_sock_recv = Dup(fd);
|
||||
Close(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call this after a fork() from the child process to separate master/parent
|
||||
sockets from child sockets */
|
||||
int diag_fork() {
|
||||
Close(diag_sock_send);
|
||||
Close(diag_sock_recv);
|
||||
if (diagopts.signalsafe) {
|
||||
return diag_sock_pair();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Linux and AIX syslog format:
|
||||
Oct 4 17:10:37 hostname socat[52798]: D signal(13, 1)
|
||||
*/
|
||||
void msg(int level, const char *format, ...) {
|
||||
struct diag_dgram diag_dgram;
|
||||
va_list ap;
|
||||
|
||||
/* does not perform a system call if nothing todo, thanks diag_msg_avail */
|
||||
|
||||
diag_dgram._errno = errno; /* keep for passing from signal handler to sock.
|
||||
reason is that strerror is definitely not
|
||||
async-signal-safe */
|
||||
DIAG_INIT;
|
||||
|
||||
/* in normal program flow (not in signal handler) */
|
||||
/* first flush the queue of datagrams from the socket */
|
||||
if (diag_msg_avail && !diag_in_handler) {
|
||||
diag_flush();
|
||||
}
|
||||
|
||||
level -= diagopts.shutup; /* decrease severity of messages? */
|
||||
|
||||
/* Just ignore this call when level too low for both logging and exiting */
|
||||
if (level < diagopts.msglevel && level < diagopts.exitlevel)
|
||||
return;
|
||||
|
||||
va_start(ap, format);
|
||||
|
||||
/* we do only a minimum in the outer parts which may run in a signal handler
|
||||
these are: get actual time, level, serialized message and write them to socket
|
||||
*/
|
||||
diag_dgram.op = DIAG_OP_MSG;
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
clock_gettime(CLOCK_REALTIME, &diag_dgram.now);
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
gettimeofday(&diag_dgram.now, NULL);
|
||||
#else
|
||||
diag_dgram.now = time(NULL);
|
||||
#endif
|
||||
diag_dgram.level = level;
|
||||
diag_dgram.exitcode = diagopts.exitstatus;
|
||||
if (level >= diagopts.msglevel)
|
||||
vsnprintf_r(diag_dgram.text, sizeof(diag_dgram.text), format, ap);
|
||||
else
|
||||
diag_dgram.text[0] = '\0';
|
||||
if (diagopts.signalsafe && diag_in_handler && !diag_immediate_msg) {
|
||||
send(diag_sock_send, &diag_dgram, sizeof(diag_dgram)-TEXTLEN + strlen(diag_dgram.text)+1,
|
||||
0 /* for canonical reasons */
|
||||
#ifdef MSG_DONTWAIT
|
||||
|MSG_DONTWAIT
|
||||
#endif
|
||||
#ifdef MSG_NOSIGNAL
|
||||
|MSG_NOSIGNAL
|
||||
#endif
|
||||
);
|
||||
diag_msg_avail = 1;
|
||||
va_end(ap);
|
||||
return;
|
||||
}
|
||||
|
||||
msg2(&diag_dgram.now, diag_dgram.level, diagopts.exitstatus, 0, diag_dgram.text);
|
||||
va_end(ap); return;
|
||||
}
|
||||
|
||||
void msg2(
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
struct timespec *now,
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
struct timeval *now,
|
||||
#else
|
||||
time_t *now,
|
||||
#endif
|
||||
int level, /* E_INFO... */
|
||||
int exitcode, /* on exit use this exit code */
|
||||
int handler, /* message comes from signal handler */
|
||||
const char *text) {
|
||||
time_t epoch;
|
||||
unsigned long micros;
|
||||
#if HAVE_STRFTIME
|
||||
struct tm struct_tm;
|
||||
#endif
|
||||
#define MSGLEN 512
|
||||
char buff[MSGLEN+2], *bufp = buff, *syslp = NULL;
|
||||
size_t bytes;
|
||||
|
||||
if (text[0] != '\0') {
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
epoch = now->tv_sec;
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
epoch = now->tv_sec;
|
||||
#else
|
||||
epoch = *now;
|
||||
#endif
|
||||
/*! consider caching instead of recalculating many times per second */
|
||||
#if HAVE_STRFTIME
|
||||
bytes = strftime(bufp, 20, "%Y/%m/%d %H:%M:%S", localtime_r(&epoch, &struct_tm));
|
||||
#else
|
||||
bytes = snprintf(bufp, 11, F_time, epoch);
|
||||
#endif
|
||||
bufp += bytes;
|
||||
*bufp = '\0';
|
||||
if (diagopts.micros) {
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
micros = now->tv_nsec/1000;
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
micros = now->tv_usec;
|
||||
#else
|
||||
micros = 0;
|
||||
#endif
|
||||
bufp += sprintf(bufp, ".%06lu ", micros);
|
||||
} else {
|
||||
*bufp++ = ' ';
|
||||
*bufp = '\0';
|
||||
}
|
||||
|
||||
if (diagopts.withhostname) {
|
||||
bytes = snprintf(bufp, MSGLEN-(bufp-buff), "%s ", diagopts.hostname);
|
||||
if (bytes >= MSGLEN-(bufp-buff))
|
||||
bytes = MSGLEN-(bufp-buff)-1;
|
||||
bufp += bytes;
|
||||
}
|
||||
bytes = snprintf(bufp, MSGLEN-(bufp-buff), "%s["F_pid"] ", diagopts.progname, getpid());
|
||||
if (bytes >= MSGLEN-(bufp-buff))
|
||||
bytes = MSGLEN-(bufp-buff)-1;
|
||||
bufp += bytes;
|
||||
syslp = bufp; /* syslog prefixes with time etc.itself */
|
||||
if (bufp < buff+MSGLEN)
|
||||
*bufp++ = "DINWEF"[level];
|
||||
#if 0 /* only for debugging socat */
|
||||
if (handler) bufp[-1] = tolower((unsigned char)bufp[-1]); /* for debugging, low chars indicate messages from signal handlers */
|
||||
#endif
|
||||
if (bufp < buff+MSGLEN)
|
||||
*bufp++ = ' ';
|
||||
strncpy(bufp, text, MSGLEN-(bufp-buff));
|
||||
bufp = strchr(bufp, '\0');
|
||||
strcpy(bufp, "\n");
|
||||
_msg(level, buff, syslp);
|
||||
}
|
||||
if (level >= diagopts.exitlevel) {
|
||||
if (E_NOTICE >= diagopts.msglevel && text[0] != '\0') {
|
||||
if ((syslp - buff) + 16 > MSGLEN+1)
|
||||
syslp = buff + MSGLEN - 15;
|
||||
snprintf_r(syslp, 16, "N exit(%d)\n", exitcode?exitcode:(diagopts.exitstatus?diagopts.exitstatus:1));
|
||||
_msg(E_NOTICE, buff, syslp);
|
||||
}
|
||||
exit(exitcode?exitcode:(diagopts.exitstatus?diagopts.exitstatus:1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _msg(int level, const char *buff, const char *syslp) {
|
||||
if (diagopts.syslog) {
|
||||
/* prevent format string attacks (thanks to CoKi) */
|
||||
syslog(syslevel[level], "%s", syslp);
|
||||
}
|
||||
if (diagopts.logfile) {
|
||||
fputs(buff, diagopts.logfile); fflush(diagopts.logfile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* handle the messages in the queue */
|
||||
void diag_flush(void) {
|
||||
struct diag_dgram recv_dgram;
|
||||
char exitmsg[20];
|
||||
|
||||
if (diag_msg_avail == 0) {
|
||||
return;
|
||||
}
|
||||
diag_msg_avail = 0;
|
||||
|
||||
if (!diagopts.signalsafe) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (recv(diag_sock_recv, &recv_dgram, sizeof(recv_dgram)-1,
|
||||
0 /* for canonical reasons */
|
||||
#ifdef MSG_DONTWAIT
|
||||
|MSG_DONTWAIT
|
||||
#endif
|
||||
) > 0) {
|
||||
recv_dgram.text[TEXTLEN-1] = '\0';
|
||||
switch (recv_dgram.op) {
|
||||
case DIAG_OP_EXIT:
|
||||
/* we want the actual time, not when this dgram was sent */
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
clock_gettime(CLOCK_REALTIME, &recv_dgram.now);
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
gettimeofday(&recv_dgram.now, NULL);
|
||||
#else
|
||||
recv_dgram.now = time(NULL);
|
||||
#endif
|
||||
if (E_NOTICE >= diagopts.msglevel) {
|
||||
snprintf_r(exitmsg, sizeof(exitmsg), "exit(%d)", recv_dgram.exitcode?recv_dgram.exitcode:1);
|
||||
msg2(&recv_dgram.now, E_NOTICE, recv_dgram.exitcode?recv_dgram.exitcode:1, 1, exitmsg);
|
||||
}
|
||||
exit(recv_dgram.exitcode?recv_dgram.exitcode:1);
|
||||
case DIAG_OP_MSG:
|
||||
if (recv_dgram._errno) {
|
||||
/* there might be a %m control in the string (glibc compatible,
|
||||
replace with strerror(...errno) ) */
|
||||
char text[TEXTLEN];
|
||||
errno = recv_dgram._errno;
|
||||
snprinterr(text, TEXTLEN, recv_dgram.text);
|
||||
msg2(&recv_dgram.now, recv_dgram.level, recv_dgram.exitcode, 1, text);
|
||||
} else {
|
||||
msg2(&recv_dgram.now, recv_dgram.level, recv_dgram.exitcode, 1, recv_dgram.text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* use a new log output file descriptor that is dup'ed from the current one.
|
||||
this is useful when socat logs to stderr but fd 2 should be redirected to
|
||||
serve other purposes */
|
||||
int diag_dup(void) {
|
||||
int newfd;
|
||||
|
||||
DIAG_INIT;
|
||||
if (diagopts.logfile == NULL) {
|
||||
return -1;
|
||||
}
|
||||
newfd = dup(fileno(diagopts.logfile));
|
||||
Fcntl_l(newfd, F_SETFD, FD_CLOEXEC);
|
||||
if (diagopts.logfile != stderr) {
|
||||
fclose(diagopts.logfile);
|
||||
}
|
||||
if (newfd >= 0) {
|
||||
diagopts.logfile = fdopen(newfd, "w");
|
||||
}
|
||||
return newfd;
|
||||
}
|
||||
|
||||
|
||||
/* this function is kind of async-signal-safe exit(). When invoked from signal
|
||||
handler it defers exit. */
|
||||
void diag_exit(int status) {
|
||||
struct diag_dgram diag_dgram;
|
||||
|
||||
if (diag_in_handler && !diag_immediate_exit) {
|
||||
diag_dgram.op = DIAG_OP_EXIT;
|
||||
diag_dgram.exitcode = status;
|
||||
send(diag_sock_send, &diag_dgram, sizeof(diag_dgram)-TEXTLEN,
|
||||
0 /* for canonical reasons */
|
||||
#ifdef MSG_DONTWAIT
|
||||
|MSG_DONTWAIT
|
||||
#endif
|
||||
#ifdef MSG_NOSIGNAL
|
||||
|MSG_NOSIGNAL
|
||||
#endif
|
||||
);
|
||||
diag_msg_avail = 1;
|
||||
return;
|
||||
}
|
||||
_diag_exit(status);
|
||||
}
|
||||
|
||||
static void _diag_exit(int status) {
|
||||
Exit(status);
|
||||
}
|
||||
|
||||
|
||||
/* a function that appears to the application like select() but that also
|
||||
monitors the diag socket diag_sock_recv and processes its messages.
|
||||
Do not call from within a signal handler. */
|
||||
int diag_select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
fd_set *exceptfds, struct timeval *timeout) {
|
||||
int result;
|
||||
fd_set save_readfds, save_writefds, save_exceptfds;
|
||||
|
||||
if (readfds) { memcpy(&save_readfds, readfds, sizeof(*readfds)); }
|
||||
if (writefds) { memcpy(&save_writefds, writefds, sizeof(*writefds)); }
|
||||
if (exceptfds) { memcpy(&save_exceptfds, exceptfds, sizeof(*exceptfds)); }
|
||||
|
||||
while (1) {
|
||||
FD_SET(diag_sock_recv, readfds);
|
||||
result = Select(nfds, readfds, writefds,
|
||||
exceptfds, timeout);
|
||||
if (!FD_ISSET(diag_sock_recv, readfds)) {
|
||||
/* select terminated not due to diag_sock_recv, normalt continuation */
|
||||
break;
|
||||
}
|
||||
diag_flush();
|
||||
if (readfds) { memcpy(readfds, &save_readfds, sizeof(*readfds)); }
|
||||
if (writefds) { memcpy(writefds, &save_writefds, sizeof(*writefds)); }
|
||||
if (exceptfds) { memcpy(exceptfds, &save_exceptfds, sizeof(*exceptfds)); }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
249
error.h
Normal file
249
error.h
Normal file
@@ -0,0 +1,249 @@
|
||||
/* source: error.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __error_h_included
|
||||
#define __error_h_included 1
|
||||
|
||||
/* these must be defines because they are used by cpp! */
|
||||
#define E_DEBUG 0 /* all, including trace */
|
||||
#define E_INFO 1 /* all status changes etc. */
|
||||
#define E_NOTICE 2 /* all interesting, e.g. for firewall relay */
|
||||
#define E_WARN 3 /* all unusual */
|
||||
#define E_ERROR 4 /* errors */
|
||||
#define E_FATAL 5 /* emergency abort */
|
||||
|
||||
#define F_strerror "%m" /* a pseudo format, replaced by strerror(errno) */
|
||||
|
||||
/* here are the macros for diag invocation; use WITH_MSGLEVEL to specify the
|
||||
lowest priority that is compiled into your program */
|
||||
#ifndef WITH_MSGLEVEL
|
||||
# define WITH_MSGLEVEL E_NOTICE
|
||||
#endif
|
||||
|
||||
#if WITH_MSGLEVEL <= E_FATAL
|
||||
#define Fatal(m) msg(E_FATAL,"%s",m)
|
||||
#define Fatal1(m,a1) msg(E_FATAL,m,a1)
|
||||
#define Fatal2(m,a1,a2) msg(E_FATAL,m,a1,a2)
|
||||
#define Fatal3(m,a1,a2,a3) msg(E_FATAL,m,a1,a2,a3)
|
||||
#define Fatal4(m,a1,a2,a3,a4) msg(E_FATAL,m,a1,a2,a3,a4)
|
||||
#define Fatal5(m,a1,a2,a3,a4,a5) msg(E_FATAL,m,a1,a2,a3,a4,a5)
|
||||
#define Fatal6(m,a1,a2,a3,a4,a5,a6) msg(E_FATAL,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Fatal7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_FATAL,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#else /* !(WITH_MSGLEVEL <= E_FATAL) */
|
||||
#define Fatal(m)
|
||||
#define Fatal1(m,a1)
|
||||
#define Fatal2(m,a1,a2)
|
||||
#define Fatal3(m,a1,a2,a3)
|
||||
#define Fatal4(m,a1,a2,a3,a4)
|
||||
#define Fatal5(m,a1,a2,a3,a4,a5)
|
||||
#define Fatal6(m,a1,a2,a3,a4,a5,a6)
|
||||
#define Fatal7(m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_FATAL) */
|
||||
|
||||
#if WITH_MSGLEVEL <= E_ERROR
|
||||
#define Error(m) msg(E_ERROR,"%s",m)
|
||||
#define Error1(m,a1) msg(E_ERROR,m,a1)
|
||||
#define Error2(m,a1,a2) msg(E_ERROR,m,a1,a2)
|
||||
#define Error3(m,a1,a2,a3) msg(E_ERROR,m,a1,a2,a3)
|
||||
#define Error4(m,a1,a2,a3,a4) msg(E_ERROR,m,a1,a2,a3,a4)
|
||||
#define Error5(m,a1,a2,a3,a4,a5) msg(E_ERROR,m,a1,a2,a3,a4,a5)
|
||||
#define Error6(m,a1,a2,a3,a4,a5,a6) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Error7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Error8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Error9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#define Error10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
#define Error11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) msg(E_ERROR,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
|
||||
#else /* !(WITH_MSGLEVEL >= E_ERROR) */
|
||||
#define Error(m)
|
||||
#define Error1(m,a1)
|
||||
#define Error2(m,a1,a2)
|
||||
#define Error3(m,a1,a2,a3)
|
||||
#define Error4(m,a1,a2,a3,a4)
|
||||
#define Error5(m,a1,a2,a3,a4,a5)
|
||||
#define Error6(m,a1,a2,a3,a4,a5,a6)
|
||||
#define Error7(m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Error8(m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Error9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#define Error10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
#define Error11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_ERROR) */
|
||||
|
||||
#if WITH_MSGLEVEL <= E_WARN
|
||||
#define Warn(m) msg(E_WARN,"%s",m)
|
||||
#define Warn1(m,a1) msg(E_WARN,m,a1)
|
||||
#define Warn2(m,a1,a2) msg(E_WARN,m,a1,a2)
|
||||
#define Warn3(m,a1,a2,a3) msg(E_WARN,m,a1,a2,a3)
|
||||
#define Warn4(m,a1,a2,a3,a4) msg(E_WARN,m,a1,a2,a3,a4)
|
||||
#define Warn5(m,a1,a2,a3,a4,a5) msg(E_WARN,m,a1,a2,a3,a4,a5)
|
||||
#define Warn6(m,a1,a2,a3,a4,a5,a6) msg(E_WARN,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Warn7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_WARN,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#else /* !(WITH_MSGLEVEL <= E_WARN) */
|
||||
#define Warn(m)
|
||||
#define Warn1(m,a1)
|
||||
#define Warn2(m,a1,a2)
|
||||
#define Warn3(m,a1,a2,a3)
|
||||
#define Warn4(m,a1,a2,a3,a4)
|
||||
#define Warn5(m,a1,a2,a3,a4,a5)
|
||||
#define Warn6(m,a1,a2,a3,a4,a5,a6)
|
||||
#define Warn7(m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_WARN) */
|
||||
|
||||
#if WITH_MSGLEVEL <= E_NOTICE
|
||||
#define Notice(m) msg(E_NOTICE,"%s",m)
|
||||
#define Notice1(m,a1) msg(E_NOTICE,m,a1)
|
||||
#define Notice2(m,a1,a2) msg(E_NOTICE,m,a1,a2)
|
||||
#define Notice3(m,a1,a2,a3) msg(E_NOTICE,m,a1,a2,a3)
|
||||
#define Notice4(m,a1,a2,a3,a4) msg(E_NOTICE,m,a1,a2,a3,a4)
|
||||
#define Notice5(m,a1,a2,a3,a4,a5) msg(E_NOTICE,m,a1,a2,a3,a4,a5)
|
||||
#define Notice6(m,a1,a2,a3,a4,a5,a6) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Notice7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Notice8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Notice9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_NOTICE,m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#else /* !(WITH_MSGLEVEL <= E_NOTICE) */
|
||||
#define Notice(m)
|
||||
#define Notice1(m,a1)
|
||||
#define Notice2(m,a1,a2)
|
||||
#define Notice3(m,a1,a2,a3)
|
||||
#define Notice4(m,a1,a2,a3,a4)
|
||||
#define Notice5(m,a1,a2,a3,a4,a5)
|
||||
#define Notice6(m,a1,a2,a3,a4,a5,a6)
|
||||
#define Notice7(m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Notice8(m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Notice9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_NOTICE) */
|
||||
|
||||
#if WITH_MSGLEVEL <= E_INFO
|
||||
#define Info(m) msg(E_INFO,"%s",m)
|
||||
#define Info1(m,a1) msg(E_INFO,m,a1)
|
||||
#define Info2(m,a1,a2) msg(E_INFO,m,a1,a2)
|
||||
#define Info3(m,a1,a2,a3) msg(E_INFO,m,a1,a2,a3)
|
||||
#define Info4(m,a1,a2,a3,a4) msg(E_INFO,m,a1,a2,a3,a4)
|
||||
#define Info5(m,a1,a2,a3,a4,a5) msg(E_INFO,m,a1,a2,a3,a4,a5)
|
||||
#define Info6(m,a1,a2,a3,a4,a5,a6) msg(E_INFO,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Info7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Info8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Info9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#define Info10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
#define Info11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) msg(E_INFO,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
|
||||
#else /* !(WITH_MSGLEVEL <= E_INFO) */
|
||||
#define Info(m)
|
||||
#define Info1(m,a1)
|
||||
#define Info2(m,a1,a2)
|
||||
#define Info3(m,a1,a2,a3)
|
||||
#define Info4(m,a1,a2,a3,a4)
|
||||
#define Info5(m,a1,a2,a3,a4,a5)
|
||||
#define Info6(m,a1,a2,a3,a4,a5,a6)
|
||||
#define Info7(m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Info8(m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Info9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#define Info10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
#define Info11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_INFO) */
|
||||
|
||||
#if WITH_MSGLEVEL <= E_DEBUG
|
||||
#define Debug(m) msg(E_DEBUG,"%s",m)
|
||||
#define Debug1(m,a1) msg(E_DEBUG,m,a1)
|
||||
#define Debug2(m,a1,a2) msg(E_DEBUG,m,a1,a2)
|
||||
#define Debug3(m,a1,a2,a3) msg(E_DEBUG,m,a1,a2,a3)
|
||||
#define Debug4(m,a1,a2,a3,a4) msg(E_DEBUG,m,a1,a2,a3,a4)
|
||||
#define Debug5(m,a1,a2,a3,a4,a5) msg(E_DEBUG,m,a1,a2,a3,a4,a5)
|
||||
#define Debug6(m,a1,a2,a3,a4,a5,a6) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Debug7(m,a1,a2,a3,a4,a5,a6,a7) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Debug8(m,a1,a2,a3,a4,a5,a6,a7,a8) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Debug9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#define Debug10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
#define Debug11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
|
||||
#define Debug12(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
|
||||
#define Debug13(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)
|
||||
#define Debug14(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)
|
||||
#define Debug15(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
|
||||
#define Debug16(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)
|
||||
#define Debug17(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17)
|
||||
#define Debug18(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18) msg(E_DEBUG,m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18)
|
||||
#else /* !(WITH_MSGLEVEL <= E_DEBUG) */
|
||||
#define Debug(m)
|
||||
#define Debug1(m,a1)
|
||||
#define Debug2(m,a1,a2)
|
||||
#define Debug3(m,a1,a2,a3)
|
||||
#define Debug4(m,a1,a2,a3,a4)
|
||||
#define Debug5(m,a1,a2,a3,a4,a5)
|
||||
#define Debug6(m,a1,a2,a3,a4,a5,a6)
|
||||
#define Debug7(m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#define Debug8(m,a1,a2,a3,a4,a5,a6,a7,a8)
|
||||
#define Debug9(m,a1,a2,a3,a4,a5,a6,a7,a8,a9)
|
||||
#define Debug10(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
|
||||
#define Debug11(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)
|
||||
#define Debug12(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)
|
||||
#define Debug13(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13)
|
||||
#define Debug14(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14)
|
||||
#define Debug15(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)
|
||||
#define Debug16(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16)
|
||||
#define Debug17(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17)
|
||||
#define Debug18(m,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_DEBUG) */
|
||||
|
||||
/* message with software controlled serverity */
|
||||
#if WITH_MSGLEVEL <= E_FATAL
|
||||
#define Msg(l,m) msg(l,"%s",m)
|
||||
#define Msg1(l,m,a1) msg(l,m,a1)
|
||||
#define Msg2(l,m,a1,a2) msg(l,m,a1,a2)
|
||||
#define Msg3(l,m,a1,a2,a3) msg(l,m,a1,a2,a3)
|
||||
#define Msg4(l,m,a1,a2,a3,a4) msg(l,m,a1,a2,a3,a4)
|
||||
#define Msg5(l,m,a1,a2,a3,a4,a5) msg(l,m,a1,a2,a3,a4,a5)
|
||||
#define Msg6(l,m,a1,a2,a3,a4,a5,a6) msg(l,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Msg7(l,m,a1,a2,a3,a4,a5,a6,a7) msg(l,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#else /* !(WITH_MSGLEVEL >= E_FATAL) */
|
||||
#define Msg(l,m)
|
||||
#define Msg1(l,m,a1)
|
||||
#define Msg2(l,m,a1,a2)
|
||||
#define Msg3(l,m,a1,a2,a3)
|
||||
#define Msg4(l,m,a1,a2,a3,a4)
|
||||
#define Msg5(l,m,a1,a2,a3,a4,a5)
|
||||
#define Msg6(l,m,a1,a2,a3,a4,a5,a6)
|
||||
#define Msg7(l,m,a1,a2,a3,a4,a5,a6,a7)
|
||||
#endif /* !(WITH_MSGLEVEL <= E_FATAL) */
|
||||
|
||||
|
||||
enum diag_op {
|
||||
DIAG_OP_MSG, /* a diagnostic message */
|
||||
DIAG_OP_EXIT, /* exit the program */
|
||||
} ;
|
||||
|
||||
/* datagram for communication between outer msg() call from signal handler to
|
||||
inner msg() call in normal flow */
|
||||
# define TEXTLEN 480
|
||||
struct diag_dgram {
|
||||
enum diag_op op;
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
struct timespec now;
|
||||
#elif HAVE_PROTOTYPE_LIB_gettimeofday
|
||||
struct timeval now;
|
||||
#else
|
||||
time_t now;
|
||||
#endif
|
||||
int level; /* E_FATAL, ... E_DEBUG */
|
||||
int _errno; /* for glibc %m format */
|
||||
int exitcode; /* if exiting take this num */
|
||||
char text[TEXTLEN];
|
||||
} ;
|
||||
|
||||
extern volatile sig_atomic_t diag_in_handler;
|
||||
extern volatile sig_atomic_t diag_immediate_msg;
|
||||
extern volatile sig_atomic_t diag_immediate_exit;
|
||||
|
||||
extern void diag_set(char what, const char *arg);
|
||||
extern void diag_set_int(char what, int arg);
|
||||
extern int diag_get_int(char what);
|
||||
extern const char *diag_get_string(char what);
|
||||
extern int diag_reserve_fd(int fd);
|
||||
extern int diag_fork(void);
|
||||
extern int diag_dup(void);
|
||||
extern int diag_dup2(int newfd);
|
||||
extern void msg(int level, const char *format, ...);
|
||||
extern void diag_flush(void);
|
||||
extern void diag_exit(int status);
|
||||
extern int diag_select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||
fd_set *exceptfds, struct timeval *timeout);
|
||||
|
||||
#endif /* !defined(__error_h_included) */
|
||||
516
fdname.c
Normal file
516
fdname.c
Normal file
@@ -0,0 +1,516 @@
|
||||
/* source: fdname.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* the subroutine sockname prints the basic info about the address of a socket
|
||||
NOTE: it works on UNIX (kernel) file descriptors, not on libc files! */
|
||||
|
||||
#include "config.h"
|
||||
#include "xioconfig.h" /* what features are enabled */
|
||||
|
||||
#include "sysincludes.h"
|
||||
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "error.h"
|
||||
#include "sycls.h"
|
||||
#include "sysutils.h"
|
||||
|
||||
#include "filan.h"
|
||||
|
||||
|
||||
struct sockopt {
|
||||
int so;
|
||||
char *name;
|
||||
};
|
||||
|
||||
|
||||
int statname(const char *file, int fd, int filetype, FILE *outfile, char style);
|
||||
int cdevname(int fd, FILE *outfile);
|
||||
int sockname(int fd, FILE *outfile, char style);
|
||||
int unixame(int fd, FILE *outfile);
|
||||
int tcpname(int fd, FILE *outfile);
|
||||
|
||||
|
||||
int fdname(const char *file, int fd, FILE *outfile, const char *numform,
|
||||
char style) {
|
||||
struct stat buf = {0};
|
||||
int filetype;
|
||||
Debug1("checking file descriptor %u", fd);
|
||||
if (fd >= 0) {
|
||||
if (Fstat(fd, &buf) < 0) {
|
||||
if (errno == EBADF) {
|
||||
Debug2("fstat(%d): %s", fd, strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
Error2("fstat(%d): %s", fd, strerror(errno));
|
||||
}
|
||||
}
|
||||
filetype = (buf.st_mode&S_IFMT)>>12;
|
||||
if (numform != NULL) {
|
||||
fprintf(outfile, numform, fd);
|
||||
}
|
||||
return statname(file, fd, filetype, outfile, style);
|
||||
} else {
|
||||
if (Stat(file, &buf) < 0) {
|
||||
Error2("stat(\"%s\"): %s", file, strerror(errno));
|
||||
}
|
||||
filetype = (buf.st_mode&S_IFMT)>>12;
|
||||
return statname(file, -1, filetype, outfile, style);
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH
|
||||
static int procgetfdname(int fd, char *filepath, size_t pathsize) {
|
||||
static pid_t pid = -1;
|
||||
char procpath[PATH_MAX];
|
||||
int len;
|
||||
|
||||
/* even if configure has shown that we have /proc, we must check if it
|
||||
exists at runtime, because we might be in a chroot environment */
|
||||
#if HAVE_STAT64
|
||||
{
|
||||
struct stat64 buf;
|
||||
if (Stat64("/proc", &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(buf.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else /* !HAVE_STAT64 */
|
||||
{
|
||||
struct stat buf;
|
||||
if (Stat("/proc", &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(buf.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_STAT64 */
|
||||
|
||||
if (pid < 0) pid = Getpid();
|
||||
snprintf(procpath, sizeof(procpath), "/proc/"F_pid"/"
|
||||
#if HAVE_PROC_DIR_PATH
|
||||
"path"
|
||||
#else
|
||||
"fd"
|
||||
#endif
|
||||
"/%d", pid, fd);
|
||||
if ((len = Readlink(procpath, filepath, pathsize-1)) < 0) {
|
||||
Notice4("readlink(\"%s\", %p, "F_Zu"): %s",
|
||||
procpath, filepath, pathsize, strerror(errno));
|
||||
len = 0;
|
||||
}
|
||||
filepath[len] = '\0';
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH */
|
||||
|
||||
int statname(const char *file, int fd, int filetype, FILE *outfile,
|
||||
char style) {
|
||||
char filepath[PATH_MAX];
|
||||
|
||||
filepath[0] = '\0';
|
||||
#if HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH
|
||||
if (fd >= 0) {
|
||||
procgetfdname(fd, filepath, sizeof(filepath));
|
||||
if (filepath[0] == '/') {
|
||||
file = filepath;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_PROC_DIR_FD || HAVE_PROC_DIR_PATH */
|
||||
/* now see for type specific infos */
|
||||
switch (filetype) {
|
||||
case (S_IFIFO>>12): /* 1, FIFO */
|
||||
fputs("pipe", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFCHR>>12): /* 2, character device */
|
||||
if (cdevname(fd, outfile) == 0) {
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
}
|
||||
break;
|
||||
case (S_IFDIR>>12): /* 4, directory */
|
||||
fputs("dir", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFBLK>>12): /* 6, block device */
|
||||
fputs("blkdev", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFREG>>12): /* 8, regular file */
|
||||
fputs("file", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFLNK>>12): /* 10, symbolic link */
|
||||
fputs("link", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
case (S_IFSOCK>>12): /* 12, socket */
|
||||
#if _WITH_SOCKET
|
||||
if (fd >= 0) {
|
||||
sockname(fd, outfile, style);
|
||||
} else if (file) {
|
||||
fprintf(outfile, "socket %s", file);
|
||||
} else {
|
||||
fputs("socket", outfile);
|
||||
}
|
||||
#else
|
||||
Error("SOCKET support not compiled in");
|
||||
return -1;
|
||||
#endif /* !_WITH_SOCKET */
|
||||
break;
|
||||
#ifdef S_IFDOOR
|
||||
case (S_IFDOOR>>12): /* 13, door (Solaris) */
|
||||
fputs("door", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
#endif /* HAVE_MACRO_S_IFDOOR */
|
||||
#ifdef S_IFPORT
|
||||
case (S_IFPORT>>12): /* 14, event port (Solaris) */
|
||||
fputs("event_port", outfile);
|
||||
if (file) fprintf(outfile, " %s", file);
|
||||
break;
|
||||
#endif /* HAVE_MACRO_S_IFPORT */
|
||||
}
|
||||
/* ioctl() */
|
||||
fputc('\n', outfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* character device analysis */
|
||||
/* return -1 on error, 0 if no name was found, or 1 if it printed ttyname */
|
||||
int cdevname(int fd, FILE *outfile) {
|
||||
int ret;
|
||||
|
||||
if ((ret = Isatty(fd)) < 0) {
|
||||
Error2("isatty(%d): %s", fd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (ret > 0) {
|
||||
char *name;
|
||||
|
||||
fputs("tty", outfile);
|
||||
if ((name = Ttyname(fd)) != NULL) {
|
||||
fputc(' ', outfile);
|
||||
fputs(name, outfile);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fputs("chrdev", outfile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sockettype(int socktype, char *typename, size_t typenamemax) {
|
||||
switch (socktype) {
|
||||
case SOCK_STREAM: strncpy(typename, "stream", typenamemax); break;
|
||||
case SOCK_DGRAM: strncpy(typename, "dgram", typenamemax); break;
|
||||
case SOCK_SEQPACKET: strncpy(typename, "seqpacket", typenamemax); break;
|
||||
case SOCK_RAW: strncpy(typename, "raw", typenamemax); break;
|
||||
case SOCK_RDM: strncpy(typename, "rdm", typenamemax); break;
|
||||
#ifdef SOCK_PACKET
|
||||
case SOCK_PACKET: strncpy(typename, "packet", typenamemax); break;
|
||||
#endif
|
||||
default: snprintf(typename, typenamemax, "socktype%u", socktype); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _WITH_SOCKET
|
||||
int sockname(int fd, FILE *outfile, char style) {
|
||||
#define FDNAME_OPTLEN 256
|
||||
#define FDNAME_NAMELEN 256
|
||||
socklen_t optlen;
|
||||
#if HAVE_GETPROTOBYNUMBER || HAVE_GETPROTOBYNUMBER_R
|
||||
struct protoent protoent, *protoentp;
|
||||
#endif
|
||||
#define PROTONAMEMAX 1024
|
||||
char protoname[PROTONAMEMAX] = "";
|
||||
#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
|
||||
int proto = 0;
|
||||
#endif
|
||||
int opttype;
|
||||
#ifdef SO_ACCEPTCONN
|
||||
int optacceptconn = 0; /* OpenBSD does not give value on unix dgram */
|
||||
#endif
|
||||
int result /*0, i*/;
|
||||
char socknamebuff[FDNAME_NAMELEN];
|
||||
char peernamebuff[FDNAME_NAMELEN];
|
||||
/* in Linux these optcodes are 'enum', but on AIX they are bits! */
|
||||
union sockaddr_union sockname, peername; /* the longest I know of */
|
||||
socklen_t socknamelen, peernamelen;
|
||||
# define TYPENAMEMAX 16
|
||||
char typename[TYPENAMEMAX];
|
||||
#if 0 && defined(SIOCGIFNAME)
|
||||
/*Linux struct ifreq ifc = {{{ 0 }}};*/
|
||||
struct ifreq ifc = {{ 0 }};
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
|
||||
optlen = sizeof(proto);
|
||||
#ifdef SO_PROTOCOL
|
||||
rc = Getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &proto, &optlen);
|
||||
#elif defined(SO_PROTOTYPE)
|
||||
rc = Getsockopt(fd, SOL_SOCKET, SO_PROTOTYPE, &proto, &optlen);
|
||||
#endif
|
||||
if (rc < 0) {
|
||||
Notice5("getsocktop(%d, SOL_SOCKET, "
|
||||
#ifdef SO_PROTOCOL
|
||||
"SO_PROTOCOL"
|
||||
#else
|
||||
"SO_PROTOTYPE"
|
||||
#endif
|
||||
", &%p, {"F_socklen"}): errno=%d (%s)", fd, &proto, optlen, errno, strerror(errno));
|
||||
}
|
||||
#endif /* defined(SO_PROTOCOL) || defined(SO_PROTOTYPE) */
|
||||
optlen = sizeof(opttype);
|
||||
Getsockopt(fd, SOL_SOCKET, SO_TYPE, &opttype, &optlen);
|
||||
sockettype(opttype, typename, sizeof(typename));
|
||||
|
||||
optlen = sizeof(optacceptconn);
|
||||
#ifdef SO_ACCEPTCONN
|
||||
Getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &optacceptconn, &optlen);
|
||||
#endif
|
||||
|
||||
#if defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)
|
||||
#if HAVE_GETPROTOBYNUMBER_R==1 /* Linux */
|
||||
rc = getprotobynumber_r(proto, &protoent, protoname, sizeof(protoname), &protoentp);
|
||||
if (protoentp == NULL) {
|
||||
Warn2("sockname(): getprotobynumber_r(proto=%d, ...): %s",
|
||||
proto, strerror(rc));
|
||||
}
|
||||
strncpy(protoname, protoentp->p_name, sizeof(protoname));
|
||||
#elif HAVE_GETPROTOBYNUMBER_R==2 /* Solaris */
|
||||
{
|
||||
# define FILAN_GETPROTOBYNUMBER_R_BUFLEN 1024
|
||||
char buffer[FILAN_GETPROTOBYNUMBER_R_BUFLEN];
|
||||
protoentp = getprotobynumber_r(proto, &protoent, buffer, FILAN_GETPROTOBYNUMBER_R_BUFLEN);
|
||||
strncpy(protoname, protoentp->p_name, sizeof(protoname));
|
||||
}
|
||||
#elif HAVE_GETPROTOBYNUMBER_R==3 /* AIX, OpenBSD */
|
||||
{
|
||||
struct protoent_data proto_data = { 0 }; /* OpenBSD might SIGSEGV */
|
||||
rc = getprotobynumber_r(proto, &protoent, &proto_data);
|
||||
if (rc == 0) {
|
||||
strncpy(protoname, protoent.p_name, sizeof(protoname));
|
||||
endprotoent_r(&proto_data);
|
||||
}
|
||||
}
|
||||
#else
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP: strcpy(protoname, "tcp"); break;
|
||||
case IPPROTO_UDP: strcpy(protoname, "udp"); break;
|
||||
case IPPROTO_SCTP: strcpy(protoname, "sctp"); break;
|
||||
default: sprintf(protoname, "proto%d", proto); break;
|
||||
}
|
||||
#endif
|
||||
#else /* ! (defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)) */
|
||||
if (opttype == SOCK_STREAM) {
|
||||
strcpy(protoname, "(stream)");
|
||||
} else if (opttype == SOCK_DGRAM) {
|
||||
strcpy(protoname, "(dgram)");
|
||||
#ifdef SOCK_RAW
|
||||
} else if (opttype == SOCK_RAW) {
|
||||
strcpy(protoname, "(raw)");
|
||||
#endif
|
||||
#ifdef SOCK_RDM
|
||||
} else if (opttype == SOCK_RDM) {
|
||||
strcpy(protoname, "(rdm)");
|
||||
#endif
|
||||
#ifdef SOCK_SEQPACKET
|
||||
} else if (opttype == SOCK_SEQPACKET) {
|
||||
strcpy(protoname, "(seqpacket)");
|
||||
#endif
|
||||
#ifdef SOCK_DCCP
|
||||
} else if (opttype == SOCK_DCCP) {
|
||||
strcpy(protoname, "(dccp)");
|
||||
#endif
|
||||
#ifdef SOCK_PACKET
|
||||
} else if (opttype == SOCK_PACKET) {
|
||||
strcpy(protoname, "(packet)");
|
||||
#endif
|
||||
} else {
|
||||
strcpy(protoname, "socket");
|
||||
}
|
||||
#endif /* ! (defined(SO_PROTOCOL) || defined(SO_PROTOTYPE)) */
|
||||
socknamelen = sizeof(sockname);
|
||||
result = Getsockname(fd, &sockname.soa, &socknamelen);
|
||||
if (result < 0) {
|
||||
Error2("getsockname(%d): %s", fd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
peernamelen = sizeof(peername);
|
||||
result = Getpeername(fd, (struct sockaddr *)&peername, &peernamelen);
|
||||
if (result < 0) {
|
||||
Warn2("getpeername(%d): %s", fd, strerror(errno));
|
||||
}
|
||||
|
||||
switch (sockname.soa.sa_family) {
|
||||
#if WITH_UNIX
|
||||
case AF_UNIX:
|
||||
switch (style) {
|
||||
case 's':
|
||||
fprintf(outfile, "unix%s%s %s",
|
||||
opttype==SOCK_DGRAM?"datagram":"",
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_unix_info(&sockname.un, socknamelen,
|
||||
socknamebuff, sizeof(socknamebuff)));
|
||||
break;
|
||||
case 'S':
|
||||
/* sockettype(opttype, typename, TYPENAMEMAX); */
|
||||
fprintf(outfile, "unix %s-%s %s %s",
|
||||
sockaddr_unix_info(&sockname.un, socknamelen,
|
||||
socknamebuff, sizeof(socknamebuff)),
|
||||
sockaddr_unix_info(&peername.un, peernamelen,
|
||||
peernamebuff, sizeof(peernamebuff)),
|
||||
typename,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_UNIX */
|
||||
#if WITH_IP4
|
||||
case AF_INET:
|
||||
switch (style) {
|
||||
case 's':
|
||||
switch (opttype) {
|
||||
#if WITH_TCP
|
||||
case SOCK_STREAM:
|
||||
fprintf(outfile, "%s%s %s %s",
|
||||
protoname,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet4_info(&sockname.ip4,
|
||||
socknamebuff, sizeof(socknamebuff)),
|
||||
sockaddr_inet4_info(&peername.ip4,
|
||||
peernamebuff, sizeof(peernamebuff)));
|
||||
break;
|
||||
#endif
|
||||
#if WITH_UDP
|
||||
case SOCK_DGRAM:
|
||||
fprintf(outfile, "%s%s %s %s",
|
||||
protoname,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet4_info(&sockname.ip4,
|
||||
socknamebuff, sizeof(socknamebuff)),
|
||||
sockaddr_inet4_info(&peername.ip4,
|
||||
peernamebuff, sizeof(peernamebuff)));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(outfile, "ip %s",
|
||||
sockaddr_inet4_info(&sockname.ip4,
|
||||
socknamebuff, sizeof(socknamebuff)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
fprintf(outfile, "%s %s-%s (%s) %s",
|
||||
protoname,
|
||||
sockaddr_inet4_info(&sockname.ip4,
|
||||
socknamebuff, sizeof(socknamebuff)),
|
||||
sockaddr_inet4_info(&peername.ip4,
|
||||
peernamebuff, sizeof(peernamebuff)),
|
||||
typename,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP4 */
|
||||
|
||||
#if WITH_IP6
|
||||
case AF_INET6:
|
||||
switch (style) {
|
||||
case 's':
|
||||
switch (opttype) {
|
||||
#if WITH_TCP
|
||||
case SOCK_STREAM:
|
||||
fprintf(outfile, "%s6%s %s %s",
|
||||
protoname,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet6_info(&sockname.ip6,
|
||||
socknamebuff, sizeof(socknamebuff)),
|
||||
sockaddr_inet6_info(&peername.ip6,
|
||||
peernamebuff, sizeof(peernamebuff)));
|
||||
break;
|
||||
#endif
|
||||
#if WITH_UDP
|
||||
case SOCK_DGRAM:
|
||||
fprintf(outfile, "%s6%s %s %s",
|
||||
protoname,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"",
|
||||
sockaddr_inet6_info(&sockname.ip6,
|
||||
socknamebuff, sizeof(socknamebuff)),
|
||||
sockaddr_inet6_info(&peername.ip6,
|
||||
peernamebuff, sizeof(peernamebuff)));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(outfile, "ip6 %s",
|
||||
sockaddr_inet6_info(&sockname.ip6,
|
||||
socknamebuff, sizeof(socknamebuff)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
fprintf(outfile, "%s6 %s-%s (%s) %s",
|
||||
protoname,
|
||||
sockaddr_inet6_info(&sockname.ip6,
|
||||
socknamebuff, sizeof(socknamebuff)),
|
||||
sockaddr_inet6_info(&peername.ip6,
|
||||
peernamebuff, sizeof(peernamebuff)),
|
||||
typename,
|
||||
#ifdef SO_ACCEPTCONN
|
||||
optacceptconn?"(listening)":
|
||||
#endif
|
||||
"");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP6 */
|
||||
|
||||
default:
|
||||
fprintf(outfile, "socket(family/domain=%d)", sockname.soa.sa_family);
|
||||
}
|
||||
|
||||
#if HAVE_GETPROTOENT
|
||||
if (ipproto >= 0) {
|
||||
endprotoent();
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
#undef FDNAME_OPTLEN
|
||||
#undef FDNAME_NAMELEN
|
||||
}
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
|
||||
|
||||
42
filan.h
Normal file
42
filan.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* source: filan.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __filan_h_included
|
||||
#define __filan_h_included 1
|
||||
|
||||
struct sockaddr; /* prevent gcc from spitting silly warning */
|
||||
struct sockaddr_un; /* prevent gcc from spitting silly warning */
|
||||
struct sockaddr_in; /* prevent gcc from spitting silly warning */
|
||||
struct sockaddr_in6; /* prevent gcc from spitting silly warning */
|
||||
|
||||
extern bool filan_followsymlinks;
|
||||
extern bool filan_rawoutput;
|
||||
|
||||
extern int filan_file(const char *filename, FILE *outfile);
|
||||
extern int filan_fd(int fd, FILE *outfile);
|
||||
extern int filan_stat(
|
||||
#if HAVE_STAT64
|
||||
struct stat64 *buf
|
||||
#else
|
||||
struct stat *buf
|
||||
#endif /* !HAVE_STAT64 */
|
||||
, int statfd, int dynfd, FILE *outfile,
|
||||
const char *filename);
|
||||
|
||||
extern int cdevan(int fd, FILE *outfile);
|
||||
|
||||
#if _WITH_SOCKET
|
||||
extern int isasocket(int fd);
|
||||
extern int sockettype(int socktype, char *typename, size_t typenamemax);
|
||||
extern int sockan(int fd, FILE *outfile);
|
||||
extern int ipan(int fd, FILE *outfile);
|
||||
extern int ip6an(int fd, FILE *outfile);
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
extern
|
||||
int fdname(const char *file, int fd, FILE *outfile, const char *numform,
|
||||
char style);
|
||||
|
||||
#endif /* !defined(__filan_h_included) */
|
||||
263
filan_main.c
Normal file
263
filan_main.c
Normal file
@@ -0,0 +1,263 @@
|
||||
/* source: filan_main.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
const char copyright[] = "filan by Gerhard Rieger and contributors - see http://www.dest-unreach.org/socat/";
|
||||
|
||||
#include "config.h"
|
||||
#include "xioconfig.h"
|
||||
#include "sysincludes.h"
|
||||
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "error.h"
|
||||
#include "sycls.h"
|
||||
#include "filan.h"
|
||||
|
||||
|
||||
#define WITH_HELP 1
|
||||
|
||||
static void filan_usage(FILE *fd);
|
||||
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
const char **arg1, *a0, *a;
|
||||
const char *filename = NULL, *waittimetxt;
|
||||
unsigned int m = 0; /* first FD (default) */
|
||||
unsigned int n = FD_SETSIZE; /* last excl. */
|
||||
unsigned int i;
|
||||
int style = 0;
|
||||
struct timespec waittime = { 0, 0 };
|
||||
FILE *fdout = stdout;
|
||||
const char *outfname = NULL;
|
||||
unsigned long fildes;
|
||||
|
||||
diag_set('I', NULL);
|
||||
diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
|
||||
|
||||
arg1 = argv+1; --argc;
|
||||
while (arg1[0] && (arg1[0][0] == '-')) {
|
||||
switch (arg1[0][1]) {
|
||||
#if WITH_HELP
|
||||
case '?': case 'h':
|
||||
filan_usage(stdout); exit(0);
|
||||
#endif
|
||||
#if LATER
|
||||
case 'V': filan_version(stdout); exit(0);
|
||||
#endif
|
||||
case 'L': filan_followsymlinks = true; break;
|
||||
case 'd': diag_set('d', NULL); break;
|
||||
case 's': style = arg1[0][1]; break;
|
||||
case 'S': style = arg1[0][1]; break;
|
||||
case 'r': filan_rawoutput = true; break;
|
||||
case 'i': if (arg1[0][2]) {
|
||||
a = a0 = *arg1+2;
|
||||
} else {
|
||||
++arg1, --argc;
|
||||
if ((a = a0 = *arg1) == NULL) {
|
||||
Error("option -i requires an argument");
|
||||
filan_usage(stderr); exit(1);
|
||||
}
|
||||
}
|
||||
m = strtoul(a, (char **)&a, 0);
|
||||
if (a == a0) {
|
||||
Error1("not a numerical arg in \"-i %s\"", a0);
|
||||
}
|
||||
if (*a != '\0') {
|
||||
Error1("trailing garbage in \"-i %s\"", a0);
|
||||
}
|
||||
n = m;
|
||||
break;
|
||||
case 'n': if (arg1[0][2]) {
|
||||
a = a0 = *arg1+2;
|
||||
} else {
|
||||
++arg1, --argc;
|
||||
if ((a = a0 = *arg1) == NULL) {
|
||||
Error("option -n requires an argument");
|
||||
filan_usage(stderr); exit(1);
|
||||
}
|
||||
}
|
||||
n = strtoul(a, (char **)&a, 0);
|
||||
if (a == a0) {
|
||||
Error1("not a numerical arg in \"-n %s\"", a0);
|
||||
}
|
||||
if (*a != '\0') {
|
||||
Error1("trailing garbage in \"-n %s\"", a0);
|
||||
}
|
||||
break;
|
||||
case 'f': if (arg1[0][2]) {
|
||||
filename = *arg1+2;
|
||||
} else {
|
||||
++arg1, --argc;
|
||||
if ((filename = *arg1) == NULL) {
|
||||
Error("option -f requires an argument");
|
||||
filan_usage(stderr); exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'T': if (arg1[0][2]) {
|
||||
waittimetxt = *arg1+2;
|
||||
} else {
|
||||
++arg1, --argc;
|
||||
if ((waittimetxt = *arg1) == NULL) {
|
||||
Error("option -T requires an argument");
|
||||
filan_usage(stderr); exit(1);
|
||||
}
|
||||
}
|
||||
{
|
||||
double waittimedbl;
|
||||
waittimedbl = strtod(waittimetxt, NULL);
|
||||
waittime.tv_sec = waittimedbl;
|
||||
waittime.tv_nsec = (waittimedbl-waittime.tv_sec) * 1000000000;
|
||||
}
|
||||
break;
|
||||
case 'o': if (arg1[0][2]) {
|
||||
outfname = *arg1+2;
|
||||
} else {
|
||||
++arg1, --argc;
|
||||
if ((outfname = *arg1) == NULL) {
|
||||
Error("option -o requires an argument");
|
||||
filan_usage(stderr); exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '\0': break;
|
||||
default:
|
||||
diag_set_int('e', E_FATAL);
|
||||
Error1("unknown option %s", arg1[0]);
|
||||
#if WITH_HELP
|
||||
filan_usage(stderr);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
#if 0
|
||||
if (arg1[0][1] == '\0')
|
||||
break;
|
||||
#endif
|
||||
++arg1; --argc;
|
||||
}
|
||||
if (argc != 0) {
|
||||
Error1("%d superfluous arguments", argc);
|
||||
filan_usage(stderr);
|
||||
exit(1);
|
||||
}
|
||||
if (outfname) {
|
||||
/* special cases */
|
||||
if (!strcmp(outfname,"stdin")) { fdout=stdin; }
|
||||
else if (!strcmp(outfname,"stdout")) { fdout=stdout; }
|
||||
else if (!strcmp(outfname,"stderr")) { fdout=stderr; }
|
||||
/* file descriptor */
|
||||
else if (*outfname == '+') {
|
||||
a = outfname+1;
|
||||
fildes = strtoul(a, (char **)&a, 0);
|
||||
if ((fdout = fdopen(fildes, "w")) == NULL) {
|
||||
Error2("can't fdopen file descriptor %lu: %s\n", fildes, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
/* file name */
|
||||
if ((fdout = fopen(outfname, "w")) == NULL) {
|
||||
Error2("can't fopen '%s': %s\n",
|
||||
outfname, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nanosleep(&waittime, NULL);
|
||||
|
||||
if (style == 0) {
|
||||
/* this style gives detailled infos, but requires a file descriptor */
|
||||
if (filename) {
|
||||
#if LATER /* this is just in case that S_ISSOCK does not work */
|
||||
struct stat buf;
|
||||
int fd;
|
||||
|
||||
if (Stat(filename, &buf) < 0) {
|
||||
Error3("stat(\"%s\", %p): %s", filename, &buf, strerror(errno));
|
||||
}
|
||||
/* note: when S_ISSOCK was undefined, it always gives 0 */
|
||||
if (S_ISSOCK(buf.st_mode)) {
|
||||
Error("cannot analyze UNIX domain socket");
|
||||
}
|
||||
#endif
|
||||
filan_file(filename, fdout);
|
||||
} else {
|
||||
if (m == n) {
|
||||
++n;
|
||||
}
|
||||
for (i = m; i < n; ++i) {
|
||||
filan_fd(i, fdout);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* this style gives only type and path / socket addresses, and works from
|
||||
file descriptor or filename (with restrictions) */
|
||||
if (filename) {
|
||||
/* filename: NULL means yet unknown; "" means no name at all */
|
||||
#if LATER
|
||||
int fd;
|
||||
if ((fd =
|
||||
Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK
|
||||
#ifdef O_LARGEFILE
|
||||
|O_LARGEFILE
|
||||
#endif
|
||||
, 0700))
|
||||
< 0) {
|
||||
Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
|
||||
filename, strerror(errno));
|
||||
}
|
||||
fdname(filename, fd, fdout, NULL, style);
|
||||
#endif
|
||||
fdname(filename, -1, fdout, NULL, style);
|
||||
} else {
|
||||
if (m == n) {
|
||||
fdname("", m, fdout, NULL, style);
|
||||
} else {
|
||||
for (i = m; i < n; ++i) {
|
||||
fdname("", i, fdout, "%5u ", style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outfname && fdout != stdout && fdout != stderr) {
|
||||
fclose(fdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if WITH_HELP
|
||||
static void filan_usage(FILE *fd) {
|
||||
fputs(copyright, fd); fputc('\n', fd);
|
||||
fputs("Analyze file descriptors of the process\n", fd);
|
||||
fputs("Usage:\n", fd);
|
||||
fputs("filan [options]\n", fd);
|
||||
fputs(" options:\n", fd);
|
||||
#if LATER
|
||||
fputs(" -V print version information to stdout, and exit\n", fd);
|
||||
#endif
|
||||
#if WITH_HELP
|
||||
fputs(" -?|-h print this help text\n", fd);
|
||||
fputs(" -d increase verbosity (use up to 4 times)\n", fd);
|
||||
#endif
|
||||
#if 0
|
||||
fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd);
|
||||
fputs(" -lf<logfile> log to file\n", fd);
|
||||
fputs(" -ls log to stderr (default if no other log)\n", fd);
|
||||
#endif
|
||||
fputs(" -i<fdnum> only analyze this fd\n", fd);
|
||||
fprintf(fd, " -n<fdnum> analyze all fds from 0 up to fdnum-1 (default: %u)\n", FD_SETSIZE);
|
||||
fputs(" -s simple output with just type and socket address or path\n", fd);
|
||||
fputs(" -S like -s but improved format and contents\n", fd);
|
||||
/* fputs(" -c alternate device visualization\n", fd);*/
|
||||
fputs(" -f<filename> analyze file system entry\n", fd);
|
||||
fputs(" -T<seconds> wait before analyzing, useful to connect with debugger\n", fd);
|
||||
fputs(" -r raw output for time stamps and rdev\n", fd);
|
||||
fputs(" -L follow symbolic links instead of showing their properties\n", fd);
|
||||
fputs(" -o<filename> output goes to filename, that can be:\n", fd);
|
||||
fputs(" a regular file name, the output goes to that\n", fd);
|
||||
fputs(" +<filedes> , output goes to the file descriptor (which must be open writable)\n", fd);
|
||||
fputs(" the 3 special names stdin stdout and stderr\n", fd);
|
||||
}
|
||||
#endif /* WITH_HELP */
|
||||
158
ftp.sh
Executable file
158
ftp.sh
Executable file
@@ -0,0 +1,158 @@
|
||||
#! /bin/sh
|
||||
# source: ftp.sh
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# example how to write a shell script that communicates with stdio on the front
|
||||
# end and with a socat address on the back end
|
||||
|
||||
# usage:
|
||||
# ftp.sh [opts] server directory/ # show directory contents on stdout
|
||||
# ftp.sh [opts] server file # print file contents to stdout
|
||||
# opts:
|
||||
# -socks socksserver # use given socks server, port 1080
|
||||
# -proxy proxyserver # use given proxy server, port 8080
|
||||
# # must be http proxy that accepts CONNECT
|
||||
# # method to ports 21 and >=1024
|
||||
# -user username # default: "ftp"
|
||||
# -passwd password # default: "anonymous@domain.org"
|
||||
# -t # shell script trace+debug
|
||||
# -d # debug on control connection (use up to 4 times)
|
||||
# -D # debug on data connection (use up to 4 times)
|
||||
# -b # block size for data connection
|
||||
# -v # verbose
|
||||
# -l* # socat logging options
|
||||
# example:
|
||||
# ftp.sh -v -d -d -D -D -D -b 65536 -proxy proxy ftp.ftp.org /README >README
|
||||
|
||||
user="ftp"
|
||||
passwd="anonymous@domain.org"
|
||||
#method="socks4:socks" # socks4 is address spec, socks is socks server name
|
||||
method=tcp
|
||||
addropts=
|
||||
|
||||
# socat options
|
||||
SO1=
|
||||
SO2=
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-socks|-socks4) shift;
|
||||
case "$1" in
|
||||
*:*) method="socks4:${1%%:*}"; addropts="socksport=${1#*:}" ;;
|
||||
*) method="socks4:$1" ;;
|
||||
esac ;;
|
||||
-socks4a) shift;
|
||||
case "$1" in
|
||||
*:*) method="socks4a:${1%%:*}"; addropts="socksport=${1#*:}" ;;
|
||||
*) method="socks4a:$1" ;;
|
||||
esac ;;
|
||||
-proxy) shift;
|
||||
case "$1" in
|
||||
*:*) method="proxy:${1%%:*}"; addropts="proxyport=${1#*:}" ;;
|
||||
*) method="proxy:$1" ;;
|
||||
esac ;;
|
||||
-user) shift; user="$1" ;;
|
||||
-passwd) shift; passwd="$1" ;;
|
||||
-t) set -vx ;;
|
||||
-d) SO1="$SO1 -d" ;;
|
||||
-D) SO2="$SO2 -d" ;;
|
||||
-b) SO2="$SO2 -b $2"; shift ;;
|
||||
-v) SO1="$SO1 -v" ;;
|
||||
-l*) SO1="$SO1 $1"; SO2="$SO2 $1" ;;
|
||||
-*) echo "unknown option \"$1\"" >&2; exit 1;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
export SO2
|
||||
|
||||
server="$1"
|
||||
dir="$2"
|
||||
|
||||
echo "addr=$method:$server:21,$addropts"; exit
|
||||
|
||||
### this is the central part to establish communication with socat ###
|
||||
### copy these lines to make new communication shell scripts
|
||||
TMPDIR=$(if [ -x /bin/mktemp ]; then
|
||||
/bin/mktemp -d /tmp/$USER/FTPSH.XXXXXX
|
||||
else
|
||||
(umask 077; d=/tmp/$USER/FTPSH.$$; mkdir $d; echo $d)
|
||||
fi)
|
||||
TO="$TMPDIR/to"; FROM="$TMPDIR/from"
|
||||
socat $SO1 fifo:$TO,nonblock,ignoreeof!!fifo:$FROM $method:$server:21,$addropts &
|
||||
S1=$!
|
||||
while ! [ -p "$TO" -a -p "$FROM" ]; do sleep 1; done
|
||||
exec 4>$TMPDIR/to 3<$TMPDIR/from
|
||||
trap "S1=" 17
|
||||
#trap "echo cleaning up...>&2; rm -r $TMPDIR; [ -n "$S1" ] && kill $S1" 0 3
|
||||
trap "rm -r $TMPDIR" 0 3
|
||||
### here the central part ends
|
||||
|
||||
|
||||
# this function waits for a complete server message, checks if its status
|
||||
# is in the permitted range (terminates session if not), and returns.
|
||||
ftp_chat () {
|
||||
local cmd="$1"
|
||||
local errlevel="$2"; [ -z "$errlevel" ] && errlevel=300
|
||||
if [ -n "$cmd" ]; then echo "$cmd" >&4; fi
|
||||
while read status message <&3;
|
||||
( case "$status" in [0-9][0-9][0-9]-*) exit 0;; [0-9][0-9][0-9]*) exit 1;; *) exit 1;; esac )
|
||||
do :; done
|
||||
#echo "got \"$status $message\"" >&2
|
||||
if [ -z "$status" ]; then echo ftp data connection failed >&2; exit; fi
|
||||
if [ "$status" -ge "$errlevel" ]; then
|
||||
echo $message >&2
|
||||
echo "QUIT" >&4; exit 1
|
||||
fi
|
||||
set +vx
|
||||
}
|
||||
|
||||
|
||||
# wait for server greeting
|
||||
ftp_chat
|
||||
|
||||
ftp_chat "USER $user" 400
|
||||
|
||||
ftp_chat "PASS $passwd"
|
||||
|
||||
#ftp_chat "CWD $dir"
|
||||
|
||||
case "$dir" in
|
||||
*/) ftp_chat "TYPE A" ;;
|
||||
*) ftp_chat "TYPE I" ;;
|
||||
esac
|
||||
|
||||
echo "PASV" >&4; read status message <&3
|
||||
info=$(expr "$message" : '.*[^0-9]\([0-9]*,[0-9]*,[0-9]*,[0-9]*,[0-9]*,[0-9]*\).*')
|
||||
echo $info |tr ',' ' ' |(read i1 i2 i3 i4 p1 p2
|
||||
|
||||
addr=$i1.$i2.$i3.$i4
|
||||
port=$(echo "256*$p1+$p2" |bc)
|
||||
#echo $addr:$port
|
||||
|
||||
trap : 20
|
||||
# open data connection and transfer data
|
||||
socat -u $SO2 $method:$server:$port,$addropts -
|
||||
) &
|
||||
S2=$!
|
||||
|
||||
case "$dir" in
|
||||
*/) ftp_chat "NLST $dir" ;;
|
||||
#*/) ftp_chat "LIST $dir" ;;
|
||||
*) ftp_chat "RETR $dir" ;;
|
||||
esac
|
||||
case "$status" in
|
||||
[45]*) kill $S2;;
|
||||
esac
|
||||
|
||||
#echo "waiting for process $S2 to terminate" >&2
|
||||
wait $S2
|
||||
|
||||
ftp_chat
|
||||
|
||||
ftp_chat "QUIT"
|
||||
|
||||
#echo "waiting for process $S1 to terminate" >&2
|
||||
wait $S1
|
||||
exit
|
||||
341
hostan.c
Normal file
341
hostan.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/* source: hostan.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* the subroutine hostan makes a "HOST ANalysis". It gathers information
|
||||
about the host environment it is running in without modifying its state
|
||||
(almost).
|
||||
*/
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "error.h"
|
||||
#include "sycls.h"
|
||||
#include "sysutils.h"
|
||||
#include "filan.h"
|
||||
|
||||
#include "hostan.h"
|
||||
|
||||
|
||||
static int iffan(FILE *outfile);
|
||||
static int vsockan(FILE *outfile);
|
||||
|
||||
|
||||
int hostan(FILE *outfile) {
|
||||
fprintf(outfile, "\nC TYPE SIZES\n");
|
||||
fprintf(outfile, "sizeof(char) = %u\n", (unsigned int)sizeof(char));
|
||||
fprintf(outfile, "sizeof(short) = %u\n", (unsigned int)sizeof(short));
|
||||
fprintf(outfile, "sizeof(int) = %u\n", (unsigned int)sizeof(int));
|
||||
fprintf(outfile, "sizeof(long) = %u\n", (unsigned int)sizeof(long));
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
fprintf(outfile, "sizeof(long long) = %u\n", (unsigned int)sizeof(long long));
|
||||
#endif
|
||||
fprintf(outfile, "sizeof(size_t) = %u\n", (unsigned int)sizeof(size_t));
|
||||
|
||||
# if HAVE_BASIC_SIZE_T==2
|
||||
fprintf(outfile, "typedef unsigned short size_t; /* sizeof(size_t) = %u */\n", (unsigned int)sizeof(size_t));
|
||||
#elif HAVE_BASIC_SIZE_T==4
|
||||
fprintf(outfile, "typedef unsigned int size_t; /* sizeof(size_t) = %u */\n", (unsigned int)sizeof(size_t));
|
||||
#elif HAVE_BASIC_SIZE_T==6
|
||||
fprintf(outfile, "typedef unsigned long size_t; /* sizeof(size_t) = %u */\n", (unsigned int)sizeof(size_t));
|
||||
#elif HAVE_BASIC_SIZE_T==8
|
||||
fprintf(outfile, "typedef unsigned long long size_t; /* sizeof(size_t) = %u */\n", (unsigned int)sizeof(size_t));
|
||||
#endif
|
||||
|
||||
# if HAVE_BASIC_MODE_T==1
|
||||
fprintf(outfile, "typedef short mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#elif HAVE_BASIC_MODE_T==2
|
||||
fprintf(outfile, "typedef unsigned short mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#elif HAVE_BASIC_MODE_T==3
|
||||
fprintf(outfile, "typedef int mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#elif HAVE_BASIC_MODE_T==4
|
||||
fprintf(outfile, "typedef unsigned int mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#elif HAVE_BASIC_MODE_T==5
|
||||
fprintf(outfile, "typedef long mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#elif HAVE_BASIC_MODE_T==6
|
||||
fprintf(outfile, "typedef unsigned long mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#elif HAVE_BASIC_MODE_T==7
|
||||
fprintf(outfile, "typedef long long mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#elif HAVE_BASIC_MODE_T==8
|
||||
fprintf(outfile, "typedef unsigned long long mode_t; /* sizeof(mode_t) = %u */\n", (unsigned int)sizeof(mode_t));
|
||||
#endif
|
||||
|
||||
# if HAVE_BASIC_PID_T==1
|
||||
fprintf(outfile, "typedef short pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#elif HAVE_BASIC_PID_T==2
|
||||
fprintf(outfile, "typedef unsigned short pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#elif HAVE_BASIC_PID_T==3
|
||||
fprintf(outfile, "typedef int pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#elif HAVE_BASIC_PID_T==4
|
||||
fprintf(outfile, "typedef unsigned int pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#elif HAVE_BASIC_PID_T==5
|
||||
fprintf(outfile, "typedef long pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#elif HAVE_BASIC_PID_T==6
|
||||
fprintf(outfile, "typedef unsigned long pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#elif HAVE_BASIC_PID_T==7
|
||||
fprintf(outfile, "typedef long long pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#elif HAVE_BASIC_PID_T==8
|
||||
fprintf(outfile, "typedef unsigned long long pid_t; /* sizeof(pid_t) = %u */\n", (unsigned int)sizeof(pid_t));
|
||||
#endif
|
||||
|
||||
# if HAVE_BASIC_UID_T==1
|
||||
fprintf(outfile, "typedef short uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#elif HAVE_BASIC_UID_T==2
|
||||
fprintf(outfile, "typedef unsigned short uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#elif HAVE_BASIC_UID_T==3
|
||||
fprintf(outfile, "typedef int uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#elif HAVE_BASIC_UID_T==4
|
||||
fprintf(outfile, "typedef unsigned int uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#elif HAVE_BASIC_UID_T==5
|
||||
fprintf(outfile, "typedef long uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#elif HAVE_BASIC_UID_T==6
|
||||
fprintf(outfile, "typedef unsigned long uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#elif HAVE_BASIC_UID_T==7
|
||||
fprintf(outfile, "typedef long long uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#elif HAVE_BASIC_UID_T==8
|
||||
fprintf(outfile, "typedef unsigned long long uid_t; /* sizeof(uid_t) = %u */\n", (unsigned int)sizeof(uid_t));
|
||||
#endif
|
||||
|
||||
# if HAVE_BASIC_GID_T==1
|
||||
fprintf(outfile, "typedef short gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#elif HAVE_BASIC_GID_T==2
|
||||
fprintf(outfile, "typedef unsigned short gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#elif HAVE_BASIC_GID_T==3
|
||||
fprintf(outfile, "typedef int gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#elif HAVE_BASIC_GID_T==4
|
||||
fprintf(outfile, "typedef unsigned int gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#elif HAVE_BASIC_GID_T==5
|
||||
fprintf(outfile, "typedef long gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#elif HAVE_BASIC_GID_T==6
|
||||
fprintf(outfile, "typedef unsigned long gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#elif HAVE_BASIC_GID_T==7
|
||||
fprintf(outfile, "typedef long long gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#elif HAVE_BASIC_GID_T==8
|
||||
fprintf(outfile, "typedef unsigned long long gid_t; /* sizeof(gid_t) = %u */\n", (unsigned int)sizeof(gid_t));
|
||||
#endif
|
||||
|
||||
# if HAVE_BASIC_TIME_T==1
|
||||
fprintf(outfile, "typedef short time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#elif HAVE_BASIC_TIME_T==2
|
||||
fprintf(outfile, "typedef unsigned short time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#elif HAVE_BASIC_TIME_T==3
|
||||
fprintf(outfile, "typedef int time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#elif HAVE_BASIC_TIME_T==4
|
||||
fprintf(outfile, "typedef unsigned int time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#elif HAVE_BASIC_TIME_T==5
|
||||
fprintf(outfile, "typedef long time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#elif HAVE_BASIC_TIME_T==6
|
||||
fprintf(outfile, "typedef unsigned long time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#elif HAVE_BASIC_TIME_T==7
|
||||
fprintf(outfile, "typedef long long time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#elif HAVE_BASIC_TIME_T==8
|
||||
fprintf(outfile, "typedef unsigned long long time_t; /* sizeof(time_t) = %u */\n", (unsigned int)sizeof(time_t));
|
||||
#endif
|
||||
|
||||
# if HAVE_BASIC_SOCKLEN_T==1
|
||||
fprintf(outfile, "typedef short socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#elif HAVE_BASIC_SOCKLEN_T==2
|
||||
fprintf(outfile, "typedef unsigned short socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#elif HAVE_BASIC_SOCKLEN_T==3
|
||||
fprintf(outfile, "typedef int socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#elif HAVE_BASIC_SOCKLEN_T==4
|
||||
fprintf(outfile, "typedef unsigned int socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#elif HAVE_BASIC_SOCKLEN_T==5
|
||||
fprintf(outfile, "typedef long socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#elif HAVE_BASIC_SOCKLEN_T==6
|
||||
fprintf(outfile, "typedef unsigned long socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#elif HAVE_BASIC_SOCKLEN_T==7
|
||||
fprintf(outfile, "typedef long long socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#elif HAVE_BASIC_SOCKLEN_T==8
|
||||
fprintf(outfile, "typedef unsigned long long socklen_t; /* sizeof(socklen_t) = %u */\n", (unsigned int)sizeof(socklen_t));
|
||||
#endif
|
||||
|
||||
# if HAVE_BASIC_OFF_T==1
|
||||
fprintf(outfile, "typedef short off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#elif HAVE_BASIC_OFF_T==2
|
||||
fprintf(outfile, "typedef unsigned short off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#elif HAVE_BASIC_OFF_T==3
|
||||
fprintf(outfile, "typedef int off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#elif HAVE_BASIC_OFF_T==4
|
||||
fprintf(outfile, "typedef unsigned int off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#elif HAVE_BASIC_OFF_T==5
|
||||
fprintf(outfile, "typedef long off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#elif HAVE_BASIC_OFF_T==6
|
||||
fprintf(outfile, "typedef unsigned long off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#elif HAVE_BASIC_OFF_T==7
|
||||
fprintf(outfile, "typedef long long off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#elif HAVE_BASIC_OFF_T==8
|
||||
fprintf(outfile, "typedef unsigned long long off_t; /* sizeof(off_t) = %u */\n", (unsigned int)sizeof(off_t));
|
||||
#endif
|
||||
|
||||
#if HAVE_TYPE_OFF64 && defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T
|
||||
# if HAVE_BASIC_OFF64_T==1
|
||||
fprintf(outfile, "typedef short off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#elif HAVE_BASIC_OFF64_T==2
|
||||
fprintf(outfile, "typedef unsigned short off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#elif HAVE_BASIC_OFF64_T==3
|
||||
fprintf(outfile, "typedef int off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#elif HAVE_BASIC_OFF64_T==4
|
||||
fprintf(outfile, "typedef unsigned int off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#elif HAVE_BASIC_OFF64_T==5
|
||||
fprintf(outfile, "typedef long off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#elif HAVE_BASIC_OFF64_T==6
|
||||
fprintf(outfile, "typedef unsigned long off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#elif HAVE_BASIC_OFF64_T==7
|
||||
fprintf(outfile, "typedef long long off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#elif HAVE_BASIC_OFF64_T==8
|
||||
fprintf(outfile, "typedef unsigned long long off64_t; /* sizeof(off64_t) = %u */\n", (unsigned int)sizeof(off64_t));
|
||||
#endif
|
||||
#endif /* defined(HAVE_BASIC_OFF64_T) && HAVE_BASIC_OFF64_T */
|
||||
|
||||
# if HAVE_BASIC_DEV_T==1
|
||||
fprintf(outfile, "typedef short dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#elif HAVE_BASIC_DEV_T==2
|
||||
fprintf(outfile, "typedef unsigned short dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#elif HAVE_BASIC_DEV_T==3
|
||||
fprintf(outfile, "typedef int dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#elif HAVE_BASIC_DEV_T==4
|
||||
fprintf(outfile, "typedef unsigned int dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#elif HAVE_BASIC_DEV_T==5
|
||||
fprintf(outfile, "typedef long dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#elif HAVE_BASIC_DEV_T==6
|
||||
fprintf(outfile, "typedef unsigned long dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#elif HAVE_BASIC_DEV_T==7
|
||||
fprintf(outfile, "typedef long long dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#elif HAVE_BASIC_DEV_T==8
|
||||
fprintf(outfile, "typedef unsigned long long dev_t; /* sizeof(dev_t) = %u */\n", (unsigned int)sizeof(dev_t));
|
||||
#endif
|
||||
|
||||
{
|
||||
struct stat x;
|
||||
# if HAVE_TYPEOF_ST_INO==1
|
||||
fprintf(outfile, "typedef short ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#elif HAVE_TYPEOF_ST_INO==2
|
||||
fprintf(outfile, "typedef unsigned short ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#elif HAVE_TYPEOF_ST_INO==3
|
||||
fprintf(outfile, "typedef int ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#elif HAVE_TYPEOF_ST_INO==4
|
||||
fprintf(outfile, "typedef unsigned int ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#elif HAVE_TYPEOF_ST_INO==5
|
||||
fprintf(outfile, "typedef long ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#elif HAVE_TYPEOF_ST_INO==6
|
||||
fprintf(outfile, "typedef unsigned long ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#elif HAVE_TYPEOF_ST_INO==7
|
||||
fprintf(outfile, "typedef long long ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#elif HAVE_TYPEOF_ST_INO==8
|
||||
fprintf(outfile, "typedef unsigned long long ino_t; /* sizeof(ino_t) = %u */\n", (unsigned int)sizeof(x.st_ino));
|
||||
#endif
|
||||
}
|
||||
{
|
||||
unsigned short x = 0x100;
|
||||
if (x == ntohs(0x100)) {
|
||||
fprintf(outfile, "#define __BYTE_ORDER __BIG_ENDIAN\t/* Motorola ea.*/\n");
|
||||
} else {
|
||||
fprintf(outfile, "#define __BYTE_ORDER __LITTLE_ENDIAN\t/* Intel ea.*/\n");
|
||||
}
|
||||
}
|
||||
|
||||
#include <sys/time.h> /* select(); OpenBSD: struct timespec */
|
||||
fprintf(outfile, "sizeof(struct timespec) = %u\n", (unsigned int)sizeof(struct timespec));
|
||||
|
||||
fprintf(outfile, "\n");
|
||||
fprintf(outfile, "/* Socat types */\n");
|
||||
fprintf(outfile, "sizeof(struct diag_dgram) = %u\n", (unsigned int)sizeof(struct diag_dgram));
|
||||
fprintf(outfile, "((struct diag_dgram *)0)->op-((struct diag_dgram *)0) = %u\n", (unsigned int)((char *)(&((struct diag_dgram *)0)->op)-(char *)((struct diag_dgram *)0)));
|
||||
fprintf(outfile, "((struct diag_dgram *)0)->now-((struct diag_dgram *)0) = %u\n", (unsigned int)((char *)(&((struct diag_dgram *)0)->now)-(char *)((struct diag_dgram *)0)));
|
||||
fprintf(outfile, "((struct diag_dgram *)0)->exitcode-((struct diag_dgram *)0) = %u\n", (unsigned int)((char *)(&((struct diag_dgram *)0)->exitcode)-(char *)((struct diag_dgram *)0)));
|
||||
fprintf(outfile, "((struct diag_dgram *)0)->text-((struct diag_dgram *)0) = %u\n", (unsigned int)((((struct diag_dgram *)0)->text)-(char *)((struct diag_dgram *)0)));
|
||||
#if _WITH_SOCKET && (_WITH_IP4 || _WITH_IP6)
|
||||
fprintf(outfile, "\nIP INTERFACES\n");
|
||||
iffan(outfile);
|
||||
#endif
|
||||
#if WITH_VSOCK
|
||||
vsockan(outfile);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if _WITH_SOCKET && (_WITH_IP4 || _WITH_IP6)
|
||||
static int iffan(FILE *outfile) {
|
||||
/* Linux: man 7 netdevice */
|
||||
/* FreeBSD, NetBSD: man 4 networking */
|
||||
/* Solaris: man 7 if_tcp */
|
||||
|
||||
/* currently we support Linux and a little FreeBSD */
|
||||
#ifdef SIOCGIFCONF /* not Solaris */
|
||||
|
||||
#define IFBUFSIZ 32*sizeof(struct ifreq) /*1024*/
|
||||
int s;
|
||||
unsigned char buff[IFBUFSIZ];
|
||||
struct ifconf ic;
|
||||
int i;
|
||||
|
||||
if ((s = Socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
|
||||
Warn1("socket(PF_INET, SOCK_DGRAM, IPPROTO_IP): %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i < IFBUFSIZ; ++i) {
|
||||
buff[i] = 255;
|
||||
}
|
||||
ic.ifc_len = sizeof(buff);
|
||||
ic.ifc_ifcu.ifcu_buf = (caddr_t)buff;
|
||||
if (Ioctl(s, SIOCGIFCONF, &ic) < 0) {
|
||||
Warn3("ioctl(%d, SIOCGIFCONF, %p): %s", s, &ic, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ic.ifc_len; i += sizeof(struct ifreq)) {
|
||||
struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
|
||||
#if 0 || defined(SIOCGIFINDEX) /* not NetBSD, OpenBSD */
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
|
||||
#if 0 || defined(SIOCGIFINDEX) /* not NetBSD, OpenBSD */
|
||||
strcpy(ifr.ifr_name, ifp->ifr_name);
|
||||
if (Ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
||||
Warn3("ioctl(%d, SIOCGIFINDEX, {\"%s\"}): %s",
|
||||
s, ifr.ifr_name, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
#if HAVE_STRUCT_IFREQ_IFR_INDEX
|
||||
fprintf(outfile, "%2d: %s\n", ifr.ifr_index, ifp->ifr_name);
|
||||
#elif HAVE_STRUCT_IFREQ_IFR_IFINDEX
|
||||
fprintf(outfile, "%2d: %s\n", ifr.ifr_ifindex, ifp->ifr_name);
|
||||
#endif /* HAVE_STRUCT_IFREQ_IFR_INDEX */
|
||||
#else /* !defined(SIOCGIFINDEX) */
|
||||
fprintf(outfile, "%2d: %s\n", i/(int)sizeof(struct ifreq), ifp->ifr_name);
|
||||
#endif /* defined(SIOCGIFINDEX) */
|
||||
}
|
||||
Close(s);
|
||||
#endif /* defined(SIOCGIFCONF) */
|
||||
return 0;
|
||||
}
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
|
||||
#if WITH_VSOCK
|
||||
static int vsockan(FILE *outfile) {
|
||||
unsigned int cid;
|
||||
int vsock;
|
||||
if (Getuid() != 0) {
|
||||
return 1;
|
||||
}
|
||||
if ((vsock = Open("/dev/vsock", O_RDONLY, 0)) < 0 ) {
|
||||
Warn1("open(\"/dev/vsock\", ...): %s", strerror(errno));
|
||||
return -1;
|
||||
} else if (Ioctl(vsock, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &cid) < 0) {
|
||||
Warn2("ioctl(%d, IOCTL_VM_SOCKETS_GET_LOCAL_CID, ...): %s",
|
||||
vsock, strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
Notice1("VSOCK CID=%u", cid);
|
||||
fprintf(outfile, "\nVSOCK_CID = %u\n", cid);
|
||||
}
|
||||
if (vsock >= 0) {
|
||||
Close(vsock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_VSOCK */
|
||||
10
hostan.h
Normal file
10
hostan.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* source: hostan.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __hostan_h_included
|
||||
#define __hostan_h_included 1
|
||||
|
||||
extern int hostan(FILE *outfile);
|
||||
|
||||
#endif /* !defined(__hostan_h_included) */
|
||||
250
install-sh
Executable file
250
install-sh
Executable file
@@ -0,0 +1,250 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
else
|
||||
instcmd=mkdir
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
true
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
true
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
true
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
73
mail.sh
Executable file
73
mail.sh
Executable file
@@ -0,0 +1,73 @@
|
||||
#! /bin/sh
|
||||
# source: mail.sh
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
#set -vx
|
||||
|
||||
# This is an example for a shell script that can be fed to socat with exec.
|
||||
# Its clue is that it does not use stdin/stdout for communication with socat,
|
||||
# so you may feed the mail message via stdin to the script. The message should
|
||||
# contain appropriate mail headers without continuation lines.
|
||||
# socat establishes the connection to the SMTP server; the script performs the
|
||||
# SMTP dialog and afterwards transfers the message body to the server.
|
||||
# Lines with only a dot are not permitted - use two dots as escape.
|
||||
# This script supports multiline answers from server, but not much more yet.
|
||||
|
||||
# Usage: cat message.txt |socat exec:"mail.sh target@domain.com",fdin=3,fdout=4 tcp:mail.relay.org:25,crlf
|
||||
|
||||
while [ "$1" ]; do
|
||||
case "$1" in
|
||||
-f) shift; mailfrom="$1"; shift;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
rcptto="$1"
|
||||
[ -z "$1" ] && rcptto="root@loopback"
|
||||
#server=$(expr "$rcptto" : '[^@]*@\(.*\)')
|
||||
[ -z "$mailfrom" ] && mailfrom="$USER@$(hostname)"
|
||||
|
||||
# this function waits for a complete server message, checks if its status
|
||||
# is in the permitted range (terminates session if not), and returns.
|
||||
mail_chat () {
|
||||
local cmd="$1"
|
||||
local errlevel="$2"; [ -z "$errlevel" ] && errlevel=300
|
||||
|
||||
if [ "$cmd" ]; then echo "> $cmd" >&2; fi
|
||||
if [ -n "$cmd" ]; then echo "$cmd" >&4; fi
|
||||
while read status message <&3;
|
||||
(
|
||||
case "$status" in
|
||||
[0-9][0-9][0-9]-*) exit 0;;
|
||||
[0-9][0-9][0-9]*) exit 1;;
|
||||
*) exit 1;;
|
||||
esac
|
||||
)
|
||||
do :; done
|
||||
if [ -z "$status" ]; then echo smtp connection failed >&2; exit; fi
|
||||
echo "< $status $message" >&2
|
||||
if [ "$status" -ge "$errlevel" ]; then
|
||||
echo $message >&2
|
||||
echo "QUIT" >&4; exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# expect server greeting
|
||||
mail_chat
|
||||
|
||||
mail_chat "HELO $(hostname)"
|
||||
|
||||
mail_chat "MAIL FROM: $mailfrom"
|
||||
|
||||
mail_chat "RCPT TO: $rcptto"
|
||||
|
||||
mail_chat "DATA" 400
|
||||
|
||||
while read l; do echo "$l" >&4; done
|
||||
mail_chat "."
|
||||
|
||||
mail_chat "QUIT"
|
||||
|
||||
exit 0
|
||||
25
mytypes.h
Normal file
25
mytypes.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* source: mytypes.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __mytypes_h_included
|
||||
#define __mytypes_h_included 1
|
||||
|
||||
/* some types and macros I miss in C89 */
|
||||
|
||||
#ifndef HAVE_TYPE_BOOL
|
||||
# undef bool
|
||||
typedef enum { false, true } bool;
|
||||
#endif
|
||||
|
||||
#ifndef Min
|
||||
#define Min(x,y) ((x)<=(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
#ifndef Max
|
||||
#define Max(x,y) ((x)>=(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
#define SOCKADDR_MAX UNIX_PATH_MAX
|
||||
|
||||
#endif /* __mytypes_h_included */
|
||||
271
nestlex.c
Normal file
271
nestlex.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/* source: nestlex.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* a function for lexical scanning of nested character patterns */
|
||||
|
||||
#include "config.h"
|
||||
#include "mytypes.h"
|
||||
|
||||
#include "sysincludes.h"
|
||||
|
||||
static int _nestlex(const char **addr,
|
||||
char **token,
|
||||
ptrdiff_t *len,
|
||||
const char *ends[],
|
||||
const char *hquotes[],
|
||||
const char *squotes[],
|
||||
const char *nests[],
|
||||
bool dropquotes,
|
||||
bool c_esc,
|
||||
bool html_esc
|
||||
);
|
||||
|
||||
/* sub: scan a string and copy its value to output string
|
||||
end scanning when an unescaped, unnested string from ends array is found
|
||||
does not copy the end pattern
|
||||
does not write a trailing \0 to token
|
||||
allows escaping with \ and quoting (\ and quotes are removed)
|
||||
allows nesting with div. parens
|
||||
returns -1 if out string was too small
|
||||
returns 1 if addr ended unexpectedly
|
||||
returns 0 if token could be extracted successfully
|
||||
*/
|
||||
int nestlex(const char **addr, /* input string; aft points to end token */
|
||||
char **token, /* output token; aft points to first unwritten
|
||||
char (caller might want to set it to \0) */
|
||||
size_t *len, /* remaining bytes in token space (incl. \0) */
|
||||
const char *ends[], /* list of end strings */
|
||||
const char *hquotes[],/* list of strings that quote (hard qu.) */
|
||||
const char *squotes[],/* list of strings that quote softly */
|
||||
const char *nests[],/* list of strings that start nesting;
|
||||
every second one is matching end */
|
||||
bool dropquotes, /* drop the outermost quotes */
|
||||
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
||||
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
||||
) {
|
||||
return
|
||||
_nestlex(addr, token, (ptrdiff_t *)len, ends, hquotes, squotes, nests,
|
||||
dropquotes, c_esc, html_esc);
|
||||
}
|
||||
|
||||
static int _nestlex(const char **addr,
|
||||
char **token,
|
||||
ptrdiff_t *len,
|
||||
const char *ends[],
|
||||
const char *hquotes[],
|
||||
const char *squotes[],
|
||||
const char *nests[],
|
||||
bool dropquotes,
|
||||
bool c_esc,
|
||||
bool html_esc
|
||||
) {
|
||||
const char *in = *addr; /* pointer into input string */
|
||||
const char **endx; /* loops over end patterns */
|
||||
const char **quotx; /* loops over quote patterns */
|
||||
const char **nestx; /* loops over nest patterns */
|
||||
char *out = *token; /* pointer into output token */
|
||||
char c;
|
||||
int i;
|
||||
int result;
|
||||
|
||||
while (true) {
|
||||
|
||||
/* is this end of input string? */
|
||||
if (*in == 0) {
|
||||
|
||||
break; /* end of string */
|
||||
}
|
||||
|
||||
/* first check the end patterns (e.g. for ']') */
|
||||
endx = ends; i = 0;
|
||||
while (*endx) {
|
||||
if (!strncmp(in, *endx, strlen(*endx))) {
|
||||
/* this end pattern matches */
|
||||
*addr = in;
|
||||
*token = out;
|
||||
return 0;
|
||||
}
|
||||
++endx;
|
||||
}
|
||||
|
||||
/* check for hard quoting pattern */
|
||||
quotx = hquotes;
|
||||
while (hquotes && *quotx) {
|
||||
if (!strncmp(in, *quotx, strlen(*quotx))) {
|
||||
/* this quote pattern matches */
|
||||
const char *endnest[2];
|
||||
if (dropquotes) {
|
||||
/* we strip this quote */
|
||||
in += strlen(*quotx);
|
||||
} else {
|
||||
for (i = strlen(*quotx); i > 0; --i) {
|
||||
*out++ = *in++;
|
||||
if (--*len <= 0) { *addr = in; *token = out; return -1; }
|
||||
}
|
||||
}
|
||||
/* we call _nestlex recursively */
|
||||
endnest[0] = *quotx;
|
||||
endnest[1] = NULL;
|
||||
result =
|
||||
_nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
|
||||
NULL/*squotes*/, NULL/*nests*/,
|
||||
false, c_esc, html_esc);
|
||||
if (result == 0 && dropquotes) {
|
||||
/* we strip this quote */
|
||||
in += strlen(*quotx);
|
||||
} else if (result < 0) {
|
||||
*addr = in; *token = out; return result;
|
||||
} else {
|
||||
/* we copy the trailing quote */
|
||||
for (i = strlen(*quotx); i > 0; --i) {
|
||||
*out++ = *in++;
|
||||
if (--*len <= 0) { *addr = in; *token = out; return -1; }
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
++quotx;
|
||||
}
|
||||
if (hquotes && *quotx != NULL) {
|
||||
/* there was a quote; string might continue with hard quote */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for soft quoting pattern */
|
||||
quotx = squotes;
|
||||
while (squotes && *quotx) {
|
||||
if (!strncmp(in, *quotx, strlen(*quotx))) {
|
||||
/* this quote pattern matches */
|
||||
/* we strip this quote */
|
||||
/* we call _nestlex recursively */
|
||||
const char *endnest[2];
|
||||
if (dropquotes) {
|
||||
/* we strip this quote */
|
||||
in += strlen(*quotx);
|
||||
} else {
|
||||
for (i = strlen(*quotx); i > 0; --i) {
|
||||
*out++ = *in++;
|
||||
if (--*len <= 0) { *addr = in; *token = out; return -1; }
|
||||
}
|
||||
}
|
||||
endnest[0] = *quotx;
|
||||
endnest[1] = NULL;
|
||||
result =
|
||||
_nestlex(&in, &out, len, endnest, hquotes,
|
||||
squotes, nests,
|
||||
false, c_esc, html_esc);
|
||||
|
||||
if (result == 0 && dropquotes) {
|
||||
/* we strip the trailing quote */
|
||||
if (!in[0] || strncmp(in, *quotx, strlen(*quotx))) return 1;
|
||||
in += strlen(*quotx);
|
||||
} else if (result < 0) {
|
||||
*addr = in; *token = out; return result;
|
||||
} else {
|
||||
/* we copy the trailing quote */
|
||||
for (i = strlen(*quotx); i > 0; --i) {
|
||||
*out++ = *in++;
|
||||
if (--*len <= 0) { *addr = in; *token = out; return -1; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
++quotx;
|
||||
}
|
||||
if (squotes && *quotx != NULL) {
|
||||
/* there was a soft quote; string might continue with any quote */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check patterns that start a nested clause */
|
||||
nestx = nests; i = 0;
|
||||
while (nests && *nestx) {
|
||||
if (!strncmp(in, *nestx, strlen(*nestx))) {
|
||||
/* this nest pattern matches */
|
||||
const char *endnest[2];
|
||||
endnest[0] = nestx[1];
|
||||
endnest[1] = NULL;
|
||||
|
||||
for (i = strlen(nestx[1]); i > 0; --i) {
|
||||
*out++ = *in++;
|
||||
if (--*len <= 0) { *addr = in; *token = out; return -1; }
|
||||
}
|
||||
|
||||
result =
|
||||
_nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
|
||||
false, c_esc, html_esc);
|
||||
if (result == 0) {
|
||||
/* copy endnest */
|
||||
i = strlen(nestx[1]); while (i > 0) {
|
||||
*out++ = *in++;
|
||||
if (--*len <= 0) {
|
||||
*addr = in;
|
||||
*token = out;
|
||||
return -1;
|
||||
}
|
||||
--i;
|
||||
}
|
||||
} else if (result < 0) {
|
||||
*addr = in; *token = out; return result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
nestx += 2; /* skip matching end pattern in table */
|
||||
}
|
||||
if (nests && *nestx) {
|
||||
/* we handled a nested expression, continue loop */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* "normal" data, possibly escaped */
|
||||
c = *in++;
|
||||
if (c == '\\') {
|
||||
/* found a plain \ escaped part */
|
||||
c = *in++;
|
||||
if (c == 0) { /* Warn("trailing '\\'");*/ break; }
|
||||
if (c_esc) { /* solve C char escapes: \n \t \0 etc */
|
||||
switch (c) {
|
||||
case '0': c = '\0'; break;
|
||||
case 'a': c = '\a'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'f': c = '\f'; break;
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'v': c = '\v'; break;
|
||||
#if LATER
|
||||
case 'x': !!! 1 to 2 hex digits; break;
|
||||
case 'u': !!! 4 hex digits?; break;
|
||||
case 'U': !!! 8 hex digits?; break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
*out++ = c;
|
||||
--*len;
|
||||
if (*len <= 0) {
|
||||
*addr = in;
|
||||
*token = out;
|
||||
return -1; /* output overflow */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* just a simple char */
|
||||
*out++ = c;
|
||||
--*len;
|
||||
if (*len <= 0) {
|
||||
*addr = in;
|
||||
*token = out;
|
||||
return -1; /* output overflow */
|
||||
}
|
||||
|
||||
}
|
||||
/* never come here? */
|
||||
|
||||
*addr = in;
|
||||
*token = out;
|
||||
return 0; /* OK */
|
||||
}
|
||||
23
nestlex.h
Normal file
23
nestlex.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* source: nestlex.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __nestlex_h_included
|
||||
#define __nestlex_h_included 1
|
||||
|
||||
extern
|
||||
int nestlex(const char **addr, /* input string; aft points to end token */
|
||||
char **token, /* output token; aft points to first unwritten
|
||||
char (caller might want to set it to \0) */
|
||||
size_t *len, /* remaining bytes in token space (incl. \0) */
|
||||
const char *ends[], /* list of end strings */
|
||||
const char *hquotes[],/* list of strings that quote (hard qu.) */
|
||||
const char *squotes[],/* list of strings that quote softly */
|
||||
const char *nests[],/* list of strings that start nesting;
|
||||
every second one is matching end */
|
||||
bool dropquotes, /* drop the outermost quotes */
|
||||
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
||||
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
||||
);
|
||||
|
||||
#endif /* !defined(__nestlex_h_included) */
|
||||
192
procan-cdefs.c
Normal file
192
procan-cdefs.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/* source: procan-cdefs.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* a function that prints compile time parameters */
|
||||
/* the set of parameters is only a small subset of the available defines and
|
||||
will be extended on demand */
|
||||
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "procan.h"
|
||||
|
||||
int procan_cdefs(FILE *outfile) {
|
||||
/* basic C/system constants */
|
||||
#ifdef FD_SETSIZE
|
||||
fprintf(outfile, "#define FD_SETSIZE %u\n", FD_SETSIZE);
|
||||
#endif
|
||||
#ifdef NFDBITS
|
||||
fprintf(outfile, "#define NFDBITS %d\n", (int)NFDBITS);
|
||||
#endif
|
||||
#ifdef O_RDONLY
|
||||
fprintf(outfile, "#define O_RDONLY %u\n", O_RDONLY);
|
||||
#endif
|
||||
#ifdef O_WRONLY
|
||||
fprintf(outfile, "#define O_WRONLY %u\n", O_WRONLY);
|
||||
#endif
|
||||
#ifdef O_RDWR
|
||||
fprintf(outfile, "#define O_RDWR %u\n", O_RDWR);
|
||||
#endif
|
||||
#ifdef SHUT_RD
|
||||
fprintf(outfile, "#define SHUT_RD %u\n", SHUT_RD);
|
||||
#endif
|
||||
#ifdef SHUT_WR
|
||||
fprintf(outfile, "#define SHUT_WR %u\n", SHUT_WR);
|
||||
#endif
|
||||
#ifdef SHUT_RDWR
|
||||
fprintf(outfile, "#define SHUT_RDWR %u\n", SHUT_RDWR);
|
||||
#endif
|
||||
|
||||
/* Compile time controls */
|
||||
#ifdef _FILE_OFFSET_BITS
|
||||
fprintf(outfile, "#define _FILE_OFFSET_BITS %u\n", _FILE_OFFSET_BITS);
|
||||
#endif
|
||||
#ifdef _LARGE_FILES
|
||||
fprintf(outfile, "#define _LARGE_FILES %u\n", _LARGE_FILES);
|
||||
#endif
|
||||
|
||||
/* termios constants */
|
||||
#ifdef CRDLY
|
||||
fprintf(outfile, "#define CRDLY 0%011o\n", CRDLY);
|
||||
#endif
|
||||
#ifdef CR0
|
||||
fprintf(outfile, "#define CR0 0%011o\n", CR0);
|
||||
#endif
|
||||
#ifdef CR1
|
||||
fprintf(outfile, "#define CR1 0%011o\n", CR1);
|
||||
#endif
|
||||
#ifdef CR2
|
||||
fprintf(outfile, "#define CR2 0%011o\n", CR2);
|
||||
#endif
|
||||
#ifdef CR3
|
||||
fprintf(outfile, "#define CR3 0%011o\n", CR3);
|
||||
#endif
|
||||
#ifdef TABDLY
|
||||
fprintf(outfile, "#define TABDLY 0%011o\n", TABDLY);
|
||||
#endif
|
||||
#ifdef TAB0
|
||||
fprintf(outfile, "#define TAB0 0%011o\n", TAB0);
|
||||
#endif
|
||||
#ifdef TAB1
|
||||
fprintf(outfile, "#define TAB1 0%011o\n", TAB1);
|
||||
#endif
|
||||
#ifdef TAB2
|
||||
fprintf(outfile, "#define TAB2 0%011o\n", TAB2);
|
||||
#endif
|
||||
#ifdef TAB3
|
||||
fprintf(outfile, "#define TAB3 0%011o\n", TAB3);
|
||||
#endif
|
||||
#ifdef CSIZE
|
||||
fprintf(outfile, "#define CSIZE 0%011o\n", CSIZE);
|
||||
#endif
|
||||
#ifdef TIOCEXCL
|
||||
fprintf(outfile, "#define TIOCEXCL 0x%lx\n", (unsigned long)TIOCEXCL);
|
||||
#endif
|
||||
|
||||
/* stdio constants */
|
||||
#ifdef FOPEN_MAX
|
||||
fprintf(outfile, "#define FOPEN_MAX %u\n", FOPEN_MAX);
|
||||
#endif
|
||||
|
||||
/* socket constants */
|
||||
#ifdef PF_UNSPEC
|
||||
fprintf(outfile, "#define PF_UNSPEC %d\n", PF_UNSPEC);
|
||||
#endif
|
||||
#ifdef PF_UNIX
|
||||
fprintf(outfile, "#define PF_UNIX %d\n", PF_UNIX);
|
||||
#elif defined(PF_LOCAL)
|
||||
fprintf(outfile, "#define PF_LOCAL %d\n", PF_LOCAL);
|
||||
#endif
|
||||
#ifdef PF_INET
|
||||
fprintf(outfile, "#define PF_INET %d\n", PF_INET);
|
||||
#endif
|
||||
#ifdef PF_INET6
|
||||
fprintf(outfile, "#define PF_INET6 %d\n", PF_INET6);
|
||||
#endif
|
||||
#ifdef PF_APPLETALK
|
||||
fprintf(outfile, "#define PF_APPLETALK %d\n", PF_APPLETALK);
|
||||
#endif
|
||||
#ifdef PF_PACKET
|
||||
fprintf(outfile, "#define PF_PACKET %d\n", PF_PACKET);
|
||||
#endif
|
||||
#ifdef PF_VSOCK
|
||||
fprintf(outfile, "#define PF_VSOCK %d\n", PF_VSOCK);
|
||||
#endif
|
||||
#ifdef SOCK_STREAM
|
||||
fprintf(outfile, "#define SOCK_STREAM %d\n", SOCK_STREAM);
|
||||
#endif
|
||||
#ifdef SOCK_DGRAM
|
||||
fprintf(outfile, "#define SOCK_DGRAM %d\n", SOCK_DGRAM);
|
||||
#endif
|
||||
#ifdef SOCK_RAW
|
||||
fprintf(outfile, "#define SOCK_RAW %d\n", SOCK_RAW);
|
||||
#endif
|
||||
#ifdef SOCK_SEQPACKET
|
||||
fprintf(outfile, "#define SOCK_SEQPACKET %d\n", SOCK_SEQPACKET);
|
||||
#endif
|
||||
#ifdef SOCK_PACKET
|
||||
fprintf(outfile, "#define SOCK_PACKET %d\n", SOCK_PACKET);
|
||||
#endif
|
||||
#ifdef IPPROTO_IP
|
||||
fprintf(outfile, "#define IPPROTO_IP %d\n", IPPROTO_IP);
|
||||
#endif
|
||||
#ifdef IPPROTO_TCP
|
||||
fprintf(outfile, "#define IPPROTO_TCP %d\n", IPPROTO_TCP);
|
||||
#endif
|
||||
#ifdef IPPROTO_UDP
|
||||
fprintf(outfile, "#define IPPROTO_UDP %d\n", IPPROTO_UDP);
|
||||
#endif
|
||||
#ifdef IPPROTO_DCCP
|
||||
fprintf(outfile, "#define IPPROTO_DCCP %d\n", IPPROTO_DCCP);
|
||||
#endif
|
||||
#ifdef IPPROTO_SCTP
|
||||
fprintf(outfile, "#define IPPROTO_SCTP %d\n", IPPROTO_SCTP);
|
||||
#endif
|
||||
#ifdef IPPROTO_UDPLITE
|
||||
fprintf(outfile, "#define IPPROTO_UDPLITE %d\n", IPPROTO_UDPLITE);
|
||||
#endif
|
||||
#ifdef IPPROTO_RAW
|
||||
fprintf(outfile, "#define IPPROTO_RAW %d\n", IPPROTO_RAW);
|
||||
#endif
|
||||
#ifdef SOL_SOCKET
|
||||
fprintf(outfile, "#define SOL_SOCKET 0x%x\n", SOL_SOCKET);
|
||||
#endif
|
||||
#ifdef SOL_PACKET
|
||||
fprintf(outfile, "#define SOL_PACKET 0x%x\n", SOL_PACKET);
|
||||
#endif
|
||||
#ifdef SOL_IP
|
||||
fprintf(outfile, "#define SOL_IP 0x%x\n", SOL_IP);
|
||||
#endif
|
||||
#ifdef SOL_IPV6
|
||||
fprintf(outfile, "#define SOL_IPV6 0x%x\n", SOL_IPV6);
|
||||
#endif
|
||||
#ifdef SOL_TCP
|
||||
fprintf(outfile, "#define SOL_TCP 0x%x\n", SOL_TCP);
|
||||
#endif
|
||||
#ifdef SOL_UDP
|
||||
fprintf(outfile, "#define SOL_UDP 0x%x\n", SOL_UDP);
|
||||
#endif
|
||||
#ifdef SOL_SCTP
|
||||
fprintf(outfile, "#define SOL_SCTP 0x%x\n", SOL_SCTP);
|
||||
#endif
|
||||
#ifdef SOL_DCCP
|
||||
fprintf(outfile, "#define SOL_DCCP 0x%x\n", SOL_DCCP);
|
||||
#endif
|
||||
#ifdef SO_PROTOCOL
|
||||
fprintf(outfile, "#define SO_PROTOCOL %d\n", SO_PROTOCOL);
|
||||
#endif
|
||||
#ifdef SO_PROTOTYPE
|
||||
fprintf(outfile, "#define SO_PROTOTYPE %d\n", SO_PROTOTYPE);
|
||||
#endif
|
||||
#ifdef SO_REUSEADDR
|
||||
fprintf(outfile, "#define SO_REUSEADDR %d\n", SO_REUSEADDR);
|
||||
#endif
|
||||
#ifdef TCP_MAXSEG
|
||||
fprintf(outfile, "#define TCP_MAXSEG %d\n", TCP_MAXSEG);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
342
procan.c
Normal file
342
procan.c
Normal file
@@ -0,0 +1,342 @@
|
||||
/* source: procan.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* the subroutine procan makes a "PROCess ANalysis". It gathers information
|
||||
about the process environment it is running in without modifying its state
|
||||
(almost).
|
||||
*/
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "error.h"
|
||||
#include "sycls.h"
|
||||
#include "sysutils.h"
|
||||
#include "sched.h"
|
||||
#include "filan.h"
|
||||
|
||||
#include <sys/resource.h> /* RLIMIT_CPU ... */
|
||||
#include <dirent.h> /* opendir() readdir() closedir() */
|
||||
|
||||
#include "procan.h"
|
||||
|
||||
|
||||
/* Search dir recursively for matching device file.
|
||||
Returns 0 on success;
|
||||
returns -1 when it failed to find the device file. */
|
||||
int find_devpath(
|
||||
char *dirname,
|
||||
unsigned int major,
|
||||
unsigned int minor,
|
||||
char *devname)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dirent;
|
||||
char devpath[PATH_MAX];
|
||||
int rc;
|
||||
|
||||
/* Pass 1: search dir flatly for this device entry */
|
||||
dirp = opendir(dirname);
|
||||
if (dirp == NULL) {
|
||||
Warn2("failed to open dir \"%s\": %s", dirname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
while ((errno = 0) || (dirent = readdir(dirp))) {
|
||||
struct stat statbuf;
|
||||
|
||||
#if HAVE_DIRENT_D_TYPE
|
||||
if (dirent->d_type != DT_CHR && dirent->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
#endif
|
||||
snprintf(devpath, PATH_MAX, "%s/%s", dirname, dirent->d_name);
|
||||
if (Stat(devpath, &statbuf) < 0) {
|
||||
Warn2("failed to stat entry \"%s\": %s", devpath, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if ((statbuf.st_mode & S_IFMT) != S_IFCHR)
|
||||
continue;
|
||||
if ((statbuf.st_rdev >> 8) == major &&
|
||||
(statbuf.st_rdev & 0xff) == minor) {
|
||||
strcpy(devname, devpath);
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
closedir(dirp);
|
||||
if (errno != 0) {
|
||||
Warn2("failed to read dir \"%s\": %s", dirname, strerror(errno));
|
||||
snprintf(devname, PATH_MAX, "device %u, %u", major, minor);
|
||||
}
|
||||
|
||||
/* Pass 2: search sub dirs */
|
||||
dirp = opendir(dirname);
|
||||
if (dirp == NULL) {
|
||||
Warn2("failed to open dir \"%s\": %s", dirname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
while ((errno = 0) || (dirent = readdir(dirp))) {
|
||||
char dirpath[PATH_MAX];
|
||||
#if HAVE_DIRENT_D_TYPE
|
||||
if (dirent->d_type != DT_DIR)
|
||||
continue;
|
||||
#else /* Solaris */
|
||||
{
|
||||
struct stat statbuf;
|
||||
if (Stat(dirent->d_name, &statbuf) < 0)
|
||||
continue;
|
||||
if ((statbuf.st_mode & S_IFMT) != S_IFDIR)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, ".."))
|
||||
continue;
|
||||
snprintf(dirpath, PATH_MAX, "%s/%s", dirname, dirent->d_name);
|
||||
rc = find_devpath(dirpath, major, minor, devname);
|
||||
if (rc == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
if (dirent == NULL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tries to determine the name of the controlling terminal.
|
||||
Returns 0 on success, the name in cttyname;
|
||||
returns 1 when only the device numbers are in cttyname;
|
||||
returns -1 when it failed to determine ctty. */
|
||||
static int controlling_term(
|
||||
FILE *outfile)
|
||||
{
|
||||
char cttypath[PATH_MAX+1];
|
||||
int rc;
|
||||
|
||||
{ /* On Linux this just gives "/dev/tty" */
|
||||
char s[L_ctermid+1];
|
||||
fprintf(outfile, "controlling terminal by ctermid(): \"%s\"\n", ctermid(s));
|
||||
}
|
||||
|
||||
{ /* Check if there is a controlling terminal */
|
||||
int fd;
|
||||
|
||||
if ((fd = Open("/dev/tty", O_NOCTTY, 0)) >= 0)
|
||||
/* On Linux this just gives "/dev/tty" */
|
||||
fprintf(outfile, "controlling terminal by /dev/tty, ttyname(): \"%s\"\n", Ttyname(fd));
|
||||
else
|
||||
fprintf(outfile, "controlling terminal by /dev/tty, ttyname(): (none)\n");
|
||||
}
|
||||
|
||||
#if HAVE_PROC_DIR
|
||||
do { /* Linux: derive ctty from info in /proc */
|
||||
const char procpath[] = "/proc/self/stat";
|
||||
FILE *procstat;
|
||||
unsigned int dev;
|
||||
int n = 0;
|
||||
unsigned int maj, min;
|
||||
|
||||
/* Linux: get device ids from /proc */
|
||||
if ((procstat = fopen(procpath, "r")) == NULL) {
|
||||
Warn1("failed to open \"%s\" for process info", procpath);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
n = fscanf(procstat, "%*s %*s %*s %*s %*s %*s %u", &dev);
|
||||
if (n != 1) {
|
||||
Warn1("failed to read ctty info from \"%s\"", procpath);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
maj = (dev>>8)&0xff;
|
||||
min = ((dev>>12)&0xfff00)|(dev&0xff);
|
||||
rc = find_devpath("/dev" /* _PATH_DEV has trailing "/" */, maj, min, cttypath);
|
||||
if (rc < 0) {
|
||||
snprintf(cttypath, PATH_MAX, "device %u, %u", maj, min);
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
rc = 0;
|
||||
} while (false);
|
||||
#else /* !HAVE_PROC_DIR */
|
||||
rc = -1;
|
||||
#endif /* !HAVE_PROC_DIR */
|
||||
if (rc >= 0)
|
||||
fprintf(outfile, "controlling terminal by /proc/<pid>/: \"%s\"\n", cttypath);
|
||||
else
|
||||
fprintf(outfile, "controlling terminal by /proc/<pid>/: (none)\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int procan(FILE *outfile) {
|
||||
|
||||
/*filan(0, outfile);*/
|
||||
|
||||
fprintf(outfile, "process id = "F_pid"\n", Getpid());
|
||||
fprintf(outfile, "process parent id = "F_pid"\n", Getppid());
|
||||
controlling_term(outfile);
|
||||
fprintf(outfile, "process group id = "F_pid"\n", Getpgrp());
|
||||
#if HAVE_GETSID
|
||||
fprintf(outfile, "process session id = "F_pid"\n", Getsid(0));
|
||||
#endif
|
||||
fprintf(outfile, "process group id if fg process / stdin = "F_pid"\n", Tcgetpgrp(0));
|
||||
fprintf(outfile, "process group id if fg process / stdout = "F_pid"\n", Tcgetpgrp(1));
|
||||
fprintf(outfile, "process group id if fg process / stderr = "F_pid"\n", Tcgetpgrp(2));
|
||||
|
||||
/* process owner, groups */
|
||||
fprintf(outfile, "user id = "F_uid"\n", Getuid());
|
||||
fprintf(outfile, "effective user id = "F_uid"\n", Geteuid());
|
||||
fprintf(outfile, "group id = "F_gid"\n", Getgid());
|
||||
fprintf(outfile, "effective group id = "F_gid"\n", Getegid());
|
||||
|
||||
/* Simple process features */
|
||||
fprintf(outfile, "\n");
|
||||
{
|
||||
mode_t mask;
|
||||
#if LATER
|
||||
char procpath[PATH_MAX];
|
||||
sprintf(procpath, "/proc/"F_pid"/status", Getpid());
|
||||
if (Stat()) {
|
||||
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
mask = Umask(0066);
|
||||
Umask(mask);
|
||||
}
|
||||
fprintf(outfile, "umask = "F_mode"\n", mask);
|
||||
}
|
||||
|
||||
{
|
||||
struct rlimit rlim;
|
||||
|
||||
fprintf(outfile, "\n/* Resource limits */\n");
|
||||
fprintf(outfile, "resource current maximum\n");
|
||||
if (getrlimit(RLIMIT_CPU, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_CPU, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"cpu time (seconds) %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
if (getrlimit(RLIMIT_FSIZE, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_FSIZE, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"file size (blocks) %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
if (getrlimit(RLIMIT_DATA, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_DATA, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"data seg size (kbytes) %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
if (getrlimit(RLIMIT_STACK, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_STACK, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"stack size (blocks) %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
if (getrlimit(RLIMIT_CORE, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_CORE, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"core file size (blocks) %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
#ifdef RLIMIT_RSS /* Linux, AIX; not Cygwin */
|
||||
if (getrlimit(RLIMIT_RSS, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_RSS, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"max resident set size %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
#endif
|
||||
#ifdef RLIMIT_NPROC /* Linux, not AIX, Cygwin */
|
||||
if (getrlimit(RLIMIT_NPROC, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_NPROC, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"max user processes %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
#endif
|
||||
#ifdef RLIMIT_NOFILE /* not AIX 4.1 */
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_NOFILE, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"open files %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
#endif
|
||||
#ifdef RLIMIT_MEMLOCK /* Linux, not AIX, Cygwin */
|
||||
if (getrlimit(RLIMIT_MEMLOCK, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_MEMLOCK, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"max locked-in-memory\n address space %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
#endif
|
||||
#ifdef RLIMIT_AS
|
||||
if (getrlimit(RLIMIT_AS, &rlim) < 0) {
|
||||
Warn2("getrlimit(RLIMIT_AS, %p): %s", &rlim, strerror(errno));
|
||||
} else {
|
||||
fprintf(outfile,
|
||||
"virtual memory (kbytes) %24"F_rlim_max"%24"F_rlim_max"\n",
|
||||
rlim.rlim_cur, rlim.rlim_max);
|
||||
}
|
||||
#endif
|
||||
fputc('\n', outfile);
|
||||
|
||||
}
|
||||
|
||||
#ifdef CC
|
||||
fprintf(outfile, "// CC: "CC"\n");
|
||||
#endif
|
||||
#ifdef __STDC_VERSION__
|
||||
fprintf(outfile, "#define __STDC_VERSION__ %ld\n", __STDC_VERSION__);
|
||||
#endif
|
||||
#ifdef SIZE_MAX
|
||||
fprintf(outfile, "SIZE_MAX = "F_Zu" /* maximum value of size_t */\n", SIZE_MAX);
|
||||
#endif
|
||||
#ifdef P_tmpdir
|
||||
fprintf(outfile, "P_tmpdir = \"%s\"\n", P_tmpdir);
|
||||
#endif
|
||||
#ifdef L_tmpnam
|
||||
fprintf(outfile, "L_tmpnam = %u\n", L_tmpnam);
|
||||
#endif
|
||||
#ifdef TMP_MAX
|
||||
fprintf(outfile, "TMP_MAX = %d\n", TMP_MAX);
|
||||
#endif
|
||||
#ifdef FD_SETSIZE
|
||||
fprintf(outfile, "FD_SETSIZE = %d /* maximum number of FDs for select() */\n", FD_SETSIZE);
|
||||
#endif
|
||||
#ifdef PIPE_BUF
|
||||
fprintf(outfile, "PIPE_BUF = %-24d\n", PIPE_BUF);
|
||||
#endif
|
||||
|
||||
/* Name spaces */
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char link[PATH_MAX];
|
||||
snprintf(path, sizeof(path)-1, "/proc/"F_pid"/ns/net", getpid());
|
||||
if (readlink(path, link, sizeof(link)-1) >= 0) {
|
||||
fprintf(outfile, "Network namespace: %s", link);
|
||||
}
|
||||
}
|
||||
|
||||
/* file descriptors */
|
||||
|
||||
/* what was this for?? */
|
||||
/*Sleep(1);*/
|
||||
return 0;
|
||||
}
|
||||
11
procan.h
Normal file
11
procan.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* source: procan.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __procan_h_included
|
||||
#define __procan_h_included 1
|
||||
|
||||
extern int procan(FILE *outfile);
|
||||
extern int procan_cdefs(FILE *outfile);
|
||||
|
||||
#endif /* !defined(__procan_h_included) */
|
||||
102
procan_main.c
Normal file
102
procan_main.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/* source: procan_main.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
const char copyright[] = "procan by Gerhard Rieger and contributors - send bug reports to socat@dest-unreach.org";
|
||||
|
||||
#include <signal.h> /* sig_atomic_t for error.h */
|
||||
#include <time.h> /* struct timespec for error.h */
|
||||
#include <stdlib.h> /* strtoul() */
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h"
|
||||
#if HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h> /* select(), fdset on FreeBSD */
|
||||
#endif
|
||||
#include "mytypes.h"
|
||||
#include "error.h"
|
||||
#include "procan.h"
|
||||
#include "hostan.h"
|
||||
|
||||
|
||||
#define WITH_HELP 1
|
||||
|
||||
static void procan_usage(FILE *fd);
|
||||
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
const char **arg1;
|
||||
#if 0
|
||||
unsigned int n = 1024; /* this is default on my Linux */
|
||||
#endif
|
||||
|
||||
diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
|
||||
|
||||
arg1 = argv+1; --argc;
|
||||
while (arg1[0] && (arg1[0][0] == '-')) {
|
||||
switch (arg1[0][1]) {
|
||||
#if WITH_HELP
|
||||
case '?': case 'h': procan_usage(stdout); exit(0);
|
||||
#endif /* WITH_HELP */
|
||||
case 'c': procan_cdefs(stdout); exit(0);
|
||||
#if LATER
|
||||
case 'V': procan_version(stdout); exit(0);
|
||||
case 'l': diag_set(arg1[0][2], &arg1[0][3]); break;
|
||||
case 'd': diag_set('d', NULL); break;
|
||||
#endif
|
||||
#if 0
|
||||
case 'n': n = strtoul(&arg1[0][2], NULL, 0); break;
|
||||
#endif
|
||||
case '\0': break;
|
||||
default:
|
||||
diag_set_int('e', E_FATAL);
|
||||
Error1("unknown option \"%s\"", arg1[0]);
|
||||
#if WITH_HELP
|
||||
procan_usage(stderr);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
if (arg1[0][1] == '\0')
|
||||
break;
|
||||
++arg1; --argc;
|
||||
}
|
||||
if (argc != 0) {
|
||||
Error1("%d superfluous arguments", argc);
|
||||
#if WITH_HELP
|
||||
procan_usage(stderr);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
procan(stdout);
|
||||
hostan(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if WITH_HELP
|
||||
static void procan_usage(FILE *fd) {
|
||||
fputs(copyright, fd); fputc('\n', fd);
|
||||
fputs("Analyze system parameters of process\n", fd);
|
||||
fputs("Usage:\n", fd);
|
||||
fputs("procan [options]\n", fd);
|
||||
fputs(" options:\n", fd);
|
||||
#if LATER
|
||||
fputs(" -V print version information to stdout, and exit\n", fd);
|
||||
#endif
|
||||
#if WITH_HELP
|
||||
fputs(" -?|-h print a help text describing command line options\n", fd);
|
||||
#endif
|
||||
fputs(" -c print values of compile time C defines\n", fd);
|
||||
#if LATER
|
||||
fputs(" -d increase verbosity (use up to 4 times; 2 are recommended)\n", fd);
|
||||
#endif
|
||||
#if 0
|
||||
fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd);
|
||||
fputs(" -lf<logfile> log to file\n", fd);
|
||||
fputs(" -ls log to stderr (default if no other log)\n", fd);
|
||||
#endif
|
||||
#if 0
|
||||
fputs(" -n<fdnum> first file descriptor number not analyzed\n", fd);
|
||||
#endif
|
||||
}
|
||||
#endif /* WITH_HELP */
|
||||
93
proxy.sh
Executable file
93
proxy.sh
Executable file
@@ -0,0 +1,93 @@
|
||||
#! /usr/bin/env bash
|
||||
# source: proxy.sh
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# perform primitive simulation of a proxy server.
|
||||
# accepts and answers correct HTTP CONNECT requests on stdio, and tries to
|
||||
# establish the connection to the given server.
|
||||
# it is required for socats test.sh
|
||||
# for TCP, use this script like:
|
||||
# socat TCP-L:8080,reuseaddr,fork EXEC:"proxy.sh",nofork
|
||||
|
||||
# 20130622 GR allow hostnames, not only IP addresses
|
||||
|
||||
if [ -z "$SOCAT" ]; then
|
||||
if type socat >/dev/null 2>&1; then
|
||||
SOCAT=socat
|
||||
else
|
||||
SOCAT="./socat"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $(echo "x\c") = "x" ]; then E=""
|
||||
elif [ $(echo -e "x\c") = "x" ]; then E="-e"
|
||||
else
|
||||
echo "cannot suppress trailing newline on echo" >&2
|
||||
exit 1
|
||||
fi
|
||||
ECHO="echo $E"
|
||||
CR=$($ECHO "\r")
|
||||
#echo "CR=$($ECHO "$CR\c" |od -c)" >&2
|
||||
|
||||
case `uname` in
|
||||
HP-UX|OSF1)
|
||||
# their cats are too stupid to work with unix domain sockets
|
||||
CAT="$SOCAT -u stdin stdout"
|
||||
;;
|
||||
*)
|
||||
CAT=cat
|
||||
;;
|
||||
esac
|
||||
|
||||
SPACES=" "
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-w) n="$2"; while [ "$n" -gt 0 ]; do SPACES="$SPACES "; n=$((n-1)); done
|
||||
shift ;;
|
||||
#-s) STAT="$2"; shift ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
badrequest () {
|
||||
$ECHO "HTTP/1.0${SPACES}500 Bad Request$CR"
|
||||
$ECHO "$CR"
|
||||
}
|
||||
|
||||
# read and parse HTTP request
|
||||
read m a h
|
||||
#echo "\"$m\" \"$a\" \"$h\"" >&2
|
||||
if [ "$m" != 'CONNECT' ]; then
|
||||
badrequest; exit 1
|
||||
fi
|
||||
if [[ "$a" == [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ ]]; then
|
||||
: go on below
|
||||
elif [[ "$a" == [0-9a-zA-Z-.][0-9a-zA-Z-.]*:[0-9][0-9]* ]]; then
|
||||
: go on below
|
||||
else
|
||||
badrequest; exit 1
|
||||
fi
|
||||
|
||||
if [[ "$h" == HTTP/1.[01][[:space:]]* ]]; then
|
||||
: go on below
|
||||
else
|
||||
badrequest; exit 1
|
||||
fi
|
||||
|
||||
# read more headers until empty line
|
||||
while [ "$l" != "$CR" ]; do
|
||||
read l
|
||||
done
|
||||
|
||||
# send status
|
||||
$ECHO "HTTP/1.0${SPACES}200 OK$CR"
|
||||
# send empty line
|
||||
$ECHO "$CR"
|
||||
|
||||
# perform proxy (relay) function
|
||||
$SOCAT $SOCAT_OPTS - tcp:$a || {
|
||||
$ECHO "HTTP/1.0${SPACES}500 Failed to connect to $a$CR"
|
||||
$ECHO $CR
|
||||
}
|
||||
|
||||
66
proxyecho.sh
Executable file
66
proxyecho.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#! /usr/bin/env bash
|
||||
# source: proxyecho.sh
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# perform primitive simulation of a proxy server with echo function via stdio.
|
||||
# accepts and answers correct HTTP CONNECT requests, but then just echoes data.
|
||||
# it is required for test.sh
|
||||
# for TCP, use this script as:
|
||||
# socat TCP-L:8080,reuseaddr,crlf SYSTEM:"proxyecho.sh"
|
||||
|
||||
# 20230423 GR Added option -V to require particular HTTP version
|
||||
|
||||
if type socat >/dev/null 2>&1; then
|
||||
SOCAT=socat
|
||||
else
|
||||
SOCAT=./socat
|
||||
fi
|
||||
|
||||
case `uname` in
|
||||
HP-UX|OSF1)
|
||||
CAT="$SOCAT -u stdin stdout"
|
||||
;;
|
||||
*)
|
||||
CAT=cat
|
||||
;;
|
||||
esac
|
||||
|
||||
SPACES=" " REQVER=1.0
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-w) n="$2"; while [ "$n" -gt 0 ]; do SPACES="$SPACES "; n=$((n-1)); done
|
||||
shift ;;
|
||||
-V) shift; REQVER="$1" ;;
|
||||
#-s) STAT="$2"; shift ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# read and parse HTTP request
|
||||
read l
|
||||
if ! echo "$l" |egrep '^CONNECT +[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ +HTTP/[1-3].[0-9]$' >/dev/null
|
||||
then
|
||||
echo "HTTP/1.0${SPACES}500 Bad Request"
|
||||
echo
|
||||
exit
|
||||
fi
|
||||
if ! echo "$l" |egrep '^CONNECT +[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ +HTTP/'"$REQVER"'$' >/dev/null
|
||||
then
|
||||
echo "HTTP/1.0${SPACES}426 Upgrade Required"
|
||||
echo
|
||||
exit
|
||||
fi
|
||||
|
||||
# read more headers until empty line
|
||||
while [ -n "$l" ]; do
|
||||
read l
|
||||
done
|
||||
|
||||
# send status
|
||||
echo "HTTP/$REQVER${SPACES}200 OK"
|
||||
# send empty line
|
||||
echo
|
||||
|
||||
# perform echo function
|
||||
exec $CAT
|
||||
47
readline-test.sh
Executable file
47
readline-test.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#! /usr/bin/env bash
|
||||
# source: readline-test.sh
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# script that simulates a simple program with authentication.
|
||||
# is just for testing the readline features
|
||||
# perform the test with something like:
|
||||
# ./socat readline,history=$HOME/.history,noecho='^Password: ' system:./readline-test.sh,pty,setsid,ctty,stderr,sigint,sigquit,echo=0,raw
|
||||
|
||||
|
||||
BANNER='readline feature test program'
|
||||
USERPROMPT='Authentication required\nUsername: '
|
||||
PWDPROMPT='Password: '
|
||||
PROMPT='prog> '
|
||||
|
||||
# degenerated user database
|
||||
CREDUSER="user"
|
||||
CREDPASS="password"
|
||||
|
||||
if [ $(echo "x\c") = "x" ]; then ECHO="echo"
|
||||
elif [ $(echo -e "x\c") = "x" ]; then ECHO="echo -e"
|
||||
fi
|
||||
|
||||
#trap "$ECHO $0 got SIGINT" INT
|
||||
trap "$ECHO $0 got SIGINT" INT
|
||||
trap "$ECHO $0 got SIGQUIT" QUIT
|
||||
|
||||
# print banner
|
||||
$ECHO "$BANNER"
|
||||
|
||||
# on (some) ksh read -p does not mean prompt
|
||||
$ECHO "$USERPROMPT\c"; read -r USERNAME
|
||||
$ECHO "$PWDPROMPT\c"; read -rs PASSWORD
|
||||
$ECHO
|
||||
|
||||
if [ "$USERNAME" != "$CREDUSER" -o "$PASSWORD" != "$CREDPASS" ]; then
|
||||
$ECHO "Authentication failed" >&2
|
||||
exit -1
|
||||
fi
|
||||
|
||||
while $ECHO "$PROMPT\c"; read -r COMMAND; do
|
||||
if [ "$COMMAND" = "exit" ]; then
|
||||
break;
|
||||
fi
|
||||
$ECHO "executing $COMMAND"
|
||||
done
|
||||
30
readline.sh
Executable file
30
readline.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#! /usr/bin/env bash
|
||||
# source: readline.sh
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# this is an attempt for a socat based readline wrapper
|
||||
# usage: readline.sh <command>
|
||||
|
||||
withhistfile=1
|
||||
|
||||
while true; do
|
||||
case "X$1" in
|
||||
X-nh|X-nohist*) withhistfile=; shift; continue ;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
PROGRAM="$@"
|
||||
if [ "$withhistfile" ]; then
|
||||
HISTFILE="$HOME/.$1_history"
|
||||
HISTOPT=",history=$HISTFILE"
|
||||
else
|
||||
HISTOPT=
|
||||
fi
|
||||
mkdir -p /tmp/$USER || exit 1
|
||||
#
|
||||
#
|
||||
|
||||
exec socat -d readline"$HISTOPT",noecho='[Pp]assword:' exec:"$PROGRAM",sigint,pty,setsid,ctty,raw,echo=0,stderr 2>/tmp/$USER/stderr2
|
||||
|
||||
85
snprinterr.c
Normal file
85
snprinterr.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/* snprinterr.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
|
||||
/* a function similar to vsnprintf() but it just handles %m */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <ctype.h> /* isdigit() */
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#if HAVE_SYSLOG_H
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <sys/utsname.h>
|
||||
#include <time.h> /* time_t, strftime() */
|
||||
#include <sys/time.h> /* gettimeofday() */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "snprinterr.h"
|
||||
|
||||
#define HAVE_STRERROR_R 0
|
||||
/* replace %m in format with actual strerror() message, write result to *str.
|
||||
keep other % formats unchanged!
|
||||
writes at most size chars including the terminating \0 to *str
|
||||
returns the number of bytes in the output without terminating \0
|
||||
result is always \0 terminated except when size==0
|
||||
*/
|
||||
int snprinterr(char *str, size_t size, const char *format) {
|
||||
char c;
|
||||
int full = 0; /* 1 means: there is no space left in * str for more data or \0 */
|
||||
int count = 0;
|
||||
if (size == 0) return 0;
|
||||
if (count >= size) full = 1;
|
||||
while (c = *format++) {
|
||||
if (c == '%') {
|
||||
c = *format++;
|
||||
switch (c) {
|
||||
case '\0':
|
||||
++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
|
||||
break;
|
||||
default:
|
||||
++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
|
||||
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
|
||||
break;
|
||||
case 'm':
|
||||
{
|
||||
#if HAVE_STRERROR_R
|
||||
# define BUFLEN 64
|
||||
char buf[BUFLEN] = "";
|
||||
#endif /* HAVE_STRERROR_R */
|
||||
char *bufp;
|
||||
#if !HAVE_STRERROR_R
|
||||
bufp = strerror(errno);
|
||||
#else
|
||||
/* there are two versions floating around... */
|
||||
# if 1 /* GNU version */
|
||||
bufp = strerror_r(errno, buf, BUFLEN);
|
||||
# else /* standard version */
|
||||
strerror_r(errno, buf, BUFLEN);
|
||||
bufp = buf;
|
||||
# endif
|
||||
#endif /* HAVE_STRERROR_R */
|
||||
while ((c = *bufp++) != '\0') {
|
||||
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
|
||||
}
|
||||
}
|
||||
c = ' '; /* not \0 ! */
|
||||
break;
|
||||
}
|
||||
if (c == '\0') break;
|
||||
} else {
|
||||
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
|
||||
}
|
||||
}
|
||||
*str++ = '\0'; /* always write terminating \0 */
|
||||
return count;
|
||||
#undef BUFLEN
|
||||
}
|
||||
|
||||
10
snprinterr.h
Normal file
10
snprinterr.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* source: snprinterr.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __snprinterr_h_included
|
||||
#define __snprinterr_h_included 1
|
||||
|
||||
int snprinterr(char *str, size_t size, const char *format);
|
||||
|
||||
#endif /* !defined(__snprinterr_h_included) */
|
||||
83
socat-broker.sh
Executable file
83
socat-broker.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#! /usr/bin/env bash
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# Shell script to perform group communications, sometimes called brokering.
|
||||
# It starts a Socat instance that forks a child process for each
|
||||
# connected client; the clients communicate via IPv4 broadcast
|
||||
|
||||
# Examples:
|
||||
|
||||
# socat-broker.sh TCP-L:1234
|
||||
# Now connect with an arbitrary number of clients like TCP:<server>:1234
|
||||
|
||||
# socat-broker.sh SSL-L:1234,cert=server.pem,cafile=clients.crt
|
||||
# Now connect with an arbitrary number of clients like SSL:<server>:1234,cafile=server.cert=clients.pem
|
||||
|
||||
ECHO="echo -e"
|
||||
|
||||
usage () {
|
||||
$ECHO "Usage: $0 <options> <listener>"
|
||||
$ECHO " <listener> is a passive address like TCP4-L or SSL-L"
|
||||
$ECHO " <options>:"
|
||||
$ECHO " -d* -S -t <timeout> -T <timeout> are passed to socat"
|
||||
$ECHO " -V prints the socat command before starting it"
|
||||
$ECHO "For example:"
|
||||
$ECHO " $0 \\"
|
||||
$ECHO " TCP4-L:1234"
|
||||
$ECHO "Then connect with clients to port 1234"
|
||||
$ECHO "Data sent by any client is forwarded to all other clients"
|
||||
}
|
||||
|
||||
VERBOSE= QUIET= OPTS=
|
||||
while [ "$1" ]; do
|
||||
case "X$1" in
|
||||
X-h) usage; exit ;;
|
||||
X-V) VERBOSE=1 ;;
|
||||
X-q) QUIET=1; OPTS="-d0" ;;
|
||||
X-d*|X-l?*) OPTS="$OPTS $1" ;;
|
||||
X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;;
|
||||
X-) break ;;
|
||||
X-*) echo "Unknown option \"$1\"" >&2
|
||||
usage >&2
|
||||
exit 1 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
LISTENER="$1"
|
||||
|
||||
if [ -z "$LISTENER" ]; then
|
||||
echo "$0: Missing parameter" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shopt -s nocasematch
|
||||
if ! [[ "$LISTENER" =~ .*,fork ]] || [[ "$LISTENER" =~ .*,fork, ]]; then
|
||||
LISTENER="$LISTENER,fork"
|
||||
fi
|
||||
|
||||
case "$0" in
|
||||
*/*) SOCAT=${0%/*}/socat ;;
|
||||
*) SOCAT=socat ;;
|
||||
esac
|
||||
|
||||
PORT=$($SOCAT -d -d -T 0.000001 UDP4-RECV:0 /dev/null 2>&1 |grep bound |sed 's/.*:\([1-9][0-9]*\)$/\1/')
|
||||
if [ -z "$PORT" ]; then
|
||||
echo "$0: Failed to determine free UDP port" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BCADDR=127.255.255.255
|
||||
|
||||
if [ "$VERBOSE" ]; then
|
||||
echo -e "$SOCAT -lp socat-broker $OPTS \\
|
||||
$LISTENER \
|
||||
UDP4-DATAGRAM:$BCADDR:$PORT,bind=:$PORT,so-broadcast,so-reuseaddr"
|
||||
fi
|
||||
$SOCAT -lp socat-broker $OPTS \
|
||||
"$LISTENER" \
|
||||
"UDP4-DATAGRAM:$BCADDR:$PORT,bind=:$PORT,so-broadcast,so-reuseaddr"
|
||||
|
||||
264
socat-chain.sh
Executable file
264
socat-chain.sh
Executable file
@@ -0,0 +1,264 @@
|
||||
#! /usr/bin/env bash
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# Shell script to build a chain of Socat instances connected via TCP sockets.
|
||||
# This allows to drive, e.g., PROXY-CONNECT over SSL, or SSL over serial.
|
||||
# Currently only a chain made from 3 addresses, resulting in two instances, is
|
||||
# implemented.
|
||||
# The 2nd address must be one of OPENSSL (SSL), PROXY-CONNECT (PROXY),
|
||||
# SOCKS4, SOCKS4A, SOCKS5
|
||||
|
||||
# This is beta!
|
||||
|
||||
# Examples:
|
||||
|
||||
# Drive HTTP CONNECT (PROXY) over SSL
|
||||
# (establish an SSL tunnel to a proxy server, request being forwarded to a
|
||||
# telnet server):
|
||||
# socat-chain.sh \
|
||||
# STDIO \
|
||||
# PROXY::<telnet-server>:23 \
|
||||
# OPENSSL:<proxy-server>:8443
|
||||
|
||||
# Accept connections that arrive on port 7777, encrypt the data, and send it
|
||||
# via socks server to final target:
|
||||
# socat-chain.sh \
|
||||
# TCP-L:7777,reuseaddr,fork \
|
||||
# OPENSSL,verify=0 \
|
||||
# SOCKS4:<socks-server>:<ssl-server>:8443
|
||||
|
||||
# Receive SSL coming from a serial lie
|
||||
# socat-chain.sh \
|
||||
# /dev/ttyS0,cfmakeraw \
|
||||
# SSL-L,cafile=server.pem,verify=0 \
|
||||
# TCP4:localhost:80
|
||||
|
||||
# Formally, this is what happens:
|
||||
# socat-chain.sh addr1 addr2 addr3
|
||||
# results in something like:
|
||||
# socat TCP-L:RANDOM addr3 &
|
||||
# socat addr1 addr2:localhost:RANDOM
|
||||
# or on passive/listening addr2:
|
||||
# socat addr2:RANDOM addr3 &
|
||||
# socat addr1 TCP:localhost:RANDOM
|
||||
|
||||
ECHO="echo -e"
|
||||
|
||||
usage () {
|
||||
$ECHO "Usage: $0 <options> <address1> <address2> <address3>"
|
||||
$ECHO " <address1> is typically a passive (listening) address like"
|
||||
$ECHO " TCP-L:1234"
|
||||
$ECHO " <address2> must be one of OPENSSL, PROXY, SOCK4, SOCKS4A, or SOCKS5,"
|
||||
$ECHO " or SSL-L (passive/listening)"
|
||||
$ECHO " Given server hostname and port are ignored and replaced by internal"
|
||||
$ECHO " communication point"
|
||||
$ECHO " <address3> is typically a client address with protocol like OPENSSL"
|
||||
$ECHO " <options>:"
|
||||
$ECHO " -d* -S <sigmask> -t <timeout> -T <timeout> are passed to socat"
|
||||
$ECHO " -V prints the socat commands before starting them"
|
||||
$ECHO "Example to drive SOCKS over TLS:"
|
||||
$ECHO " $0 \\"
|
||||
$ECHO " TCP4-L:1234,reuseaddr,fork \\"
|
||||
$ECHO " SOCKS::<server>:<port> \\"
|
||||
$ECHO " OPENSSL:10.2.3.4:12345,cafile=..."
|
||||
$ECHO " Clients that connect to port 1234 will be forwarded to <server>:<port> using socks"
|
||||
$ECHO " over TLS"
|
||||
}
|
||||
|
||||
|
||||
LOCALHOST=127.0.0.1
|
||||
|
||||
VERBOSE= QUIET= OPTS=
|
||||
while [ "$1" ]; do
|
||||
case "X$1" in
|
||||
X-h) usage; exit ;;
|
||||
X-V) VERBOSE=1 ;;
|
||||
X-q) QUIET=1; OPTS="-d0" ;;
|
||||
X-d*|X-l?*) OPTS="$OPTS $1" ;;
|
||||
X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;;
|
||||
X-) break ;;
|
||||
X-*) echo "$0: Unknown option \"$1\"" >&2
|
||||
usage >&2
|
||||
exit 1 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
ARG0="$1"
|
||||
ARG1="$2"
|
||||
ARG2="$3"
|
||||
|
||||
if [ -z "$ARG0" -o -z "$ARG1" -o -z "$ARG2" ]; then
|
||||
echo "$0: Three addresses required" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
mkprogname () {
|
||||
ARG="$1"
|
||||
if [[ "$ARG" =~ .*[:].* ]]; then
|
||||
NAME="${ARG%%:*}"
|
||||
elif [[ "$ARG" =~ .*[,].* ]]; then
|
||||
NAME="${ARG%%,*}"
|
||||
elif [ "X$ARG" = X- ]; then
|
||||
NAME=stdio
|
||||
else
|
||||
NAME="$ARG"
|
||||
fi
|
||||
NAME="${NAME,,*}"
|
||||
echo $NAME
|
||||
}
|
||||
|
||||
|
||||
# You may place a fork option in the first address
|
||||
# in which case the following internal listeners do fork too
|
||||
FORK=
|
||||
case "$ARG0" in
|
||||
*,fork,*|*,fork) FORK=fork ;;
|
||||
esac
|
||||
|
||||
# Split middle address for insertion of additional parts
|
||||
if [[ "$ARG1" =~ .*,.* ]]; then
|
||||
ARG1A="${ARG1%%,*}"
|
||||
ARG1B="${ARG1#*,}"
|
||||
else
|
||||
ARG1A="$ARG1"
|
||||
ARG1B=
|
||||
fi
|
||||
|
||||
case "$0" in
|
||||
*/*) SOCAT=${0%/*}/socat ;;
|
||||
*) SOCAT=socat ;;
|
||||
esac
|
||||
|
||||
PORT=$($SOCAT -d -d TCP4-L:0,accept-timeout=0.000001 /dev/null 2>&1 |grep listening |sed 's/.*:\([1-9][0-9]*\)$/\1/')
|
||||
if [ -z "$PORT" ]; then
|
||||
echo "$0: Failed to determine free TCP port" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PASSIVE= # is the second address passive/listening/server?
|
||||
case "${ARG1A^^*}" in
|
||||
OPENSSL|OPENSSL:*|SSL|SSL:.*)
|
||||
OPTS1A=
|
||||
#if [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3
|
||||
if [[ $ARG1A =~ ^([^:]*):([^:]*):([^,]*)(.*) ]]; then
|
||||
OPTS1A="${BASH_REMATCH[4]}"
|
||||
#elif [[ $ARG1A =~ ^\([^,]*\)\(.*\) ]]; then # bash 3
|
||||
elif [[ $ARG1A =~ ^([^,]*)(.*) ]]; then
|
||||
OPTS1A="${BASH_REMATCH[2]}"
|
||||
else
|
||||
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||
exit 1
|
||||
fi
|
||||
PROG1="${BASH_REMATCH[1]}"
|
||||
NAME1=$(mkprogname "${BASH_REMATCH[1]}")
|
||||
NAME2=$(mkprogname "$ARG2")
|
||||
ARG1A=$PROG1:$LOCALHOST:$PORT$OPTS1A ;;
|
||||
PROXY-CONNECT:*|PROXY:*)
|
||||
#if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3
|
||||
if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^,]*)(.*) ]]; then
|
||||
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||
exit 1
|
||||
fi
|
||||
#echo "0:\"${BASH_REMATCH[0]}\" 1:\"${BASH_REMATCH[1]}\" 2:\"${BASH_REMATCH[2]}\" 3:\"${BASH_REMATCH[3]}\" 4:\"${BASH_REMATCH[4]}\""
|
||||
PROG1="${BASH_REMATCH[1]}"
|
||||
NAME1=$(mkprogname "${PROG1,,*}")
|
||||
NAME2=$(mkprogname "$ARG2")
|
||||
OPTS1A="${BASH_REMATCH[5]}"
|
||||
ARG1A="$PROG1:$LOCALHOST:${BASH_REMATCH[3]}:${BASH_REMATCH[4]},proxyport=$PORT,$OPTS1A" ;;
|
||||
SOCKS:*|SOCKS4:*|SOCKS4A*)
|
||||
#if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^:,]*\),* ]]; then # bash 3
|
||||
if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^:,]*),* ]]; then
|
||||
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||
exit 1
|
||||
fi
|
||||
PROG1="${BASH_REMATCH[1]}"
|
||||
NAME1=$(mkprogname "${PROG1,,*}")
|
||||
NAME2=$(mkprogname "$ARG2")
|
||||
OPTS1A="${BASH_REMATCH[5]}"
|
||||
ARG1A="$PROG1:$LOCALHOST:${BASH_REMATCH[3]}:${BASH_REMATCH[4]},socksport=$PORT,$OPTS1A" ;;
|
||||
SOCKS5:*|SOCKS5-CONNECT*)
|
||||
#if ! [[ $ARG1A =~ ^\([^:]*\):\([^:]*\):\([^:]*\):\([^:,]*\):\([^:,]*\),* ]]; then # bash 3
|
||||
if ! [[ $ARG1A =~ ^([^:]*):([^:]*):([^:]*):([^:,]*):([^:,]*),* ]]; then
|
||||
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||
exit 1
|
||||
fi
|
||||
PROG1="${BASH_REMATCH[1]}"
|
||||
NAME1=$(mkprogname "${PROG1,,*}")
|
||||
NAME2=$(mkprogname "$ARG2")
|
||||
OPTS1A="${BASH_REMATCH[6]}"
|
||||
ARG1A="$PROG1:$LOCALHOST:$PORT:${BASH_REMATCH[4]}:${BASH_REMATCH[5]},$OPTS1A" ;;
|
||||
# Passive (server) addresses
|
||||
OPENSSL-LISTEN|OPENSSL-LISTEN:*|SSL-L|SSL-L:.*)
|
||||
PASSIVE=1
|
||||
OPTS1A=
|
||||
#if [[ $ARG1A =~ ^\([^:]*\):\([^,]*\)\(.*\) ]]; then # bash 3
|
||||
if [[ $ARG1A =~ ^([^:]*):([^,]*)(.*) ]]; then
|
||||
OPTS1A="${BASH_REMATCH[3]}"
|
||||
#elif [[ $ARG1A =~ ^\([^,]*\)\(.*\) ]]; then # bash 3
|
||||
elif [[ $ARG1A =~ ^([^,]*)(.*) ]]; then
|
||||
OPTS1A="${BASH_REMATCH[2]}"
|
||||
else
|
||||
echo "$0: \"$ARG1A\": invalid arguments" >&2
|
||||
exit 1
|
||||
fi
|
||||
PROG1="${BASH_REMATCH[1]}"
|
||||
NAME1=$(mkprogname "$ARG0")
|
||||
NAME2=$(mkprogname "${BASH_REMATCH[1]}")
|
||||
ARG1A=$PROG1:$PORT$OPTS1A ;;
|
||||
*) echo "$0: Unsupported address \"$ARG1A\"" >&2
|
||||
usage >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
|
||||
ADDR1A="$ARG0"
|
||||
if [ -z "$PASSIVE" ]; then
|
||||
ADDR1B="$ARG1A,bind=$LOCALHOST,$ARG1B"
|
||||
ADDR2A="TCP4-L:$PORT,reuseaddr,$FORK,bind=$LOCALHOST,range=$LOCALHOST/32"
|
||||
else
|
||||
ADDR1B="TCP4:$LOCALHOST:$PORT,bind=$LOCALHOST"
|
||||
ADDR2A="$ARG1A,reuseaddr,$FORK,bind=$LOCALHOST,range=$LOCALHOST/32,$ARG1B"
|
||||
fi
|
||||
ADDR2B="$ARG2"
|
||||
|
||||
|
||||
pid1= pid2=
|
||||
trap '[ "$pid1" ] && kill $pid1 2>/dev/null; [ "$pid2" ] && kill $pid2 2>/dev/null' EXIT
|
||||
|
||||
set -bm
|
||||
trap 'rc=$?; if ! kill -n 0 $pid2 2>/dev/null; then [ -z "$QUIET" -a $rc -ne 0 ] && echo "$0: socat-$NAME2 exited with rc=$rc" >&2; exit $rc; fi' SIGCHLD
|
||||
|
||||
# Start instance 2 first, because instance 1 ("left") connects to 2
|
||||
if [ "$VERBOSE" ]; then
|
||||
$ECHO "$SOCAT $OPTS -lp socat-$NAME2 \\
|
||||
\"$ADDR2A\" \\
|
||||
\"$ADDR2B\" &"
|
||||
fi
|
||||
$SOCAT $OPTS -lp socat-$NAME2 \
|
||||
"$ADDR2A" \
|
||||
"$ADDR2B" &
|
||||
pid2=$!
|
||||
sleep 0.1
|
||||
|
||||
#trap 'if ! kill -n 0 $pid1 2>/dev/null; then [ -z "$QUIET" ] && echo "$0: socat-$NAME1 exited with rc=$?" >&2; kill $pid2 2>/dev/null; exit 1; elif ! kill -n 0 $pid2 2>/dev/null; then [ -z "$QUIET" ] && echo "$0: socat-$NAME2 exited with rc=$?" >&2; kill $pid1 2>/dev/null; exit 1; fi' SIGCHLD
|
||||
|
||||
if [ "$VERBOSE" ]; then
|
||||
$ECHO "$SOCAT $OPTS -lp socat-$NAME1 \\
|
||||
\"$ADDR1A\" \\
|
||||
\"$ADDR1B\""
|
||||
fi
|
||||
$SOCAT $OPTS -lp socat-$NAME1 \
|
||||
"$ADDR1A" \
|
||||
"$ADDR1B"
|
||||
#pid1=$!
|
||||
rc1=$?
|
||||
|
||||
kill $pid2 2>/dev/null
|
||||
wait 2>/dev/null
|
||||
#wait -f
|
||||
|
||||
exit $rc1
|
||||
115
socat-mux.sh
Executable file
115
socat-mux.sh
Executable file
@@ -0,0 +1,115 @@
|
||||
#! /usr/bin/env bash
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# Shell script to build a many-to-one, one-to-all communication
|
||||
# It starts two Socat instances that communicate via IPv4 broadcast,
|
||||
# the first of which forks a child process for each connected client.
|
||||
|
||||
# Example:
|
||||
|
||||
# Consider a serial device connected to the Internet on TCP port 1234, it
|
||||
# accepts only one connection at a time.
|
||||
# On a proxy/relay server run this script:
|
||||
# socat-mux.sh \
|
||||
# TCP-L:1234,reuseaddr,fork \
|
||||
# TCP:<addr-of-device>:1234
|
||||
# Now connect with an arbitrary number of clients to TCP:<proxy>:1234;
|
||||
# data sent by the device goes to all clients, data from any client is sent to
|
||||
# the device.
|
||||
|
||||
ECHO="echo -e"
|
||||
|
||||
usage () {
|
||||
$ECHO "Usage: $0 <options> <listener> <target>"
|
||||
$ECHO "Example:"
|
||||
$ECHO " $0 TCP4-L:1234,reuseaddr,fork TCP:10.2.3.4:12345"
|
||||
$ECHO "Clients may connect to port 1234; data sent by any client is forwarded to 10.2.3.4,"
|
||||
$ECHO "data provided by 10.2.3.4 is sent to ALL clients"
|
||||
$ECHO " <options>:"
|
||||
$ECHO "\t-h\tShow this help text and exit"
|
||||
$ECHO "\t-V\tShow Socat commands"
|
||||
$ECHO "\t-q\tSuppress most messages"
|
||||
$ECHO "\t-d*\tOptions beginning with -d are passed to Socat processes"
|
||||
$ECHO "\t-l*\tOptions beginning with -l are passed to Socat processes"
|
||||
$ECHO "\t-b|-S|-t|-T|-l <arg>\tThese options are passed to Socat processes"
|
||||
}
|
||||
|
||||
VERBOSE= QUIET= OPTS=
|
||||
while [ "$1" ]; do
|
||||
case "X$1" in
|
||||
X-h) usage; exit ;;
|
||||
X-V) VERBOSE=1 ;;
|
||||
X-q) QUIET=1; OPTS="-d0" ;;
|
||||
X-d*|X-l?*) OPTS="$OPTS $1" ;;
|
||||
X-b|X-S|X-t|X-T|X-l) OPT=$1; shift; OPTS="$OPTS $OPT $1" ;;
|
||||
X-) break ;;
|
||||
X-*) echo "$0: Unknown option \"$1\"" >&2
|
||||
usage >&2
|
||||
exit 1 ;;
|
||||
*) break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
LISTENER="$1"
|
||||
TARGET="$2"
|
||||
|
||||
if [ -z "$LISTENER" -o -z "$TARGET" ]; then
|
||||
echo "$0: Missing parameter(s)" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shopt -s nocasematch
|
||||
if ! [[ "$LISTENER" =~ .*,fork ]] || [[ "$LISTENER" =~ .*,fork, ]]; then
|
||||
LISTENER="$LISTENER,fork"
|
||||
fi
|
||||
|
||||
case "$0" in
|
||||
*/*) SOCAT=${0%/*}/socat ;;
|
||||
*) SOCAT=socat ;;
|
||||
esac
|
||||
|
||||
PORT1=$($SOCAT -d -d -T 0.000001 UDP4-RECV:0 /dev/null 2>&1 |grep bound |sed 's/.*:\([1-9][0-9]*\)$/\1/')
|
||||
PORT2=$($SOCAT -d -d -T 0.000001 UDP4-RECV:0 /dev/null 2>&1 |grep bound |sed 's/.*:\([1-9][0-9]*\)$/\1/')
|
||||
if [ -z "$PORT1" -o -z "$PORT2" ]; then
|
||||
echo "$0: Failed to determine free UDP ports" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PORT1" = "$PORT2" ]; then # seen on etch
|
||||
PORT2=$((PORT1+1))
|
||||
fi
|
||||
|
||||
IFADDR=127.0.0.1
|
||||
BCADDR=127.255.255.255
|
||||
|
||||
|
||||
pid1= pid2=
|
||||
trap '[ "$pid1" ] && kill $pid1 2>/dev/null; [ "$pid2" ] && kill $pid2 2>/dev/null' EXIT
|
||||
|
||||
set -bm
|
||||
trap 'if kill -n 0 $pid1 2>/dev/null; then [ -z "$QUIET" ] && echo "$0: socat-listener exited with rc=$?" >&2; kill $pid1; else [ -z "$QUIET" ] && echo "$0: socat-multiplexer exited with rc=$?" >&2; kill $pid2 2>/dev/null; fi; exit 1' SIGCHLD
|
||||
|
||||
if [ "$VERBOSE" ]; then
|
||||
$ECHO "$SOCAT -lp muxfwd $OPTS \\
|
||||
\"$TARGET\" \\
|
||||
\"UDP4-DATAGRAM:$BCADDR:$PORT2,bind=$IFADDR:$PORT1,so-broadcast\" &"
|
||||
fi
|
||||
$SOCAT -lp muxfwd $OPTS \
|
||||
"$TARGET" \
|
||||
"UDP4-DATAGRAM:$BCADDR:$PORT2,bind=$IFADDR:$PORT1,so-broadcast" &
|
||||
pid1=$!
|
||||
|
||||
if [ "$VERBOSE" ]; then
|
||||
$ECHO "$SOCAT -lp muxlst $OPTS \\
|
||||
\"$LISTENER\" \\
|
||||
\"UDP4-DATAGRAM:$IFADDR:$PORT1,bind=:$PORT2,so-broadcast,so-reuseaddr\" &"
|
||||
fi
|
||||
$SOCAT -lp muxlst $OPTS \
|
||||
"$LISTENER" \
|
||||
"UDP4-DATAGRAM:$IFADDR:$PORT1,bind=:$PORT2,so-broadcast,so-reuseaddr" &
|
||||
pid2=$!
|
||||
|
||||
wait
|
||||
#wait -f
|
||||
63
socat.spec
Normal file
63
socat.spec
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
%define majorver 1.8
|
||||
%define minorver 0.0
|
||||
|
||||
Summary: socat - multipurpose relay
|
||||
Name: socat
|
||||
Version: %{majorver}.%{minorver}
|
||||
Release: 1
|
||||
License: GPL
|
||||
Group: Applications/Communications
|
||||
Source0: http://www.dest-unreach.org/socat/download/socat-%{version}.tar.bz2
|
||||
Requires: readline
|
||||
Requires: openssl
|
||||
BuildRoot: /var/tmp/%{name}-buildroot
|
||||
|
||||
%description
|
||||
socat is a relay for bidirectional data transfer between two independent data
|
||||
channels. Each of these data channels may be a file, pipe, device (terminal or
|
||||
modem etc.), socket (UNIX, IP4, IP6 - raw, UDP, TCP), a file descriptor (stdin
|
||||
etc.), a program, or an arbitrary combination of two of these.
|
||||
|
||||
%prep
|
||||
%setup -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
# the CPPFLAGS setting is required for RedHat Linux
|
||||
if [ -d /usr/kerberos/include ]; then
|
||||
CPPFLAGS="-I/usr/kerberos/include" ./configure --prefix=%{_prefix} --mandir=%{_mandir}
|
||||
else
|
||||
./configure --prefix=%{_prefix} --mandir=%{_mandir}
|
||||
fi
|
||||
make
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT%{_bindir}
|
||||
mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1
|
||||
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
mv $RPM_BUILD_ROOT%{_bindir}/socat $RPM_BUILD_ROOT%{_bindir}/socat1
|
||||
mv $RPM_BUILD_ROOT%{_mandir}/man1/socat.1 $RPM_BUILD_ROOT%{_mandir}/man1/socat1.1
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc README CHANGES EXAMPLES SECURITY doc/socat.html FAQ BUGREPORTS
|
||||
%doc COPYING COPYING.OpenSSL FILES PORTING DEVELOPMENT
|
||||
%{_bindir}/socat1
|
||||
%{_bindir}/socat
|
||||
%{_bindir}/procan
|
||||
%{_bindir}/filan
|
||||
%{_mandir}/man1/socat1.1
|
||||
|
||||
%post
|
||||
ln -s -f socat1 %{_binddir}/socat
|
||||
ln -s -f socat1.1 %{_mandir}/man1/socat.1
|
||||
|
||||
%postun
|
||||
rm -f %{_bindir}/socat
|
||||
rm -f %{_mandir}/man1/socat.1
|
||||
137
socat_buildscript_for_android.sh
Executable file
137
socat_buildscript_for_android.sh
Executable file
@@ -0,0 +1,137 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Customize these parameters according to your environment
|
||||
ANDROID_NDK="${HOME}/bin/android-ndk-r6b"
|
||||
|
||||
# Check for parameters
|
||||
if [ ! -d "${ANDROID_NDK}" ]; then
|
||||
echo "Android NDK not found in ${ANDROID_NDK}, please edit $0 to fix it."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh" ]; then
|
||||
echo "Your Android NDK is not compatible (make-standalone-toolchain.sh not found)."
|
||||
echo "Android NDK r6b is known to work."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract the Android toolchain from NDK
|
||||
ANDROID_PLATFORM="android-3"
|
||||
ROOT="`pwd`"
|
||||
OUT="${ROOT}/out"
|
||||
${ANDROID_NDK}/build/tools/make-standalone-toolchain.sh \
|
||||
--ndk-dir="${ANDROID_NDK}" \
|
||||
--platform="${ANDROID_PLATFORM}" \
|
||||
--install-dir="${OUT}/toolchain" \
|
||||
|| exit 1
|
||||
# Remove resolv.h because it is quite unusable as is
|
||||
rm ${OUT}/toolchain/sysroot/usr/include/resolv.h
|
||||
|
||||
# Create configure script
|
||||
cd ${ROOT}
|
||||
autoconf || exit 1
|
||||
|
||||
# Create config.h and Makefile
|
||||
cd ${OUT}
|
||||
${ROOT}/configure \
|
||||
--host \
|
||||
--disable-openssl \
|
||||
--disable-unix \
|
||||
CC="${OUT}/toolchain/bin/arm-linux-androideabi-gcc" \
|
||||
|| exit 1
|
||||
|
||||
# Replace misconfigured values in config.h and enable PTY functions
|
||||
mv config.h config.old
|
||||
cat config.old \
|
||||
| sed 's/CRDLY_SHIFT.*/CRDLY_SHIFT 9/' \
|
||||
| sed 's/TABDLY_SHIFT.*/TABDLY_SHIFT 11/' \
|
||||
| sed 's/CSIZE_SHIFT.*/CSIZE_SHIFT 4/' \
|
||||
| sed 's/\/\* #undef HAVE_OPENPTY \*\//#define HAVE_OPENPTY 1/' \
|
||||
| sed 's/\/\* #undef HAVE_GRANTPT \*\//#define HAVE_GRANTPT 1/' \
|
||||
> config.h
|
||||
|
||||
# Enable openpty() in Makefile
|
||||
mv Makefile Makefile.old
|
||||
cat Makefile.old | sed 's/error.c/error.c openpty.c/' > Makefile
|
||||
|
||||
# Provide openpty.c
|
||||
cat >openpty.c <<EOF
|
||||
/* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define _PATH_DEVPTMX "/dev/ptmx"
|
||||
|
||||
int openpty (int *amaster, int *aslave, char *name, struct termios *termp,
|
||||
struct winsize *winp)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
int master, slave;
|
||||
|
||||
master = open(_PATH_DEVPTMX, O_RDWR);
|
||||
if (master == -1)
|
||||
return -1;
|
||||
|
||||
if (grantpt(master))
|
||||
goto fail;
|
||||
|
||||
if (unlockpt(master))
|
||||
goto fail;
|
||||
|
||||
if (ptsname_r(master, buf, sizeof buf))
|
||||
goto fail;
|
||||
|
||||
slave = open(buf, O_RDWR | O_NOCTTY);
|
||||
if (slave == -1)
|
||||
goto fail;
|
||||
|
||||
/* XXX Should we ignore errors here? */
|
||||
if (termp)
|
||||
tcsetattr(slave, TCSAFLUSH, termp);
|
||||
if (winp)
|
||||
ioctl(slave, TIOCSWINSZ, winp);
|
||||
|
||||
*amaster = master;
|
||||
*aslave = slave;
|
||||
if (name != NULL)
|
||||
strcpy(name, buf);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
close(master);
|
||||
return -1;
|
||||
}
|
||||
EOF
|
||||
|
||||
# Compile
|
||||
make socat || exit 1
|
||||
|
||||
# Done
|
||||
echo "Build finished, socat has been generated successfuly in out/socat"
|
||||
|
||||
115
socks4a-echo.sh
Executable file
115
socks4a-echo.sh
Executable file
@@ -0,0 +1,115 @@
|
||||
#! /usr/bin/env bash
|
||||
# source: socks4a-echo.sh
|
||||
#set -vx
|
||||
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# perform primitive simulation of a socks4a server with echo function via stdio.
|
||||
# accepts and answers correct SOCKS4a requests, but then just echoes data.
|
||||
# it is required for test.sh
|
||||
# for TCP, use this script as:
|
||||
# socat tcp-l:1080,reuseaddr,crlf system:"socks4a-echo.sh"
|
||||
|
||||
# older bash and ksh do not have -n option to read command; we try dd then
|
||||
#if echo a |read -n 1 null >/dev/null 2>&1; then
|
||||
# HAVE_READ_N=1
|
||||
#else
|
||||
# and newer bash (4.3) has some other problem with read -n
|
||||
HAVE_READ_N=
|
||||
#fi
|
||||
|
||||
if type socat >/dev/null 2>&1; then
|
||||
SOCAT=socat
|
||||
else
|
||||
SOCAT=./socat
|
||||
fi
|
||||
|
||||
case `uname` in
|
||||
HP-UX|OSF1)
|
||||
CAT="$SOCAT -u stdin stdout"
|
||||
;;
|
||||
*)
|
||||
CAT=cat
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $(echo "x\c") = "x" ]; then E=""
|
||||
elif [ $(echo -e "x\c") = "x" ]; then E="-e"
|
||||
else
|
||||
echo "cannot suppress trailing newline on echo" >&2
|
||||
exit 1
|
||||
fi
|
||||
ECHO="echo $E"
|
||||
|
||||
if [ $($ECHO "\0101") = "A" ]; then
|
||||
SOCKSREPLY_FAILED="\0\0133\0\0\0\0\0\0\c"
|
||||
SOCKSREPLY_OK="\0\0132\0\0\0\0\0\0\c"
|
||||
else
|
||||
SOCKSREPLY_FAILED="\0\133\0\0\0\0\0\0\c"
|
||||
SOCKSREPLY_OK="\0\132\0\0\0\0\0\0\c"
|
||||
fi
|
||||
|
||||
# read and parse SOCKS4a header
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 1 vn # bash 2.0.3 does not support -n
|
||||
else
|
||||
vn=$(dd bs=1 count=1 2>/dev/null)
|
||||
fi
|
||||
if [ "$vn" != $($ECHO "\04") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks version requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 1 cd
|
||||
else
|
||||
cd=$(dd bs=1 count=1 2>/dev/null)
|
||||
fi
|
||||
if [ "$cd" != $($ECHO "\01") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks operation requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
a=$(dd bs=1 count=6 2>/dev/null)
|
||||
#echo a a a >/dev/tty
|
||||
#echo "$a" |od -c >/dev/tty
|
||||
#$ECHO "$a" |od -c >/dev/tty
|
||||
#echo>/dev/tty
|
||||
#echo a a a >/dev/tty
|
||||
if [ "$a" != "$($ECHO "}m\0\0\0\01")" ]; then
|
||||
sleep 1
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks address or port requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 7 u
|
||||
else
|
||||
u=$(dd bs=1 count=7 2>/dev/null)
|
||||
fi
|
||||
if [ "$u" != "nobody" ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks user requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 10 h
|
||||
else
|
||||
h=$(dd bs=1 count=10 2>/dev/null)
|
||||
fi
|
||||
if [ "$h" != "localhost" ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks address requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
# send ok status
|
||||
$ECHO "$SOCKSREPLY_OK"
|
||||
|
||||
# perform echo function
|
||||
$CAT
|
||||
102
socks4echo.sh
Executable file
102
socks4echo.sh
Executable file
@@ -0,0 +1,102 @@
|
||||
#! /usr/bin/env bash
|
||||
# source: socks4echo.sh
|
||||
|
||||
# Copyright Gerhard Rieger and contributors (see file CHANGES)
|
||||
# Published under the GNU General Public License V.2, see file COPYING
|
||||
|
||||
# perform primitive simulation of a socks4 server with echo function via stdio.
|
||||
# accepts and answers correct SOCKS4 requests, but then just echoes data.
|
||||
# it is required for test.sh
|
||||
# for TCP, use this script as:
|
||||
# socat tcp-l:1080,reuseaddr,crlf system:"socks4echo.sh"
|
||||
|
||||
# older bash and ksh do not have -n option to read command; we try dd then
|
||||
#if echo a |read -n 1 null >/dev/null 2>&1; then
|
||||
# HAVE_READ_N=1
|
||||
#else
|
||||
# and newer bash (4.3) has some other problem with read -n
|
||||
HAVE_READ_N=
|
||||
#fi
|
||||
|
||||
if type socat >/dev/null 2>&1; then
|
||||
SOCAT=socat
|
||||
else
|
||||
SOCAT=./socat
|
||||
fi
|
||||
|
||||
case `uname` in
|
||||
HP-UX|OSF1)
|
||||
CAT="$SOCAT -u stdin stdout"
|
||||
;;
|
||||
*)
|
||||
CAT=cat
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ $(echo "x\c") = "x" ]; then E=""
|
||||
elif [ $(echo -e "x\c") = "x" ]; then E="-e"
|
||||
else
|
||||
echo "cannot suppress trailing newline on echo" >&2
|
||||
exit 1
|
||||
fi
|
||||
ECHO="echo $E"
|
||||
|
||||
if [ $($ECHO "\0101") = "A" ]; then
|
||||
SOCKSREPLY_FAILED="\0\0133\0\0\0\0\0\0\c"
|
||||
SOCKSREPLY_OK="\0\0132\0\0\0\0\0\0\c"
|
||||
else
|
||||
SOCKSREPLY_FAILED="\0\133\0\0\0\0\0\0\c"
|
||||
SOCKSREPLY_OK="\0\132\0\0\0\0\0\0\c"
|
||||
fi
|
||||
|
||||
# read and parse SOCKS4 header
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 1 vn # bash 2.0.3 does not support -n
|
||||
else
|
||||
vn=$(dd bs=1 count=1 2>/dev/null)
|
||||
fi
|
||||
if [ "$vn" != $($ECHO "\04") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks version requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 1 cd
|
||||
else
|
||||
cd=$(dd bs=1 count=1 2>/dev/null)
|
||||
fi
|
||||
if [ "$cd" != $($ECHO "\01") ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "invalid socks operation requested" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 6 a
|
||||
else
|
||||
a=$(dd bs=1 count=6 2>/dev/null)
|
||||
fi
|
||||
if [ "$a" != "$($ECHO "}m bL6")" ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "$0: wrong socks address or port requested" >&2
|
||||
echo "$0: expected $($ECHO "}m bL6"|od -t x1), received $($ECHO "$a"|od -t x1)" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$HAVE_READ_N" ]; then
|
||||
read -r -n 7 u
|
||||
else
|
||||
u=$(dd bs=1 count=7 2>/dev/null)
|
||||
fi
|
||||
if [ "$u" != "nobody" ]; then
|
||||
$ECHO "$SOCKSREPLY_FAILED"
|
||||
echo "wrong socks user requested (expected \"nobody\")" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
# send ok status
|
||||
$ECHO "$SOCKSREPLY_OK"
|
||||
|
||||
# perform echo function
|
||||
$CAT
|
||||
525
sslcls.c
Normal file
525
sslcls.c
Normal file
@@ -0,0 +1,525 @@
|
||||
/* source: sslcls.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* explicit system call and C library trace function, for those who miss strace
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "xioconfig.h" /* what features are enabled */
|
||||
|
||||
#if WITH_SYCLS && WITH_OPENSSL
|
||||
|
||||
#include "sysincludes.h"
|
||||
|
||||
#include "mytypes.h"
|
||||
#include "compat.h"
|
||||
#include "errno.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "filan.h"
|
||||
#include "sysutils.h"
|
||||
#include "sycls.h"
|
||||
|
||||
#if HAVE_OPENSSL_INIT_SSL
|
||||
/* OpenBSD 7.2 does not know OPENSSL_INIT_SETTING */
|
||||
int sycOPENSSL_init_ssl(uint64_t opts, const void *settings) {
|
||||
int result;
|
||||
Debug2("OPENSSL_init_ssl("F_uint64_t", %p)", opts, settings);
|
||||
result = OPENSSL_init_ssl(opts, settings);
|
||||
Debug1("OPENSSL_init_ssl() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !(defined(HAVE_OPENSSL_INIT_SSL) && defined(HAVE_OPENSSL_INIT_new))
|
||||
void sycSSL_load_error_strings(void) {
|
||||
Debug("SSL_load_error_strings()");
|
||||
SSL_load_error_strings();
|
||||
Debug("SSL_load_error_strings() ->");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SSL_library_init
|
||||
int sycSSL_library_init(void) {
|
||||
int result;
|
||||
Debug("SSL_library_init()");
|
||||
result = SSL_library_init();
|
||||
Debug1("SSL_library_init() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_TLS_client_method
|
||||
const SSL_METHOD *sycTLS_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLS_client_method()");
|
||||
result = TLS_client_method();
|
||||
Debug1("TLS_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_TLS_server_method
|
||||
const SSL_METHOD *sycTLS_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLS_server_method()");
|
||||
result = TLS_server_method();
|
||||
Debug1("TLS_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SSLv2_client_method
|
||||
const SSL_METHOD *sycSSLv2_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("SSLv2_client_method()");
|
||||
result = SSLv2_client_method();
|
||||
Debug1("SSLv2_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SSLv2_server_method
|
||||
const SSL_METHOD *sycSSLv2_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("SSLv2_server_method()");
|
||||
result = SSLv2_server_method();
|
||||
Debug1("SSLv2_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SSLv3_client_method
|
||||
const SSL_METHOD *sycSSLv3_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("SSLv3_client_method()");
|
||||
result = SSLv3_client_method();
|
||||
Debug1("SSLv3_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SSLv3_server_method
|
||||
const SSL_METHOD *sycSSLv3_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("SSLv3_server_method()");
|
||||
result = SSLv3_server_method();
|
||||
Debug1("SSLv3_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
const SSL_METHOD *sycSSLv23_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("SSLv23_client_method()");
|
||||
result = SSLv23_client_method();
|
||||
Debug1("SSLv23_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
const SSL_METHOD *sycSSLv23_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("SSLv23_server_method()");
|
||||
result = SSLv23_server_method();
|
||||
Debug1("SSLv23_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if HAVE_TLSv1_client_method
|
||||
const SSL_METHOD *sycTLSv1_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLSv1_client_method()");
|
||||
result = TLSv1_client_method();
|
||||
Debug1("TLSv1_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_TLSv1_server_method
|
||||
const SSL_METHOD *sycTLSv1_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLSv1_server_method()");
|
||||
result = TLSv1_server_method();
|
||||
Debug1("TLSv1_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_TLSv1_1_client_method
|
||||
const SSL_METHOD *sycTLSv1_1_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLSv1_1_client_method()");
|
||||
result = TLSv1_1_client_method();
|
||||
Debug1("TLSv1_1_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_TLSv1_1_server_method
|
||||
const SSL_METHOD *sycTLSv1_1_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLSv1_1_server_method()");
|
||||
result = TLSv1_1_server_method();
|
||||
Debug1("TLSv1_1_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_TLSv1_2_client_method
|
||||
const SSL_METHOD *sycTLSv1_2_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLSv1_2_client_method()");
|
||||
result = TLSv1_2_client_method();
|
||||
Debug1("TLSv1_2_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_TLSv1_2_server_method
|
||||
const SSL_METHOD *sycTLSv1_2_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("TLSv1_2_server_method()");
|
||||
result = TLSv1_2_server_method();
|
||||
Debug1("TLSv1_2_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DTLS_client_method
|
||||
const SSL_METHOD *sycDTLS_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("DTLS_client_method()");
|
||||
result = DTLS_client_method();
|
||||
Debug1("DTLS_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DTLS_server_method
|
||||
const SSL_METHOD *sycDTLS_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("DTLS_server_method()");
|
||||
result = DTLS_server_method();
|
||||
Debug1("DTLS_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DTLSv1_client_method
|
||||
const SSL_METHOD *sycDTLSv1_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("DTLSv1_client_method()");
|
||||
result = DTLSv1_client_method();
|
||||
Debug1("DTLSv1_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DTLSv1_server_method
|
||||
const SSL_METHOD *sycDTLSv1_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("DTLSv1_server_method()");
|
||||
result = DTLSv1_server_method();
|
||||
Debug1("DTLSv1_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DTLSv1_2_client_method
|
||||
const SSL_METHOD *sycDTLSv1_2_client_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("DTLSv1_2_client_method()");
|
||||
result = DTLSv1_2_client_method();
|
||||
Debug1("DTLSv1_2_client_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DTLSv1_2_server_method
|
||||
const SSL_METHOD *sycDTLSv1_2_server_method(void) {
|
||||
const SSL_METHOD *result;
|
||||
Debug("DTLSv1_2_server_method()");
|
||||
result = DTLSv1_2_server_method();
|
||||
Debug1("DTLSv1_2_server_method() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method) {
|
||||
SSL_CTX *result;
|
||||
Debug1("SSL_CTX_new(%p)", method);
|
||||
result = SSL_CTX_new(method);
|
||||
Debug1("SSL_CTX_new() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
SSL *sycSSL_new(SSL_CTX *ctx) {
|
||||
SSL *result;
|
||||
Debug1("SSL_new(%p)", ctx);
|
||||
result = SSL_new(ctx);
|
||||
Debug1("SSL_new() -> %p", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
|
||||
const char *CApath) {
|
||||
int result;
|
||||
Debug7("SSL_CTX_load_verify_locations(%p, %s%s%s, %s%s%s)", ctx,
|
||||
CAfile?"\"":"", CAfile?CAfile:"", CAfile?"\"":"",
|
||||
CApath?"\"":"", CApath?CApath:"", CApath?"\"":"");
|
||||
result = SSL_CTX_load_verify_locations(ctx, CAfile, CApath);
|
||||
Debug1("SSL_CTX_load_verify_locations() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) {
|
||||
int result;
|
||||
Debug3("SSL_CTX_use_certificate_file(%p, \"%s\", %d)", ctx, file, type);
|
||||
result = SSL_CTX_use_certificate_file(ctx, file, type);
|
||||
Debug1("SSL_CTX_use_certificate_file() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) {
|
||||
int result;
|
||||
Debug2("SSL_CTX_use_certificate_chain_file(%p, \"%s\")", ctx, file);
|
||||
result = SSL_CTX_use_certificate_chain_file(ctx, file);
|
||||
Debug1("SSL_CTX_use_certificate_chain_file() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) {
|
||||
int result;
|
||||
Debug3("SSL_CTX_use_PrivateKey_file(%p, \"%s\", %d)", ctx, file, type);
|
||||
result = SSL_CTX_use_PrivateKey_file(ctx, file, type);
|
||||
Debug1("SSL_CTX_use_PrivateKey_file() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void sycSSL_CTX_set_verify(SSL_CTX *ctx, int mode,
|
||||
int (*verify_callback)(int, X509_STORE_CTX *)) {
|
||||
Debug3("SSL_CTX_set_verify(%p, %u, %p)", ctx, mode, verify_callback);
|
||||
SSL_CTX_set_verify(ctx, mode, verify_callback);
|
||||
Debug("SSL_CTX_set_verify() -> ");
|
||||
}
|
||||
|
||||
int sycSSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) {
|
||||
int result;
|
||||
Debug2("SSL_CTX_set_cipher_list(%p, \"%s\")", ctx, str);
|
||||
result = SSL_CTX_set_cipher_list(ctx, str);
|
||||
Debug1("SSL_CTX_set_cipher_list() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh) {
|
||||
int result;
|
||||
Debug2("SSL_CTX_set_tmp_dh(%p, %p)", ctx, dh);
|
||||
result = SSL_CTX_set_tmp_dh(ctx, dh);
|
||||
Debug1("SSL_CTX_set_tmp_dh() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
|
||||
int sycSSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode) {
|
||||
int result;
|
||||
Debug2("SSL_CTX_set_tlsext_max_fragment_length(%p, %u)", ctx, mode);
|
||||
result = SSL_CTX_set_tlsext_max_fragment_length(ctx, mode);
|
||||
Debug1("SSL_CTX_set_tlsext_max_fragment_length() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
|
||||
int sycSSL_CTX_set_max_send_fragment(SSL_CTX *ctx, long msf) {
|
||||
int result;
|
||||
Debug2("SSL_CTX_set_max_send_fragment(%p, %ld)", ctx, msf);
|
||||
result = SSL_CTX_set_max_send_fragment(ctx, msf);
|
||||
Debug1("SSL_CTX_set_max_send_fragment() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
int sycSSL_set_cipher_list(SSL *ssl, const char *str) {
|
||||
int result;
|
||||
Debug2("SSL_set_cipher_list(%p, \"%s\")", ssl, str);
|
||||
result = SSL_set_cipher_list(ssl, str);
|
||||
Debug1("SSL_set_cipher_list() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
long sycSSL_get_verify_result(SSL *ssl) {
|
||||
long result;
|
||||
Debug1("SSL_get_verify_result(%p)", ssl);
|
||||
result = SSL_get_verify_result(ssl);
|
||||
Debug1("SSL_get_verify_result() -> %lx", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_set_fd(SSL *ssl, int fd) {
|
||||
int result;
|
||||
Debug2("SSL_set_fd(%p, %d)", ssl, fd);
|
||||
result = SSL_set_fd(ssl, fd);
|
||||
Debug1("SSL_set_fd() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_connect(SSL *ssl) {
|
||||
int result;
|
||||
Debug1("SSL_connect(%p)", ssl);
|
||||
result = SSL_connect(ssl);
|
||||
Debug1("SSL_connect() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_accept(SSL *ssl) {
|
||||
int result;
|
||||
Debug1("SSL_accept(%p)", ssl);
|
||||
result = SSL_accept(ssl);
|
||||
Debug1("SSL_accept() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_read(SSL *ssl, void *buf, int num) {
|
||||
int result;
|
||||
Debug3("SSL_read(%p, %p, %d)", ssl, buf, num);
|
||||
result = SSL_read(ssl, buf, num);
|
||||
Debug1("SSL_read() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_pending(SSL *ssl) {
|
||||
int result;
|
||||
Debug1("SSL_pending(%p)", ssl);
|
||||
result = SSL_pending(ssl);
|
||||
Debug1("SSL_pending() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_write(SSL *ssl, const void *buf, int num) {
|
||||
int result;
|
||||
Debug3("SSL_write(%p, %p, %d)", ssl, buf, num);
|
||||
result = SSL_write(ssl, buf, num);
|
||||
Debug1("SSL_write() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
X509 *sycSSL_get_peer_certificate(SSL *ssl) {
|
||||
X509 *result;
|
||||
Debug1("SSL_get_peer_certificate(%p)", ssl);
|
||||
result = SSL_get_peer_certificate(ssl);
|
||||
if (result) {
|
||||
Debug1("SSL_get_peer_certificate() -> %p", result);
|
||||
} else {
|
||||
Debug("SSL_get_peer_certificate() -> NULL");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int sycSSL_shutdown(SSL *ssl) {
|
||||
int result;
|
||||
Debug1("SSL_shutdown(%p)", ssl);
|
||||
result = SSL_shutdown(ssl);
|
||||
Debug1("SSL_shutdown() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void sycSSL_CTX_free(SSL_CTX *ctx) {
|
||||
Debug1("SSL_CTX_free(%p)", ctx);
|
||||
SSL_CTX_free(ctx);
|
||||
Debug("SSL_CTX_free() -> void");
|
||||
return;
|
||||
}
|
||||
|
||||
void sycSSL_free(SSL *ssl) {
|
||||
Debug1("SSL_free(%p)", ssl);
|
||||
SSL_free(ssl);
|
||||
Debug("SSL_free() -> void");
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_NO_EGD) && HAVE_RAND_egd
|
||||
int sycRAND_egd(const char *path) {
|
||||
int result;
|
||||
Debug1("RAND_egd(\"%s\")", path);
|
||||
result = RAND_egd(path);
|
||||
Debug1("RAND_egd() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
DH *sycPEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) {
|
||||
DH *result;
|
||||
Debug4("PEM_read_bio_DHparams(%p, %p, %p, %p)",
|
||||
bp, x, cb, u);
|
||||
result = PEM_read_bio_DHparams(bp, x, cb, u);
|
||||
if (result) {
|
||||
/*Debug2("PEM_read_bio_DHparams(, {%p},,) -> %p", *x, result);*/
|
||||
Debug1("PEM_read_bio_DHparams() -> %p", result);
|
||||
} else {
|
||||
Debug("PEM_read_bio_DHparams() -> NULL");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BIO *sycBIO_new_file(const char *filename, const char *mode) {
|
||||
BIO *result;
|
||||
Debug2("BIO_new_file(\"%s\", \"%s\")", filename, mode);
|
||||
result = BIO_new_file(filename, mode);
|
||||
if (result) {
|
||||
Debug1("BIO_new_file() -> %p", result);
|
||||
} else {
|
||||
Debug("BIO_new_file() -> NULL");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if WITH_FIPS
|
||||
int sycFIPS_mode_set(int onoff) {
|
||||
int result;
|
||||
Debug1("FIPS_mode_set(%d)", onoff);
|
||||
result = FIPS_mode_set(onoff);
|
||||
Debug1("FIPS_mode_set() -> %d", result);
|
||||
return result;
|
||||
}
|
||||
#endif /* WITH_FIPS */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP)
|
||||
const COMP_METHOD *sycSSL_get_current_compression(SSL *ssl) {
|
||||
const COMP_METHOD *result;
|
||||
Debug1("SSL_get_current_compression(%p)", ssl);
|
||||
result = SSL_get_current_compression(ssl);
|
||||
if (result) {
|
||||
Debug1("SSL_get_current_compression() -> %p", result);
|
||||
} else {
|
||||
Debug("SSL_get_current_compression() -> NULL");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const COMP_METHOD *sycSSL_get_current_expansion(SSL *ssl) {
|
||||
const COMP_METHOD *result;
|
||||
Debug1("SSL_get_current_expansion(%p)", ssl);
|
||||
result = SSL_get_current_expansion(ssl);
|
||||
if (result) {
|
||||
Debug1("SSL_get_current_expansion() -> %p", result);
|
||||
} else {
|
||||
Debug("SSL_get_current_expansion() -> NULL");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *sycSSL_COMP_get_name(const COMP_METHOD *comp) {
|
||||
const char *result;
|
||||
Debug1("SSL_COMP_get_name(%p)", comp);
|
||||
result = SSL_COMP_get_name(comp);
|
||||
if (result) {
|
||||
Debug1("SSL_COMP_get_name() -> \"%s\"", result);
|
||||
} else {
|
||||
Debug("SSL_COMP_get_name() -> NULL");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WITH_SYCLS && WITH_OPENSSL */
|
||||
152
sslcls.h
Normal file
152
sslcls.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* source: sslcls.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __sslcls_h_included
|
||||
#define __sslcls_h_included 1
|
||||
|
||||
#if WITH_SYCLS
|
||||
#if WITH_OPENSSL
|
||||
|
||||
#if HAVE_OPENSSL_INIT_SSL
|
||||
int sycOPENSSL_init_ssl(uint64_t opts, const void *settings);
|
||||
#endif
|
||||
void sycSSL_load_error_strings(void);
|
||||
int sycSSL_library_init(void);
|
||||
const SSL_METHOD *sycTLS_client_method(void);
|
||||
const SSL_METHOD *sycTLS_server_method(void);
|
||||
const SSL_METHOD *sycSSLv2_client_method(void);
|
||||
const SSL_METHOD *sycSSLv2_server_method(void);
|
||||
const SSL_METHOD *sycSSLv3_client_method(void);
|
||||
const SSL_METHOD *sycSSLv3_server_method(void);
|
||||
const SSL_METHOD *sycSSLv23_client_method(void);
|
||||
const SSL_METHOD *sycSSLv23_server_method(void);
|
||||
const SSL_METHOD *sycTLSv1_client_method(void);
|
||||
const SSL_METHOD *sycTLSv1_server_method(void);
|
||||
const SSL_METHOD *sycTLSv1_1_client_method(void);
|
||||
const SSL_METHOD *sycTLSv1_1_server_method(void);
|
||||
const SSL_METHOD *sycTLSv1_2_client_method(void);
|
||||
const SSL_METHOD *sycTLSv1_2_server_method(void);
|
||||
const SSL_METHOD *sycDTLS_client_method(void);
|
||||
const SSL_METHOD *sycDTLS_server_method(void);
|
||||
const SSL_METHOD *sycDTLSv1_client_method(void);
|
||||
const SSL_METHOD *sycDTLSv1_server_method(void);
|
||||
const SSL_METHOD *sycDTLSv1_2_client_method(void);
|
||||
const SSL_METHOD *sycDTLSv1_2_server_method(void);
|
||||
SSL_CTX *sycSSL_CTX_new(const SSL_METHOD *method);
|
||||
SSL *sycSSL_new(SSL_CTX *ctx);
|
||||
int sycSSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
|
||||
const char *CApath);
|
||||
int sycSSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);
|
||||
int sycSSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
|
||||
int sycSSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);
|
||||
void sycSSL_CTX_set_verify(SSL_CTX *ctx, int mode,
|
||||
int (*verify_callback)(int, X509_STORE_CTX *));
|
||||
int sycSSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh);
|
||||
int sycSSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
|
||||
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
|
||||
int sycSSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
|
||||
#endif
|
||||
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
|
||||
int sycSSL_CTX_set_max_send_fragment(SSL_CTX *ctx, long msf);
|
||||
#endif
|
||||
int sycSSL_set_cipher_list(SSL *ssl, const char *str);
|
||||
long sycSSL_get_verify_result(SSL *ssl);
|
||||
int sycSSL_set_fd(SSL *ssl, int fd);
|
||||
int sycSSL_connect(SSL *ssl);
|
||||
int sycSSL_accept(SSL *ssl);
|
||||
int sycSSL_read(SSL *ssl, void *buf, int num);
|
||||
int sycSSL_pending(SSL *ssl);
|
||||
int sycSSL_write(SSL *ssl, const void *buf, int num);
|
||||
X509 *sycSSL_get_peer_certificate(SSL *ssl);
|
||||
int sycSSL_shutdown(SSL *ssl);
|
||||
void sycSSL_CTX_free(SSL_CTX *ctx);
|
||||
void sycSSL_free(SSL *ssl);
|
||||
int sycRAND_egd(const char *path);
|
||||
|
||||
DH *sycPEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u);
|
||||
|
||||
BIO *sycBIO_new_file(const char *filename, const char *mode);
|
||||
|
||||
int sycFIPS_mode_set(int onoff);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00908000L && !defined(OPENSSL_NO_COMP)
|
||||
const COMP_METHOD *sycSSL_get_current_compression(SSL *ssl);
|
||||
const COMP_METHOD *sycSSL_get_current_expansion(SSL *ssl);
|
||||
const char *sycSSL_COMP_get_name(const COMP_METHOD *comp);
|
||||
#endif
|
||||
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
#else /* !WITH_SYCLS */
|
||||
|
||||
#if WITH_OPENSSL
|
||||
|
||||
#define sycOPENSSL_init_ssl(o,s) OPENSSL_init_ssl(o,s)
|
||||
#define sycSSL_load_error_strings() SSL_load_error_strings()
|
||||
#define sycSSL_library_init() SSL_library_init()
|
||||
#define sycTLS_client_method() TLS_client_method()
|
||||
#define sycTLS_server_method() TLS_server_method()
|
||||
#define sycSSLv2_client_method() SSLv2_client_method()
|
||||
#define sycSSLv2_server_method() SSLv2_server_method()
|
||||
#define sycSSLv3_client_method() SSLv3_client_method()
|
||||
#define sycSSLv3_server_method() SSLv3_server_method()
|
||||
#define sycSSLv23_client_method() SSLv23_client_method()
|
||||
#define sycSSLv23_server_method() SSLv23_server_method()
|
||||
#define sycTLSv1_client_method() TLSv1_client_method()
|
||||
#define sycTLSv1_server_method() TLSv1_server_method()
|
||||
#define sycTLSv1_1_client_method() TLSv1_1_client_method()
|
||||
#define sycTLSv1_1_server_method() TLSv1_1_server_method()
|
||||
#define sycTLSv1_2_client_method() TLSv1_2_client_method()
|
||||
#define sycTLSv1_2_server_method() TLSv1_2_server_method()
|
||||
#define sycDTLS_client_method() DTLS_client_method()
|
||||
#define sycDTLS_server_method() DTLS_server_method()
|
||||
#define sycDTLSv1_client_method() DTLSv1_client_method()
|
||||
#define sycDTLSv1_server_method() DTLSv1_server_method()
|
||||
#define sycDTLSv1_2_client_method() DTLSv1_2_client_method()
|
||||
#define sycDTLSv1_2_server_method() DTLSv1_2_server_method()
|
||||
#define sycSSL_CTX_new(m) SSL_CTX_new(m)
|
||||
#define sycSSL_new(c) SSL_new(c)
|
||||
#define sycSSL_CTX_load_verify_locations(c,f,p) SSL_CTX_load_verify_locations(c,f,p)
|
||||
#define sycSSL_CTX_use_certificate_file(c,f,t) SSL_CTX_use_certificate_file(c,f,t)
|
||||
#define sycSSL_CTX_use_certificate_chain_file(c,f) SSL_CTX_use_certificate_chain_file(c,f)
|
||||
#define sycSSL_CTX_use_PrivateKey_file(c,f,t) SSL_CTX_use_PrivateKey_file(c,f,t)
|
||||
#define sycSSL_CTX_set_verify(c,m,v) SSL_CTX_set_verify(c,m,v)
|
||||
#define sycSSL_CTX_set_tmp_dh(c,d) SSL_CTX_set_tmp_dh(c,d)
|
||||
#define sycSSL_CTX_set_cipher_list(c,s) SSL_CTX_set_cipher_list(c,s)
|
||||
#if HAVE_SSL_CTX_set_tlsext_max_fragment_length || defined(SSL_CTX_set_tlsext_max_fragment_length)
|
||||
#define sycSSL_CTX_set_tlsext_max_fragment_length(c,m) SSL_CTX_set_tlsext_max_fragment_length(c, m)
|
||||
#endif
|
||||
#if HAVE_SSL_CTX_set_max_send_fragment || defined(SSL_CTX_set_max_send_fragment)
|
||||
#define sycSSL_CTX_set_max_send_fragment(c,m) SSL_CTX_set_max_send_fragment(c, m)
|
||||
#endif
|
||||
#define sycSSL_set_cipher_list(s,t) SSL_set_cipher_list(s,t)
|
||||
#define sycSSL_get_verify_result(s) SSL_get_verify_result(s)
|
||||
#define sycSSL_set_fd(s,f) SSL_set_fd(s,f)
|
||||
#define sycSSL_connect(s) SSL_connect(s)
|
||||
#define sycSSL_accept(s) SSL_accept(s)
|
||||
#define sycSSL_read(s,b,n) SSL_read(s,b,n)
|
||||
#define sycSSL_pending(s) SSL_pending(s)
|
||||
#define sycSSL_write(s,b,n) SSL_write(s,b,n)
|
||||
#define sycSSL_get_peer_certificate(s) SSL_get_peer_certificate(s)
|
||||
#define sycSSL_shutdown(s) SSL_shutdown(s)
|
||||
#define sycSSL_CTX_free(c) SSL_CTX_free(c)
|
||||
#define sycSSL_free(s) SSL_free(s)
|
||||
#define sycRAND_egd(p) RAND_egd(p)
|
||||
|
||||
#define sycPEM_read_bio_DHparams(b,x,p,u) PEM_read_bio_DHparams(b,x,p,u)
|
||||
|
||||
#define sycBIO_new_file(f,m) BIO_new_file(f,m)
|
||||
|
||||
#define sycSSL_get_current_compression(s) SSL_get_current_compression(s)
|
||||
#define sycSSL_get_current_expansion(s) SSL_get_current_expansion(s)
|
||||
#define sycSSL_COMP_get_name(c) SSL_COMP_get_name(c)
|
||||
|
||||
#endif /* WITH_OPENSSL */
|
||||
|
||||
#define sycFIPS_mode_set(o) FIPS_mode_set(o)
|
||||
|
||||
#endif /* !WITH_SYCLS */
|
||||
|
||||
#endif /* !defined(__sslcls_h_included) */
|
||||
|
||||
288
sycls.h
Normal file
288
sycls.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/* source: sycls.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __sycls_h_included
|
||||
#define __sycls_h_included 1
|
||||
|
||||
#if WITH_SYCLS
|
||||
struct termios; /* prevent gcc from spitting silly warning */
|
||||
struct utsname;
|
||||
struct flock;
|
||||
struct addrinfo;
|
||||
|
||||
int Posix_memalign(void **memptr, size_t alignment, size_t size);
|
||||
mode_t Umask(mode_t mask);
|
||||
#endif /* WITH_SYCLS */
|
||||
int Open(const char *pathname, int flags, mode_t mode);
|
||||
#if WITH_SYCLS
|
||||
int Creat(const char *pathname, mode_t mode);
|
||||
off_t Lseek(int fildes, off_t offset, int whence);
|
||||
#if HAVE_LSEEK64
|
||||
off64_t Lseek64(int fildes, off64_t offset, int whence);
|
||||
#endif
|
||||
pid_t Getpid(void);
|
||||
pid_t Getppid(void);
|
||||
pid_t Getpgrp(void);
|
||||
int Getpgid(pid_t pid);
|
||||
int Setpgid(pid_t pid, pid_t pgid);
|
||||
int Setpgrp(void);
|
||||
pid_t Tcgetpgrp(int fd);
|
||||
int Tcsetpgrp(int fd, pid_t pgrpid);
|
||||
pid_t Getsid(pid_t pid);
|
||||
pid_t Setsid(void);
|
||||
uid_t Getuid(void);
|
||||
uid_t Geteuid(void);
|
||||
int Setuid(uid_t uid);
|
||||
gid_t Getgid(void);
|
||||
gid_t Getegid(void);
|
||||
int Setgid(gid_t gid);
|
||||
int Initgroups(const char *user, gid_t group);
|
||||
int Getgroups(int size, gid_t list[]);
|
||||
int Setgroups(size_t size, const gid_t *list);
|
||||
int Getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
|
||||
int Chdir(const char *path);
|
||||
int Chroot(const char *path);
|
||||
int Gettimeofday(struct timeval *tv, struct timezone *tz);
|
||||
int Mknod(const char *pathname, mode_t mode, dev_t dev);
|
||||
int Mkfifo(const char *pathname, mode_t mode);
|
||||
int Stat(const char *file_name, struct stat *buf);
|
||||
int Fstat(int filedes, struct stat *buf);
|
||||
int Lstat(const char *file_name, struct stat *buf);
|
||||
#if HAVE_STAT64
|
||||
int Stat64(const char *file_name, struct stat64 *buf);
|
||||
int Fstat64(int filedes, struct stat64 *buf);
|
||||
int Lstat64(const char *file_name, struct stat64 *buf);
|
||||
#endif /* HAVE_STAT64 */
|
||||
int Dup(int oldfd);
|
||||
int Dup2(int oldfd, int newfd);
|
||||
int Pipe(int filedes[2]);
|
||||
#endif /* WITH_SYCLS */
|
||||
ssize_t Read(int fd, void *buf, size_t count);
|
||||
ssize_t Write(int fd, const void *buf, size_t count);
|
||||
int Fcntl(int fd, int cmd);
|
||||
int Fcntl_i(int fd, int cmd, int arg);
|
||||
int Fcntl_l(int fd, int cmd, long arg);
|
||||
int Fcntl_lock(int fd, int cmd, struct flock *l);
|
||||
#if WITH_SYCLS
|
||||
int Ftruncate(int fd, off_t length);
|
||||
#if HAVE_FTRUNCATE64
|
||||
int Ftruncate64(int fd, off64_t length);
|
||||
#endif /* HAVE_FTRUNCATE64 */
|
||||
#endif /* WITH_SYCLS */
|
||||
int Flock(int fd, int operation);
|
||||
int Ioctl(int d, int request, void *argp);
|
||||
int Ioctl_int(int d, int request, int arg);
|
||||
#if WITH_SYCLS
|
||||
int Close(int fd);
|
||||
int Fchown(int fd, uid_t owner, gid_t group);
|
||||
int Fchmod(int fd, mode_t mode);
|
||||
int Unlink(const char *pathname);
|
||||
int Symlink(const char *oldpath, const char *newpath);
|
||||
int Readlink(const char *path, char *buf, size_t bufsiz);
|
||||
int Chown(const char *path, uid_t owner, gid_t group);
|
||||
int Chmod(const char *path, mode_t mode);
|
||||
#endif /* WITH_SYCLS */
|
||||
int Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
|
||||
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
struct timeval *timeout);
|
||||
int Pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
const struct timespec *timeout, const sigset_t *sigmask);
|
||||
#if WITH_SYCLS
|
||||
pid_t Fork(void);
|
||||
#endif /* WITH_SYCLS */
|
||||
pid_t Waitpid(pid_t pid, int *status, int options);
|
||||
#if WITH_SYCLS
|
||||
#ifndef HAVE_TYPE_SIGHANDLER
|
||||
typedef RETSIGTYPE (*sighandler_t)(int);
|
||||
#endif
|
||||
sighandler_t Signal(int signum, sighandler_t handler);
|
||||
int Sigaction(int signum, const struct sigaction *act,
|
||||
struct sigaction *oldact);
|
||||
int Sigprocmask(int how, const sigset_t *set, sigset_t *oset);
|
||||
unsigned int Alarm(unsigned int seconds);
|
||||
int Kill(pid_t pid, int sig);
|
||||
int Link(const char *oldpath, const char *newpath);
|
||||
int Execvp(const char *file, char *const argv[]);
|
||||
#endif /* WITH_SYCLS */
|
||||
int System(const char *string);
|
||||
#if WITH_SYCLS
|
||||
int Socketpair(int d, int type, int protocol, int sv[2]);
|
||||
#endif /* WITH_SYCLS */
|
||||
#if _WITH_SOCKET
|
||||
#if WITH_SYCLS
|
||||
int Socket(int domain, int type, int protocol);
|
||||
int Bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
|
||||
#endif /* WITH_SYCLS */
|
||||
int Connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
|
||||
#if WITH_SYCLS
|
||||
int Listen(int s, int backlog);
|
||||
#endif /* WITH_SYCLS */
|
||||
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
#if WITH_SYCLS
|
||||
int Getsockname(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int Getpeername(int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int Getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int Setsockopt(int s, int level, int optname, const void *optval, int optlen);
|
||||
#endif /* WITH_SYCLS */
|
||||
int Recv(int s, void *buf, size_t len, int flags);
|
||||
int Recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
|
||||
socklen_t *fromlen);
|
||||
int Recvmsg(int s, struct msghdr *msg, int flags);
|
||||
int Send(int s, const void *mesg, size_t len, int flags);
|
||||
int Sendto(int s, const void *msg, size_t len, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen);
|
||||
#if WITH_SYCLS
|
||||
int Shutdown(int fd, int how);
|
||||
#endif /* WITH_SYCLS */
|
||||
#endif /* _WITH_SOCKET */
|
||||
#if WITH_SYCLS
|
||||
unsigned int Sleep(unsigned int seconds);
|
||||
unsigned int Nanosleep(const struct timespec *req, struct timespec *rem);
|
||||
int Pause(void);
|
||||
struct hostent *Gethostbyname(const char *name);
|
||||
int Getaddrinfo(const char *node, const char *service,
|
||||
const struct addrinfo *hints, struct addrinfo **res);
|
||||
struct hostent *Getipnodebyname(const char *name, int af, int flags,
|
||||
int *error_num);
|
||||
void *Malloc(size_t size);
|
||||
void *Calloc(size_t nmemb, size_t size);
|
||||
void *Realloc(void *ptr, size_t size);
|
||||
int Tcgetattr(int fd, struct termios *termios_p);
|
||||
int Tcsetattr(int fd, int optional_actions, struct termios *termios_p);
|
||||
char *Ttyname(int fd);
|
||||
int Isatty(int fd);
|
||||
struct winsize; /* avoid warnings */
|
||||
int Openpty(int *ptyfd, int *ttyfd, char *ptyname, struct termios *termp,
|
||||
struct winsize *winp);
|
||||
char *Ptsname(int fd);
|
||||
int Grantpt(int fd);
|
||||
int Unlockpt(int fd);
|
||||
int Gethostname(char *name, size_t len);
|
||||
int Uname(struct utsname *buf);
|
||||
int Atexit(void (*func)(void));
|
||||
#endif /* WITH_SYCLS */
|
||||
void Exit(int status);
|
||||
#if WITH_SYCLS
|
||||
void Abort(void);
|
||||
int Mkstemp(char *template);
|
||||
int Setenv(const char *name, const char *value, int overwrite);
|
||||
void Unsetenv(const char *name);
|
||||
int Setns(int fd, int nstype);
|
||||
#endif /* WITH_SYCLS */
|
||||
#if WITH_SYCLS
|
||||
|
||||
char *Readline(const char *prompt);
|
||||
void Using_history(void);
|
||||
int Read_history(const char *filename);
|
||||
int Write_history(const char *filename);
|
||||
int Append_history(int nelements, const char *filename);
|
||||
int Read_history(const char *filename);
|
||||
void Add_history(const char *string);
|
||||
|
||||
#else /* !WITH_SYCLS */
|
||||
|
||||
#define Posix_memalign(m,a,s) posix_memalign(m,a,s)
|
||||
#define Umask(m) umask(m)
|
||||
#define Creat(p,m) creat(p,m)
|
||||
#define Lseek(f,o,w) lseek(f,o,w)
|
||||
#define Lseek64(f,o,w) lseek64(f,o,w)
|
||||
#define Getpid() getpid()
|
||||
#define Getppid() getppid()
|
||||
#define Getpgrp() getpgrp()
|
||||
#define Getpgid(p) getpgid(p)
|
||||
#define Setpgid(p,g) setpgid(p,g)
|
||||
#define Setpgrp() setpgrp()
|
||||
#define Tcgetpgrp(f) tcgetpgrp(f)
|
||||
#define Tcsetpgrp(f,p) tcsetpgrp(f,p)
|
||||
#define Getsid(p) getsid(p)
|
||||
#define Setsid() setsid()
|
||||
#define Getuid() getuid()
|
||||
#define Geteuid() geteuid()
|
||||
#define Setuid(u) setuid(u)
|
||||
#define Getgid() getgid()
|
||||
#define Getegid() getegid()
|
||||
#define Setgid(g) setgid(g)
|
||||
#define Initgroups(u,g) initgroups(u,g)
|
||||
#define Getgroups(s,l) getgroups(s,l)
|
||||
#define Setgroups(s,l) setgroups(s,l)
|
||||
#define Getgrouplist(u,g,gs,n) getgrouplist(u,g,gs,n)
|
||||
#define Chdir(p) chdir(p)
|
||||
#define Chroot(p) chroot(p)
|
||||
#define Gettimeofday(tv,tz) gettimeofday(tv,tz)
|
||||
#define Mknod(p,m,d) mknod(p,m,d)
|
||||
#define Mkfifo(p,m) mkfifo(p,m)
|
||||
#define Stat(f,b) stat(f,b)
|
||||
#define Stat64(f,b) stat64(f,b)
|
||||
#define Fstat(f,b) fstat(f,b)
|
||||
#define Fstat64(f,b) fstat64(f,b)
|
||||
#define Lstat(f,b) lstat(f,b)
|
||||
#define Lstat64(f,b) lstat64(f,b)
|
||||
#define Dup(o) dup(o)
|
||||
#define Dup2(o,n) dup2(o,n)
|
||||
#define Pipe(f) pipe(f)
|
||||
#define Ftruncate(f,l) ftruncate(f,l)
|
||||
#define Ftruncate64(f,l) ftruncate64(f,l)
|
||||
#define Close(f) close(f)
|
||||
#define Fchown(f,o,g) fchown(f,o,g)
|
||||
#define Fchmod(f,m) fchmod(f,m)
|
||||
#define Unlink(p) unlink(p)
|
||||
#define Symlink(op,np) symlink(op,np)
|
||||
#define Readlink(p,b,s) readlink(p,b,s)
|
||||
#define Chown(p,o,g) chown(p,o,g)
|
||||
#define Chmod(p,m) chmod(p,m)
|
||||
#define Fork() fork()
|
||||
#define Signal(s,h) signal(s,h)
|
||||
#define Sigaction(s,a,o) sigaction(s,a,o)
|
||||
#define Sigprocmask(h,s,o) sigprocmask(h,s,o)
|
||||
#define Alarm(s) alarm(s)
|
||||
#define Kill(p,s) kill(p,s)
|
||||
#define Link(o,n) link(o,n)
|
||||
#define Execvp(f,a) execvp(f,a)
|
||||
#define Socketpair(d,t,p,s) socketpair(d,t,p,s)
|
||||
#define Socket(d,t,p) socket(d,t,p)
|
||||
#define Bind(s,m,a) bind(s,m,a)
|
||||
#define Listen(s,b) listen(s,b)
|
||||
#define Getsockname(s,n,l) getsockname(s,n,l)
|
||||
#define Getpeername(s,n,l) getpeername(s,n,l)
|
||||
#define Getsockopt(s,d,n,v,l) getsockopt(s,d,n,v,l)
|
||||
#define Setsockopt(s,d,n,v,l) setsockopt(s,d,n,v,l)
|
||||
#define Shutdown(f,h) shutdown(f,h)
|
||||
#define Sleep(s) sleep(s)
|
||||
#define Nanosleep(req,rem) nanosleep(req,rem)
|
||||
#define Pause() pause()
|
||||
#define Gethostbyname(n) gethostbyname(n)
|
||||
#define Getaddrinfo(n,s,h,r) getaddrinfo(n,s,h,r)
|
||||
#define Getipnodebyname(n,a,f,e) getipnodebyname(n,a,f,e)
|
||||
#define Malloc(s) malloc(s)
|
||||
#define Calloc(n,s) calloc(n,s)
|
||||
#define Realloc(p,s) realloc(p,s)
|
||||
#define Tcgetattr(f,t) tcgetattr(f,t)
|
||||
#define Tcsetattr(f,o,t) tcsetattr(f,o,t)
|
||||
#define Ttyname(f) ttyname(f)
|
||||
#define Isatty(f) isatty(f)
|
||||
#define Openpty(p,t,n,i,f) openpty(p,t,n,i,f)
|
||||
#define Ptsname(f) ptsname(f)
|
||||
#define Grantpt(f) grantpt(f)
|
||||
#define Unlockpt(f) unlockpt(f)
|
||||
#define Getpgid(p) getpgid(p)
|
||||
#define Gethostname(n,l) gethostname(n,l)
|
||||
#define Uname(b) uname(b)
|
||||
#define Atexit(f) atexit(f)
|
||||
#define Abort() abort()
|
||||
#define Mkstemp(t) mkstemp(t)
|
||||
#define Setenv(n,v,o) setenv(n,v,o)
|
||||
#define Unsetenv(n) unsetenv(n)
|
||||
#define Setns(f,n) setns(f,n)
|
||||
|
||||
#define Readline(p) readline(p)
|
||||
#define Using_history() using_history()
|
||||
#define Read_history(f) read_history(f)
|
||||
#define Write_history(f) write_history(f)
|
||||
#define Append_history(n,f) append_history(n,f)
|
||||
#define Read_history(f) read_history(f)
|
||||
#define Add_history(s) add_history(s)
|
||||
|
||||
#endif /* !WITH_SYCLS */
|
||||
|
||||
#endif /* !defined(__sycls_h_included) */
|
||||
207
sysincludes.h
Normal file
207
sysincludes.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/* source: sysincludes.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __sysincludes_h_included
|
||||
#define __sysincludes_h_included 1
|
||||
|
||||
/* Sorry for this... */
|
||||
#if defined(__sun) || defined(__sun__) || defined(__SunOS)
|
||||
# define BSD_COMP 1 /* for SIOCGIFFLAGS */
|
||||
#endif
|
||||
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#if HAVE_STDBOOL_H
|
||||
#include <stdbool.h> /* bool, true, false */
|
||||
#endif
|
||||
#if HAVE_INTTYPES_H
|
||||
#include <inttypes.h> /* uint16_t */
|
||||
#endif
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h> /* USHRT_MAX */
|
||||
#endif
|
||||
#include <math.h> /* HUGE_VAL */
|
||||
#include <assert.h>
|
||||
#include <stdarg.h> /* for msg() */
|
||||
#include <string.h> /* strerror(), strchr() */
|
||||
#if HAVE_STRINGS_H
|
||||
#include <strings.h> /* strcasecmp(), bzero() for FD_ZERO */
|
||||
#endif
|
||||
#include <stdlib.h> /* malloc(), free() */
|
||||
#include <ctype.h> /* isdigit() */
|
||||
#include <stdio.h> /* FILE */
|
||||
#include <errno.h> /* errno */
|
||||
#if HAVE_SYSLOG_H
|
||||
#include <syslog.h> /* openlog(), syslog(), closelog() */
|
||||
#endif
|
||||
#include <signal.h> /* signal(), SIGPIPE, SIG_IGN */
|
||||
#include <time.h> /* struct timeval, strftime(), clock_gettime() */
|
||||
#if 0
|
||||
#include <sys/timeb.h> /* struct timeb */
|
||||
#endif
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h> /* select(), read(), write(), stat(), fork() */
|
||||
#endif
|
||||
#if HAVE_PWD_H
|
||||
#include <pwd.h> /* getpwnam() */
|
||||
#endif
|
||||
#if HAVE_GRP_H
|
||||
#include <grp.h> /* getgrnam() */
|
||||
#endif
|
||||
#if HAVE_PTY_H && (_WITH_TERMIOS || HAVE_OPENPTY)
|
||||
#include <pty.h>
|
||||
#endif
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h> /* Linux 2.4 NGROUPS */
|
||||
#endif
|
||||
#if HAVE_SYS_TIME_H
|
||||
#include <sys/time.h> /* select(); OpenBSD: struct timespec */
|
||||
#endif
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h> /* uint8_t */
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h> /* pid_t, select(), socket(), connect(), open(), u_short */
|
||||
#endif
|
||||
#if HAVE_POLL_H
|
||||
#include <poll.h> /* poll() */
|
||||
#elif HAVE_SYS_POLL_H
|
||||
#include <sys/poll.h> /* poll() */
|
||||
#endif
|
||||
#if HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h> /* struct sockaddr, struct linger, socket(), connect() */
|
||||
#endif
|
||||
#if HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h> /* struct iovec */
|
||||
#endif
|
||||
#if HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h> /* struct stat, stat(), open() */
|
||||
#endif
|
||||
#if HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h> /* WNOHANG */
|
||||
#endif
|
||||
#if HAVE_FCNTL_H
|
||||
#include <fcntl.h> /* open(), O_RDWR */
|
||||
#endif
|
||||
#if HAVE_NETDB_H && (_WITH_IP4 || _WITH_IP6)
|
||||
#include <netdb.h> /* struct hostent, gethostbyname() */
|
||||
#endif
|
||||
#if HAVE_SYS_UN_H && WITH_UNIX
|
||||
#include <sys/un.h> /* struct sockaddr_un, unix domain sockets */
|
||||
#endif
|
||||
#if HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h> /* ioctl() */
|
||||
#endif
|
||||
#if HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h> /* select(), fdset on AIX 4.1 */
|
||||
#endif
|
||||
#if HAVE_SYS_FILE_H
|
||||
#include <sys/file.h> /* LOCK_EX, on AIX directly included */
|
||||
#endif
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
# if HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h> /* struct sockaddr_in, htonl() */
|
||||
# endif
|
||||
#endif /* _WITH_SOCKET */
|
||||
#if _WITH_SOCKET && (_WITH_IP4 || _WITH_IP6)
|
||||
# if HAVE_NETINET_IN_SYSTM_H
|
||||
#include <netinet/in_systm.h> /* Solaris, FreeBSD: n_long */
|
||||
# endif
|
||||
# if HAVE_NETINET_IP_H
|
||||
#include <netinet/ip.h> /* struct ip - past netinet/in.h on AIX! */
|
||||
# endif
|
||||
# if HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h> /* TCP_RFC1323 */
|
||||
# endif
|
||||
# if HAVE_NETINET_IP6_H && _WITH_IP6
|
||||
#include <netinet/ip6.h>
|
||||
# endif
|
||||
# if HAVE_NETINET6_IN6_H && _WITH_IP6
|
||||
#include <netinet6/in6.h>
|
||||
# endif
|
||||
#include <arpa/inet.h> /* Linux: inet_aton() */
|
||||
#if HAVE_ARPA_NAMESER_H
|
||||
#include <arpa/nameser.h> /* req for resolv.h (esp. on MacOSX) */
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
#if HAVE_NET_IF_DL_H
|
||||
#include <net/if_dl.h> /* FreeBSD: struct sockaddr_dl */
|
||||
#endif
|
||||
#if HAVE_RESOLV_H
|
||||
#include <resolv.h> /* _res */
|
||||
#endif
|
||||
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||
/*#include <linux/sockios.h>*/
|
||||
#if HAVE_NET_IF_H
|
||||
#include <net/if.h>
|
||||
#endif /* HAVE_NET_IF_H */
|
||||
#if HAVE_LINUX_TYPES_H
|
||||
#include <linux/types.h> /* __u32 for linux/errqueue.h */
|
||||
#endif
|
||||
#if HAVE_LINUX_ERRQUEUE_H
|
||||
#include <linux/errqueue.h> /* struct sock_extended_err */
|
||||
#endif
|
||||
#if HAVE_LINUX_IF_PACKET_H
|
||||
#include <linux/if_packet.h>
|
||||
#endif
|
||||
#if HAVE_NETINET_IF_ETHER_H
|
||||
#include <netinet/if_ether.h>
|
||||
#endif
|
||||
#if HAVE_LINUX_IF_TUN_H
|
||||
#include <linux/if_tun.h>
|
||||
#endif
|
||||
#if HAVE_LINUX_DCCP_H
|
||||
#include <linux/dccp.h>
|
||||
#endif
|
||||
#if HAVE_TERMIOS_H && _WITH_TERMIOS
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#if HAVE_SYS_UTSNAME_H
|
||||
#include <sys/utsname.h> /* uname(), struct utsname */
|
||||
#endif
|
||||
#if HAVE_UTIL_H
|
||||
#include <util.h> /* NetBSD, OpenBSD openpty() */
|
||||
#endif
|
||||
#if HAVE_BSD_LIBUTIL_H
|
||||
#include <bsd/libutil.h> /* FreeBSD openpty() */
|
||||
#elif HAVE_LIBUTIL_H
|
||||
#include <libutil.h> /* FreeBSD openpty() */
|
||||
#endif
|
||||
#if HAVE_SYS_STROPTS_H
|
||||
#include <sys/stropts.h> /* SunOS I_PUSH ... */
|
||||
#endif
|
||||
#if HAVE_REGEX_H
|
||||
#include <regex.h>
|
||||
#endif
|
||||
#if HAVE_LINUX_FS_H
|
||||
#include <linux/fs.h> /* Linux filesystem definitions */
|
||||
#endif
|
||||
#if HAVE_LINUX_EXT2_FS_H
|
||||
#include <linux/ext2_fs.h> /* Linux ext2 filesystem definitions */
|
||||
#endif
|
||||
#if WITH_NAMESPACES && HAVE_SCHED_H
|
||||
#include <sched.h>
|
||||
#endif
|
||||
#if WITH_POSIXMQ
|
||||
#include <mqueue.h> /* POSIX MQ */
|
||||
#endif
|
||||
#if WITH_READLINE
|
||||
# if HAVE_READLINE_READLINE_H
|
||||
#include <readline/readline.h>
|
||||
# endif
|
||||
# if HAVE_READLINE_HISTORY_H
|
||||
#include <readline/history.h>
|
||||
# endif
|
||||
#endif /* WITH_READLINE */
|
||||
#if WITH_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
#endif
|
||||
#if HAVE_LINUX_VM_SOCKETS_H
|
||||
#include <linux/vm_sockets.h>
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__sysincludes_h_included) */
|
||||
1153
sysutils.c
Normal file
1153
sysutils.c
Normal file
File diff suppressed because it is too large
Load Diff
122
sysutils.h
Normal file
122
sysutils.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/* source: sysutils.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __sysutils_h_included
|
||||
#define __sysutils_h_included 1
|
||||
|
||||
#if WITH_IP6
|
||||
/* not all OSes provide in6_addr that allows splitting to 16 or 32 bit junks of
|
||||
the host address part of sockaddr_in6; here we help ourselves */
|
||||
union xioin6_u {
|
||||
uint8_t u6_addr8[16];
|
||||
uint16_t u6_addr16[8];
|
||||
uint32_t u6_addr32[4];
|
||||
} ;
|
||||
#endif /* WITH_IP6 */
|
||||
|
||||
#if _WITH_SOCKET
|
||||
union sockaddr_union {
|
||||
struct sockaddr soa;
|
||||
#if WITH_UNIX
|
||||
struct sockaddr_un un;
|
||||
#endif /* WITH_UNIX */
|
||||
#if _WITH_IP4
|
||||
struct sockaddr_in ip4;
|
||||
#endif /* _WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
struct sockaddr_in6 ip6;
|
||||
#endif /* WITH_IP6 */
|
||||
#if WITH_VSOCK
|
||||
struct sockaddr_vm vm;
|
||||
#endif /* WITH_IP6 */
|
||||
#if _WITH_INTERFACE
|
||||
struct sockaddr_ll ll;
|
||||
#endif
|
||||
} ;
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
#if _WITH_SOCKET
|
||||
struct xiorange {
|
||||
union sockaddr_union netaddr;
|
||||
union sockaddr_union netmask;
|
||||
} ;
|
||||
#endif /* _WITH_SOCKET */
|
||||
|
||||
#if _WITH_INTERFACE
|
||||
extern const int one;
|
||||
#endif
|
||||
|
||||
extern ssize_t writefull(int fd, const void *buff, size_t bytes);
|
||||
|
||||
#if _WITH_SOCKET
|
||||
extern socklen_t socket_init(int af, union sockaddr_union *sa);
|
||||
#endif
|
||||
#if WITH_UNIX
|
||||
extern void socket_un_init(struct sockaddr_un *sa);
|
||||
#endif /* WITH_UNIX */
|
||||
#if _WITH_IP4
|
||||
extern void socket_in_init(struct sockaddr_in *sa);
|
||||
#endif /* _WITH_IP4 */
|
||||
#if _WITH_IP6
|
||||
extern void socket_in6_init(struct sockaddr_in6 *sa);
|
||||
#endif /* _WITH_IP4 */
|
||||
|
||||
#if _WITH_SOCKET
|
||||
extern char *sockaddr_info(const struct sockaddr *sa, socklen_t salen, char *buff, size_t blen);
|
||||
#endif
|
||||
#if WITH_UNIX
|
||||
extern char *sockaddr_unix_info(const struct sockaddr_un *sa, socklen_t salen, char *buff, size_t blen);
|
||||
#endif /* WITH_UNIX */
|
||||
#if WITH_IP4
|
||||
extern char *inet4addr_info(uint32_t addr, char *buff, size_t blen);
|
||||
extern char *sockaddr_inet4_info(const struct sockaddr_in *sa, char *buff, size_t blen);
|
||||
#endif /* WITH_IP4 */
|
||||
#if WITH_IP6
|
||||
extern char *sockaddr_inet6_info(const struct sockaddr_in6 *sa, char *buff, size_t blen);
|
||||
#endif /* WITH_IP6 */
|
||||
#if WITH_VSOCK
|
||||
extern char *sockaddr_vm_info(const struct sockaddr_vm *sa, char *buff, size_t blen);
|
||||
extern int sockaddr_vm_parse(struct sockaddr_vm *sa, const char *cid_str,
|
||||
const char *port_str);
|
||||
#endif /* WITH_VSOCK */
|
||||
#if !HAVE_INET_NTOP
|
||||
extern const char *inet_ntop(int pf, const void *binaddr,
|
||||
char *addrtext, socklen_t textlen);
|
||||
#endif
|
||||
extern int check_ip4addr(const char *address);
|
||||
extern int check_ip6addr(const char *address);
|
||||
extern int check_ipaddr(const char *address);
|
||||
|
||||
#if defined(HAVE_SETGRENT) && defined(HAVE_GETGRENT) && defined(HAVE_ENDGRENT)
|
||||
extern int getusergroups(const char *user, gid_t *list, int *ngroups);
|
||||
#endif
|
||||
|
||||
#if !HAVE_HSTRERROR
|
||||
extern const char *hstrerror(int err);
|
||||
#endif
|
||||
|
||||
extern int xiopoll(struct pollfd fds[], unsigned long nfds, struct timeval *timeout);
|
||||
|
||||
extern int parseport(const char *portname, int proto);
|
||||
|
||||
extern int ifindexbyname(const char *ifname, int anysock);
|
||||
extern int ifindex(const char *ifname, unsigned int *ifindex, int anysock);
|
||||
|
||||
extern int xiosetenv(const char *varname, const char *value, int overwrite, const char *sep);
|
||||
extern int
|
||||
xiosetenv2(const char *varname, const char *varname2, const char *value,
|
||||
int overwrite, const char *sep);
|
||||
extern int
|
||||
xiosetenv3(const char *varname, const char *varname2, const char *varname3,
|
||||
const char *value, int overwrite, const char *sep);
|
||||
extern int xiosetenvulong(const char *varname, unsigned long value,
|
||||
int overwrite);
|
||||
extern int xiosetenvushort(const char *varname, unsigned short value,
|
||||
int overwrite);
|
||||
extern unsigned long int Strtoul(const char *nptr, char **endptr, int base, const char *txt);
|
||||
extern long long int Strtoll(const char *nptr, char **endptr, int base, const char *txt);
|
||||
extern double Strtod(const char *nptr, char **endptr, const char *txt);
|
||||
extern int xio_opensnifffile(const char *a, struct timeval *tv);
|
||||
|
||||
#endif /* !defined(__sysutils_h_included) */
|
||||
181
utils.c
Normal file
181
utils.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/* source: utils.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* useful additions to C library */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "sysincludes.h"
|
||||
|
||||
#include "compat.h" /* socklen_t */
|
||||
#include "mytypes.h"
|
||||
#include "sycls.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
#if !HAVE_PROTOTYPE_LIB_memrchr
|
||||
/* GNU extension, available since glibc 2.1.91 */
|
||||
void *memrchr(const void *s, int c, size_t n) {
|
||||
const unsigned char *t = ((unsigned char *)s)+n;
|
||||
while (--t >= (unsigned char *)s) {
|
||||
if (*t == c) break;
|
||||
}
|
||||
if (t < (unsigned char *)s)
|
||||
return NULL;
|
||||
return (void *)t;
|
||||
}
|
||||
#endif /* !HAVE_PROTOTYPE_LIB_memrchr */
|
||||
|
||||
void *memdup(const void *src, size_t n) {
|
||||
void *dest;
|
||||
|
||||
if ((dest = Malloc(n)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(dest, src, n);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/* search the keyword-table for a match of the leading part of name. */
|
||||
/* returns the pointer to the matching field of the keyword or NULL if no
|
||||
keyword was found. */
|
||||
const struct wordent *keyw(const struct wordent *keywds, const char *name, unsigned int nkeys) {
|
||||
unsigned int lower, upper, mid;
|
||||
int r;
|
||||
|
||||
lower = 0;
|
||||
upper = nkeys;
|
||||
|
||||
while (upper - lower > 1)
|
||||
{
|
||||
mid = (upper + lower) >> 1;
|
||||
if (!(r = strcasecmp(keywds[mid].name, name)))
|
||||
{
|
||||
return &keywds[mid];
|
||||
}
|
||||
if (r < 0)
|
||||
lower = mid;
|
||||
else
|
||||
upper = mid;
|
||||
}
|
||||
if (nkeys > 0 && !(strcasecmp(keywds[lower].name, name)))
|
||||
{
|
||||
return &keywds[lower];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Linux: setenv(), AIX (4.3?): putenv() */
|
||||
#if !HAVE_SETENV
|
||||
int setenv(const char *name, const char *value, int overwrite) {
|
||||
int result;
|
||||
char *env;
|
||||
if (!overwrite) {
|
||||
if (getenv(name)) return 0; /* already exists */
|
||||
}
|
||||
if ((env = Malloc(strlen(name)+strlen(value)+2)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
sprintf(env, "%s=%s", name, value);
|
||||
if ((result = putenv(env)) != 0) { /* AIX docu says "... nonzero ..." */
|
||||
free(env);
|
||||
result = -1;
|
||||
}
|
||||
/* linux "man putenv" says: ...this string becomes part of the environment*/
|
||||
return result;
|
||||
}
|
||||
#endif /* !HAVE_SETENV */
|
||||
|
||||
|
||||
/* sanitizes an "untrusted" character. output buffer must provide at least 4
|
||||
characters space.
|
||||
Does not append \0. returns length of output (currently: max 4) */
|
||||
static size_t sanitize_char(char c, char *o, int style) {
|
||||
int hn; /* high nibble */
|
||||
int ln; /* low nibble */
|
||||
int n; /* written chars */
|
||||
if (isprint((unsigned char)c)) {
|
||||
*o = c;
|
||||
return 1;
|
||||
}
|
||||
*o++ = '\\';
|
||||
n = 2;
|
||||
switch (c) {
|
||||
case '\0': *o++ = '0'; break;
|
||||
case '\a': *o++ = 'a'; break;
|
||||
case '\b': *o++ = 'b'; break;
|
||||
case '\t': *o++ = 't'; break;
|
||||
case '\n': *o++ = 'n'; break;
|
||||
case '\v': *o++ = 'v'; break;
|
||||
case '\f': *o++ = 'f'; break;
|
||||
case '\r': *o++ = 'r'; break;
|
||||
case '\'': *o++ = '\''; break;
|
||||
case '\"': *o++ = '"'; break;
|
||||
case '\\': *o++ = '\\'; break;
|
||||
default:
|
||||
*o++ = 'x';
|
||||
hn = (c>>4)&0x0f;
|
||||
ln = c&0x0f;
|
||||
*o++ = (hn>=10 ? (('A'-1)+(hn-10)) : ('0'+hn));
|
||||
*o++ = (ln>=10 ? (('A'-1)+(ln-10)) : ('0'+ln));
|
||||
n = 4;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* sanitizes "untrusted" text, replacing special control characters with the C
|
||||
string version (eg."\n"), and replacing unprintable chars with hex
|
||||
representation ("\xAB").
|
||||
text can grow to four times of input, so keep output buffer long enough!
|
||||
returns a pointer to the first untouched byte of the output buffer.
|
||||
Output is not \0 terminated.
|
||||
*/
|
||||
char *sanitize_string(const char *data, /* input data */
|
||||
size_t bytes, /* length of input data, >=0 */
|
||||
char *coded, /* output buffer, must be long enough */
|
||||
int style
|
||||
) {
|
||||
int c;
|
||||
|
||||
while (bytes > 0) {
|
||||
c = *(unsigned char *)data++;
|
||||
coded += sanitize_char(c, coded, style);
|
||||
--bytes;
|
||||
}
|
||||
return coded;
|
||||
}
|
||||
|
||||
/* copies a substring out of a given buff
|
||||
returns scratch, \0 terminated; scratch must provide len+1 bytes
|
||||
*/
|
||||
char *xiosubstr(char *scratch, const char *str, size_t from, size_t len) {
|
||||
char *scratch0 = scratch;
|
||||
str += from;
|
||||
while (len--) {
|
||||
*scratch++ = *str++;
|
||||
}
|
||||
*scratch = '\0';
|
||||
return scratch0;
|
||||
}
|
||||
|
||||
|
||||
/* since version 1.7.2.4 socat supports C-99 behaviour of snprintf but still
|
||||
can handle the old glibc case with -1 return on truncation.
|
||||
Do not rely on exact return value in case of truncation
|
||||
*/
|
||||
int xio_snprintf(char *str, size_t size, const char *format, ...) {
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start(ap, format);
|
||||
result = vsnprintf(str, size, format, ap);
|
||||
#if ! HAVE_C99_SNPRINTF
|
||||
if (result < 0) {
|
||||
result = size+63; /* indicate truncation with just some guess */
|
||||
}
|
||||
#endif /* !HAVE_C99_SNPRINTF */
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
72
utils.h
Normal file
72
utils.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* source: utils.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __utils_h_included
|
||||
#define __utils_h_included 1
|
||||
|
||||
/* a generic name table entry */
|
||||
struct wordent {
|
||||
const char *name;
|
||||
void *desc;
|
||||
} ;
|
||||
|
||||
#if !HAVE_PROTOTYPE_LIB_memrchr
|
||||
extern void *memrchr(const void *s, int c, size_t n);
|
||||
#endif
|
||||
extern void *memdup(const void *src, size_t n);
|
||||
#if !HAVE_SETENV
|
||||
extern int setenv(const char *name, const char *value, int overwrite);
|
||||
#endif /* !HAVE_SETENV */
|
||||
|
||||
extern const struct wordent *keyw(const struct wordent *keywds, const char *name, unsigned int nkeys);
|
||||
|
||||
|
||||
#define XIOSAN_ZERO_MASK 0x000f
|
||||
#define XIOSAN_ZERO_DEFAULT 0x0000
|
||||
#define XIOSAN_ZERO_DOT 0x0001
|
||||
#define XIOSAN_ZERO_BACKSLASH_OCT_3 0x0002
|
||||
#define XIOSAN_ZERO_BACKSLASH_OCT_4 0x0003
|
||||
#define XIOSAN_ZERO_BACKSLASHX_HEX_UP 0x0004
|
||||
#define XIOSAN_ZERO_BACKSLASHX_HEX_LOW 0x0005
|
||||
#define XIOSAN_ZERO_PERCENT_HEX_UP 0x0006
|
||||
#define XIOSAN_ZERO_PERCENT_HEX_LOW 0x0007
|
||||
#define XIOSAN_CONTROL_MASK 0x00f0
|
||||
#define XIOSAN_CONTROL_DEFAULT 0x0000
|
||||
#define XIOSAN_CONTROL_DOT 0x0010
|
||||
#define XIOSAN_CONTROL_BACKSLASH_OCT_3 0x0020
|
||||
#define XIOSAN_CONTROL_BACKSLASH_OCT_4 0x0030
|
||||
#define XIOSAN_CONTROL_BACKSLASHX_HEX_UP 0x0040
|
||||
#define XIOSAN_CONTROL_BACKSLASHX_HEX_LOW 0x0050
|
||||
#define XIOSAN_CONTROL_PERCENT_HEX_UP 0x0060
|
||||
#define XIOSAN_CONTROL_PERCENT_HEX_LOW 0x0070
|
||||
#define XIOSAN_UNPRINT_MASK 0x0f00
|
||||
#define XIOSAN_UNPRINT_DEFAULT 0x0000
|
||||
#define XIOSAN_UNPRINT_DOT 0x0100
|
||||
#define XIOSAN_UNPRINT_BACKSLASH_OCT_3 0x0200
|
||||
#define XIOSAN_UNPRINT_BACKSLASH_OCT_4 0x0300
|
||||
#define XIOSAN_UNPRINT_BACKSLASHX_HEX_UP 0x0400
|
||||
#define XIOSAN_UNPRINT_BACKSLASHX_HEX_LOW 0x0500
|
||||
#define XIOSAN_UNPRINT_PERCENT_HEX_UP 0x0600
|
||||
#define XIOSAN_UNPRINT_PERCENT_HEX_LOW 0x0700
|
||||
#define XIOSAN_DEFAULT_MASK 0xf000
|
||||
#define XIOSAN_DEFAULT_BACKSLASH_DOT 0x1000
|
||||
#define XIOSAN_DEFAULT_BACKSLASH_OCT_3 0x2000
|
||||
#define XIOSAN_DEFAULT_BACKSLASH_OCT_4 0x3000
|
||||
#define XIOSAN_DEFAULT_BACKSLASHX_HEX_UP 0x4000
|
||||
#define XIOSAN_DEFAULT_BACKSLASHX_HEX_LOW 0x5000
|
||||
#define XIOSAN_DEFAULT_PERCENT_HEX_UP 0x6000
|
||||
#define XIOSAN_DEFAULT_PERCENT_HEX_LOW 0x7000
|
||||
|
||||
extern
|
||||
char *sanitize_string(const char *data, /* input data */
|
||||
size_t bytes, /* length of input data, >=0 */
|
||||
char *coded, /* output buffer, must be long enough */
|
||||
int style);
|
||||
extern
|
||||
char *xiosubstr(char *scratch, const char *str, size_t from, size_t len);
|
||||
|
||||
extern
|
||||
int xio_snprintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
#endif /* !defined(__utils_h_included) */
|
||||
569
vsnprintf_r.c
Normal file
569
vsnprintf_r.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/* vsnprintf_r.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
|
||||
/* a reduced but async-signal-safe and thread-safe version of vsnprintf */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <ctype.h> /* isdigit() */
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#if HAVE_SYSLOG_H
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
#include <sys/utsname.h>
|
||||
#include <time.h> /* time_t, strftime() */
|
||||
#include <sys/time.h> /* gettimeofday() */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "vsnprintf_r.h"
|
||||
|
||||
/* helper functions for vsnprintf_r():
|
||||
e.g. convert an unsigned long to decimal string.
|
||||
in: field (must be long enough for all digits and \0
|
||||
n: length of field in bytes
|
||||
ulo: the value
|
||||
returns: the pointer to the result string (need not be ==field)
|
||||
*/
|
||||
|
||||
/* this function converts an unsigned long number to decimal ASCII
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *_diag_ulong_to_dec(char *field, size_t n, unsigned long ulo) {
|
||||
char *np = field+n; /* point to the end */
|
||||
|
||||
if (n == 0) return NULL;
|
||||
*--np = '\0'; /* \0 in last char of string */
|
||||
/* this is not optimal - uses much CPU, but simple to implement */
|
||||
/* calculate the result from right to left */
|
||||
do { if (np==field) return NULL; *--np = '0'+(ulo%10); } while (ulo/=10);
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts an unsigned long number to decimal ASCII
|
||||
and pads it with space or '0' when size and leading0 are set appropriately
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it reduces size to n-1 if it is greater or equal
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *diag_ulong_to_dec(char *field, size_t n, unsigned long ulo, int leading0, int size) {
|
||||
char *np;
|
||||
char c;
|
||||
int i;
|
||||
|
||||
if (n == 0) return NULL;
|
||||
np = _diag_ulong_to_dec(field, n, ulo);
|
||||
if (np == NULL) return np;
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
if (leading0) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
i = size - strlen(np);
|
||||
while (--i >= 0) {
|
||||
*--np = c;
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts a signed long number to decimal ASCII
|
||||
and pads it with space or '0' when size and leading0 are set appropriately
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it reduces size to n-1 if it is greater or equal
|
||||
it terminates result with \0
|
||||
*/
|
||||
/* like diag_ulong_to_dec but signed; fields need also space for '-' */
|
||||
static char *diag_long_to_dec(char *field, size_t n, long lo, int leading0, int size) {
|
||||
char *np;
|
||||
int minus;
|
||||
unsigned long ulo;
|
||||
int i;
|
||||
|
||||
if ((minus = (lo < 0))) {
|
||||
ulo = (~lo)+1;
|
||||
} else {
|
||||
ulo = lo;
|
||||
}
|
||||
np = _diag_ulong_to_dec(field, n, ulo);
|
||||
if (np == NULL) return np;
|
||||
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
i = size - strlen(np);
|
||||
if (leading0) {
|
||||
if (minus) --i;
|
||||
while (--i >= 0) {
|
||||
*--np = '0';
|
||||
}
|
||||
if (minus) *--np = '-';
|
||||
} else {
|
||||
if (minus) { *--np = '-'; --i; }
|
||||
while (--i >= 0) {
|
||||
*--np = ' ';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (minus) *--np = '-';
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts an unsigned long number to hexadecimal ASCII
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *diag_ulong_to_hex(char *field, size_t n, unsigned long ulo, int leading0, size_t size) {
|
||||
char *np = field+n; /* point to the end */
|
||||
int i;
|
||||
char c;
|
||||
|
||||
if (n == 0) return NULL;
|
||||
*--np = '\0'; /* \0 in last char of string */
|
||||
/* calculate the result from right to left */
|
||||
do { if (np==field) return NULL; i = (ulo&0x0f);
|
||||
*--np = (i<10?'0':('a'-10))+i; }
|
||||
while (ulo>>=4);
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
if (leading0) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
i = size - strlen(np);
|
||||
while (--i >= 0) {
|
||||
*--np = c;
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts an unsigned long number to octal ASCII
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *diag_ulong_to_oct(char *field, size_t n, unsigned long ulo, int leading0, size_t size) {
|
||||
char *np = field+n; /* point to the end */
|
||||
int i;
|
||||
char c;
|
||||
|
||||
if (n == 0) return NULL;
|
||||
*--np = '\0'; /* \0 in last char of string */
|
||||
/* calculate the result from right to left */
|
||||
do { if (np==field) return NULL; i = (ulo&0x07); *--np = '0'+i; }
|
||||
while (ulo>>=3);
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
if (leading0) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
i = size - strlen(np);
|
||||
while (--i >= 0) {
|
||||
*--np = c;
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
|
||||
/* this function converts an unsigned long long number to decimal ASCII
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *_diag_ulonglong_to_dec(char *field, size_t n, unsigned long long ull) {
|
||||
char *np = field+n; /* point to the end */
|
||||
|
||||
if (n == 0) return NULL;
|
||||
*--np = '\0'; /* \0 in last char of string */
|
||||
/* this is not optimal - uses much CPU, but simple to implement */
|
||||
/* calculate the result from right to left */
|
||||
do { if (np==field) return NULL; *--np = '0'+(ull%10); } while (ull/=10);
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts an unsigned long long number to decimal ASCII
|
||||
and pads it with space or '0' when size and leading0 are set appropriately
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it reduces size to n-1 if it is greater or equal
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *diag_ulonglong_to_dec(char *field, size_t n, unsigned long long ull, int leading0, int size) {
|
||||
char *np;
|
||||
char c;
|
||||
int i;
|
||||
|
||||
if (n == 0) return NULL;
|
||||
np = _diag_ulonglong_to_dec(field, n, ull);
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
if (leading0) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
i = size - strlen(np);
|
||||
while (i-- > 0) {
|
||||
*--np = c;
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts a signed long long number to decimal ASCII
|
||||
and pads it with space or '0' when size and leading0 are set appropriately
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it reduces size to n-1 if it is greater or equal
|
||||
it terminates result with \0
|
||||
*/
|
||||
/* like diag_ulonglong_to_dec but signed; fields need also space for '-' */
|
||||
static char *diag_longlong_to_dec(char *field, size_t n, long long ll, int leading0, int size) {
|
||||
char *np;
|
||||
int minus;
|
||||
unsigned long ull;
|
||||
int i;
|
||||
|
||||
if ((minus = (ll < 0))) {
|
||||
ull = (~ll)+1;
|
||||
} else {
|
||||
ull = ll;
|
||||
}
|
||||
np = _diag_ulonglong_to_dec(field, n, ull);
|
||||
if (np == NULL) return np;
|
||||
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
i = size - strlen(np);
|
||||
if (leading0) {
|
||||
if (minus) --i;
|
||||
while (--i >= 0) {
|
||||
*--np = '0';
|
||||
}
|
||||
if (minus) *--np = '-';
|
||||
} else {
|
||||
if (minus) { *--np = '-'; --i; }
|
||||
while (--i >= 0) {
|
||||
*--np = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts an unsigned long long number to hexadecimal ASCII
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *diag_ulonglong_to_hex(char *field, size_t n, unsigned long long ull, int leading0, size_t size) {
|
||||
char *np = field+n; /* point to the end */
|
||||
ptrdiff_t i;
|
||||
char c;
|
||||
|
||||
if (n == 0) return NULL;
|
||||
*--np = '\0'; /* \0 in last char of string */
|
||||
/* calculate the result from right to left */
|
||||
do { if (np==field) return NULL; i = (ull&0x0f);
|
||||
*--np = (i<10?'0':('a'-10))+i; }
|
||||
while (ull>>=4);
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
if (leading0) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
i = size - strlen(np);
|
||||
while (i-- > 0) {
|
||||
*--np = c;
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
/* this function converts an unsigned long long number to octal ASCII
|
||||
it is async signal safe and thread safe
|
||||
it returns NULL if n==0
|
||||
it returns NULL if field is too short to hold the result
|
||||
it returns a pointer to the result string (somewhere within field)
|
||||
it terminates result with \0
|
||||
*/
|
||||
static char *diag_ulonglong_to_oct(char *field, size_t n, unsigned long long ull, int leading0, size_t size) {
|
||||
char *np = field+n; /* point to the end */
|
||||
int i;
|
||||
char c;
|
||||
|
||||
if (n == 0) return NULL;
|
||||
*--np = '\0'; /* \0 in last char of string */
|
||||
/* calculate the result from right to left */
|
||||
do { if (np==field) return NULL; i = (ull&0x07); *--np = '0'+i; }
|
||||
while (ull>>=3);
|
||||
if (size) {
|
||||
if (size >= n) size = n-1;
|
||||
if (leading0) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
i = size - strlen(np);
|
||||
while (--i >= 0) {
|
||||
*--np = c;
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
#endif /* HAVE_TYPE_LONGLONG */
|
||||
|
||||
|
||||
/* this function is designed as a variant of vsnprintf(3) but async signal safe
|
||||
and thread safe
|
||||
it currently only implements a subset of the format directives
|
||||
returns <0 if an error occurred (no scenario know yet)
|
||||
returns >=size if output is truncated (conforming to C99 standard)
|
||||
*/
|
||||
int vsnprintf_r(char *str, size_t size, const char *format, va_list ap) {
|
||||
size_t i = 0;
|
||||
char c;
|
||||
int full = 0; /* indicate if output buffer full */
|
||||
|
||||
--size; /* without trailing \0 */
|
||||
while (c = *format++) {
|
||||
if (c == '\\') {
|
||||
|
||||
} else if (c == '%') {
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
# define num_buff_len ((sizeof(unsigned long long)*8+2)/3+1) /* hold up to u long long in octal w/ \0 */
|
||||
#else
|
||||
# define num_buff_len ((sizeof(unsigned long)*8+2)/3+1) /* hold up to u long in octal w/ \0 */
|
||||
#endif
|
||||
char lengthmod = '\0'; /* 'h' 'l' 'L' 'z' */
|
||||
int leading0 = 0; /* or 1 */
|
||||
size_t fsize = 0; /* size of field */
|
||||
const char *st; /* string */
|
||||
long lo; unsigned long ulo;
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
long long ll; unsigned long long ull;
|
||||
#endif
|
||||
char field[num_buff_len]; /* result of number conversion */
|
||||
char *np; /* num pointer */
|
||||
|
||||
c = *format++;
|
||||
if (c == '\0') { break; }
|
||||
|
||||
/* flag characters */
|
||||
switch (c) {
|
||||
case '0': leading0 = 1; c = *format++; break;
|
||||
/* not handled: '#' '-' ' ' '+' '\'' */
|
||||
}
|
||||
if (c == '\0') { break; }
|
||||
|
||||
/* field width */
|
||||
switch (c) {
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
do {
|
||||
fsize = 10*fsize+(c-'0');
|
||||
c = *format++;
|
||||
} while (c && isdigit((unsigned char)c));
|
||||
break;
|
||||
}
|
||||
if (c == '\0') { break; }
|
||||
|
||||
/* precision - not handles */
|
||||
|
||||
/* length modifier */
|
||||
switch (c) {
|
||||
/* not handled: 'q' 'j' 't' */
|
||||
/* handled: 'h' 'hh'->'H' 'z' 'Z'->'z' 'l' 'll'->'L' 'L' */
|
||||
case 'Z': c = 'z'; /* fall through */
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
case 'L':
|
||||
#endif
|
||||
case 'z': lengthmod = c; c = *format++; break;
|
||||
case 'h':
|
||||
lengthmod = c;
|
||||
if ((c = *format++) == 'h') {
|
||||
lengthmod = 'H'; c = *format++;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
lengthmod = c;
|
||||
if ((c = *format++) == 'l') {
|
||||
lengthmod = 'L'; c = *format++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c == '\0') { break; }
|
||||
|
||||
/* conversion specifier */
|
||||
switch (c) {
|
||||
case 'c': c = va_arg(ap, int); /* fall through */
|
||||
case '%': *str++ = c; if (++i == size) { full = 1; } break;
|
||||
|
||||
case 's': st = va_arg(ap, const char *);
|
||||
/* no modifier handled! */
|
||||
while (c = *st++) {
|
||||
*str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
if (lengthmod == 'L') {
|
||||
ll = va_arg(ap, long long);
|
||||
np = diag_longlong_to_dec(field, num_buff_len, ll, leading0, fsize);
|
||||
while (c = *np++) {
|
||||
*str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
switch (lengthmod) {
|
||||
case 'l': lo = va_arg(ap, long); break;
|
||||
case 'z': lo = va_arg(ap, ptrdiff_t); break;
|
||||
default: lo = va_arg(ap, int); break;
|
||||
}
|
||||
np = diag_long_to_dec(field, num_buff_len, lo, leading0, fsize);
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
if (lengthmod == 'L') {
|
||||
ull = va_arg(ap, unsigned long long);
|
||||
np = diag_ulonglong_to_dec(field, num_buff_len, ull, leading0, fsize);
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
switch (lengthmod) {
|
||||
case 'l': ulo = va_arg(ap, unsigned long); break;
|
||||
case 'z': ulo = va_arg(ap, size_t); break;
|
||||
default: ulo = va_arg(ap, unsigned int); break;
|
||||
}
|
||||
np = diag_ulong_to_dec(field, num_buff_len, ulo, leading0, fsize);
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
ulo = va_arg(ap, size_t);
|
||||
np = diag_ulong_to_hex(field, num_buff_len, ulo, leading0, fsize);
|
||||
*str++ = '0'; if (++i == size) { full = 1; break; }
|
||||
*str++ = 'x'; if (++i == size) { full = 1; break; }
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
if (lengthmod == 'L') {
|
||||
ull = va_arg(ap, unsigned long long);
|
||||
np = diag_ulonglong_to_hex(field, num_buff_len, ull, leading0, fsize);
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
switch (lengthmod) {
|
||||
case 'l': ulo = va_arg(ap, unsigned long); break;
|
||||
case 'z': ulo = va_arg(ap, size_t); break;
|
||||
default: ulo = va_arg(ap, unsigned int); break;
|
||||
}
|
||||
np = diag_ulong_to_hex(field, num_buff_len, ulo, leading0, fsize);
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
#if HAVE_TYPE_LONGLONG
|
||||
if (lengthmod == 'L') {
|
||||
ull = va_arg(ap, unsigned long long);
|
||||
np = diag_ulonglong_to_oct(field, num_buff_len, ull, leading0, fsize);
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) break;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
switch (lengthmod) {
|
||||
case 'l': ulo = va_arg(ap, unsigned long); break;
|
||||
case 'z': ulo = va_arg(ap, size_t); break;
|
||||
default: ulo = va_arg(ap, unsigned int); break;
|
||||
}
|
||||
np = diag_ulong_to_oct(field, num_buff_len, ulo, leading0, fsize);
|
||||
while (c = *np++) { *str++ = c;
|
||||
if (++i == size) { full = 1; break; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*str++ = c; if (++i == size) { full = 1; break; }
|
||||
}
|
||||
if (full) break;
|
||||
} else {
|
||||
*str++ = c;
|
||||
if (++i == size) break;
|
||||
}
|
||||
}
|
||||
*str = '\0';
|
||||
return i;
|
||||
}
|
||||
|
||||
int snprintf_r(char *str, size_t size, const char *format, ...) {
|
||||
int result;
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
result = vsnprintf_r(str, size, format, ap);
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
|
||||
11
vsnprintf_r.h
Normal file
11
vsnprintf_r.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/* source: vsnprintf_r.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __vsnprintf_r_h_included
|
||||
#define __vsnprintf_r_h_included 1
|
||||
|
||||
int vsnprintf_r(char *str, size_t size, const char *format, va_list ap);
|
||||
int snprintf_r(char *str, size_t size, const char *format, ...);
|
||||
|
||||
#endif /* !defined(__vsnprintf_r_h_included) */
|
||||
158
xio-ascii.c
Normal file
158
xio-ascii.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/* source: xio-ascii.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains functions for text encoding, decoding, and conversions */
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xio-ascii.h"
|
||||
|
||||
/* for each 6 bit pattern we have an ASCII character in the arry */
|
||||
const static int base64chars[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/',
|
||||
} ;
|
||||
|
||||
#define CHAR64(c) (base64chars[c])
|
||||
|
||||
char *
|
||||
xiob64encodeline(const char *data, /* input data */
|
||||
size_t bytes, /* length of input data, >=0 */
|
||||
char *coded /* output buffer, must be long enough */
|
||||
) {
|
||||
int c1, c2, c3;
|
||||
|
||||
while (bytes > 0) {
|
||||
c1 = *data++;
|
||||
*coded++ = CHAR64(c1>>2);
|
||||
if (--bytes == 0) {
|
||||
*coded++ = CHAR64((c1&0x03)<<4);
|
||||
*coded++ = '=';
|
||||
*coded++ = '=';
|
||||
} else {
|
||||
c2 = *data++;
|
||||
*coded++ = CHAR64(((c1&0x03)<<4)|(c2>>4));
|
||||
if (--bytes == 0) {
|
||||
*coded++ = CHAR64((c2&0x0f)<<2);
|
||||
*coded++ = '=';
|
||||
} else {
|
||||
c3 = *data++; --bytes;
|
||||
*coded++ = CHAR64(((c2&0x0f)<<2)|(c3>>6));
|
||||
*coded++ = CHAR64(c3&0x3f);
|
||||
}
|
||||
}
|
||||
}
|
||||
return coded;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* sanitize "untrusted" text, replacing special control characters with the C
|
||||
string version ("\x"), and replacing unprintable chars with ".".
|
||||
text can grow to double size, so keep output buffer long enough!
|
||||
returns a pointer to the first untouched byte of the output buffer.
|
||||
*/
|
||||
char *xiosanitize(const char *data, /* input data */
|
||||
size_t bytes, /* length of input data, >=0 */
|
||||
char *coded /* output buffer, must be long enough */
|
||||
) {
|
||||
int c;
|
||||
|
||||
while (bytes > 0) {
|
||||
c = *(unsigned char *)data++;
|
||||
switch (c) {
|
||||
case '\0' : *coded++ = '\\'; *coded++ = '0'; break;
|
||||
case '\a' : *coded++ = '\\'; *coded++ = 'a'; break;
|
||||
case '\b' : *coded++ = '\\'; *coded++ = 'b'; break;
|
||||
case '\t' : *coded++ = '\\'; *coded++ = 't'; break;
|
||||
case '\n' : *coded++ = '\\'; *coded++ = 'n'; break;
|
||||
case '\v' : *coded++ = '\\'; *coded++ = 'v'; break;
|
||||
case '\f' : *coded++ = '\\'; *coded++ = 'f'; break;
|
||||
case '\r' : *coded++ = '\\'; *coded++ = 'r'; break;
|
||||
case '\'' : *coded++ = '\\'; *coded++ = '\''; break;
|
||||
case '\"' : *coded++ = '\\'; *coded++ = '"'; break;
|
||||
case '\\' : *coded++ = '\\'; *coded++ = '\\'; break;
|
||||
default:
|
||||
if (!isprint(c))
|
||||
c = '.';
|
||||
*coded++ = c;
|
||||
break;
|
||||
}
|
||||
--bytes;
|
||||
}
|
||||
return coded;
|
||||
}
|
||||
|
||||
|
||||
/* print the bytes in hex */
|
||||
char *
|
||||
xiohexdump(const unsigned char *data, size_t bytes, char *coded) {
|
||||
int space = 0;
|
||||
while (bytes-- > 0) {
|
||||
if (space) { *coded++ = ' '; }
|
||||
coded += sprintf(coded, "%02x", *data++);
|
||||
space = 1;
|
||||
}
|
||||
return coded;
|
||||
}
|
||||
|
||||
/* write the binary data to output buffer codbuff in human readable form.
|
||||
bytes gives the length of the data, codlen the available space in codbuff.
|
||||
coding specifies how the data is to be presented. Not much to select now.
|
||||
returns a pointer to the first char in codbuff that has not been overwritten;
|
||||
it might also point to the first char after the buffer!
|
||||
this function does not write a terminating \0
|
||||
*/
|
||||
static char *
|
||||
_xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen,
|
||||
int coding) {
|
||||
int start = 1;
|
||||
int space = coding & 0xff;
|
||||
|
||||
if (bytes <= 0) { return codbuff; }
|
||||
if (codlen < 1) { return codbuff; }
|
||||
if (space == 0) space = -1;
|
||||
if (0) {
|
||||
; /* for canonical reasons */
|
||||
} else if (1) {
|
||||
/* simple hexadecimal output */
|
||||
if (3*bytes+1 > codlen) {
|
||||
bytes = (codlen-1)/3; /* "truncate" data so generated text fits */
|
||||
}
|
||||
*codbuff++ = 'x';
|
||||
while (bytes-- > 0) {
|
||||
if (start == 0 && space == 0) {
|
||||
*codbuff++ = ' ';
|
||||
space = (coding & 0xff);
|
||||
}
|
||||
codbuff += sprintf(codbuff, "%02x", *data++);
|
||||
start = 0;
|
||||
}
|
||||
}
|
||||
return codbuff;
|
||||
}
|
||||
|
||||
/* write the binary data to codbuff in human readable form.
|
||||
bytes gives the length of the data, codlen the available space in codbuff.
|
||||
coding specifies how the data is to be presented. Not much to select now.
|
||||
null terminates the output. returns a pointer to the output string.
|
||||
*/
|
||||
char *
|
||||
xiodump(const unsigned char *data, size_t bytes, char *codbuff, size_t codlen,
|
||||
int coding) {
|
||||
char *result;
|
||||
|
||||
result = _xiodump(data, bytes, codbuff, codlen-1, coding);
|
||||
*result = '\0';
|
||||
return codbuff;
|
||||
}
|
||||
24
xio-ascii.h
Normal file
24
xio-ascii.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* source: xio-ascii.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ascii_h_included
|
||||
#define __xio_ascii_h_included 1
|
||||
|
||||
extern char *
|
||||
xiob64encodeline(const char *data, /* input data */
|
||||
size_t bytes, /* length of input data, >=0 */
|
||||
char *coded /* output buffer, must be long enough */
|
||||
);
|
||||
extern char *xiosanitize(const char *data, /* input data */
|
||||
size_t bytes, /* length of input data, >=0 */
|
||||
char *coded /* output buffer, must be long enough */
|
||||
);
|
||||
extern char *
|
||||
xiohexdump(const unsigned char *data, size_t bytes, char *coded);
|
||||
|
||||
extern char *
|
||||
xiodump(const unsigned char *data, size_t bytes, char *coded, size_t codlen,
|
||||
int coding);
|
||||
|
||||
#endif /* !defined(__xio_ascii_h_included) */
|
||||
90
xio-creat.c
Normal file
90
xio-creat.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/* source: xio-creat.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of create type */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if WITH_CREAT
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-named.h"
|
||||
#include "xio-creat.h"
|
||||
|
||||
|
||||
static int xioopen_creat(int arg, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||
|
||||
|
||||
/*! within stream model, this is a write-only address - use 2 instead of 3 */
|
||||
const struct addrdesc xioaddr_creat = { "CREATE", 1+XIO_WRONLY, xioopen_creat, GROUP_FD|GROUP_NAMED|GROUP_FILE, 0, 0, 0 HELP(":<filename>") };
|
||||
|
||||
|
||||
/* retrieve the mode option and perform the creat() call.
|
||||
returns the file descriptor or a negative value. */
|
||||
static int _xioopen_creat(const char *path, int rw, struct opt *opts) {
|
||||
mode_t mode = 0666;
|
||||
int fd;
|
||||
|
||||
retropt_modet(opts, OPT_PERM, &mode);
|
||||
|
||||
if ((fd = Creat(path, mode)) < 0) {
|
||||
Error3("creat(\"%s\", 0%03o): %s",
|
||||
path, mode, strerror(errno));
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
static int xioopen_creat(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
struct opt *opts,
|
||||
int xioflags,
|
||||
xiofile_t *xxfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
struct single *sfd = &xxfd->stream;
|
||||
const char *filename = argv[1];
|
||||
int rw = (xioflags&XIO_ACCMODE);
|
||||
bool exists;
|
||||
bool opt_unlink_close = false;
|
||||
int result;
|
||||
|
||||
/* remove old file, or set user/permissions on old file; parse options */
|
||||
if ((result =
|
||||
_xioopen_named_early(argc, argv, xxfd, addrdesc->groups, &exists, opts,
|
||||
addrdesc->syntax))
|
||||
< 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((sfd->unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]);
|
||||
if ((result = _xioopen_creat(filename, rw, opts)) < 0)
|
||||
return result;
|
||||
sfd->fd = result;
|
||||
|
||||
applyopts_named(filename, opts, PH_PASTOPEN);
|
||||
if ((result = applyopts2(sfd, -1, opts, PH_PASTOPEN, PH_LATE2)) < 0)
|
||||
return result;
|
||||
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
applyopts_fchown(sfd->fd, opts);
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WITH_CREAT */
|
||||
10
xio-creat.h
Normal file
10
xio-creat.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* source: xio-creat.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_creat_h_included
|
||||
#define __xio_creat_h_included 1
|
||||
|
||||
extern const struct addrdesc xioaddr_creat;
|
||||
|
||||
#endif /* !defined(__xio_creat_h_included) */
|
||||
46
xio-dccp.c
Normal file
46
xio-dccp.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* source: xio-dccp.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for DCCP related functions and options */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if WITH_DCCP
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-listen.h"
|
||||
#include "xio-ip4.h"
|
||||
#include "xio-ipapp.h"
|
||||
#include "xio-dccp.h"
|
||||
|
||||
/****** DCCP addresses ******/
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
const struct addrdesc xioaddr_dccp_connect = { "DCCP-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_CHILD|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_UNSPEC HELP(":<host>:<port>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_dccp_listen = { "DCCP-LISTEN", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_UNSPEC HELP(":<port>") };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if WITH_IP4
|
||||
const struct addrdesc xioaddr_dccp4_connect = { "DCCP4-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_DCCP|GROUP_CHILD|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET HELP(":<host>:<port>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_dccp4_listen = { "DCCP4-LISTEN", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_DCCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET HELP(":<port>") };
|
||||
#endif
|
||||
#endif /* WITH_IP4 */
|
||||
|
||||
#if WITH_IP6
|
||||
const struct addrdesc xioaddr_dccp6_connect = { "DCCP6-CONNECT", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_CHILD|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET6 HELP(":<host>:<port>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_dccp6_listen = { "DCCP6-LISTEN", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_DCCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_DCCP, IPPROTO_DCCP, PF_INET6 HELP(":<port>") };
|
||||
#endif
|
||||
#endif /* WITH_IP6 */
|
||||
|
||||
/****** DCCP address options ******/
|
||||
|
||||
#if defined(SOL_DCCP) && defined(DCCP_SOCKOPT_QPOLICY_ID)
|
||||
const struct optdesc xioopt_dccp_set_ccid = { "dccp-set-ccid", "ccid", OPT_DCCP_SET_CCID, GROUP_IP_DCCP, PH_PASTSOCKET, TYPE_BYTE, OFUNC_SOCKOPT, SOL_DCCP, DCCP_SOCKOPT_CCID };
|
||||
#endif
|
||||
|
||||
#endif /* WITH_DCCP */
|
||||
17
xio-dccp.h
Normal file
17
xio-dccp.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* source: xio-dccp.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_dccp_h_included
|
||||
#define __xio_dccp_h_included 1
|
||||
|
||||
extern const struct addrdesc xioaddr_dccp_connect;
|
||||
extern const struct addrdesc xioaddr_dccp_listen;
|
||||
extern const struct addrdesc xioaddr_dccp4_connect;
|
||||
extern const struct addrdesc xioaddr_dccp4_listen;
|
||||
extern const struct addrdesc xioaddr_dccp6_connect;
|
||||
extern const struct addrdesc xioaddr_dccp6_listen;
|
||||
|
||||
extern const struct optdesc xioopt_dccp_set_ccid;
|
||||
|
||||
#endif /* !defined(__xio_dccp_h_included) */
|
||||
150
xio-exec.c
Normal file
150
xio-exec.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/* source: xio-exec.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of exec type */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "xioopen.h"
|
||||
#include "nestlex.h"
|
||||
|
||||
#include "xio-progcall.h"
|
||||
#include "xio-exec.h"
|
||||
|
||||
#if WITH_EXEC
|
||||
|
||||
static int xioopen_exec(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
|
||||
const struct addrdesc xioaddr_exec = { "EXEC", 3, xioopen_exec, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 0, 0, 0 HELP(":<command-line>") };
|
||||
|
||||
const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };
|
||||
|
||||
static int xioopen_exec(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
struct opt *opts,
|
||||
int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
|
||||
xiofile_t *xfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
struct single *sfd = &xfd->stream;
|
||||
int status;
|
||||
bool dash = false;
|
||||
int duptostderr;
|
||||
int numleft;
|
||||
|
||||
if (argc != 2) {
|
||||
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_DASH, &dash);
|
||||
|
||||
status =
|
||||
_xioopen_foxec(xioflags, sfd, addrdesc->groups, &opts, &duptostderr);
|
||||
if (status < 0)
|
||||
return status;
|
||||
if (status == 0) { /* child */
|
||||
const char *ends[] = { " ", NULL };
|
||||
const char *hquotes[] = { "'", NULL };
|
||||
const char *squotes[] = { "\"", NULL };
|
||||
const char *nests[] = {
|
||||
"'", "'",
|
||||
"(", ")",
|
||||
"[", "]",
|
||||
"{", "}",
|
||||
NULL
|
||||
} ;
|
||||
char **pargv = NULL;
|
||||
int pargc;
|
||||
size_t len;
|
||||
const char *strp;
|
||||
char *token; /*! */
|
||||
char *tokp;
|
||||
char *path = NULL;
|
||||
char *tmp;
|
||||
|
||||
/*! Close(something) */
|
||||
/* parse command line */
|
||||
Debug1("child: args = \"%s\"", argv[1]);
|
||||
pargv = Malloc(8*sizeof(char *));
|
||||
if (pargv == NULL) return STAT_RETRYLATER;
|
||||
len = strlen(argv[1])+1;
|
||||
strp = argv[1];
|
||||
token = Malloc(len); /*! */
|
||||
tokp = token;
|
||||
if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
|
||||
true, true, false) < 0) {
|
||||
Error("internal: miscalculated string lengths");
|
||||
}
|
||||
*tokp++ = '\0';
|
||||
pargv[0] = strrchr(tokp-1, '/');
|
||||
if (pargv[0] == NULL) pargv[0] = token; else ++pargv[0];
|
||||
pargc = 1;
|
||||
while (*strp == ' ') {
|
||||
while (*++strp == ' ') ;
|
||||
if ((pargc & 0x07) == 0) {
|
||||
pargv = Realloc(pargv, (pargc+8)*sizeof(char *));
|
||||
if (pargv == NULL) return STAT_RETRYLATER;
|
||||
}
|
||||
pargv[pargc++] = tokp;
|
||||
if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
|
||||
true, true, false) < 0) {
|
||||
Error("internal: miscalculated string lengths");
|
||||
}
|
||||
*tokp++ = '\0';
|
||||
}
|
||||
pargv[pargc] = NULL;
|
||||
|
||||
if ((tmp = Malloc(strlen(pargv[0])+2)) == NULL) {
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
if (dash) {
|
||||
tmp[0] = '-';
|
||||
strcpy(tmp+1, pargv[0]);
|
||||
} else {
|
||||
strcpy(tmp, pargv[0]);
|
||||
}
|
||||
pargv[0] = tmp;
|
||||
|
||||
if (setopt_path(opts, &path) < 0) {
|
||||
/* this could be dangerous, so let us abort this child... */
|
||||
Exit(1);
|
||||
}
|
||||
|
||||
dropopts(opts, PH_PASTEXEC);
|
||||
if ((numleft = leftopts(opts)) > 0) {
|
||||
showleft(opts);
|
||||
Error1("INTERNAL: %d option(s) remained unused", numleft);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
/* only now redirect stderr */
|
||||
if (duptostderr >= 0) {
|
||||
diag_dup();
|
||||
Dup2(duptostderr, 2);
|
||||
}
|
||||
Notice1("execvp'ing \"%s\"", token);
|
||||
Execvp(token, pargv);
|
||||
/* here we come only if execvp() failed */
|
||||
switch (pargc) {
|
||||
case 1:
|
||||
Error3("execvp(\"%s\", \"%s\"): %s",
|
||||
token, pargv[0], strerror(errno)); break;
|
||||
case 2:
|
||||
Error4("execvp(\"%s\", \"%s\", \"%s\"): %s",
|
||||
token, pargv[0], pargv[1], strerror(errno)); break;
|
||||
case 3:
|
||||
default:
|
||||
Error5("execvp(\"%s\", \"%s\", \"%s\", \"%s\", ...): %s", token,
|
||||
pargv[0], pargv[1], pargv[2], strerror(errno));
|
||||
break;
|
||||
}
|
||||
Exit(1); /* this child process */
|
||||
}
|
||||
|
||||
/* parent */
|
||||
_xio_openlate(sfd, opts);
|
||||
return 0;
|
||||
}
|
||||
#endif /* WITH_EXEC */
|
||||
12
xio-exec.h
Normal file
12
xio-exec.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/* source: xio-exec.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_exec_h_included
|
||||
#define __xio_exec_h_included 1
|
||||
|
||||
extern const struct addrdesc xioaddr_exec;
|
||||
|
||||
extern const struct optdesc opt_dash;
|
||||
|
||||
#endif /* !defined(__xio_exec_h_included) */
|
||||
93
xio-fd.c
Normal file
93
xio-fd.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* source: xio-fd.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains common file descriptor related option definitions */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "xioopen.h"
|
||||
|
||||
#include "xio-fd.h"
|
||||
|
||||
/****** for ALL addresses - with open() or fcntl(F_SETFL) ******/
|
||||
const struct optdesc opt_append = { "append", NULL, OPT_O_APPEND, GROUP_OPEN|GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_APPEND };
|
||||
const struct optdesc opt_nonblock = { "o-nonblock", "nonblock", OPT_O_NONBLOCK, GROUP_OPEN|GROUP_FD, PH_FD, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NONBLOCK };
|
||||
#if defined(O_NDELAY) && (!defined(O_NONBLOCK) || O_NDELAY != O_NONBLOCK)
|
||||
const struct optdesc opt_o_ndelay = { "o-ndelay", NULL, OPT_O_NDELAY, GROUP_OPEN|GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NDELAY };
|
||||
#endif
|
||||
#ifdef O_ASYNC
|
||||
const struct optdesc opt_async = { "async", NULL, OPT_O_ASYNC, GROUP_OPEN|GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_ASYNC };
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
const struct optdesc opt_o_binary = { "o-binary", "binary", OPT_O_BINARY, GROUP_OPEN|GROUP_FD, PH_OPEN, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_BINARY };
|
||||
#endif
|
||||
#ifdef O_TEXT
|
||||
const struct optdesc opt_o_text = { "o-text", "text", OPT_O_TEXT, GROUP_OPEN|GROUP_FD, PH_OPEN, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_TEXT };
|
||||
#endif
|
||||
#ifdef O_NOINHERIT
|
||||
const struct optdesc opt_o_noinherit = { "o-noinherit", "noinherit", OPT_O_NOINHERIT, GROUP_OPEN|GROUP_FD, PH_OPEN, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NOINHERIT };
|
||||
#endif
|
||||
#ifdef O_NOATIME
|
||||
const struct optdesc opt_o_noatime = { "o-noatime", "noatime", OPT_O_NOATIME, GROUP_OPEN|GROUP_FD, PH_FD, TYPE_BOOL, OFUNC_FCNTL, F_SETFL, O_NOATIME };
|
||||
#endif
|
||||
/****** for ALL addresses - with fcntl(F_SETFD) ******/
|
||||
const struct optdesc opt_cloexec = { "cloexec", NULL, OPT_CLOEXEC, GROUP_FD, PH_LATE, TYPE_BOOL, OFUNC_FCNTL, F_SETFD, FD_CLOEXEC };
|
||||
/****** ftruncate() ******/
|
||||
/* this record is good for ftruncate() or ftruncate64() if available */
|
||||
#if HAVE_FTRUNCATE64
|
||||
const struct optdesc opt_ftruncate32 = { "ftruncate32", NULL, OPT_FTRUNCATE32, GROUP_REG, PH_LATE, TYPE_OFF32, OFUNC_SPEC };
|
||||
const struct optdesc opt_ftruncate64 = { "ftruncate64", "truncate", OPT_FTRUNCATE64, GROUP_REG, PH_LATE, TYPE_OFF64, OFUNC_SPEC };
|
||||
#else
|
||||
const struct optdesc opt_ftruncate32 = { "ftruncate32", "truncate", OPT_FTRUNCATE32, GROUP_REG, PH_LATE, TYPE_OFF32, OFUNC_SPEC };
|
||||
#endif /* !HAVE_FTRUNCATE64 */
|
||||
/****** for ALL addresses - permissions, ownership, and positioning ******/
|
||||
const struct optdesc opt_group = { "group", "gid", OPT_GROUP, GROUP_FD|GROUP_NAMED,PH_FD,TYPE_GIDT,OFUNC_SPEC };
|
||||
const struct optdesc opt_group_late= { "group-late","gid-l", OPT_GROUP_LATE,GROUP_FD, PH_LATE, TYPE_GIDT, OFUNC_SPEC };
|
||||
const struct optdesc opt_perm = { "perm", "mode", OPT_PERM, GROUP_FD|GROUP_NAMED, PH_FD, TYPE_MODET,OFUNC_SPEC };
|
||||
const struct optdesc opt_perm_late = { "perm-late", NULL, OPT_PERM_LATE, GROUP_FD, PH_LATE, TYPE_MODET,OFUNC_SPEC };
|
||||
const struct optdesc opt_user = { "user", "uid", OPT_USER, GROUP_FD|GROUP_NAMED, PH_FD, TYPE_UIDT, OFUNC_SPEC };
|
||||
const struct optdesc opt_user_late = { "user-late", "uid-l", OPT_USER_LATE, GROUP_FD, PH_LATE, TYPE_UIDT, OFUNC_SPEC };
|
||||
/* for something like random access files */
|
||||
#if HAVE_LSEEK64
|
||||
const struct optdesc opt_lseek32_cur = { "lseek32-cur", NULL, OPT_SEEK32_CUR, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_CUR };
|
||||
const struct optdesc opt_lseek32_end = { "lseek32-end", NULL, OPT_SEEK32_END, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_END };
|
||||
const struct optdesc opt_lseek32_set = { "lseek32-set", NULL, OPT_SEEK32_SET, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_SET };
|
||||
const struct optdesc opt_lseek64_cur = { "lseek64-cur", "seek-cur", OPT_SEEK64_CUR, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF64, OFUNC_SEEK64, SEEK_CUR };
|
||||
const struct optdesc opt_lseek64_end = { "lseek64-end", "seek-end", OPT_SEEK64_END, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF64, OFUNC_SEEK64, SEEK_END };
|
||||
const struct optdesc opt_lseek64_set = { "lseek64-set", "seek", OPT_SEEK64_SET, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF64, OFUNC_SEEK64, SEEK_SET };
|
||||
#else
|
||||
const struct optdesc opt_lseek32_cur = { "lseek32-cur", "seek-cur", OPT_SEEK32_CUR, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_CUR };
|
||||
const struct optdesc opt_lseek32_end = { "lseek32-end", "seek-end", OPT_SEEK32_END, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_END };
|
||||
const struct optdesc opt_lseek32_set = { "lseek32-set", "seek", OPT_SEEK32_SET, GROUP_REG|GROUP_BLK, PH_LATE, TYPE_OFF32, OFUNC_SEEK32, SEEK_SET };
|
||||
#endif /* !HAVE_LSEEK64 */
|
||||
/* for all addresses (?) */
|
||||
const struct optdesc opt_f_setlk_rd = { "f-setlk-rd", "setlk-rd", OPT_F_SETLK_RD, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLK, F_RDLCK };
|
||||
const struct optdesc opt_f_setlkw_rd = { "f-setlkw-rd", "setlkw-rd",OPT_F_SETLKW_RD, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLKW, F_RDLCK };
|
||||
const struct optdesc opt_f_setlk_wr = { "f-setlk-wr", "setlk", OPT_F_SETLK_WR, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLK, F_WRLCK };
|
||||
const struct optdesc opt_f_setlkw_wr = { "f-setlkw-wr", "setlkw", OPT_F_SETLKW_WR, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_SPEC, F_SETLKW, F_WRLCK };
|
||||
#if HAVE_FLOCK
|
||||
const struct optdesc opt_flock_sh = { "flock-sh", NULL, OPT_FLOCK_SH, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_SH };
|
||||
const struct optdesc opt_flock_sh_nb = { "flock-sh-nb", NULL, OPT_FLOCK_SH_NB, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_SH|LOCK_NB };
|
||||
const struct optdesc opt_flock_ex = { "flock-ex", "flock", OPT_FLOCK_EX, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_EX };
|
||||
const struct optdesc opt_flock_ex_nb = { "flock-ex-nb", "flock-nb", OPT_FLOCK_EX_NB, GROUP_FD, PH_FD,TYPE_BOOL, OFUNC_FLOCK, LOCK_EX|LOCK_NB };
|
||||
#endif /* HAVE_FLOCK */
|
||||
const struct optdesc opt_cool_write = { "cool-write", "coolwrite", OPT_COOL_WRITE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(cool_write) };
|
||||
|
||||
/* control closing of connections */
|
||||
const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROUP_FD, PH_OFFSET, TYPE_CONST, OFUNC_OFFSET, XIO_OFFSETOF(howtoend), END_CLOSE };
|
||||
const struct optdesc opt_shut_none = { "shut-none", NULL, OPT_SHUT_NONE, GROUP_FD, PH_OFFSET, TYPE_CONST, OFUNC_OFFSET, XIO_OFFSETOF(howtoshut), XIOSHUT_NONE };
|
||||
const struct optdesc opt_shut_down = { "shut-down", NULL, OPT_SHUT_DOWN, GROUP_FD, PH_OFFSET, TYPE_CONST, OFUNC_OFFSET, XIO_OFFSETOF(howtoshut), XIOSHUT_DOWN };
|
||||
const struct optdesc opt_shut_close= { "shut-close", NULL, OPT_SHUT_CLOSE, GROUP_FD, PH_OFFSET, TYPE_CONST, OFUNC_OFFSET, XIO_OFFSETOF(howtoshut), XIOSHUT_CLOSE };
|
||||
const struct optdesc opt_shut_null = { "shut-null", NULL, OPT_SHUT_NULL, GROUP_FD, PH_OFFSET, TYPE_CONST, OFUNC_OFFSET, XIO_OFFSETOF(howtoshut), XIOSHUT_NULL };
|
||||
|
||||
/****** generic ioctl() options ******/
|
||||
const struct optdesc opt_ioctl_void = { "ioctl-void", "ioctl", OPT_IOCTL_VOID, GROUP_FD, PH_FD, TYPE_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_int = { "ioctl-int", NULL, OPT_IOCTL_INT, GROUP_FD, PH_FD, TYPE_INT_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_intp = { "ioctl-intp", NULL, OPT_IOCTL_INTP, GROUP_FD, PH_FD, TYPE_INT_INTP, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_bin = { "ioctl-bin", NULL, OPT_IOCTL_BIN, GROUP_FD, PH_FD, TYPE_INT_BIN, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
const struct optdesc opt_ioctl_string = { "ioctl-string",NULL, OPT_IOCTL_STRING,GROUP_FD, PH_FD, TYPE_INT_STRING,OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
|
||||
/* POSIX STREAMS */
|
||||
#define ENABLE_OPTIONS
|
||||
#include "xio-streams.c"
|
||||
#undef ENABLE_OPTIONS
|
||||
51
xio-fd.h
Normal file
51
xio-fd.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* source: xio-fd.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_fd_h_included
|
||||
#define __xio_fd_h_included 1
|
||||
|
||||
extern const struct optdesc opt_ioctl_void;
|
||||
extern const struct optdesc opt_ioctl_int;
|
||||
extern const struct optdesc opt_ioctl_intp;
|
||||
extern const struct optdesc opt_ioctl_bin;
|
||||
extern const struct optdesc opt_ioctl_string;
|
||||
extern const struct optdesc opt_append;
|
||||
extern const struct optdesc opt_nonblock;
|
||||
extern const struct optdesc opt_o_ndelay;
|
||||
extern const struct optdesc opt_async;
|
||||
extern const struct optdesc opt_o_binary;
|
||||
extern const struct optdesc opt_o_text;
|
||||
extern const struct optdesc opt_o_noinherit;
|
||||
extern const struct optdesc opt_cloexec;
|
||||
extern const struct optdesc opt_ftruncate32;
|
||||
extern const struct optdesc opt_ftruncate64;
|
||||
extern const struct optdesc opt_group;
|
||||
extern const struct optdesc opt_group_late;
|
||||
extern const struct optdesc opt_perm;
|
||||
extern const struct optdesc opt_perm_late;
|
||||
extern const struct optdesc opt_user;
|
||||
extern const struct optdesc opt_user_late;
|
||||
extern const struct optdesc opt_lseek32_cur;
|
||||
extern const struct optdesc opt_lseek32_end;
|
||||
extern const struct optdesc opt_lseek32_set;
|
||||
extern const struct optdesc opt_lseek64_cur;
|
||||
extern const struct optdesc opt_lseek64_end;
|
||||
extern const struct optdesc opt_lseek64_set;
|
||||
extern const struct optdesc opt_flock_sh;
|
||||
extern const struct optdesc opt_flock_sh_nb;
|
||||
extern const struct optdesc opt_flock_ex;
|
||||
extern const struct optdesc opt_flock_ex_nb;
|
||||
extern const struct optdesc opt_f_setlk_rd;
|
||||
extern const struct optdesc opt_f_setlkw_rd;
|
||||
extern const struct optdesc opt_f_setlk_wr;
|
||||
extern const struct optdesc opt_f_setlkw_wr;
|
||||
extern const struct optdesc opt_cool_write;
|
||||
extern const struct optdesc opt_end_close;
|
||||
extern const struct optdesc opt_shut_none;
|
||||
extern const struct optdesc opt_shut_down;
|
||||
extern const struct optdesc opt_shut_close;
|
||||
extern const struct optdesc opt_shut_null;
|
||||
extern const struct optdesc opt_streams_i_push;
|
||||
|
||||
#endif /* !defined(__xio_fd_h_included) */
|
||||
135
xio-fdnum.c
Normal file
135
xio-fdnum.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/* source: xio-fdnum.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of fdnum type */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "xioopen.h"
|
||||
|
||||
#include "xio-listen.h"
|
||||
|
||||
#include "xio-fdnum.h"
|
||||
|
||||
|
||||
#if WITH_FDNUM
|
||||
|
||||
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
static int xioopen_accept_fd(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
|
||||
|
||||
const struct addrdesc xioaddr_fd = { "FD", 1+XIO_RDWR, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<fdnum>") };
|
||||
#if WITH_LISTEN
|
||||
const struct addrdesc xioaddr_accept_fd = { "ACCEPT-FD", 1+XIO_RDWR, xioopen_accept_fd, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, 0, 0, 0 HELP(":<fdnum>") };
|
||||
#endif /* WITH_LISTEN */
|
||||
|
||||
|
||||
/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
|
||||
static int xioopen_fdnum(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
struct opt *opts,
|
||||
int xioflags,
|
||||
xiofile_t *xfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
char *a1;
|
||||
int rw = (xioflags&XIO_ACCMODE);
|
||||
int numfd;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||
}
|
||||
|
||||
numfd = strtoul(argv[1], &a1, 0);
|
||||
if (*a1 != '\0') {
|
||||
Error1("error in FD number \"%s\"", argv[1]);
|
||||
}
|
||||
/* we dont want to see these fds in child processes */
|
||||
if (Fcntl_l(numfd, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
|
||||
}
|
||||
Notice2("using file descriptor %d for %s", numfd, ddirection[rw]);
|
||||
if ((result = xioopen_fd(opts, rw, &xfd->stream, numfd)) < 0) {
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WITH_LISTEN
|
||||
|
||||
/* Use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
|
||||
static int xioopen_accept_fd(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
struct opt *opts,
|
||||
int xioflags,
|
||||
xiofile_t *xfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
char *a1;
|
||||
int rw = (xioflags&XIO_ACCMODE);
|
||||
int numfd;
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen = sizeof(union sockaddr_union);
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
numfd = strtoul(argv[1], &a1, 0);
|
||||
if (*a1 != '\0') {
|
||||
Error1("error in FD number \"%s\"", argv[1]);
|
||||
}
|
||||
/* we dont want to see these fds in child processes */
|
||||
if (Fcntl_l(numfd, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
|
||||
}
|
||||
|
||||
if (Getsockname(numfd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||
Warn2("getsockname(fd=%d, ...): %s", numfd, strerror(errno));
|
||||
}
|
||||
Notice2("using file descriptor %d accepting a connection for %s", numfd, ddirection[rw]);
|
||||
xfd->stream.fd = numfd;
|
||||
if ((result = _xioopen_accept_fd(&xfd->stream, xioflags, (struct sockaddr *)&us, uslen, opts, us.soa.sa_family, 0, 0)) < 0) {
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WITH_LISTEN */
|
||||
#endif /* WITH_FDNUM */
|
||||
|
||||
|
||||
#if WITH_FD
|
||||
|
||||
/* Retrieves and apply options to a standard file descriptor.
|
||||
Does not set FD_CLOEXEC flag. */
|
||||
int xioopen_fd(struct opt *opts, int rw, struct single *sfd, int numfd) {
|
||||
|
||||
sfd->fd = numfd;
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_NONE;
|
||||
|
||||
#if WITH_TERMIOS
|
||||
if (Isatty(sfd->fd)) {
|
||||
if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
|
||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||
sfd->fd, strerror(errno));
|
||||
} else {
|
||||
sfd->ttyvalid = true;
|
||||
}
|
||||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0)
|
||||
return -1;
|
||||
|
||||
applyopts2(sfd, -1, opts, PH_INIT, PH_FD);
|
||||
|
||||
return _xio_openlate(sfd, opts);
|
||||
}
|
||||
|
||||
#endif /* WITH_FD */
|
||||
13
xio-fdnum.h
Normal file
13
xio-fdnum.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* source: xio-fdnum.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_fdnum_h_included
|
||||
#define __xio_fdnum_h_included 1
|
||||
|
||||
extern const struct addrdesc xioaddr_fd;
|
||||
extern const struct addrdesc xioaddr_accept_fd;
|
||||
|
||||
extern int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd);
|
||||
|
||||
#endif /* !defined(__xio_fdnum_h_included) */
|
||||
135
xio-file.c
Normal file
135
xio-file.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/* source: xio-file.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of open type */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "xioopen.h"
|
||||
|
||||
#include "xio-named.h"
|
||||
#include "xio-file.h"
|
||||
|
||||
|
||||
static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||
|
||||
|
||||
#if WITH_OPEN
|
||||
|
||||
/****** OPEN addresses ******/
|
||||
const struct optdesc opt_o_rdonly = { "o-rdonly", "rdonly", OPT_O_RDONLY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_RDONLY, O_ACCMODE };
|
||||
const struct optdesc opt_o_wronly = { "o-wronly", "wronly", OPT_O_WRONLY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_WRONLY, O_ACCMODE };
|
||||
const struct optdesc opt_o_rdwr = { "o-rdwr", "rdwr", OPT_O_RDWR, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG_PATTERN, O_RDWR, O_ACCMODE };
|
||||
const struct optdesc opt_o_create = { "o-create", "creat", OPT_O_CREATE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_CREAT };
|
||||
const struct optdesc opt_o_excl = { "o-excl", "excl", OPT_O_EXCL, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_EXCL };
|
||||
const struct optdesc opt_o_noctty = { "o-noctty", "noctty", OPT_O_NOCTTY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_NOCTTY };
|
||||
#ifdef O_SYNC
|
||||
const struct optdesc opt_o_sync = { "o-sync", "sync", OPT_O_SYNC, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_SYNC };
|
||||
#endif
|
||||
#ifdef O_NOFOLLOW
|
||||
const struct optdesc opt_o_nofollow = { "o-nofollow", "nofollow",OPT_O_NOFOLLOW, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_NOFOLLOW };
|
||||
#endif
|
||||
#ifdef O_DIRECTORY
|
||||
const struct optdesc opt_o_directory = { "o-directory", "directory",OPT_O_DIRECTORY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DIRECTORY };
|
||||
#endif
|
||||
#ifdef O_LARGEFILE
|
||||
const struct optdesc opt_o_largefile = { "o-largefile", "largefile",OPT_O_LARGEFILE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_LARGEFILE };
|
||||
#endif
|
||||
#ifdef O_NSHARE
|
||||
const struct optdesc opt_o_nshare = { "o-nshare", "nshare", OPT_O_NSHARE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_NSHARE };
|
||||
#endif
|
||||
#ifdef O_RSHARE
|
||||
const struct optdesc opt_o_rshare = { "o-rshare", "rshare", OPT_O_RSHARE, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_RSHARE };
|
||||
#endif
|
||||
#ifdef O_DEFER
|
||||
const struct optdesc opt_o_defer = { "o-defer", "defer", OPT_O_DEFER, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DEFER };
|
||||
#endif
|
||||
#ifdef O_DIRECT
|
||||
const struct optdesc opt_o_direct = { "o-direct", "direct", OPT_O_DIRECT, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DIRECT };
|
||||
#endif
|
||||
#ifdef O_DSYNC
|
||||
const struct optdesc opt_o_dsync = { "o-dsync", "dsync", OPT_O_DSYNC, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DSYNC };
|
||||
#endif
|
||||
#ifdef O_RSYNC
|
||||
const struct optdesc opt_o_rsync = { "o-rsync", "rsync", OPT_O_RSYNC, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_RSYNC };
|
||||
#endif
|
||||
#ifdef O_DELAY
|
||||
const struct optdesc opt_o_delay = { "o-delay", "delay", OPT_O_DELAY, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_DELAY };
|
||||
#endif
|
||||
#ifdef O_PRIV
|
||||
const struct optdesc opt_o_priv = { "o-priv", "priv", OPT_O_PRIV, GROUP_OPEN, PH_OPEN, TYPE_BOOL, OFUNC_FLAG, O_PRIV };
|
||||
#endif
|
||||
const struct optdesc opt_o_trunc = { "o-trunc", "trunc", OPT_O_TRUNC, GROUP_OPEN, PH_LATE, TYPE_BOOL, OFUNC_FLAG, O_TRUNC };
|
||||
|
||||
#endif /* WITH_OPEN */
|
||||
|
||||
|
||||
#if _WITH_FILE /*! inconsistent name FILE vs. OPEN */
|
||||
|
||||
const struct addrdesc xioaddr_open = { "OPEN", 3, xioopen_open, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS, 0, 0, 0 HELP(":<filename>") };
|
||||
|
||||
/* open for writing:
|
||||
if the filesystem entry already exists, the data is appended
|
||||
if it does not exist, a file is created and the data is appended
|
||||
*/
|
||||
static int xioopen_open(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
struct opt *opts,
|
||||
int xioflags,
|
||||
xiofile_t *xfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
const char *filename = argv[1];
|
||||
int rw = (xioflags & XIO_ACCMODE);
|
||||
struct single *sfd = &xfd->stream;
|
||||
bool exists;
|
||||
bool opt_unlink_close = false;
|
||||
int result;
|
||||
|
||||
/* remove old file, or set user/permissions on old file; parse options */
|
||||
if ((result =
|
||||
_xioopen_named_early(argc, argv, xfd, addrdesc->groups, &exists, opts,
|
||||
addrdesc->syntax))
|
||||
< 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((sfd->unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
Notice3("opening %s \"%s\" for %s",
|
||||
filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]);
|
||||
if ((result = _xioopen_open(filename, rw, opts)) < 0)
|
||||
return result;
|
||||
sfd->fd = result;
|
||||
|
||||
#if WITH_TERMIOS
|
||||
if (Isatty(sfd->fd)) {
|
||||
if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
|
||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||
sfd->fd, strerror(errno));
|
||||
} else {
|
||||
sfd->ttyvalid = true;
|
||||
}
|
||||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
|
||||
applyopts_named(filename, opts, PH_FD);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
|
||||
applyopts_fchown(sfd->fd, opts);
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WITH_FILE */
|
||||
31
xio-file.h
Normal file
31
xio-file.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* source: xio-file.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_file_h_included
|
||||
#define __xio_file_h_included 1
|
||||
|
||||
extern const struct optdesc opt_o_rdonly;
|
||||
extern const struct optdesc opt_o_wronly;
|
||||
extern const struct optdesc opt_o_rdwr;
|
||||
extern const struct optdesc opt_o_create;
|
||||
extern const struct optdesc opt_o_excl;
|
||||
extern const struct optdesc opt_o_noctty;
|
||||
extern const struct optdesc opt_o_sync;
|
||||
extern const struct optdesc opt_o_nofollow;
|
||||
extern const struct optdesc opt_o_directory;
|
||||
extern const struct optdesc opt_o_largefile;
|
||||
extern const struct optdesc opt_o_nshare;
|
||||
extern const struct optdesc opt_o_rshare;
|
||||
extern const struct optdesc opt_o_defer;
|
||||
extern const struct optdesc opt_o_direct;
|
||||
extern const struct optdesc opt_o_dsync;
|
||||
extern const struct optdesc opt_o_rsync;
|
||||
extern const struct optdesc opt_o_delay;
|
||||
extern const struct optdesc opt_o_priv;
|
||||
extern const struct optdesc opt_o_trunc;
|
||||
extern const struct optdesc opt_o_noatime;
|
||||
|
||||
extern const struct addrdesc xioaddr_open;
|
||||
|
||||
#endif /* !defined(__xio_file_h_included) */
|
||||
134
xio-fs.c
Normal file
134
xio-fs.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/* source: xio-fs.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for handling Linux fs options
|
||||
they can also be set with chattr(1) and viewed with lsattr(1) */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "xioopen.h"
|
||||
|
||||
#include "xio-fs.h"
|
||||
|
||||
|
||||
#if WITH_FS
|
||||
|
||||
/****** FD options ******/
|
||||
|
||||
#if defined(EXT2_IOC_GETFLAGS) && !defined(FS_IOC_GETFLAGS)
|
||||
# define FS_IOC_GETFLAGS EXT2_IOC_GETFLAGS
|
||||
#endif
|
||||
#if defined(EXT2_IOC_SETFLAGS) && !defined(FS_IOC_SETFLAGS)
|
||||
# define FS_IOC_SETFLAGS EXT2_IOC_SETFLAGS
|
||||
#endif
|
||||
|
||||
#if defined(EXT2_SECRM_FL) && !defined(FS_SECRM_FL)
|
||||
# define FS_SECRM_FL EXT2_SECRM_FL
|
||||
#endif
|
||||
#ifdef FS_SECRM_FL
|
||||
/* secure deletion, chattr 's' */
|
||||
const struct optdesc opt_fs_secrm = { "fs-secrm", "secrm", OPT_FS_SECRM, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_SECRM_FL };
|
||||
#endif
|
||||
|
||||
#if defined(EXT2_UNRM_FL) && !defined(FS_UNRM_FL)
|
||||
# define FS_UNRM_FL EXT2_UNRM_FL
|
||||
#endif
|
||||
#ifdef FS_UNRM_FL
|
||||
/* undelete, chattr 'u' */
|
||||
const struct optdesc opt_fs_unrm = { "fs-unrm", "unrm", OPT_FS_UNRM, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_UNRM_FL };
|
||||
#endif /* FS_UNRM_FL */
|
||||
|
||||
#if defined(EXT2_COMPR_FL) && !defined(FS_COMPR_FL)
|
||||
# define FS_COMPR_FL EXT2_COMPR_FL
|
||||
#endif
|
||||
#ifdef FS_COMPR_FL
|
||||
/* compress file, chattr 'c' */
|
||||
const struct optdesc opt_fs_compr = { "fs-compr", "compr", OPT_FS_COMPR, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_COMPR_FL };
|
||||
#endif /* FS_COMPR_FL */
|
||||
|
||||
#if defined(EXT2_SYNC_FL) && !defined(FS_SYNC_FL)
|
||||
# define FS_SYNC_FL EXT2_SYNC_FL
|
||||
#endif
|
||||
#ifdef FS_SYNC_FL
|
||||
/* synchronous update, chattr 'S' */
|
||||
const struct optdesc opt_fs_sync = { "fs-sync", "sync", OPT_FS_SYNC, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_SYNC_FL };
|
||||
#endif /* FS_SYNC_FL */
|
||||
|
||||
#if defined(EXT2_IMMUTABLE_FL) && !defined(FS_IMMUTABLE_FL)
|
||||
# define FS_IMMUTABLE_FL EXT2_IMMUTABLE_FL
|
||||
#endif
|
||||
#ifdef FS_IMMUTABLE_FL
|
||||
/* immutable file, chattr 'i' */
|
||||
const struct optdesc opt_fs_immutable = { "fs-immutable", "immutable", OPT_FS_IMMUTABLE, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_IMMUTABLE_FL };
|
||||
#endif /* FS_IMMUTABLE_FL */
|
||||
|
||||
#if defined(EXT2_APPEND_FL) && !defined(FS_APPEND_FL)
|
||||
# define FS_APPEND_FL EXT2_APPEND_FL
|
||||
#endif
|
||||
#ifdef FS_APPEND_FL
|
||||
/* writes to file may only append, chattr 'a' */
|
||||
const struct optdesc opt_fs_append = { "fs-append", "append", OPT_FS_APPEND, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_APPEND_FL };
|
||||
#endif /* FS_APPEND_FL */
|
||||
|
||||
#if defined(EXT2_NODUMP_FL) && !defined(FS_NODUMP_FL)
|
||||
# define FS_NODUMP_FL EXT2_NODUMP_FL
|
||||
#endif
|
||||
#ifdef FS_NODUMP_FL
|
||||
/* do not dump file, chattr 'd' */
|
||||
const struct optdesc opt_fs_nodump = { "fs-nodump", "nodump", OPT_FS_NODUMP, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_NODUMP_FL };
|
||||
#endif /* FS_NODUMP_FL */
|
||||
|
||||
#if defined(EXT2_NOATIME_FL) && !defined(FS_NOATIME_FL)
|
||||
# define FS_NOATIME_FL EXT2_NOATIME_FL
|
||||
#endif
|
||||
#ifdef FS_NOATIME_FL
|
||||
/* do not update atime, chattr 'A' */
|
||||
const struct optdesc opt_fs_noatime = { "fs-noatime", "noatime", OPT_FS_NOATIME, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_NOATIME_FL };
|
||||
#endif /* FS_NOATIME_FL */
|
||||
|
||||
/* FS_DIRTY_FL ??? */
|
||||
/* FS_COMPRBLK_FL one ore more compress clusters */
|
||||
/* FS_NOCOMPR_FL access raw compressed data */
|
||||
/* FS_ECOMPR_FL compression error */
|
||||
/* FS_BTREE_FL btree format dir */
|
||||
/* FS_INDEX_FL hash indexed directory */
|
||||
/* FS_IMAGIC ??? */
|
||||
|
||||
#if defined(EXT2_JOURNAL_DATA_FL) && !defined(FS_JOURNAL_DATA_FL)
|
||||
# define FS_JOURNAL_DATA_FL EXT2_JOURNAL_DATA_FL
|
||||
#endif
|
||||
#ifdef FS_JOURNAL_DATA_FL
|
||||
/* file data should be journaled, chattr 'j' */
|
||||
const struct optdesc opt_fs_journal_data = { "fs-journal-data", "journal-data", OPT_FS_JOURNAL_DATA, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_JOURNAL_DATA_FL };
|
||||
#endif /* FS_JOURNAL_DATA_FL */
|
||||
|
||||
#if defined(EXT2_NOTAIL_FL) && !defined(FS_NOTAIL_FL)
|
||||
# define FS_NOTAIL_FL EXT2_NOTAIL_FL
|
||||
#endif
|
||||
#ifdef FS_NOTAIL_FL
|
||||
/* file tail should not be merged, chattr 't' */
|
||||
const struct optdesc opt_fs_notail = { "fs-notail", "notail", OPT_FS_NOTAIL, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_NOTAIL_FL };
|
||||
#endif /* FS_NOTAIL_FL */
|
||||
|
||||
#if defined(EXT2_DIRSYNC_FL) && !defined(FS_DIRSYNC_FL)
|
||||
# define FS_DIRSYNC_FL EXT2_DIRSYNC_FL
|
||||
#endif
|
||||
#ifdef FS_DIRSYNC_FL
|
||||
/* synchronous directory modifications, chattr 'D' */
|
||||
const struct optdesc opt_fs_dirsync = { "fs-dirsync", "dirsync", OPT_FS_DIRSYNC, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_DIRSYNC_FL };
|
||||
#endif /* FS_DIRSYNC_FL */
|
||||
|
||||
#if defined(EXT2_TOPDIR_FL) && !defined(FS_TOPDIR_FL)
|
||||
# define FS_TOPDIR_FL EXT2_TOPDIR_FL
|
||||
#endif
|
||||
#ifdef FS_TOPDIR_FL
|
||||
/* top of directory hierarchies, chattr 'T' */
|
||||
const struct optdesc opt_fs_topdir = { "fs-topdir", "topdir", OPT_FS_TOPDIR, GROUP_REG, PH_FD, TYPE_BOOL, OFUNC_IOCTL_MASK_LONG, FS_IOC_GETFLAGS, FS_IOC_SETFLAGS, FS_TOPDIR_FL };
|
||||
#endif /* FS_TOPDIR_FL */
|
||||
|
||||
/* EXTENTS inode uses extents */
|
||||
|
||||
|
||||
#endif /* WITH_FS */
|
||||
|
||||
|
||||
58
xio-fs.h
Normal file
58
xio-fs.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* source: xio-fs.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_fs_h_included
|
||||
#define __xio_fs_h_included 1
|
||||
|
||||
#if defined(EXT2_SECRM_FL) && !defined(FS_SECRM_FL)
|
||||
# define FS_SECRM_FL EXT2_SECRM_FL
|
||||
#endif
|
||||
#if defined(EXT2_UNRM_FL) && !defined(FS_UNRM_FL)
|
||||
# define FS_UNRM_FL EXT2_UNRM_FL
|
||||
#endif
|
||||
#if defined(EXT2_COMPR_FL) && !defined(FS_COMPR_FL)
|
||||
# define FS_COMPR_FL EXT2_COMPR_FL
|
||||
#endif
|
||||
#if defined(EXT2_SYNC_FL) && !defined(FS_SYNC_FL)
|
||||
# define FS_SYNC_FL EXT2_SYNC_FL
|
||||
#endif
|
||||
#if defined(EXT2_IMMUTABLE_FL) && !defined(FS_IMMUTABLE_FL)
|
||||
# define FS_IMMUTABLE_FL EXT2_IMMUTABLE_FL
|
||||
#endif
|
||||
#if defined(EXT2_APPEND_FL) && !defined(FS_APPEND_FL)
|
||||
# define FS_APPEND_FL EXT2_APPEND_FL
|
||||
#endif
|
||||
#if defined(EXT2_NODUMP_FL) && !defined(FS_NODUMP_FL)
|
||||
# define FS_NODUMP_FL EXT2_NODUMP_FL
|
||||
#endif
|
||||
#if defined(EXT2_NOATIME_FL) && !defined(FS_NOATIME_FL)
|
||||
# define FS_NOATIME_FL EXT2_NOATIME_FL
|
||||
#endif
|
||||
#if defined(EXT2_JOURNAL_DATA_FL) && !defined(FS_JOURNAL_DATA_FL)
|
||||
# define FS_JOURNAL_DATA_FL EXT2_JOURNAL_DATA_FL
|
||||
#endif
|
||||
#if defined(EXT2_NOTAIL_FL) && !defined(FS_NOTAIL_FL)
|
||||
# define FS_NOTAIL_FL EXT2_NOTAIL_FL
|
||||
#endif
|
||||
#if defined(EXT2_DIRSYNC_FL) && !defined(FS_DIRSYNC_FL)
|
||||
# define FS_DIRSYNC_FL EXT2_DIRSYNC_FL
|
||||
#endif
|
||||
#if defined(EXT2_TOPDIR_FL) && !defined(FS_TOPDIR_FL)
|
||||
# define FS_TOPDIR_FL EXT2_TOPDIR_FL
|
||||
#endif
|
||||
|
||||
extern const struct optdesc opt_fs_secrm;
|
||||
extern const struct optdesc opt_fs_unrm;
|
||||
extern const struct optdesc opt_fs_compr;
|
||||
extern const struct optdesc opt_fs_sync;
|
||||
extern const struct optdesc opt_fs_immutable;
|
||||
extern const struct optdesc opt_fs_append;
|
||||
extern const struct optdesc opt_fs_nodump;
|
||||
extern const struct optdesc opt_fs_noatime;
|
||||
extern const struct optdesc opt_fs_journal_data;
|
||||
extern const struct optdesc opt_fs_notail;
|
||||
extern const struct optdesc opt_fs_dirsync;
|
||||
extern const struct optdesc opt_fs_topdir;
|
||||
|
||||
#endif /* !defined(__xio_fs_h_included) */
|
||||
134
xio-gopen.c
Normal file
134
xio-gopen.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/* source: xio-gopen.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of generic open type */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
#include "xioopen.h"
|
||||
|
||||
#include "xio-named.h"
|
||||
#include "xio-unix.h"
|
||||
#include "xio-gopen.h"
|
||||
|
||||
|
||||
#if WITH_GOPEN
|
||||
|
||||
static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
|
||||
|
||||
|
||||
const struct addrdesc xioaddr_gopen = { "GOPEN", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":<filename>") };
|
||||
|
||||
static int xioopen_gopen(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
struct opt *opts,
|
||||
int xioflags,
|
||||
xiofile_t *xxfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
struct single *sfd = &xxfd->stream;
|
||||
const char *filename = argv[1];
|
||||
flags_t openflags = (xioflags & XIO_ACCMODE);
|
||||
mode_t st_mode;
|
||||
bool exists;
|
||||
bool opt_unlink_close = false;
|
||||
int result;
|
||||
|
||||
if ((result =
|
||||
_xioopen_named_early(argc, argv, xxfd, GROUP_NAMED|addrdesc->groups, &exists,
|
||||
opts, addrdesc->syntax))
|
||||
< 0) {
|
||||
return result;
|
||||
}
|
||||
st_mode = result;
|
||||
|
||||
if (exists) {
|
||||
/* file (or at least named entry) exists */
|
||||
if ((xioflags&XIO_ACCMODE) != XIO_RDONLY) {
|
||||
openflags |= O_APPEND;
|
||||
}
|
||||
} else {
|
||||
openflags |= O_CREAT;
|
||||
}
|
||||
|
||||
/* note: when S_ISSOCK was undefined, it always gives 0 */
|
||||
if (exists && S_ISSOCK(st_mode)) {
|
||||
#if WITH_UNIX
|
||||
union sockaddr_union us;
|
||||
socklen_t uslen = sizeof(us);
|
||||
char infobuff[256];
|
||||
|
||||
Info1("\"%s\" is a socket, connecting to it", filename);
|
||||
|
||||
result =
|
||||
_xioopen_unix_client(sfd, xioflags, addrdesc->groups, 0, opts,
|
||||
filename, addrdesc);
|
||||
if (result < 0) {
|
||||
return result;
|
||||
}
|
||||
applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
|
||||
|
||||
if (Getsockname(sfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
|
||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||
sfd->fd, &us, uslen, strerror(errno));
|
||||
} else {
|
||||
Notice1("successfully connected via %s",
|
||||
sockaddr_unix_info(&us.un, uslen,
|
||||
infobuff, sizeof(infobuff)));
|
||||
}
|
||||
#else
|
||||
Error("\"%s\" is a socket, but UNIX socket support is not compiled in");
|
||||
return -1;
|
||||
#endif /* WITH_UNIX */
|
||||
|
||||
} else {
|
||||
/* a file name */
|
||||
|
||||
Info1("\"%s\" is not a socket, open()'ing it", filename);
|
||||
|
||||
retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close);
|
||||
if (opt_unlink_close) {
|
||||
if ((sfd->unlink_close = strdup(filename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", filename);
|
||||
}
|
||||
sfd->opt_unlink_close = true;
|
||||
}
|
||||
|
||||
Notice3("opening %s \"%s\" for %s",
|
||||
filetypenames[(st_mode&S_IFMT)>>12], filename, ddirection[(xioflags&XIO_ACCMODE)]);
|
||||
if ((result = _xioopen_open(filename, openflags, opts)) < 0)
|
||||
return result;
|
||||
#ifdef I_PUSH
|
||||
if (S_ISCHR(st_mode) && Ioctl(result, I_FIND, "ldterm\0") == 0) {
|
||||
Ioctl(result, I_PUSH, "ptem\0\0\0"); /* pad string length ... */
|
||||
Ioctl(result, I_PUSH, "ldterm\0"); /* ... to requirements of ... */
|
||||
Ioctl(result, I_PUSH, "ttcompat"); /* ... AdressSanitizer */
|
||||
}
|
||||
#endif
|
||||
sfd->fd = result;
|
||||
|
||||
#if WITH_TERMIOS
|
||||
if (Isatty(sfd->fd)) {
|
||||
if (Tcgetattr(sfd->fd, &sfd->savetty) < 0) {
|
||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||
sfd->fd, strerror(errno));
|
||||
} else {
|
||||
sfd->ttyvalid = true;
|
||||
}
|
||||
}
|
||||
#endif /* WITH_TERMIOS */
|
||||
applyopts_named(filename, opts, PH_FD);
|
||||
applyopts(sfd, -1, opts, PH_FD);
|
||||
applyopts_cloexec(sfd->fd, opts);
|
||||
}
|
||||
|
||||
if ((result = applyopts2(sfd, -1, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
|
||||
return result;
|
||||
|
||||
if ((result = _xio_openlate(sfd, opts)) < 0)
|
||||
return result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WITH_GOPEN */
|
||||
10
xio-gopen.h
Normal file
10
xio-gopen.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* source: xio-gopen.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_gopen_h_included
|
||||
#define __xio_gopen_h_included 1
|
||||
|
||||
extern const struct addrdesc xioaddr_gopen;
|
||||
|
||||
#endif /* !defined(__xio_gopen_h_included) */
|
||||
342
xio-interface.c
Normal file
342
xio-interface.c
Normal file
@@ -0,0 +1,342 @@
|
||||
/* source: xio-interface.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for opening addresses of raw socket type */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if _WITH_INTERFACE
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-socket.h"
|
||||
#include "xio-ascii.h"
|
||||
|
||||
#include "xio-interface.h"
|
||||
|
||||
|
||||
static int xioopen_interface(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, const struct addrdesc *addrdesc);
|
||||
|
||||
/*0 const struct optdesc opt_interface_addr = { "interface-addr", "address", OPT_INTERFACE_ADDR, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
|
||||
/*0 const struct optdesc opt_interface_netmask = { "interface-netmask", "netmask", OPT_INTERFACE_NETMASK, GROUP_INTERFACE, PH_FD, TYPE_STRING, OFUNC_SPEC };*/
|
||||
const struct optdesc opt_iff_up = { "iff-up", "up", OPT_IFF_UP, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_UP };
|
||||
const struct optdesc opt_iff_broadcast = { "iff-broadcast", NULL, OPT_IFF_BROADCAST, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_BROADCAST };
|
||||
const struct optdesc opt_iff_debug = { "iff-debug" , NULL, OPT_IFF_DEBUG, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_DEBUG };
|
||||
const struct optdesc opt_iff_loopback = { "iff-loopback" , "loopback", OPT_IFF_LOOPBACK, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_LOOPBACK };
|
||||
const struct optdesc opt_iff_pointopoint = { "iff-pointopoint", "pointopoint",OPT_IFF_POINTOPOINT, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_POINTOPOINT };
|
||||
const struct optdesc opt_iff_notrailers = { "iff-notrailers", "notrailers", OPT_IFF_NOTRAILERS, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_NOTRAILERS };
|
||||
const struct optdesc opt_iff_running = { "iff-running", "running", OPT_IFF_RUNNING, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_RUNNING };
|
||||
const struct optdesc opt_iff_noarp = { "iff-noarp", "noarp", OPT_IFF_NOARP, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_NOARP };
|
||||
const struct optdesc opt_iff_promisc = { "iff-promisc", "promisc", OPT_IFF_PROMISC, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_PROMISC };
|
||||
const struct optdesc opt_iff_allmulti = { "iff-allmulti", "allmulti", OPT_IFF_ALLMULTI, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_ALLMULTI };
|
||||
#ifdef IFF_MASTER
|
||||
const struct optdesc opt_iff_master = { "iff-master", "master", OPT_IFF_MASTER, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_MASTER };
|
||||
#endif
|
||||
#ifdef IFF_SLAVE
|
||||
const struct optdesc opt_iff_slave = { "iff-slave", "slave", OPT_IFF_SLAVE, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_SLAVE };
|
||||
#endif
|
||||
const struct optdesc opt_iff_multicast = { "iff-multicast", NULL, OPT_IFF_MULTICAST, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_MULTICAST };
|
||||
#ifdef IFF_PORTSEL
|
||||
const struct optdesc opt_iff_portsel = { "iff-portsel", "portsel", OPT_IFF_PORTSEL, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_PORTSEL };
|
||||
#endif
|
||||
#ifdef IFF_AUTOMEDIA
|
||||
const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", OPT_IFF_AUTOMEDIA, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_AUTOMEDIA };
|
||||
#endif
|
||||
/*const struct optdesc opt_iff_dynamic = { "iff-dynamic", "dynamic", OPT_IFF_DYNAMIC, GROUP_INTERFACE, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(short), IFF_DYNAMIC };*/
|
||||
#ifdef PACKET_AUXDATA
|
||||
const struct optdesc opt_retrieve_vlan = { "retrieve-vlan", NULL, OPT_RETRIEVE_VLAN, GROUP_INTERFACE, PH_LATE, TYPE_CONST, OFUNC_SPEC };
|
||||
#endif
|
||||
#if LATER
|
||||
const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
|
||||
#endif
|
||||
|
||||
#if WITH_INTERFACE
|
||||
const struct addrdesc xioaddr_interface = { "INTERFACE", 3, xioopen_interface, GROUP_FD|GROUP_SOCKET|GROUP_INTERFACE, PF_PACKET, 0, 0 HELP(":<interface>") };
|
||||
#endif /* WITH_INTERFACE */
|
||||
|
||||
|
||||
static
|
||||
int _xioopen_interface(const char *ifname,
|
||||
struct opt *opts, int xioflags, xiofile_t *xxfd,
|
||||
groups_t groups, int pf) {
|
||||
xiosingle_t *sfd = &xxfd->stream;
|
||||
union sockaddr_union us = {{0}};
|
||||
socklen_t uslen;
|
||||
int socktype = SOCK_RAW;
|
||||
unsigned int ifidx;
|
||||
bool needbind = false;
|
||||
char *bindstring = NULL;
|
||||
struct sockaddr_ll sall = { 0 };
|
||||
int rc;
|
||||
|
||||
if (ifindex(ifname, &ifidx, -1) < 0) {
|
||||
Error1("unknown interface \"%s\"", ifname);
|
||||
ifidx = 0; /* desparate attempt to continue */
|
||||
}
|
||||
|
||||
if (sfd->howtoend == END_UNSPEC)
|
||||
sfd->howtoend = END_INTERFACE;
|
||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||
|
||||
retropt_socket_pf(opts, &pf);
|
||||
|
||||
/* ...res_opts[] */
|
||||
if (applyopts_single(sfd, opts, PH_INIT) < 0) return -1;
|
||||
applyopts(sfd, -1, opts, PH_INIT);
|
||||
|
||||
sfd->salen = sizeof(sfd->peersa);
|
||||
if (pf == PF_UNSPEC) {
|
||||
pf = sfd->peersa.soa.sa_family;
|
||||
}
|
||||
|
||||
sfd->dtype = XIODATA_RECVFROM_SKIPIP;
|
||||
|
||||
if (retropt_string(opts, OPT_BIND, &bindstring)) {
|
||||
needbind = true;
|
||||
}
|
||||
/*!!! parse by ':' */
|
||||
us.ll.sll_family = pf;
|
||||
us.ll.sll_protocol = htons(ETH_P_ALL);
|
||||
us.ll.sll_ifindex = ifidx;
|
||||
uslen = sizeof(sall);
|
||||
needbind = true;
|
||||
sfd->peersa = (union sockaddr_union)us;
|
||||
|
||||
rc =
|
||||
_xioopen_dgram_sendto(needbind?&us:NULL, uslen,
|
||||
opts, xioflags, sfd, groups, pf, socktype, 0, 0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
strncpy(sfd->para.interface.name, ifname, IFNAMSIZ);
|
||||
_xiointerface_get_iff(sfd->fd, ifname, &sfd->para.interface.save_iff);
|
||||
_xiointerface_apply_iff(sfd->fd, ifname, sfd->para.interface.iff_opts);
|
||||
if (_interface_retrieve_vlan(sfd, opts) < 0)
|
||||
return STAT_NORETRY;
|
||||
|
||||
#ifdef PACKET_IGNORE_OUTGOING
|
||||
/* Raw socket might also provide packets that are outbound - we are not
|
||||
interested in these and disable this "feature" in kernel if possible */
|
||||
if (Setsockopt(sfd->fd, SOL_PACKET, PACKET_IGNORE_OUTGOING, &one, sizeof(one)) < 0) {
|
||||
Warn2("setsockopt(%d, SOL_PACKET, PACKET_IGNORE_OUTGOING, {1}): %s",
|
||||
sfd->fd, strerror(errno));
|
||||
}
|
||||
#endif /*defined(PACKET_IGNORE_OUTGOING) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int _interface_retrieve_vlan(struct single *sfd, struct opt *opts) {
|
||||
#if HAVE_STRUCT_TPACKET_AUXDATA
|
||||
if (retropt_bool(opts, OPT_RETRIEVE_VLAN,
|
||||
&sfd->para.socket.retrieve_vlan)
|
||||
== 0) {
|
||||
if (!xioparms.experimental) {
|
||||
Warn1("option %s is experimental", opts->desc->defname);
|
||||
}
|
||||
}
|
||||
if (sfd->para.socket.retrieve_vlan) {
|
||||
if (_interface_setsockopt_auxdata(sfd->fd, 1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_STRUCT_TPACKET_AUXDATA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _interface_setsockopt_auxdata(int fd, int auxdata) {
|
||||
#ifdef PACKET_AUXDATA
|
||||
/* Linux strips VLAN tag off incoming packets and makes it available per
|
||||
ancillary data as auxdata. Apply option packet-auxdata if you want the
|
||||
VLAN tag to be restored by Socat in the received packet */
|
||||
if (auxdata) {
|
||||
int rc;
|
||||
Info1("setsockopt(fd=%d, level=SOL_PACKET, optname=PACKET_AUXDATA)", fd);
|
||||
rc = Setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, &auxdata, sizeof(auxdata));
|
||||
if (rc < 0) {
|
||||
Error3("setsockopt(%d, SOL_PACKET, PACKET_AUXDATA, , {%d}): %s",
|
||||
fd, auxdata, strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif /* defined(PACKET_AUXDATA) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int xioopen_interface(
|
||||
int argc,
|
||||
const char *argv[],
|
||||
struct opt *opts,
|
||||
int xioflags,
|
||||
xiofile_t *xxfd,
|
||||
const struct addrdesc *addrdesc)
|
||||
{
|
||||
xiosingle_t *sfd = &xxfd->stream;
|
||||
int result;
|
||||
|
||||
if (argc != 2) {
|
||||
xio_syntax(argv[0], 1, argc-1, addrdesc->syntax);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if ((result =
|
||||
_xioopen_interface(argv[1], opts, xioflags, xxfd, addrdesc->groups,
|
||||
addrdesc->arg1))
|
||||
!= STAT_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
sfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
|
||||
if (addrdesc->arg1 == PF_INET) {
|
||||
sfd->dtype |= XIOREAD_RECV_SKIPIP;
|
||||
}
|
||||
|
||||
sfd->para.socket.la.soa.sa_family = sfd->peersa.soa.sa_family;
|
||||
|
||||
_xio_openlate(sfd, opts);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Retrieves the interface flags related to sockfd */
|
||||
int _xiointerface_get_iff(
|
||||
int sockfd,
|
||||
const char *name,
|
||||
short *save_iff)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
||||
if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
|
||||
sockfd, ifr.ifr_name, strerror(errno));
|
||||
}
|
||||
*save_iff = ifr.ifr_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Applies the interface flags to the socket FD.
|
||||
Used by INTERFACE and TUN
|
||||
*/
|
||||
int _xiointerface_set_iff(
|
||||
int sockfd,
|
||||
const char *name,
|
||||
short new_iff)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
||||
if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
|
||||
sockfd, ifr.ifr_name, strerror(errno));
|
||||
}
|
||||
ifr.ifr_flags = new_iff;
|
||||
if (Ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
|
||||
Error4("ioctl(%d, SIOCSIFFLAGS, {\"%s\", %hd}: %s",
|
||||
sockfd, ifr.ifr_name, ifr.ifr_flags, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Applies the interface flags to the socket FD
|
||||
Used by INTERFACE and TUN
|
||||
*/
|
||||
int _xiointerface_apply_iff(
|
||||
int sockfd,
|
||||
const char *name,
|
||||
short iff_opts[2])
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
||||
if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
|
||||
sockfd, ifr.ifr_name, strerror(errno));
|
||||
}
|
||||
Debug2("\"%s\": system set flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
|
||||
ifr.ifr_flags |= iff_opts[0];
|
||||
ifr.ifr_flags &= ~iff_opts[1];
|
||||
Debug2("\"%s\": xio merged flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
|
||||
if (Ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0) {
|
||||
Error4("ioctl(%d, SIOCSIFFLAGS, {\"%s\", %hd}: %s",
|
||||
sockfd, ifr.ifr_name, ifr.ifr_flags, strerror(errno));
|
||||
}
|
||||
ifr.ifr_flags = 0;
|
||||
if (Ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
Error3("ioctl(%d, SIOCGIFFLAGS, {\"%s\"}: %s",
|
||||
sockfd, ifr.ifr_name, strerror(errno));
|
||||
}
|
||||
Debug2("\"%s\": resulting flags: 0x%hx", ifr.ifr_name, ifr.ifr_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_STRUCT_CMSGHDR && HAVE_STRUCT_TPACKET_AUXDATA
|
||||
/* Converts the ancillary message in *cmsg into a form useable for further
|
||||
processing. Knows the specifics of common message types.
|
||||
On PACKET_AUXDATA it stored the ancillary data in the XFD.
|
||||
For other types:
|
||||
returns the number of resulting syntax elements in *num,
|
||||
returns a sequence of \0 terminated type strings in *typbuff,
|
||||
returns a sequence of \0 terminated name strings in *nambuff,
|
||||
returns a sequence of \0 terminated value strings in *valbuff,
|
||||
the respective len parameters specify the available space in the buffers
|
||||
returns STAT_OK or other STAT_*
|
||||
*/
|
||||
int
|
||||
xiolog_ancillary_packet(struct single *sfd,
|
||||
struct cmsghdr *cmsg, int *num,
|
||||
char *typbuff, int typlen,
|
||||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen) {
|
||||
#if LATER
|
||||
const char *cmsgtype, *cmsgname, *cmsgenvn;
|
||||
size_t msglen;
|
||||
#endif
|
||||
struct tpacket_auxdata *auxp;
|
||||
int rc = STAT_OK;
|
||||
|
||||
*num = 0;
|
||||
|
||||
#if defined(CMSG_DATA)
|
||||
|
||||
#if LATER
|
||||
msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg);
|
||||
#endif
|
||||
switch (cmsg->cmsg_type) {
|
||||
#if HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TPID
|
||||
case PACKET_AUXDATA:
|
||||
#if LATER
|
||||
cmsgname = "packet_auxdata";
|
||||
cmsgtype = "auxdata";
|
||||
cmsgenvn = "AUXDATA";
|
||||
#endif
|
||||
auxp = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
|
||||
Info8("%s(): Ancillary message: PACKET_AUXDATA: status="F_uint32_t", len="F_uint32_t", snaplen="F_uint32_t", mac="F_uint16_t", net="F_uint16_t", vlan_tci="F_uint16_t", vlan_tpid="F_uint16_t"", __func__, auxp->tp_status, auxp->tp_len, auxp->tp_snaplen, auxp->tp_mac, auxp->tp_net, auxp->tp_vlan_tci, auxp->tp_vlan_tpid);
|
||||
sfd->para.socket.ancill_data_packet_auxdata = *auxp;
|
||||
sfd->para.socket.ancill_flag.packet_auxdata = 1;
|
||||
snprintf(typbuff, typlen, "PACKET.%u", cmsg->cmsg_type);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "vlan", namlen-1);
|
||||
snprintf(strchr(valbuff, '\0')-1/*def \n*/, vallen-strlen(valbuff)+1, ", %d", auxp->tp_vlan_tci);
|
||||
break;
|
||||
#endif /* HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TPID */
|
||||
default: /* binary data */
|
||||
Warn1("xiolog_ancillary_packet(): INTERNAL: cmsg_type=%d not handled", cmsg->cmsg_type);
|
||||
return rc;
|
||||
}
|
||||
return rc;
|
||||
|
||||
#else /* !defined(CMSG_DATA) */
|
||||
|
||||
return STAT_NORETRY;
|
||||
|
||||
#endif /* !defined(CMSG_DATA) */
|
||||
}
|
||||
#endif /* HAVE_STRUCT_CMSGHDR && HAVE_STRUCT_TPACKET_AUXDATA */
|
||||
|
||||
#endif /* _WITH_INTERFACE */
|
||||
38
xio-interface.h
Normal file
38
xio-interface.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* source: xio-interface.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_interface_h_included
|
||||
#define __xio_interface_h_included 1
|
||||
|
||||
extern const struct addrdesc xioaddr_interface;
|
||||
|
||||
extern const struct optdesc opt_interface_addr;
|
||||
extern const struct optdesc opt_interface_netmask;
|
||||
extern const struct optdesc opt_iff_up;
|
||||
extern const struct optdesc opt_iff_broadcast;
|
||||
extern const struct optdesc opt_iff_debug;
|
||||
extern const struct optdesc opt_iff_loopback;
|
||||
extern const struct optdesc opt_iff_pointopoint;
|
||||
extern const struct optdesc opt_iff_notrailers;
|
||||
extern const struct optdesc opt_iff_running;
|
||||
extern const struct optdesc opt_iff_noarp;
|
||||
extern const struct optdesc opt_iff_promisc;
|
||||
extern const struct optdesc opt_iff_allmulti;
|
||||
extern const struct optdesc opt_iff_master;
|
||||
extern const struct optdesc opt_iff_slave;
|
||||
extern const struct optdesc opt_iff_multicast;
|
||||
extern const struct optdesc opt_iff_portsel;
|
||||
extern const struct optdesc opt_iff_automedia;
|
||||
/*extern const struct optdesc opt_iff_dynamic;*/
|
||||
extern const struct optdesc opt_retrieve_vlan;
|
||||
|
||||
extern int xiolog_ancillary_packet(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
|
||||
|
||||
extern int _interface_retrieve_vlan(struct single *fd, struct opt *opts);
|
||||
extern int _xiointerface_get_iff(int sockfd, const char *name, short *save_iff);
|
||||
extern int _xiointerface_set_iff(int sockfd, const char *name, short new_iff);
|
||||
extern int _xiointerface_apply_iff(int sockfd, const char *name, short iff_opts[2]);
|
||||
extern int _interface_setsockopt_auxdata(int fd, int auxdata);
|
||||
|
||||
#endif /* !defined(__xio_interface_h_included) */
|
||||
65
xio-ip.h
Normal file
65
xio-ip.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* source: xio-ip.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ip_h_included
|
||||
#define __xio_ip_h_included 1
|
||||
|
||||
extern const struct optdesc opt_ip_options;
|
||||
extern const struct optdesc opt_ip_pktinfo;
|
||||
extern const struct optdesc opt_ip_recvtos;
|
||||
extern const struct optdesc opt_ip_recvttl;
|
||||
extern const struct optdesc opt_ip_recvopts;
|
||||
extern const struct optdesc opt_ip_retopts;
|
||||
extern const struct optdesc opt_ip_tos;
|
||||
extern const struct optdesc opt_ip_ttl;
|
||||
extern const struct optdesc opt_ip_hdrincl;
|
||||
extern const struct optdesc opt_ip_recverr;
|
||||
extern const struct optdesc opt_ip_mtu_discover;
|
||||
extern const struct optdesc opt_ip_mtu;
|
||||
extern const struct optdesc opt_ip_freebind;
|
||||
extern const struct optdesc opt_ip_router_alert;
|
||||
extern const struct optdesc opt_ip_multicast_ttl;
|
||||
extern const struct optdesc opt_ip_multicast_loop;
|
||||
extern const struct optdesc opt_ip_multicast_if;
|
||||
extern const struct optdesc opt_ip_pktoptions;
|
||||
extern const struct optdesc opt_ip_add_membership;
|
||||
extern const struct optdesc opt_ip_add_source_membership;
|
||||
extern const struct optdesc opt_ip_recvdstaddr;
|
||||
extern const struct optdesc opt_ip_recvif;
|
||||
extern const struct optdesc opt_ip_transparent;
|
||||
|
||||
extern const struct optdesc opt_ai_addrconfig;
|
||||
extern const struct optdesc opt_ai_passive;
|
||||
extern const struct optdesc opt_ai_v4mapped;
|
||||
|
||||
extern const struct optdesc opt_res_debug;
|
||||
extern const struct optdesc opt_res_aaonly;
|
||||
extern const struct optdesc opt_res_usevc;
|
||||
extern const struct optdesc opt_res_primary;
|
||||
extern const struct optdesc opt_res_igntc;
|
||||
extern const struct optdesc opt_res_recurse;
|
||||
extern const struct optdesc opt_res_defnames;
|
||||
extern const struct optdesc opt_res_stayopen;
|
||||
extern const struct optdesc opt_res_dnsrch;
|
||||
extern const struct optdesc opt_res_retrans;
|
||||
extern const struct optdesc opt_res_retry;
|
||||
extern const struct optdesc opt_res_nsaddr;
|
||||
|
||||
extern int xioinit_ip(int *pf, char ipv);
|
||||
|
||||
extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo **res, const int ai_flags[2]);
|
||||
extern void xiofreeaddrinfo(struct addrinfo *res);
|
||||
extern int xioresolve(const char *node, const char *service, int family, int socktype, int protocol, union sockaddr_union *addr, socklen_t *addrlen, const int ai_flags[2]);
|
||||
extern int xiolog_ancillary_ip(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
|
||||
extern int xiotype_ip_add_membership(char *token, const struct optname *ent, struct opt *opt);
|
||||
extern int xioapply_ip_add_membership(xiosingle_t *xfd, struct opt *opt);
|
||||
extern int xiotype_ip_add_source_membership(char* token, const struct optname *ent, struct opt *opt);
|
||||
extern int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt);
|
||||
|
||||
#if WITH_RESOLVE && HAVE_RESOLV_H
|
||||
extern int xio_res_init(struct single *sfd, struct __res_state *save_res);
|
||||
extern int xio_res_restore(struct __res_state *save_res);
|
||||
#endif /* WITH_RESOLVE && HAVE_RESOLV_H */
|
||||
|
||||
#endif /* !defined(__xio_ip_h_included) */
|
||||
142
xio-ip4.c
Normal file
142
xio-ip4.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/* source: xio-ip4.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for IP4 related functions */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if WITH_IP4
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-socket.h"
|
||||
#include "xio-ip.h"
|
||||
#include "xio-ip4.h"
|
||||
|
||||
|
||||
int xioparsenetwork_ip4(
|
||||
const char *rangename,
|
||||
struct xiorange *range,
|
||||
const int ai_flags[2])
|
||||
{
|
||||
struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
|
||||
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
|
||||
char *rangename1; /* a copy of rangename with writing allowed */
|
||||
char *delimpos; /* absolute address of delimiter */
|
||||
unsigned int bits; /* netmask bits */
|
||||
union sockaddr_union sau;
|
||||
socklen_t socklen = sizeof(sau);
|
||||
int rc;
|
||||
|
||||
if ((rangename1 = strdup(rangename)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", rangename);
|
||||
return STAT_RETRYLATER;
|
||||
}
|
||||
|
||||
if (delimpos = strchr(rangename1, '/')) {
|
||||
char *endptr;
|
||||
bits = strtoul(delimpos+1, &endptr, 10);
|
||||
if (! ((*(delimpos+1) != '\0') && (*endptr == '\0'))) {
|
||||
Error1("not a valid IPv4 netmask in \"%s\"", rangename);
|
||||
bits = 32; /* most secure selection */
|
||||
} else if (bits > 32) {
|
||||
Error1("IPv4 netmask \"%s\" is too large", rangename);
|
||||
bits = 32;
|
||||
}
|
||||
if (bits <= 0) {
|
||||
netmask_in->s_addr = 0;
|
||||
} else {
|
||||
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
|
||||
}
|
||||
} else if (delimpos = strchr(rangename1, ':')) {
|
||||
if ((rc = xioresolve(delimpos+1, NULL, PF_INET, 0, 0,
|
||||
&sau, &socklen, ai_flags))
|
||||
!= STAT_OK) {
|
||||
return rc;
|
||||
}
|
||||
netmask_in->s_addr = sau.ip4.sin_addr.s_addr;
|
||||
} else {
|
||||
Error1("xioparsenetwork_ip4(\"%s\",,): missing netmask delimiter", rangename);
|
||||
free(rangename1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
{
|
||||
*delimpos = 0;
|
||||
if ((rc = xioresolve(rangename1, NULL, PF_INET, 0, 0,
|
||||
&sau, &socklen, ai_flags))
|
||||
!= STAT_OK) {
|
||||
return rc;
|
||||
}
|
||||
netaddr_in->s_addr = sau.ip4.sin_addr.s_addr;
|
||||
}
|
||||
free(rangename1);
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* check if peer address is within permitted range.
|
||||
return >= 0 if so. */
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range) {
|
||||
struct in_addr *netaddr_in = &range->netaddr.ip4.sin_addr;
|
||||
struct in_addr *netmask_in = &range->netmask.ip4.sin_addr;
|
||||
char addrbuf[256], maskbuf[256];
|
||||
char peername[256];
|
||||
|
||||
/* is provided client address valid? */
|
||||
if (pa->sin_addr.s_addr == 0) {
|
||||
Warn("invalid client address 0.0.0.0");
|
||||
return -1;
|
||||
}
|
||||
/* client address restriction */
|
||||
Debug2("permitted client subnet: %s:%s",
|
||||
inet4addr_info(ntohl(netaddr_in->s_addr), addrbuf, sizeof(addrbuf)),
|
||||
inet4addr_info(ntohl(netmask_in->s_addr), maskbuf, sizeof(maskbuf)));
|
||||
Debug1("client address is 0x%08x",
|
||||
ntohl(pa->sin_addr.s_addr));
|
||||
Debug1("masked address is 0x%08x",
|
||||
ntohl(pa->sin_addr.s_addr & netmask_in->s_addr));
|
||||
if ((pa->sin_addr.s_addr & netmask_in->s_addr)
|
||||
!= netaddr_in->s_addr) {
|
||||
Debug1("client address %s is not permitted",
|
||||
sockaddr_inet4_info(pa, peername, sizeof(peername)));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns information that can be used for constructing an environment
|
||||
variable describing the socket address.
|
||||
if idx is 0, this function writes "ADDR" into namebuff and the IP address
|
||||
into valuebuff, and returns 1 (which means that one more info is there).
|
||||
if idx is 1, it writes "PORT" into namebuff and the port number into
|
||||
valuebuff, and returns 0 (no more info)
|
||||
namelen and valuelen contain the max. allowed length of output chars in the
|
||||
respective buffer.
|
||||
on error this function returns -1.
|
||||
*/
|
||||
int
|
||||
xiosetsockaddrenv_ip4(int idx, char *namebuff, size_t namelen,
|
||||
char *valuebuff, size_t valuelen,
|
||||
struct sockaddr_in *sa, int ipproto) {
|
||||
switch (idx) {
|
||||
case 0:
|
||||
strcpy(namebuff, "ADDR");
|
||||
inet4addr_info(ntohl(sa->sin_addr.s_addr), valuebuff, valuelen);
|
||||
switch (ipproto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
#ifdef IPPROTO_SCTP
|
||||
case IPPROTO_SCTP:
|
||||
#endif
|
||||
return 1; /* there is port information to also be retrieved */
|
||||
default:
|
||||
return 0; /* no port info coming */
|
||||
}
|
||||
case 1:
|
||||
strcpy(namebuff, "PORT");
|
||||
snprintf(valuebuff, valuelen, "%u", ntohs(sa->sin_port));
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* WITH_IP4 */
|
||||
18
xio-ip4.h
Normal file
18
xio-ip4.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* source: xio-ip4.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ip4_h_included
|
||||
#define __xio_ip4_h_included 1
|
||||
|
||||
extern const struct optdesc opt_ip4_add_membership;
|
||||
|
||||
extern int xioparsenetwork_ip4(const char *rangename, struct xiorange *range, const int ai_flags[2]);
|
||||
extern
|
||||
int xiocheckrange_ip4(struct sockaddr_in *pa, struct xiorange *range);
|
||||
extern int
|
||||
xiosetsockaddrenv_ip4(int idx, char *namebuff, size_t namelen,
|
||||
char *valuebuff, size_t valuelen,
|
||||
struct sockaddr_in *sa, int ipproto);
|
||||
|
||||
#endif /* !defined(__xio_ip4_h_included) */
|
||||
671
xio-ip6.c
Normal file
671
xio-ip6.c
Normal file
@@ -0,0 +1,671 @@
|
||||
/* source: xio-ip6.c */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for IP6 related functions */
|
||||
|
||||
#include "xiosysincludes.h"
|
||||
|
||||
#if WITH_IP6
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-ascii.h"
|
||||
#include "xio-socket.h"
|
||||
#include "xio-ip.h" /* xioresolve() */
|
||||
|
||||
#include "xio-ip6.h"
|
||||
#include "nestlex.h"
|
||||
|
||||
|
||||
static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen);
|
||||
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6ONLY, GROUP_SOCK_IP6, PH_PREBIND, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_V6ONLY };
|
||||
#endif
|
||||
#ifdef IPV6_JOIN_GROUP
|
||||
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP };
|
||||
#endif
|
||||
#ifdef MCAST_JOIN_SOURCE_GROUP
|
||||
const struct optdesc opt_ipv6_join_source_group = { "ipv6-join-source-group", "join-source-group", OPT_IPV6_JOIN_SOURCE_GROUP, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_GROUP_SOURCE_REQ, OFUNC_SOCKOPT, SOL_IPV6, MCAST_JOIN_SOURCE_GROUP };
|
||||
#endif
|
||||
#ifdef IPV6_PKTINFO
|
||||
const struct optdesc opt_ipv6_pktinfo = { "ipv6-pktinfo", "pktinfo", OPT_IPV6_PKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_PKTINFO };
|
||||
#endif
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
const struct optdesc opt_ipv6_recvpktinfo = { "ipv6-recvpktinfo", "recvpktinfo", OPT_IPV6_RECVPKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPKTINFO };
|
||||
#endif
|
||||
#ifdef IPV6_RTHDR
|
||||
const struct optdesc opt_ipv6_rthdr = { "ipv6-rthdr", "rthdr", OPT_IPV6_RTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RTHDR };
|
||||
#endif
|
||||
#ifdef IPV6_RECVRTHDR
|
||||
const struct optdesc opt_ipv6_recvrthdr = { "ipv6-recvrthdr", "recvrthdr", OPT_IPV6_RECVRTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVRTHDR };
|
||||
#endif
|
||||
#ifdef IPV6_AUTHHDR
|
||||
const struct optdesc opt_ipv6_authhdr = { "ipv6-authhdr", "authhdr", OPT_IPV6_AUTHHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_AUTHHDR };
|
||||
#endif
|
||||
#ifdef IPV6_DSTOPTS
|
||||
const struct optdesc opt_ipv6_dstopts = { "ipv6-dstopts", "dstopts", OPT_IPV6_DSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_DSTOPTS };
|
||||
#endif
|
||||
#ifdef IPV6_RECVDSTOPTS
|
||||
const struct optdesc opt_ipv6_recvdstopts = { "ipv6-recvdstopts", "recvdstopts", OPT_IPV6_RECVDSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVDSTOPTS };
|
||||
#endif
|
||||
#ifdef IPV6_HOPOPTS
|
||||
const struct optdesc opt_ipv6_hopopts = { "ipv6-hopopts", "hopopts", OPT_IPV6_HOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPOPTS };
|
||||
#endif
|
||||
#ifdef IPV6_RECVHOPOPTS
|
||||
const struct optdesc opt_ipv6_recvhopopts = { "ipv6-recvhopopts", "recvhopopts", OPT_IPV6_RECVHOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPOPTS };
|
||||
#endif
|
||||
#ifdef IPV6_FLOWINFO /* is in linux/in6.h */
|
||||
const struct optdesc opt_ipv6_flowinfo= { "ipv6-flowinfo","flowinfo",OPT_IPV6_FLOWINFO,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_FLOWINFO };
|
||||
#endif
|
||||
#ifdef IPV6_HOPLIMIT
|
||||
const struct optdesc opt_ipv6_hoplimit= { "ipv6-hoplimit","hoplimit",OPT_IPV6_HOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPLIMIT };
|
||||
#endif
|
||||
const struct optdesc opt_ipv6_unicast_hops= { "ipv6-unicast-hops","unicast-hops",OPT_IPV6_UNICAST_HOPS,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_UNICAST_HOPS };
|
||||
#ifdef IPV6_RECVHOPLIMIT
|
||||
const struct optdesc opt_ipv6_recvhoplimit= { "ipv6-recvhoplimit","recvhoplimit",OPT_IPV6_RECVHOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPLIMIT };
|
||||
#endif
|
||||
#ifdef IPV6_RECVERR
|
||||
const struct optdesc opt_ipv6_recverr = { "ipv6-recverr", "recverr", OPT_IPV6_RECVERR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVERR };
|
||||
#endif
|
||||
#ifdef IPV6_TCLASS
|
||||
const struct optdesc opt_ipv6_tclass = { "ipv6-tclass", "tclass", OPT_IPV6_TCLASS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_TCLASS };
|
||||
#endif
|
||||
#ifdef IPV6_RECVTCLASS
|
||||
const struct optdesc opt_ipv6_recvtclass = { "ipv6-recvtclass", "recvtclass", OPT_IPV6_RECVTCLASS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVTCLASS };
|
||||
#endif
|
||||
#ifdef IPV6_RECVPATHMTU
|
||||
const struct optdesc opt_ipv6_recvpathmtu = { "ipv6-recvpathmtu", "recvpathmtu", OPT_IPV6_RECVPATHMTU, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPATHMTU };
|
||||
#endif
|
||||
|
||||
/* Returns canonical form of IPv6 address.
|
||||
IPv6 address may be enclose in brackets.
|
||||
Returns STAT_OK on success, STAT_NORETRY on failure. */
|
||||
int xioip6_pton(
|
||||
const char *src,
|
||||
struct in6_addr *dst,
|
||||
const int ai_flags[2])
|
||||
{
|
||||
union sockaddr_union sockaddr;
|
||||
socklen_t sockaddrlen = sizeof(sockaddr);
|
||||
|
||||
if (src[0] == '[') {
|
||||
char plainaddr[INET6_ADDRSTRLEN];
|
||||
char *clos;
|
||||
|
||||
strncpy(plainaddr, src+1, INET6_ADDRSTRLEN);
|
||||
plainaddr[INET6_ADDRSTRLEN-1] = '\0';
|
||||
if ((clos = strchr(plainaddr, ']')) != NULL)
|
||||
*clos = '\0';
|
||||
return xioip6_pton(plainaddr, dst, ai_flags);
|
||||
}
|
||||
if (xioresolve(src, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
|
||||
ai_flags)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
*dst = sockaddr.ip6.sin6_addr;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
int xioparsenetwork_ip6(
|
||||
const char *rangename,
|
||||
struct xiorange *range,
|
||||
const int ai_flags[2])
|
||||
{
|
||||
char *delimpos; /* absolute address of delimiter */
|
||||
size_t delimind; /* index of delimiter in string */
|
||||
unsigned int bits; /* netmask bits */
|
||||
char *endptr;
|
||||
char *baseaddr;
|
||||
union sockaddr_union sockaddr;
|
||||
socklen_t sockaddrlen = sizeof(sockaddr);
|
||||
union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr;
|
||||
union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6.sin6_addr;
|
||||
union xioin6_u *nameaddr = (union xioin6_u *)&sockaddr.ip6.sin6_addr;
|
||||
|
||||
if ((delimpos = strchr(rangename, '/')) == NULL) {
|
||||
Error1("xioparsenetwork_ip6(\"%s\",,): missing mask bits delimiter '/'",
|
||||
rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
delimind = delimpos - rangename;
|
||||
if (rangename[0] != '[' || rangename[delimind-1] != ']') {
|
||||
Error1("missing brackets for IPv6 range definition \"%s\"",
|
||||
rangename);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
|
||||
if ((baseaddr = strndup(rangename+1,delimind-2)) == NULL) {
|
||||
Error1("strdup(\"%s\"): out of memory", rangename+1);
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
baseaddr[delimind-2] = '\0';
|
||||
if (xioresolve(baseaddr, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
|
||||
ai_flags)
|
||||
!= STAT_OK) {
|
||||
return STAT_NORETRY;
|
||||
}
|
||||
rangeaddr->u6_addr32[0] = nameaddr->u6_addr32[0];
|
||||
rangeaddr->u6_addr32[1] = nameaddr->u6_addr32[1];
|
||||
rangeaddr->u6_addr32[2] = nameaddr->u6_addr32[2];
|
||||
rangeaddr->u6_addr32[3] = nameaddr->u6_addr32[3];
|
||||
bits = strtoul(delimpos+1, &endptr, 10);
|
||||
if (! ((*(delimpos+1) != '\0') && (*endptr == '\0'))) {
|
||||
Error1("not a valid netmask in \"%s\"", rangename);
|
||||
bits = 128; /* most secure selection */
|
||||
} else if (bits > 128) {
|
||||
Error1("netmask \"%s\" is too large", rangename);
|
||||
bits = 128;
|
||||
}
|
||||
|
||||
/* I am starting to dislike C...uint32_t << 32 is undefined... */
|
||||
if (bits == 0) {
|
||||
rangemask->u6_addr32[0] = 0;
|
||||
rangemask->u6_addr32[1] = 0;
|
||||
rangemask->u6_addr32[2] = 0;
|
||||
rangemask->u6_addr32[3] = 0;
|
||||
} else if (bits <= 32) {
|
||||
rangemask->u6_addr32[0] = htonl(0xffffffff << (32-bits));
|
||||
rangemask->u6_addr32[1] = 0;
|
||||
rangemask->u6_addr32[2] = 0;
|
||||
rangemask->u6_addr32[3] = 0;
|
||||
} else if (bits <= 64) {
|
||||
rangemask->u6_addr32[0] = 0xffffffff;
|
||||
rangemask->u6_addr32[1] = htonl(0xffffffff << (64-bits));
|
||||
rangemask->u6_addr32[2] = 0;
|
||||
rangemask->u6_addr32[3] = 0;
|
||||
} else if (bits <= 96) {
|
||||
rangemask->u6_addr32[0] = 0xffffffff;
|
||||
rangemask->u6_addr32[1] = 0xffffffff;
|
||||
rangemask->u6_addr32[2] = htonl(0xffffffff << (96-bits));
|
||||
rangemask->u6_addr32[3] = 0;
|
||||
} else {
|
||||
rangemask->u6_addr32[0] = 0xffffffff;
|
||||
rangemask->u6_addr32[1] = 0xffffffff;
|
||||
rangemask->u6_addr32[2] = 0xffffffff;
|
||||
rangemask->u6_addr32[3] = htonl(0xffffffff << (128-bits));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xiorange_ip6andmask(struct xiorange *range) {
|
||||
int i;
|
||||
#if 0
|
||||
range->addr.s6_addr32[0] &= range->mask.s6_addr32[0];
|
||||
range->addr.s6_addr32[1] &= range->mask.s6_addr32[1];
|
||||
range->addr.s6_addr32[2] &= range->mask.s6_addr32[2];
|
||||
range->addr.s6_addr32[3] &= range->mask.s6_addr32[3];
|
||||
#else
|
||||
for (i = 0; i < 16; ++i) {
|
||||
range->netaddr.ip6.sin6_addr.s6_addr[i] &=
|
||||
range->netmask.ip6.sin6_addr.s6_addr[i];
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if peer address is within permitted range.
|
||||
return >= 0 if so. */
|
||||
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) {
|
||||
union xioin6_u masked;
|
||||
int i;
|
||||
char peername[256];
|
||||
union xioin6_u *rangeaddr = (union xioin6_u *)&range->netaddr.ip6.sin6_addr;
|
||||
union xioin6_u *rangemask = (union xioin6_u *)&range->netmask.ip6.sin6_addr;
|
||||
|
||||
Debug16("permitted client subnet: [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
htons(rangeaddr->u6_addr16[0]), htons(rangeaddr->u6_addr16[1]),
|
||||
htons(rangeaddr->u6_addr16[2]), htons(rangeaddr->u6_addr16[3]),
|
||||
htons(rangeaddr->u6_addr16[4]), htons(rangeaddr->u6_addr16[5]),
|
||||
htons(rangeaddr->u6_addr16[6]), htons(rangeaddr->u6_addr16[7]),
|
||||
htons(rangemask->u6_addr16[0]), htons(rangemask->u6_addr16[1]),
|
||||
htons(rangemask->u6_addr16[2]), htons(rangemask->u6_addr16[3]),
|
||||
htons(rangemask->u6_addr16[4]), htons(rangemask->u6_addr16[5]),
|
||||
htons(rangemask->u6_addr16[6]), htons(rangemask->u6_addr16[7]));
|
||||
Debug1("client address is %s",
|
||||
sockaddr_inet6_info(pa, peername, sizeof(peername)));
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
masked.u6_addr32[i] = ((union xioin6_u *)&pa->sin6_addr.s6_addr[0])->u6_addr32[i] & rangemask->u6_addr32[i];
|
||||
}
|
||||
Debug8("masked address is [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
htons(masked.u6_addr16[0]), htons(masked.u6_addr16[1]),
|
||||
htons(masked.u6_addr16[2]), htons(masked.u6_addr16[3]),
|
||||
htons(masked.u6_addr16[4]), htons(masked.u6_addr16[5]),
|
||||
htons(masked.u6_addr16[6]), htons(masked.u6_addr16[7]));
|
||||
|
||||
if (masked.u6_addr32[0] != rangeaddr->u6_addr32[0] ||
|
||||
masked.u6_addr32[1] != rangeaddr->u6_addr32[1] ||
|
||||
masked.u6_addr32[2] != rangeaddr->u6_addr32[2] ||
|
||||
masked.u6_addr32[3] != rangeaddr->u6_addr32[3]) {
|
||||
Debug1("client address %s is not permitted", peername);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
||||
/* provides info about the ancillary message:
|
||||
converts the ancillary message in *cmsg into a form useable for further
|
||||
processing. knows the specifics of common message types.
|
||||
returns the number of resulting syntax elements in *num
|
||||
returns a sequence of \0 terminated type strings in *typbuff
|
||||
returns a sequence of \0 terminated name strings in *nambuff
|
||||
returns a sequence of \0 terminated value strings in *valbuff
|
||||
the respective len parameters specify the available space in the buffers
|
||||
returns STAT_OK on success
|
||||
*/
|
||||
int xiolog_ancillary_ip6(
|
||||
struct single *sfd,
|
||||
struct cmsghdr *cmsg,
|
||||
int *num,
|
||||
char *typbuff, int typlen,
|
||||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen)
|
||||
{
|
||||
char scratch1[42]; /* can hold an IPv6 address in ASCII */
|
||||
char scratch2[32];
|
||||
size_t msglen;
|
||||
|
||||
*num = 1; /* good for most message types */
|
||||
msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg);
|
||||
envbuff[0] = '\0';
|
||||
switch (cmsg->cmsg_type) {
|
||||
#if defined(IPV6_PKTINFO) && HAVE_STRUCT_IN6_PKTINFO
|
||||
case IPV6_PKTINFO: {
|
||||
struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
|
||||
*num = 2;
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_PKTINFO", typlen-1);
|
||||
snprintf(nambuff, namlen, "%s%c%s", "dstaddr", '\0', "if");
|
||||
snprintf(envbuff, envlen, "%s%c%s", "IPV6_DSTADDR", '\0', "IPV6_IF");
|
||||
snprintf(valbuff, vallen, "%s%c%s",
|
||||
inet6addr_info(&pktinfo->ipi6_addr, scratch1, sizeof(scratch1)),
|
||||
'\0', xiogetifname(pktinfo->ipi6_ifindex, scratch2, -1));
|
||||
}
|
||||
return STAT_OK;
|
||||
#endif /* defined(IPV6_PKTINFO) && HAVE_STRUCT_IN6_PKTINFO */
|
||||
#ifdef IPV6_HOPLIMIT
|
||||
case IPV6_HOPLIMIT:
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_HOPLIMIT", typlen-1);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "hoplimit", namlen-1);
|
||||
{
|
||||
int *intp = (int *)CMSG_DATA(cmsg);
|
||||
snprintf(valbuff, vallen, "%d", *intp);
|
||||
}
|
||||
return STAT_OK;
|
||||
#endif /* defined(IPV6_HOPLIMIT) */
|
||||
#ifdef IPV6_RTHDR
|
||||
case IPV6_RTHDR:
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_RTHDR", typlen-1);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "rthdr", namlen-1);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#endif /* defined(IPV6_RTHDR) */
|
||||
#ifdef IPV6_AUTHHDR
|
||||
case IPV6_AUTHHDR:
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_AUTHHDR", typlen-1);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "authhdr", namlen-1);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#endif
|
||||
#ifdef IPV6_DSTOPTS
|
||||
case IPV6_DSTOPTS:
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_DSTOPTS", typlen-1);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "dstopts", namlen-1);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#endif /* defined(IPV6_DSTOPTS) */
|
||||
#ifdef IPV6_HOPOPTS
|
||||
case IPV6_HOPOPTS:
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_HOPOPTS", typlen-1);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "hopopts", namlen-1);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#endif /* defined(IPV6_HOPOPTS) */
|
||||
#ifdef IPV6_FLOWINFO
|
||||
case IPV6_FLOWINFO:
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_FLOWINFO", typlen-1);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "flowinfo", namlen-1);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#endif
|
||||
#ifdef IPV6_TCLASS
|
||||
case IPV6_TCLASS: {
|
||||
unsigned int u;
|
||||
typbuff[0] = '\0'; strncat(typbuff, "IPV6_TCLASS", typlen-1);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "tclass", namlen-1);
|
||||
u = ntohl(*(unsigned int *)CMSG_DATA(cmsg));
|
||||
xiodump((const unsigned char *)&u, msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
snprintf(typbuff, typlen, "IPV6.%u", cmsg->cmsg_type);
|
||||
nambuff[0] = '\0'; strncat(nambuff, "data", namlen-1);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
}
|
||||
return STAT_OK;
|
||||
}
|
||||
#endif /* defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) */
|
||||
|
||||
|
||||
/* convert the IP6 socket address to human readable form. buff should be at
|
||||
least 50 chars long. output includes the port number */
|
||||
static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen) {
|
||||
if (xio_snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
#if HAVE_IP6_SOCKADDR==0
|
||||
(sa->s6_addr[0]<<8)+sa->s6_addr[1],
|
||||
(sa->s6_addr[2]<<8)+sa->s6_addr[3],
|
||||
(sa->s6_addr[4]<<8)+sa->s6_addr[5],
|
||||
(sa->s6_addr[6]<<8)+sa->s6_addr[7],
|
||||
(sa->s6_addr[8]<<8)+sa->s6_addr[9],
|
||||
(sa->s6_addr[10]<<8)+sa->s6_addr[11],
|
||||
(sa->s6_addr[12]<<8)+sa->s6_addr[13],
|
||||
(sa->s6_addr[14]<<8)+sa->s6_addr[15]
|
||||
#elif HAVE_IP6_SOCKADDR==1
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[7])
|
||||
#elif HAVE_IP6_SOCKADDR==2
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[7])
|
||||
#elif HAVE_IP6_SOCKADDR==3
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[7])
|
||||
#elif HAVE_IP6_SOCKADDR==4
|
||||
(sa->_S6_un._S6_u8[0]<<8)|(sa->_S6_un._S6_u8[1]&0xff),
|
||||
(sa->_S6_un._S6_u8[2]<<8)|(sa->_S6_un._S6_u8[3]&0xff),
|
||||
(sa->_S6_un._S6_u8[4]<<8)|(sa->_S6_un._S6_u8[5]&0xff),
|
||||
(sa->_S6_un._S6_u8[6]<<8)|(sa->_S6_un._S6_u8[7]&0xff),
|
||||
(sa->_S6_un._S6_u8[8]<<8)|(sa->_S6_un._S6_u8[9]&0xff),
|
||||
(sa->_S6_un._S6_u8[10]<<8)|(sa->_S6_un._S6_u8[11]&0xff),
|
||||
(sa->_S6_un._S6_u8[12]<<8)|(sa->_S6_un._S6_u8[13]&0xff),
|
||||
(sa->_S6_un._S6_u8[14]<<8)|(sa->_S6_un._S6_u8[15]&0xff)
|
||||
#elif HAVE_IP6_SOCKADDR==5
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[7])
|
||||
#endif
|
||||
) >= blen) {
|
||||
Warn("sockaddr_inet6_info(): buffer too short");
|
||||
buff[blen-1] = '\0';
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
/* returns information that can be used for constructing an environment
|
||||
variable describing the socket address.
|
||||
if idx is 0, this function writes "ADDR" into namebuff and the IP address
|
||||
into valuebuff, and returns 1 (which means that one more info is there).
|
||||
if idx is 1, it writes "PORT" into namebuff and the port number into
|
||||
valuebuff, and returns 0 (no more info)
|
||||
namelen and valuelen contain the max. allowed length of output chars in the
|
||||
respective buffer.
|
||||
on error this function returns -1.
|
||||
*/
|
||||
int
|
||||
xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen,
|
||||
char *valuebuff, size_t valuelen,
|
||||
struct sockaddr_in6 *sa, int ipproto) {
|
||||
switch (idx) {
|
||||
case 0:
|
||||
strcpy(namebuff, "ADDR");
|
||||
snprintf(valuebuff, valuelen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
(sa->sin6_addr.s6_addr[0]<<8)+
|
||||
sa->sin6_addr.s6_addr[1],
|
||||
(sa->sin6_addr.s6_addr[2]<<8)+
|
||||
sa->sin6_addr.s6_addr[3],
|
||||
(sa->sin6_addr.s6_addr[4]<<8)+
|
||||
sa->sin6_addr.s6_addr[5],
|
||||
(sa->sin6_addr.s6_addr[6]<<8)+
|
||||
sa->sin6_addr.s6_addr[7],
|
||||
(sa->sin6_addr.s6_addr[8]<<8)+
|
||||
sa->sin6_addr.s6_addr[9],
|
||||
(sa->sin6_addr.s6_addr[10]<<8)+
|
||||
sa->sin6_addr.s6_addr[11],
|
||||
(sa->sin6_addr.s6_addr[12]<<8)+
|
||||
sa->sin6_addr.s6_addr[13],
|
||||
(sa->sin6_addr.s6_addr[14]<<8)+
|
||||
sa->sin6_addr.s6_addr[15]);
|
||||
switch (ipproto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
#ifdef IPPROTO_SCTP
|
||||
case IPPROTO_SCTP:
|
||||
#endif
|
||||
return 1; /* there is port information to also be retrieved */
|
||||
default:
|
||||
return 0; /* no port info coming */
|
||||
}
|
||||
case 1:
|
||||
strcpy(namebuff, "PORT");
|
||||
snprintf(valuebuff, valuelen, "%u", ntohs(sa->sin6_port));
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_STRUCT_IPV6_MREQ)
|
||||
int xioapply_ipv6_join_group(
|
||||
struct single *sfd,
|
||||
struct opt *opt)
|
||||
{
|
||||
struct ipv6_mreq ip6_mreq = {{{{0}}}};
|
||||
union sockaddr_union sockaddr1;
|
||||
socklen_t socklen1 = sizeof(sockaddr1.ip6);
|
||||
int res;
|
||||
|
||||
/* Always two parameters */
|
||||
/* First parameter is multicast address */
|
||||
if ((res =
|
||||
xioresolve(opt->value.u_string/*multiaddr*/, NULL,
|
||||
sfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1,
|
||||
sfd->para.socket.ip.ai_flags))
|
||||
!= STAT_OK) {
|
||||
return res;
|
||||
}
|
||||
ip6_mreq.ipv6mr_multiaddr = sockaddr1.ip6.sin6_addr;
|
||||
if (ifindex(opt->value2.u_string/*param2*/,
|
||||
&ip6_mreq.ipv6mr_interface, -1)
|
||||
< 0) {
|
||||
Error1("interface \"%s\" not found",
|
||||
opt->value2.u_string/*param2*/);
|
||||
ip6_mreq.ipv6mr_interface = htonl(0);
|
||||
}
|
||||
|
||||
if (Setsockopt(sfd->fd, opt->desc->major, opt->desc->minor,
|
||||
&ip6_mreq, sizeof(ip6_mreq)) < 0) {
|
||||
Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
|
||||
sfd->fd, opt->desc->major, opt->desc->minor,
|
||||
ip6_mreq.ipv6mr_interface,
|
||||
sizeof(ip6_mreq),
|
||||
strerror(errno));
|
||||
opt->desc = ODESC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(HAVE_STRUCT_IPV6_MREQ) */
|
||||
|
||||
#if HAVE_STRUCT_GROUP_SOURCE_REQ
|
||||
int xiotype_ip6_join_source_group(
|
||||
char *token, const struct optname *ent, struct opt *opt)
|
||||
{
|
||||
/* We do not resolve the addresses here because we do not yet know
|
||||
if we are coping with an IPv4 or IPv6 socat address */
|
||||
const char *ends[] = { ":", NULL };
|
||||
const char *nests[] = { "[","]", NULL };
|
||||
char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
|
||||
char *tokp = token;
|
||||
int parsres;
|
||||
|
||||
/* Parse first IP address (mcast group), expect ':' */
|
||||
parsres =
|
||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||
ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
if (parsres < 0) {
|
||||
Error1("option too long: \"%s\"", token);
|
||||
return -1;
|
||||
} else if (parsres > 0) {
|
||||
Error1("syntax error in \"%s\"", token);
|
||||
return -1;
|
||||
}
|
||||
if (*tokp != ':') {
|
||||
Error1("syntax in option %s: missing ':'", token);
|
||||
}
|
||||
*buffp++ = '\0';
|
||||
if ((opt->value.u_string/*mcaddr*/ = strdup(buff)) == NULL) {
|
||||
int _errno = errno;
|
||||
Error1("strdup(\"%s\"): out of memory", buff);
|
||||
errno = _errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
++tokp;
|
||||
/* Parse interface name/index, expect ':' or '\0'' */
|
||||
buffp = buff;
|
||||
parsres =
|
||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||
ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
if (parsres < 0) {
|
||||
Error1("option too long: \"%s\"", token);
|
||||
return -1;
|
||||
} else if (parsres > 0) {
|
||||
Error1("syntax error in \"%s\"", token);
|
||||
return -1;
|
||||
}
|
||||
if (*tokp != ':') {
|
||||
Error1("syntax in option %s: missing ':'", token);
|
||||
}
|
||||
*buffp++ = '\0';
|
||||
if ((opt->value2.u_string/*ifindex*/ = Malloc(IF_NAMESIZE)) == NULL) {
|
||||
int _errno = errno;
|
||||
free(opt->value.u_string);
|
||||
errno = _errno;
|
||||
return -1;
|
||||
}
|
||||
strncpy(opt->value2.u_string/*ifindex*/, buff, IF_NAMESIZE);
|
||||
|
||||
++tokp;
|
||||
/* Parse second IP address (source address), expect ':' or '\0'' */
|
||||
buffp = buff;
|
||||
parsres =
|
||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||
ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
if (parsres < 0) {
|
||||
Error1("option too long: \"%s\"", token);
|
||||
return -1;
|
||||
} else if (parsres > 0) {
|
||||
Error1("syntax error in \"%s\"", token);
|
||||
return -1;
|
||||
}
|
||||
if (*tokp) {
|
||||
Error1("syntax in option %s: trailing cruft", token);
|
||||
}
|
||||
*buffp++ = '\0';
|
||||
if ((opt->value3.u_string/*srcaddr*/ = strdup(buff)) == NULL) {
|
||||
int _errno = errno;
|
||||
Error1("strdup(\"%s\"): out of memory", buff);
|
||||
free(opt->value.u_string);
|
||||
errno = _errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Info4("setting option \"%s\" to {\"%s\",\"%s\",\"%s\"}",
|
||||
ent->desc->defname,
|
||||
opt->value.u_string/*mcaddr*/,
|
||||
opt->value2.u_string/*ifindex*/,
|
||||
opt->value3.u_string/*srcaddr*/);
|
||||
|
||||
if (!xioparms.experimental) {
|
||||
Warn1("option %s is experimental", opt->desc->defname);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xioapply_ip6_join_source_group(struct single *sfd, struct opt *opt) {
|
||||
struct group_source_req ip6_gsr = {0};
|
||||
union sockaddr_union sockaddr1;
|
||||
socklen_t socklen1 = sizeof(sockaddr1.ip6);
|
||||
union sockaddr_union sockaddr2;
|
||||
socklen_t socklen2 = sizeof(sockaddr2.ip6);
|
||||
int res;
|
||||
|
||||
/* First parameter is always multicast address */
|
||||
if ((res =
|
||||
xioresolve(opt->value.u_string/*mcaddr*/, NULL,
|
||||
sfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP, &sockaddr1, &socklen1,
|
||||
sfd->para.socket.ip.ai_flags))
|
||||
!= STAT_OK) {
|
||||
return res;
|
||||
}
|
||||
memcpy(&ip6_gsr.gsr_group, &sockaddr1.ip6, socklen1);
|
||||
/* Second parameter is interface name/index */
|
||||
if (ifindex(opt->value2.u_string/*ifindex*/,
|
||||
&ip6_gsr.gsr_interface, -1)
|
||||
< 0) {
|
||||
Error1("interface \"%s\" not found",
|
||||
opt->value.u_string/*ifindex*/);
|
||||
ip6_gsr.gsr_interface = 0;
|
||||
}
|
||||
/* Third parameter is source address */
|
||||
if ((res =
|
||||
xioresolve(opt->value3.u_string/*srcaddr*/, NULL,
|
||||
sfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP, &sockaddr2, &socklen2,
|
||||
sfd->para.socket.ip.ai_flags))
|
||||
!= STAT_OK) {
|
||||
return res;
|
||||
}
|
||||
memcpy(&ip6_gsr.gsr_source, &sockaddr2.ip6, socklen2);
|
||||
if (Setsockopt(sfd->fd, opt->desc->major, opt->desc->minor,
|
||||
&ip6_gsr, sizeof(ip6_gsr)) < 0) {
|
||||
Error6("setsockopt(%d, %d, %d, {%d,...}, "F_Zu"): %s",
|
||||
sfd->fd, opt->desc->major, opt->desc->minor,
|
||||
ip6_gsr.gsr_interface,
|
||||
sizeof(ip6_gsr),
|
||||
strerror(errno));
|
||||
opt->desc = ODESC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_STRUCT_GROUP_SOURCE_REQ */
|
||||
|
||||
#endif /* WITH_IP6 */
|
||||
54
xio-ip6.h
Normal file
54
xio-ip6.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* source: xio-ip6.h */
|
||||
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_ip6_h_included
|
||||
#define __xio_ip6_h_included 1
|
||||
|
||||
#if WITH_IP6
|
||||
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
# define INET6_ADDRSTRLEN 46
|
||||
#endif
|
||||
|
||||
extern const struct optdesc opt_ipv6_v6only;
|
||||
extern const struct optdesc opt_ipv6_join_group;
|
||||
extern const struct optdesc opt_ipv6_join_source_group;
|
||||
extern const struct optdesc opt_ipv6_pktinfo;
|
||||
extern const struct optdesc opt_ipv6_recvpktinfo;
|
||||
extern const struct optdesc opt_ipv6_rthdr;
|
||||
extern const struct optdesc opt_ipv6_recvrthdr;
|
||||
extern const struct optdesc opt_ipv6_authhdr;
|
||||
extern const struct optdesc opt_ipv6_dstopts;
|
||||
extern const struct optdesc opt_ipv6_recvdstopts;
|
||||
extern const struct optdesc opt_ipv6_hopopts;
|
||||
extern const struct optdesc opt_ipv6_unicast_hops;
|
||||
extern const struct optdesc opt_ipv6_recvhopopts;
|
||||
extern const struct optdesc opt_ipv6_flowinfo;
|
||||
extern const struct optdesc opt_ipv6_hoplimit;
|
||||
extern const struct optdesc opt_ipv6_recvhoplimit;
|
||||
extern const struct optdesc opt_ipv6_recverr;
|
||||
extern const struct optdesc opt_ipv6_tclass;
|
||||
extern const struct optdesc opt_ipv6_recvtclass;
|
||||
extern const struct optdesc opt_ipv6_recvpathmtu;
|
||||
|
||||
extern int xioip6_pton(const char *src, struct in6_addr *dst, const int ai_flags[2]);
|
||||
extern int xioparsenetwork_ip6(const char *rangename, struct xiorange *range, const int ai_flags[2]);
|
||||
extern int xiorange_ip6andmask(struct xiorange *range);
|
||||
|
||||
extern
|
||||
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range);
|
||||
extern
|
||||
int xiolog_ancillary_ip6(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
|
||||
extern int
|
||||
xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen,
|
||||
char *valuebuff, size_t valuelen,
|
||||
struct sockaddr_in6 *sa, int ipproto);
|
||||
extern int xioapply_ipv6_join_group(xiosingle_t *xfd, struct opt *opt);
|
||||
|
||||
extern int xiotype_ip6_join_source_group(char* token, const struct optname *ent, struct opt *opt);
|
||||
extern int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt);
|
||||
|
||||
#endif /* WITH_IP6 */
|
||||
|
||||
#endif /* !defined(__xio_ip6_h_included) */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user