diff options
author | jeff <jeff@FreeBSD.org> | 2011-03-21 09:58:24 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2011-03-21 09:58:24 +0000 |
commit | 5115240a6cdc054f7eea804355742f97c74578d8 (patch) | |
tree | 3051c12f4ce44a65c025b72ec5821b35b2ec46be /contrib/ofed/libsdp | |
parent | 2d7d8c05e7404fbebf1f0fe24c13bc5bb58d2338 (diff) | |
download | FreeBSD-src-5115240a6cdc054f7eea804355742f97c74578d8.zip FreeBSD-src-5115240a6cdc054f7eea804355742f97c74578d8.tar.gz |
- Merge in OFED 1.5.3 from projects/ofed/head
Diffstat (limited to 'contrib/ofed/libsdp')
-rw-r--r-- | contrib/ofed/libsdp/COPYING | 36 | ||||
-rw-r--r-- | contrib/ofed/libsdp/ChangeLog | 96 | ||||
-rw-r--r-- | contrib/ofed/libsdp/Makefile.am | 23 | ||||
-rw-r--r-- | contrib/ofed/libsdp/NEWS | 4 | ||||
-rw-r--r-- | contrib/ofed/libsdp/README | 68 | ||||
-rwxr-xr-x | contrib/ofed/libsdp/autogen.sh | 8 | ||||
-rwxr-xr-x | contrib/ofed/libsdp/changelog_from_git.sh | 3 | ||||
-rwxr-xr-x | contrib/ofed/libsdp/config/libsdp_indent | 71 | ||||
-rw-r--r-- | contrib/ofed/libsdp/configure.in | 59 | ||||
-rw-r--r-- | contrib/ofed/libsdp/libsdp.conf | 139 | ||||
-rw-r--r-- | contrib/ofed/libsdp/libsdp.spec.in | 55 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/Makefile.am | 29 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/config_parser.c | 1890 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/config_parser.h | 95 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/config_scanner.c | 1885 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/libsdp.h | 131 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/linux/sdp_inet.h | 52 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/log.c | 236 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/match.c | 296 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/port.c | 2629 | ||||
-rw-r--r-- | contrib/ofed/libsdp/src/socket.c | 167 |
21 files changed, 7972 insertions, 0 deletions
diff --git a/contrib/ofed/libsdp/COPYING b/contrib/ofed/libsdp/COPYING new file mode 100644 index 0000000..fac7531 --- /dev/null +++ b/contrib/ofed/libsdp/COPYING @@ -0,0 +1,36 @@ +This software is available to you under a choice of one of two +licenses. You may choose to be licensed under the terms of the GNU +General Public License (GPL) Version 2, available at +<http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD +license, included below. + +Copyright (c) 2004 Topspin Communications. All rights reserved. +Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. + + +OpenIB.org BSD license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * 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. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"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 +COPYRIGHT OWNER 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. diff --git a/contrib/ofed/libsdp/ChangeLog b/contrib/ofed/libsdp/ChangeLog new file mode 100644 index 0000000..d38dc69 --- /dev/null +++ b/contrib/ofed/libsdp/ChangeLog @@ -0,0 +1,96 @@ +2010-12-26 18:14:02 +0200 Amir Vadai <amirv@mellanox.co.il> + * 9c2ad15 libsdp: full ipv6 support + +2010-11-29 11:43:51 +0200 Amir Vadai <amirv@mellanox.co.il> + * 0a3d5c3 libsdp: BUG2130 - libsdp.so is not installed + version + 1.1.106 +2010-11-08 14:41:27 +0200 Amir Vadai <amirv@mellanox.co.il> + * 7a1880f libsdp: updated version to 1.1.105 + +2010-11-08 14:31:13 +0200 Amir Vadai <amirv@mellanox.co.il> + * c6efc06 libsdp: fix security issues with log file + +2010-11-02 15:28:06 +0200 Amir Vadai <amirv@mellanox.co.il> + * 09343d1 libsdp: fix bad permissions + +2010-10-28 13:46:39 +0200 root <root@swv300.lab.mtl.com> + * 46d845d libsdp: fixed indentation + +2010-10-04 11:49:46 +0200 Amir Vadai <amirv@mellanox.co.il> + * 59b6a36 libsdp: updated version to 1.1.104 + +2010-10-04 11:22:23 +0200 Amir Vadai <amirv@mellanox.co.il> + * 21b63e0 libsdp: fix libsdp.so permissions + +2010-10-04 11:20:49 +0200 Amir Vadai <amirv@mellanox.co.il> + * 3180e25 libsdp: fix "make dist" + +2010-09-13 10:31:52 +0200 Amir Vadai <amirv@mellanox.co.il> + * df744a5 libsdp: updated version to 1.1.103 + +2010-09-13 10:45:40 +0200 Amir Vadai <amirv@mellanox.co.il> + * e3ce469 libsdp: don't make libsdp depend on sdp_socket.h from ib-kernel + +2010-08-03 15:35:11 +0300 Amir Vadai <amirv@mellanox.co.il> + * c5ff8e2 libsdp: updated version to 1.1.102 + +2010-08-03 15:33:57 +0300 Amir Vadai <amirv@mellanox.co.il> + * 82fe3f9 libsdp: search openib headers according to 'prefix' + +2010-04-11 11:38:47 +0300 Amir Vadai <amirv@mellanox.co.il> + * 76060c5 libsdp: changed version to 1.1.101 + +2010-04-08 09:33:29 +0300 Eldad Zinger <eldadz@mellanox.co.il> + * 8bf57aa libsdp: added differentiation between bind failures of sdp. + +2010-03-23 10:13:45 +0200 Eldad Zinger <eldadz@mellanox.co.il> + * 93706ed sdp: BUG1984 - fix for bad memory access. + +2010-04-08 15:40:55 +0300 Amir Vadai <amirv@mellanox.co.il> + * dadef4b libsdp: add path to openib include's + +2010-02-18 11:04:29 +0200 Amir Vadai <amirv@mellanox.co.il> + * 920ea31 libsdp: changed version to 1.1.100 + +2010-02-18 11:02:20 +0200 Amir Vadai <amirv@mellanox.co.il> + * 0fe8a11 libsdp: updated changelog from git + script to get change log + +2010-02-18 10:49:42 +0200 Amir Vadai <amirv@mellanox.co.il> + * a298098 libsdp: Fix memory leak. free libsdp_fd_attributes + +2010-02-18 10:49:00 +0200 Amir Vadai <amirv@mellanox.co.il> + * cf4ceab libsdp: make libsdp.so have gid bit on + +2008-11-26 13:44:26 +0200 Amir Vadai <amirv@mellanox.co.il> + * b1eaecb libsdp: Enable building libsdp on Solaris + +2008-11-23 Amir Vadai <amirv@mellanox.co.il> + * BUG1405 - conflict when running an application that use yacc. + +2008-12-08 18:29:09 +0200 Yossi Etigin <yossi.openib@gmail.com> + * dcfca98 libsdp: BUG1256 - Add epoll support + +2008-11-23 16:09:21 +0200 Amir Vadai <amirv@mellanox.co.il> + * 02404fb libsdp: BUG1405 - conflict when running an application that use yacc. + +2008-09-02 15:13:22 +0300 Yossi Etigin <[yossi.openib@gmail.com]> + * 64adc0e libsdp: enable fallback to TCP for nonblocking sockets + +2008-08-21 10:52:19 +0300 Yossi Etigin <[yossi.openib@gmail.com]> + * cee8053 libsdp: write fcntl argument in debug prints + +2008-07-21 22:01:21 +0300 Amir Vadai <amirv@mellanox.co.il> + * 81d6ec3 removed not unnecessary use of va_copy. + +2008-06-12 14:13:07 +0300 Amir Vadai <amirv@mellanox.co.il> + * 90f25b7 Fixed compilation error on Fedora Release 9 + +2006-05-29 Eitan Zahavi <eitan@mellanox.co.il> + + * Support IPv4 embedded in IPv6 addresses. Since SDP currently does + not support IPv6 we need to convert to IPv4 and back on queries. + + * port.c - cleanup abnd re-written for clearer flow. Added verbose + messages. + + * Major re-write of the parser to support new syntax and using BNF diff --git a/contrib/ofed/libsdp/Makefile.am b/contrib/ofed/libsdp/Makefile.am new file mode 100644 index 0000000..13c5680 --- /dev/null +++ b/contrib/ofed/libsdp/Makefile.am @@ -0,0 +1,23 @@ +SUBDIRS = src + +EXTRA_DIST = libsdp.spec.in libsdp.conf + +dist-hook: libsdp.spec + cp libsdp.spec $(distdir) + +install-data-hook: + if test -e $(DESTDIR)$(sysconfdir)/libsdp.conf; then \ + diff -q $(srcdir)/libsdp.conf $(DESTDIR)$(sysconfdir)/libsdp.conf 1> /dev/null; \ + if test $$? == 1; then \ + t=$(shell date +'%Y%m%d%H%M%S'); \ + cp -p $(srcdir)/libsdp.conf \ + $(DESTDIR)$(sysconfdir)/libsdp.conf.$$t; \ + echo "NOTE: existing libsdp.conf was not updated."; \ + echo " libsdp.conf installed as ibsdp.conf.$$t instead."; \ + fi; \ + else \ + if test ! -d $(DESTDIR)$(sysconfdir); then \ + mkdir -p $(DESTDIR)$(sysconfdir); \ + fi; \ + cp -p $(srcdir)/libsdp.conf $(DESTDIR)$(sysconfdir)/libsdp.conf; \ + fi diff --git a/contrib/ofed/libsdp/NEWS b/contrib/ofed/libsdp/NEWS new file mode 100644 index 0000000..1fb082b --- /dev/null +++ b/contrib/ofed/libsdp/NEWS @@ -0,0 +1,4 @@ +0.9.0 - Initial release. +1.0.0 - Following RFC for enhanced configuration semantics, strong parsing, + major cleanup, verbosity logging and thread safe code +
\ No newline at end of file diff --git a/contrib/ofed/libsdp/README b/contrib/ofed/libsdp/README new file mode 100644 index 0000000..6499bbc --- /dev/null +++ b/contrib/ofed/libsdp/README @@ -0,0 +1,68 @@ +LIBSDP - A User Level Socket Switch for Seemless Migration to SDP +----------------------------------------------------------------- + +OVERVIEW: +--------- +libsdp is a LD_PRELOAD-able library that can be used to migrate existing +applications use InfiniBand Sockets Direct Protocol (SDP) instead of +TCP sockets, transparently and without recompilations. To setup libsdp +please follow the instructions below. + +SETUP: +------ +libsdp.so isn't setup automatically. it can be used in one of 2 ways: +1) LD_PRELOAD environment variable. Setting this to the name of the + library you want to use will cause it to be preloaded. +2) Adding the name of the library into /etc/ld.so.preload. This will + cause the library to be preloaded for every executable that is linked + with libc. + +The library should be installed in a directory in which the dynamic loader +searches for shared libraries (as specified by LD_LIBRARY_PATH, +/etc/ld.so.conf, etc). Alternatively, you can specify the full path to the +library that you want to use in LD_PRELOAD or /etc/ld.so.preload as described +above. + +The last option cant be used if you have multiple library versions +(e.g. 64/32 bit) and want the linker to select between them automatically. +The best way to handle such case is to use LD_LIBRARY_PATH to point to both the +lib (the 32 bit version) and lib64 directories and LD_RELOAD the libsdp.so. +This way the correct 32/64bit libsdp.so will be selected. +For example running ssh over SDP with OFED distribution from bash this can be written: +LD_LIBRARY_PATH=/usr/local/ofed/lib64:/usr/local/ofed/lib LD_PRELOAD=libsdp.so ssh + +CONFIGURATION: +-------------- +libsdp supports two modes of configuration: +* simple operation where it converts all calls to socket(2) with a family + of AF_INET(6) and a type of SOCK_STREAM into family of AF_INET_SDP. +* selective mode where it uses a configuration file to select which sockets + will be using SDP and which will not. + +For real world applications where communication with X, authentication, +DNS and other servers connected through TCP is required the selective mode +is required. + +Simple mode will be selected in one of the following conditions: +* the environment variable SIMPLE_LIBSDP to a non-empty value +* no configuration file is defined or is un-readble +* the configuration file does not include any address family rule + +For information on how to configure libsdp, see libsdp.conf, which is installed +in $(sysconfdir) (usually /usr/local/etc or /etc). The user can further control +the file to be used for configuration by setting the environment variable: +LIBSDP_CONFIG_FILE + +LIMITATIONS: +------------ +1. Applications statically linked with libc will not allow dynamic pre-loading + to port these applications to use SDP one needs to replace specific socket + calls (within the application) with AF_INET_SDP and recompile. +2. If for some reason the dynamic linker fail to pre-load libc before the + libsdp.so is initialized or it does not support RTDL_NEXT, libsdp will + fail to find the libc socket API. To overcome this situation a simple + implementation of hijacking "socket" call is provided in libsdp_sys. + This partial implementation does not support any configuration and is + limited to i386 architecture. +3. Non-blocking connect in "both" mode defaults to SDP. Specific rules might be + needed for applications to operate properly. diff --git a/contrib/ofed/libsdp/autogen.sh b/contrib/ofed/libsdp/autogen.sh new file mode 100755 index 0000000..fd47839 --- /dev/null +++ b/contrib/ofed/libsdp/autogen.sh @@ -0,0 +1,8 @@ +#! /bin/sh + +set -x +aclocal -I config +libtoolize --force --copy +autoheader +automake --foreign --add-missing --copy +autoconf diff --git a/contrib/ofed/libsdp/changelog_from_git.sh b/contrib/ofed/libsdp/changelog_from_git.sh new file mode 100755 index 0000000..e3d86b2 --- /dev/null +++ b/contrib/ofed/libsdp/changelog_from_git.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +git log --pretty=format:"%ai %an <%ae>%n * %h %s%n" diff --git a/contrib/ofed/libsdp/config/libsdp_indent b/contrib/ofed/libsdp/config/libsdp_indent new file mode 100755 index 0000000..6bae67d --- /dev/null +++ b/contrib/ofed/libsdp/config/libsdp_indent @@ -0,0 +1,71 @@ +#!/bin/bash +# +# Copyright (c) 2006 Mellanox Technologies LTD. All rights reserved. +# +# This software is available to you under a choice of one of two +# licenses. You may choose to be licensed under the terms of the GNU +# General Public License (GPL) Version 2, available from the file +# COPYING in the main directory of this source tree, or the +# OpenIB.org BSD license below: +# +# Redistribution and use in source and binary forms, with or +# without modification, are permitted provided that the following +# conditions are met: +# +# - Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# - 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. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# $Id: osm_indent 4707 2006-01-03 16:18:08Z halr $ +# +######################################################################### +# +# Abstract: +# Indent script for enforcing source code formatting. +# +# This is the indent format used for libsdp: +# +# -bad Blank line after declarations +# -bap Blank line after Procedures +# -nbbb NO Blank line before block comments +# -nbbo NO Break after Boolean operator +# -bl Break after if line +# -bli0 Indent for braces is 0 +# -bls Break after struct declarations +# -cbi0 Case break indent 0 +# -ci3 Continue indent 3 spaces +# -cli0 Case label indent 0 spaces +# -ncs No space after cast operator +# -hnl Honor existing newlines on long lines +# -i3 Substitute indent with 3 spaces +# -npcs No space after procedure calls +# -prs Space after parenthesis +# -nsai No space after if keyword - removed +# -nsaw No space after while keyword - removed +# -sc Put * at left of comments in a block comment style +# -nsob Don't swallow unnecessary blank lines +# -ts3 Tab size is 3 +# -psl Type of procedure return in a separate line +# -bfda Function declaration arguments in a separate line. +# -ut No tabs as we allow spaces +# -br Put braces on line with if, etc +# -ce Cuddle else and preceeding } +# +######################################################################### + +eval indent -bad -bap -nbbb -nbbo -bl -bli0 -bls -cbi0 -ci3 -cli0 -ncs \ + -hnl -i3 -npcs -prs -sc -nsob -ts3 -psl -bfda -ut -br -ce $* diff --git a/contrib/ofed/libsdp/configure.in b/contrib/ofed/libsdp/configure.in new file mode 100644 index 0000000..b1f34a4 --- /dev/null +++ b/contrib/ofed/libsdp/configure.in @@ -0,0 +1,59 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + + +AC_PREREQ(2.57) +AC_INIT(libsdp, 1.1.108, openib-general@openib.org) +AC_CONFIG_SRCDIR([src/port.c]) +AC_CONFIG_AUX_DIR(config) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE(libsdp, 1.1.108) + +AC_CANONICAL_HOST +AM_MAINTAINER_MODE + +AC_DISABLE_STATIC +AC_PROG_LIBTOOL + +# Checks for programs. +AC_PROG_CC +AM_PROG_LEX +AC_PROG_YACC + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/inet.h netinet/in.h stdlib.h string.h sys/socket.h syslog.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST + +# Checks for library functions. +AC_REPLACE_FNMATCH +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MALLOC +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([dup2 memset socket strcasecmp strchr strdup strpbrk strrchr strtoul]) + +# check OS +case "${host}" in +i[[3456]]86-*-linux*) AC_DEFINE(LINUX_BUILD, 1, [OS is linux]) ac_cv_linux_build="yes" ;; +sparc*-sun-solaris*) AC_DEFINE(SOLARIS_BUILD, 1, [OS is sparc solaris]) ac_cv_solaris_build="yes";; +esac + +AM_CONDITIONAL(LINUX_BUILD, test "$ac_cv_linux_build" = "yes") +AM_CONDITIONAL(SOLARIS_BUILD, test "$ac_cv_solaris_build" = "yes") + +# Check if we should build libsdp_sys +AC_CACHE_CHECK(whether to build i386-specific libsdp_sys, ac_cv_libsdp_sys, + AC_TRY_COMPILE(,[ + #if !i386 + #error Not i386 + #endif + ], ac_cv_libsdp_sys="yes", ac_cv_libsdp_sys="no")) + +AM_CONDITIONAL(WANT_LIBSDP_SYS, test "$ac_cv_libsdp_sys" = "yes") + +AC_CONFIG_FILES([Makefile src/Makefile libsdp.spec]) +AC_OUTPUT diff --git a/contrib/ofed/libsdp/libsdp.conf b/contrib/ofed/libsdp/libsdp.conf new file mode 100644 index 0000000..65f1f83 --- /dev/null +++ b/contrib/ofed/libsdp/libsdp.conf @@ -0,0 +1,139 @@ +# libsdp.conf - configuration file for libsdp +# +# $Id$ +# +# Comments are starts with # and cause the entire line after it to be ignored. +# Any beginning whitespace is skipped. Any line that is empty is also skipped. +# +# There are 2 main types of statements supported by this configuration file: +# - "use" - which defines the address family to be used for the sockets that +# match the line +# - "log" - for setting logging related configuration. As the log settings +# takes immidiate effect we define these at the beggining of the file. +# +############################################################################## +# DEAFUALT SETTINGS: +# Please do not forget to comment if you want to change these. +# (the rest of this file explains the syntax and give examples) +# +# Get errors printed into the files /tmp/libsdp.log.<uid>/log +# or /var/log/<path> for root +log min-level 9 destination file libsdp.log +# +# By default we let all servers and client try SDP first. +# to exclude SDP add "use tcp" rules before these defaults. +use both server * *:* +use both client * *:* +# +# +############################################################################## +# +# LOG CONFIGURATION: +# ------------------ +# The log directive allows the user to specify which and where debug and error +# messages get sent. The log statement format is: +# log [destination stderr|syslog|file <path>] [min-level <1-9>] +# +# destination - defines the destination of the log messages: +# stderr - messages will be forwarded to the stderr +# syslog - messages sent to the syslog service +# file <path> - messages will be written to the file /var/log/<path> for root. +# for regular user, if full path is requsted <path>.<uid>/log +# or /tmp/<path>.<uid>/log if no path is requested +# Due to security reasons, <path> must not be: +# 1. a soft link +# 2. owned by other user. +# 3. Other permissions except User permissions. +# +# min-level - defines the verbosity of the log: +# 9 - only errors are printed +# 8 - warnings +# 7 - connect and listen summary (useful for tracking SDP usage) +# 4 - positive match summary (useful for config file debug) +# 3 - negative match summary (useful for config file debug) +# 2 - function calls and return values +# 1 - debug messages +# +# Examples: +# +# Get SDP usage per connect and listen into stderr +# log min-level 7 destination stderr +# +# Send errors only into syslog +# log min-level 9 destination syslog +# +############################################################################## +# +# SOCKET ADDRESS FAMILY CONTROL: +# ------------------------------ +# The socket control statements allows the user to specify when libsdp will +# replace AF_INET/SOCK_STREAM sockets with AF_SDP/SOCK_STREAM +# sockets. Each control statement specifies a matching rule that all its +# subexpressions must evaluate as true (logical and) to apply. +# +# The statements that control which type of sockets to open are made +# of the following: +# use <address-family> <role> <program name> <address|*>:<port range|*> +# +# <address-family> can be one of: +# "sdp" - for specifying when an SDP should be used +# "tcp" - for specifying when SDP socket should not be matched +# "both" - for specifying when both SDP and AF_INET sockets should be used. +# +# Note: that "both" semantics is different between "server" and "client" roles: +# For a "server" is means that the server will be listening on both sdp and tcp +# For a "client" the connect will prefer using sdp but will silently +# fall back to tcp if the sdp connection failed. +# +# <role> can be one of: +# "server" or "listen" - for defining the listening port address family +# "client" or "connect" - for defining the connected port address family +# +# <program-name|*> field: +# Defines the program name (not including the path) the rule applies to. +# Wildcards with same semantics as "ls" are supported (* and ?). +# So db2* would match on any program with a name starting with db2. +# t?cp would match on ttcp, etc. +# If not provided (default) the statement matches all programs. +# +# <address|*> means: +# Either the local address the server is bind to or the remote server +# address the client connects to. Syntax for address matching is: +# <IPv4 address>[/<prefix_length>]|* +# IPv4 address = [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ each sub number < 255 +# prefix_length = [0-9]+ and with value <= 32. A prefix_length of 24 +# matches the subnet mask 255.255.255.0 . A prefix_length of 32 +# requires matching of the exact IP. +# +# <port range> is: +# start-port[-end-port] where port numbers are >0 and < 65536 +# +# Rules are evaluated in order of definition. So the first match wins. +# If no match is made libsdp will default to "both". +# +# Examples: +# +# Use SDP by clients connecting to machines that belongs to subnet 192.168.1.* +# family role program address:port[-range] +# use sdp connect * 192.168.1.0/24:* +# +# Use SDP by ttcp when it connects to port 5001 of any machine +# family role program address:port[-range] +# use sdp listen ttcp *:5001 +# +# Use TCP for any program with name starting with ttcp* serving ports 22 to 25 +# family role program address:port[-range] +# use tcp server ttcp* *:22-25 +# +# Listen on both TCP and SDP by any server that listen on port 8080 +# family role program address:port[-range] +# use both server * *:8080 +# +# Connect ssh through SDP and fallback to TCP to hosts on 11.4.8.* port 22 +# family role program address:port[-range] +# use both connect * 11.4.8.0/24:22 +# +# NOTE: If all "use" rules are commented SDP will take "simple SDP" +# mode and use SDP for all connections +# +############################################################################## diff --git a/contrib/ofed/libsdp/libsdp.spec.in b/contrib/ofed/libsdp/libsdp.spec.in new file mode 100644 index 0000000..c7ba35a --- /dev/null +++ b/contrib/ofed/libsdp/libsdp.spec.in @@ -0,0 +1,55 @@ + +Summary: LD_PRELOAD-able library for using SDP +Name: libsdp +Version: @VERSION@ +Release: 1%{?dist} +License: GPL/BSD +Group: System Environment/Libraries +BuildRoot: %{_tmppath}/%{name}-%{version}-root +Source: http://www.openfabrics.org/downloads/%{name}-%{version}.tar.gz +Url: http://www.openfabrics.org/ + +%description +libsdp can be LD_PRELOAD-ed to have a sockets application use +InfiniBand Sockets Direct Protocol (SDP) instead of TCP, transparently +and without recompiling the application. + +%package devel +Summary: Development files for the libsdp +Group: System Environment/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Development files of libsdp that may be linked directly to an +application, which may be useful for debugging. + +%prep +%setup -q + +%build +%configure +make + +%install +make DESTDIR=${RPM_BUILD_ROOT} install +# remove unpackaged files from the buildroot +rm -f $RPM_BUILD_ROOT%{_libdir}/*.la + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(6644,root,root) +%{_libdir}/libsdp*.so* +%defattr(0644,root,root) +%config(noreplace) %{_sysconfdir}/libsdp.conf +%config(noreplace) %{_includedir}/linux/sdp_inet.h +%doc README NEWS ChangeLog COPYING + +%files devel +%defattr(6644,root,root,-) +%{_libdir}/libsdp*.so + +%changelog +* Sun Jul 22 2007 Vladimir Sokolovsky <vlad@mellanox.co.il> +- Initial packaging diff --git a/contrib/ofed/libsdp/src/Makefile.am b/contrib/ofed/libsdp/src/Makefile.am new file mode 100644 index 0000000..f6907b27 --- /dev/null +++ b/contrib/ofed/libsdp/src/Makefile.am @@ -0,0 +1,29 @@ +lib_LTLIBRARIES = libsdp.la $(LIB_SDP_SYS) +if WANT_LIBSDP_SYS +LIB_SDP_SYS = libsdp_sys.la +endif + +AM_CFLAGS = -Wall -DSYSCONFDIR=\"$(sysconfdir)\" + +libsdp_la_SOURCES = log.c match.c port.c config_parser.c config_scanner.c +libsdp_la_LDFLAGS = -version-info 1 -ldl -lc +if SOLARIS_BUILD +libsdp_la_LDFLAGS += -lsocket +endif +libsdp_sys_la_SOURCES = socket.c +libsdp_sys_la_LDFLAGS = -version-info 1 + +EXTRA_DIST = libsdp.h linux/sdp_inet.h config_parser.h + +config_parser.c: @MAINTAINER_MODE_TRUE@ $(srcdir)/config_parser.y + $(YACC) -y -plibsdp_yy -d $(srcdir)/config_parser.y + mv y.tab.c config_parser.c + mv y.tab.h config_parser.h + cp -f config_parser.c config_parser.h $(srcdir)/ + +config_scanner.c: @MAINTAINER_MODE_TRUE@ $(srcdir)/config_scanner.l + $(LEX) -Plibsdp_yy $(srcdir)/config_scanner.l + mv lex.libsdp_yy.c config_scanner.c + cp -f config_scanner.c $(srcdir)/config_scanner.c + +nobase_include_HEADERS = linux/sdp_inet.h diff --git a/contrib/ofed/libsdp/src/config_parser.c b/contrib/ofed/libsdp/src/config_parser.c new file mode 100644 index 0000000..87968fc --- /dev/null +++ b/contrib/ofed/libsdp/src/config_parser.c @@ -0,0 +1,1890 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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, 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. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse libsdp_yyparse +#define yylex libsdp_yylex +#define yyerror libsdp_yyerror +#define yylval libsdp_yylval +#define yychar libsdp_yychar +#define yydebug libsdp_yydebug +#define yynerrs libsdp_yynerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + USE = 258, + CLIENT = 259, + SERVER = 260, + TCP = 261, + SDP = 262, + BOTH = 263, + INT = 264, + LOG = 265, + DEST = 266, + STDERR = 267, + SYSLOG = 268, + FILENAME = 269, + NAME = 270, + LEVEL = 271, + LINE = 272 + }; +#endif +/* Tokens. */ +#define USE 258 +#define CLIENT 259 +#define SERVER 260 +#define TCP 261 +#define SDP 262 +#define BOTH 263 +#define INT 264 +#define LOG 265 +#define DEST 266 +#define STDERR 267 +#define SYSLOG 268 +#define FILENAME 269 +#define NAME 270 +#define LEVEL 271 +#define LINE 272 + + + + +/* Copy the first part of user declarations. */ +#line 39 "./config_parser.y" + + +/* header section */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "libsdp.h" +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#define YYERROR_VERBOSE 1 + +extern int yyerror(char *msg); +extern int yylex(void); +static int parse_err = 0; + +struct use_family_rule *__sdp_clients_family_rules_head = NULL; +struct use_family_rule *__sdp_clients_family_rules_tail = NULL; +struct use_family_rule *__sdp_servers_family_rules_head = NULL; +struct use_family_rule *__sdp_servers_family_rules_tail = NULL; + +/* some globals to store intermidiate parser state */ +static struct use_family_rule __sdp_rule; +static int current_role = 0; + +int __sdp_config_empty( + void + ) +{ + return ( (__sdp_clients_family_rules_head == NULL) && + (__sdp_servers_family_rules_head == NULL) ); +} + +/* define the address by 4 integers */ +static void __sdp_set_ipv4_addr(short a0, short a1, short a2, short a3) +{ + char buf[16]; + sprintf(buf,"%d.%d.%d.%d", a0, a1, a2, a3); + if (!inet_aton(buf, &( __sdp_rule.ipv4 ))) + { + parse_err = 1; + yyerror("provided address is not legal"); + } +} + +static void __sdp_set_prog_name_expr(char *prog_name_expr) +{ + __sdp_rule.prog_name_expr = strdup(prog_name_expr); + if (!__sdp_rule.prog_name_expr) { + yyerror("fail to allocate program name expression"); + } +} + +static char *__sdp_get_role_str(int role) +{ + if (role == 1) return("server"); + if (role == 2) return("client"); + return("unknown role"); +} + +extern int __sdp_min_level; + +/* dump the current state in readable format */ +static void __sdp_dump_config_state() { + char buf[1024]; + sprintf(buf, "CONFIG: use %s %s %s", + __sdp_get_family_str(__sdp_rule.target_family), + __sdp_get_role_str( current_role ), + __sdp_rule.prog_name_expr); + if (__sdp_rule.match_by_addr) { + if ( __sdp_rule.prefixlen != 32 ) + sprintf(buf+strlen(buf), " %s/%d", + inet_ntoa( __sdp_rule.ipv4 ), __sdp_rule.prefixlen); + else + sprintf(buf+strlen(buf), " %s", inet_ntoa( __sdp_rule.ipv4 )); + } else { + sprintf(buf+strlen(buf), " *"); + } + if (__sdp_rule.match_by_port) { + sprintf(buf+strlen(buf), ":%d",__sdp_rule.sport); + if (__sdp_rule.eport > __sdp_rule.sport) + sprintf(buf+strlen(buf), "-%d",__sdp_rule.eport); + } + else + sprintf(buf+strlen(buf), ":*"); + sprintf(buf+strlen(buf), "\n"); + __sdp_log(1, buf); +} + +/* use the above state for making a new rule */ +static void __sdp_add_rule() { + struct use_family_rule **p_tail, **p_head, *rule; + + if (__sdp_min_level <= 1) __sdp_dump_config_state(); + if ( current_role == 1 ) { + p_tail = &__sdp_servers_family_rules_tail; + p_head = &__sdp_servers_family_rules_head; + } else if ( current_role == 2 ) { + p_tail = &__sdp_clients_family_rules_tail; + p_head = &__sdp_clients_family_rules_head; + } else { + yyerror("ignoring unknown role"); + parse_err = 1; + return; + } + + rule = (struct use_family_rule *)malloc(sizeof(*rule)); + if (!rule) { + yyerror("fail to allocate new rule"); + parse_err = 1; + return; + } + + memset(rule, 0, sizeof(*rule)); + *rule = __sdp_rule; + rule->prev = *p_tail; + if (!(*p_head)) { + *p_head = rule; + } else { + (*p_tail)->next = rule; + } /* if */ + *p_tail = rule; +} + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 167 "./config_parser.y" +{ + int ival; + char *sval; +} +/* Line 193 of yacc.c. */ +#line 270 "y.tab.c" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ +#line 192 "./config_parser.y" + + long __sdp_config_line_num; + + +/* Line 216 of yacc.c. */ +#line 286 "y.tab.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 7 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 36 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 23 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 17 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 33 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 53 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 272 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 19, 2, 2, 22, 21, 20, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 18, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = +{ + 0, 0, 3, 5, 8, 9, 11, 14, 15, 18, + 20, 22, 26, 27, 30, 33, 36, 39, 43, 46, + 55, 57, 59, 61, 63, 65, 67, 69, 71, 75, + 77, 85, 87, 91 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 26, 0, -1, 17, -1, 24, 17, -1, -1, 24, + -1, 25, 27, -1, -1, 27, 28, -1, 29, -1, + 33, -1, 10, 30, 24, -1, -1, 30, 31, -1, + 30, 32, -1, 11, 12, -1, 11, 13, -1, 11, + 14, 15, -1, 16, 9, -1, 3, 34, 35, 36, + 37, 18, 39, 24, -1, 6, -1, 7, -1, 8, + -1, 5, -1, 4, -1, 15, -1, 19, -1, 38, + -1, 38, 20, 9, -1, 19, -1, 9, 21, 9, + 21, 9, 21, 9, -1, 9, -1, 9, 22, 9, + -1, 19, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 198, 198, 199, 201, 202, 205, 208, 209, 213, + 214, 218, 221, 222, 223, 227, 228, 229, 233, 237, + 241, 242, 243, 247, 248, 252, 253, 257, 258, 259, + 263, 267, 268, 269 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "\"use\"", "\"client or connect\"", + "\"server or listen\"", "\"tcp\"", "\"sdp\"", "\"both\"", + "\"integer value\"", "\"log statement\"", "\"destination\"", + "\"stderr\"", "\"syslog\"", "\"file\"", "\"a name\"", "\"min-level\"", + "\"new line\"", "':'", "'*'", "'/'", "'.'", "'-'", "$accept", "NL", + "ONL", "config", "statements", "statement", "log_statement", "log_opts", + "log_dest", "verbosity", "socket_statement", "family", "role", "program", + "address", "ipv4", "ports", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 58, 42, + 47, 46, 45 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 23, 24, 24, 25, 25, 26, 27, 27, 28, + 28, 29, 30, 30, 30, 31, 31, 31, 32, 33, + 34, 34, 34, 35, 35, 36, 36, 37, 37, 37, + 38, 39, 39, 39 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 2, 0, 1, 2, 0, 2, 1, + 1, 3, 0, 2, 2, 2, 2, 3, 2, 8, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, + 7, 1, 3, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 4, 2, 5, 7, 0, 3, 6, 1, 0, 12, + 8, 9, 10, 20, 21, 22, 0, 0, 24, 23, + 0, 0, 0, 11, 13, 14, 25, 26, 0, 15, + 16, 0, 18, 0, 29, 0, 27, 17, 0, 0, + 0, 0, 31, 33, 0, 28, 0, 0, 19, 0, + 32, 0, 30 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 2, 3, 4, 6, 10, 11, 17, 24, 25, + 12, 16, 20, 28, 35, 36, 44 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -18 +static const yytype_int8 yypact[] = +{ + -13, -18, 4, -18, 22, -18, 0, -18, 9, -18, + -18, -18, -18, -18, -18, -18, 2, -3, -18, -18, + -10, 6, 14, 4, -18, -18, -18, -18, -8, -18, + -18, 10, -18, 3, -18, 8, 11, -18, 19, -7, + 20, 12, 13, -18, -13, -18, 21, 23, 4, 15, + -18, 25, -18 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -18, -17, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, -18, -18, -18, -18 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = +{ + 23, 33, 42, 8, 1, 26, 18, 19, 21, 27, + 9, 34, 43, 22, 1, 13, 14, 15, 29, 30, + 31, 5, 7, 32, 38, 37, 39, 48, 41, 45, + 49, 40, 50, 46, 52, 47, 51 +}; + +static const yytype_uint8 yycheck[] = +{ + 17, 9, 9, 3, 17, 15, 4, 5, 11, 19, + 10, 19, 19, 16, 17, 6, 7, 8, 12, 13, + 14, 17, 0, 9, 21, 15, 18, 44, 9, 9, + 9, 20, 9, 21, 9, 22, 21 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 17, 24, 25, 26, 17, 27, 0, 3, 10, + 28, 29, 33, 6, 7, 8, 34, 30, 4, 5, + 35, 11, 16, 24, 31, 32, 15, 19, 36, 12, + 13, 14, 9, 9, 19, 37, 38, 15, 21, 18, + 20, 9, 9, 19, 39, 9, 21, 22, 24, 9, + 9, 21, 9 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 15: +#line 227 "./config_parser.y" + { __sdp_log_set_log_stderr(); } + break; + + case 16: +#line 228 "./config_parser.y" + { __sdp_log_set_log_syslog(); } + break; + + case 17: +#line 229 "./config_parser.y" + { __sdp_log_set_log_file((yyvsp[(3) - (3)].sval)); } + break; + + case 18: +#line 233 "./config_parser.y" + { __sdp_log_set_min_level((yyvsp[(2) - (2)].ival)); } + break; + + case 19: +#line 237 "./config_parser.y" + { __sdp_add_rule(); } + break; + + case 20: +#line 241 "./config_parser.y" + { __sdp_rule.target_family = USE_TCP; } + break; + + case 21: +#line 242 "./config_parser.y" + { __sdp_rule.target_family = USE_SDP; } + break; + + case 22: +#line 243 "./config_parser.y" + { __sdp_rule.target_family = USE_BOTH; } + break; + + case 23: +#line 247 "./config_parser.y" + { current_role = 1; } + break; + + case 24: +#line 248 "./config_parser.y" + { current_role = 2; } + break; + + case 25: +#line 252 "./config_parser.y" + { __sdp_set_prog_name_expr((yyvsp[(1) - (1)].sval)); } + break; + + case 26: +#line 253 "./config_parser.y" + { __sdp_set_prog_name_expr("*"); } + break; + + case 27: +#line 257 "./config_parser.y" + { __sdp_rule.match_by_addr = 1; __sdp_rule.prefixlen = 32; } + break; + + case 28: +#line 258 "./config_parser.y" + { __sdp_rule.match_by_addr = 1; __sdp_rule.prefixlen = (yyvsp[(3) - (3)].ival); } + break; + + case 29: +#line 259 "./config_parser.y" + { __sdp_rule.match_by_addr = 0; __sdp_rule.prefixlen = 32; } + break; + + case 30: +#line 263 "./config_parser.y" + { __sdp_set_ipv4_addr((yyvsp[(1) - (7)].ival),(yyvsp[(3) - (7)].ival),(yyvsp[(5) - (7)].ival),(yyvsp[(7) - (7)].ival)); } + break; + + case 31: +#line 267 "./config_parser.y" + { __sdp_rule.match_by_port = 1; __sdp_rule.sport= (yyvsp[(1) - (1)].ival); __sdp_rule.eport= (yyvsp[(1) - (1)].ival); } + break; + + case 32: +#line 268 "./config_parser.y" + { __sdp_rule.match_by_port = 1; __sdp_rule.sport= (yyvsp[(1) - (3)].ival); __sdp_rule.eport= (yyvsp[(3) - (3)].ival); } + break; + + case 33: +#line 269 "./config_parser.y" + { __sdp_rule.match_by_port = 0; __sdp_rule.sport= 0 ; __sdp_rule.eport= 0; } + break; + + +/* Line 1267 of yacc.c. */ +#line 1614 "y.tab.c" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 272 "./config_parser.y" + + +int yyerror(char *msg) +{ + /* replace the $undefined and $end if exists */ + char *orig_msg = (char*)malloc(strlen(msg)+25); + char *final_msg = (char*)malloc(strlen(msg)+25); + + strcpy(orig_msg, msg); + + char *word = strtok(orig_msg, " "); + final_msg[0] = '\0'; + while (word != NULL) { + if (!strncmp(word, "$undefined", 10)) { + strcat(final_msg, "unrecognized-token "); + } else if (!strncmp(word, "$end",4)) { + strcat(final_msg, "end-of-file "); + } else { + strcat(final_msg, word); + strcat(final_msg, " "); + } + word = strtok(NULL, " "); + } + + __sdp_log(9, "Error (line:%ld) : %s\n", __sdp_config_line_num, final_msg); + parse_err = 1; + + free(orig_msg); + free(final_msg); + return 1; +} + +#include <unistd.h> +#include <errno.h> + +/* parse apollo route dump file */ +int __sdp_parse_config (const char *fileName) { + extern FILE * libsdp_yyin; + + /* open the file */ + if (access(fileName, R_OK)) { + printf("libsdp Error: No access to open File:%s %s\n", + fileName, strerror(errno)); + return(1); + } + + libsdp_yyin = fopen(fileName,"r"); + if (!libsdp_yyin) { + printf("libsdp Error: Fail to open File:%s\n", fileName); + return(1); + } + parse_err = 0; + __sdp_config_line_num = 1; + + /* parse it */ + yyparse(); + + fclose(libsdp_yyin); + return(parse_err); +} + + + diff --git a/contrib/ofed/libsdp/src/config_parser.h b/contrib/ofed/libsdp/src/config_parser.h new file mode 100644 index 0000000..fd193f3 --- /dev/null +++ b/contrib/ofed/libsdp/src/config_parser.h @@ -0,0 +1,95 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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, 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. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + USE = 258, + CLIENT = 259, + SERVER = 260, + TCP = 261, + SDP = 262, + BOTH = 263, + INT = 264, + LOG = 265, + DEST = 266, + STDERR = 267, + SYSLOG = 268, + FILENAME = 269, + NAME = 270, + LEVEL = 271, + LINE = 272 + }; +#endif +/* Tokens. */ +#define USE 258 +#define CLIENT 259 +#define SERVER 260 +#define TCP 261 +#define SDP 262 +#define BOTH 263 +#define INT 264 +#define LOG 265 +#define DEST 266 +#define STDERR 267 +#define SYSLOG 268 +#define FILENAME 269 +#define NAME 270 +#define LEVEL 271 +#define LINE 272 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 167 "./config_parser.y" +{ + int ival; + char *sval; +} +/* Line 1529 of yacc.c. */ +#line 88 "y.tab.h" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +extern YYSTYPE libsdp_yylval; + diff --git a/contrib/ofed/libsdp/src/config_scanner.c b/contrib/ofed/libsdp/src/config_scanner.c new file mode 100644 index 0000000..661b584 --- /dev/null +++ b/contrib/ofed/libsdp/src/config_scanner.c @@ -0,0 +1,1885 @@ +#define yy_create_buffer libsdp_yy_create_buffer +#define yy_delete_buffer libsdp_yy_delete_buffer +#define yy_scan_buffer libsdp_yy_scan_buffer +#define yy_scan_string libsdp_yy_scan_string +#define yy_scan_bytes libsdp_yy_scan_bytes +#define yy_flex_debug libsdp_yy_flex_debug +#define yy_init_buffer libsdp_yy_init_buffer +#define yy_flush_buffer libsdp_yy_flush_buffer +#define yy_load_buffer_state libsdp_yy_load_buffer_state +#define yy_switch_to_buffer libsdp_yy_switch_to_buffer +#define yyin libsdp_yyin +#define yyleng libsdp_yyleng +#define yylex libsdp_yylex +#define yyout libsdp_yyout +#define yyrestart libsdp_yyrestart +#define yytext libsdp_yytext +#define yywrap libsdp_yywrap + +/* A lexical scanner generated by flex*/ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> +#include <unistd.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* Some routines like yy_flex_realloc() are emitted as static but are + not called by all lexers. This generates warnings in some compilers, + notably GCC. Arrange to suppress these. */ +#ifdef __GNUC__ +#define YY_MAY_BE_UNUSED __attribute__((unused)) +#else +#define YY_MAY_BE_UNUSED +#endif + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )) YY_MAY_BE_UNUSED; +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 20 +#define YY_END_OF_BUFFER 21 +static yyconst short int yy_accept[171] = + { 0, + 0, 0, 0, 0, 21, 19, 18, 16, 17, 2, + 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 18, 1, 15, 15, 2, 2, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 1, 18, 17, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 1, 1, 15, 15, 2, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 1, 0, 0, 0, 0, 0, 0, + 3, 0, 11, 0, 0, 0, 10, 9, 1, 15, + 15, 15, 15, 15, 15, 3, 15, 11, 15, 15, + + 15, 10, 9, 12, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 12, 15, 15, 15, 8, 15, 15, + 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 15, 15, 15, 15, 15, 15, 13, + 0, 0, 14, 0, 6, 7, 13, 15, 15, 14, + 15, 6, 7, 0, 0, 15, 15, 0, 0, 15, + 15, 0, 5, 15, 5, 0, 15, 4, 4, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 5, 1, 1, 6, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 8, 9, 10, 11, + + 12, 13, 14, 15, 16, 1, 1, 17, 18, 19, + 20, 21, 1, 22, 23, 24, 25, 26, 1, 1, + 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[28] = + { 0, + 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[177] = + { 0, + 0, 26, 30, 56, 214, 215, 211, 215, 0, 215, + 55, 192, 46, 199, 194, 48, 193, 58, 198, 184, + 63, 0, 0, 204, 0, 65, 185, 56, 192, 187, + 58, 186, 68, 191, 177, 197, 196, 0, 77, 173, + 180, 176, 171, 176, 169, 177, 171, 168, 166, 176, + 163, 164, 172, 73, 0, 0, 0, 181, 80, 158, + 165, 161, 156, 161, 154, 162, 156, 153, 151, 161, + 148, 149, 157, 166, 152, 154, 146, 140, 151, 138, + 215, 156, 215, 134, 147, 141, 215, 215, 0, 142, + 144, 136, 130, 141, 128, 0, 146, 0, 124, 137, + + 131, 0, 0, 215, 128, 134, 129, 215, 132, 126, + 130, 119, 120, 0, 120, 126, 121, 0, 124, 118, + 122, 111, 112, 107, 120, 110, 109, 115, 104, 103, + 110, 99, 112, 102, 101, 107, 96, 95, 102, 215, + 91, 106, 215, 87, 215, 215, 0, 88, 103, 0, + 84, 0, 0, 85, 96, 83, 94, 78, 76, 75, + 73, 69, 215, 68, 0, 62, 40, 215, 0, 215, + 95, 97, 28, 99, 101, 103 + } ; + +static yyconst short int yy_def[177] = + { 0, + 170, 1, 170, 3, 170, 170, 170, 170, 171, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 172, 173, 174, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 175, 170, 171, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 176, 172, 173, 174, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 175, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 176, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + + 173, 173, 173, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 170, 170, 170, 170, 170, 170, 170, + 170, 173, 173, 173, 173, 173, 173, 173, 173, 170, + 170, 170, 170, 170, 170, 170, 173, 173, 173, 173, + 173, 173, 173, 170, 170, 173, 173, 170, 170, 173, + 173, 170, 170, 173, 173, 170, 173, 170, 173, 0, + 170, 170, 170, 170, 170, 170 + } ; + +static yyconst short int yy_nxt[243] = + { 0, + 6, 7, 8, 9, 6, 10, 11, 6, 12, 13, + 14, 6, 15, 6, 6, 6, 16, 17, 6, 6, + 6, 6, 18, 19, 20, 6, 6, 21, 57, 22, + 23, 7, 8, 24, 23, 25, 26, 23, 27, 28, + 29, 23, 30, 23, 23, 23, 31, 32, 23, 23, + 23, 23, 33, 34, 35, 23, 23, 21, 169, 36, + 39, 39, 41, 45, 54, 42, 55, 46, 48, 49, + 59, 59, 61, 65, 54, 62, 55, 66, 68, 69, + 168, 50, 39, 39, 51, 59, 59, 167, 166, 165, + 164, 70, 163, 162, 71, 38, 38, 56, 56, 58, + + 58, 74, 74, 89, 89, 161, 160, 159, 158, 157, + 156, 147, 155, 154, 140, 153, 152, 150, 151, 150, + 149, 148, 147, 146, 145, 143, 144, 143, 142, 141, + 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, + 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, + 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, + 110, 109, 108, 107, 106, 105, 104, 56, 103, 102, + 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, + 91, 90, 38, 88, 87, 86, 85, 84, 83, 82, + 81, 80, 79, 78, 77, 76, 75, 37, 56, 73, + + 72, 67, 64, 63, 60, 38, 53, 52, 47, 44, + 43, 40, 37, 170, 5, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170 + } ; + +static yyconst short int yy_chk[243] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 173, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 4, 167, 4, + 11, 11, 13, 16, 21, 13, 21, 16, 18, 18, + 26, 26, 28, 31, 54, 28, 54, 31, 33, 33, + 166, 18, 39, 39, 18, 59, 59, 164, 162, 161, + 160, 33, 159, 158, 33, 171, 171, 172, 172, 174, + + 174, 175, 175, 176, 176, 157, 156, 155, 154, 151, + 149, 148, 144, 142, 141, 139, 138, 137, 136, 135, + 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, + 124, 123, 122, 121, 120, 119, 117, 116, 115, 113, + 112, 111, 110, 109, 107, 106, 105, 101, 100, 99, + 97, 95, 94, 93, 92, 91, 90, 86, 85, 84, + 82, 80, 79, 78, 77, 76, 75, 74, 73, 72, + 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, + 61, 60, 58, 53, 52, 51, 50, 49, 48, 47, + 46, 45, 44, 43, 42, 41, 40, 37, 36, 35, + + 34, 32, 30, 29, 27, 24, 20, 19, 17, 15, + 14, 12, 7, 5, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "./config_scanner.l" +#define INITIAL 0 +/* + * Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - 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. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: ibnl_scanner.ll,v 1.4 2005/02/23 21:08:37 eitan Exp $ + */ +#line 36 "./config_scanner.l" + +/* #define DEBUG 1 */ + +#define yyparse libsdp_yyparse +#define yylex libsdp_yylex +#define yyerror libsdp_yyerror +#define yylval libsdp_yylval +#define yychar libsdp_yychar +#define yydebug libsdp_yydebug +#define yynerrs libsdp_yynerrs + +#define yywrap libsdp_yywrap + +#include <string.h> +#include <stdio.h> +#include "config_parser.h" +extern long __sdp_config_line_num; +#define CANNAME 1 + +#line 550 "lex.libsdp_yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + yy_current_buffer->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp = NULL, *yy_bp = NULL; + register int yy_act; + +#line 55 "./config_scanner.l" + + +#line 707 "lex.libsdp_yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 171 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 215 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 57 "./config_scanner.l" +{} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 59 "./config_scanner.l" +{ + yylval.ival = atoi(yytext); +#ifdef DEBUG + printf("INT:%d\n",yylval.ival); +#endif + return INT; +} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 67 "./config_scanner.l" +{ + yylval.ival = LOG; +#ifdef DEBUG + printf("LOG\n"); +#endif + return LOG; +} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 75 "./config_scanner.l" +{ + yylval.ival = DEST; +#ifdef DEBUG + printf("DEST\n"); +#endif + return DEST; +} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 83 "./config_scanner.l" +{ + yylval.ival = LEVEL; +#ifdef DEBUG + printf("LEVEL\n"); +#endif + return LEVEL; +} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 91 "./config_scanner.l" +{ + yylval.ival = STDERR; +#ifdef DEBUG + printf("STDERR\n"); +#endif + return STDERR; +} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 99 "./config_scanner.l" +{ + yylval.ival = SYSLOG; +#ifdef DEBUG + printf("SYSLOG\n"); +#endif + return SYSLOG; +} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 107 "./config_scanner.l" +{ + yylval.ival = FILENAME; +#ifdef DEBUG + printf("FILENAME\n"); +#endif + BEGIN(CANNAME); + return FILENAME; +} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 116 "./config_scanner.l" +{ + yylval.ival = USE; +#ifdef DEBUG + printf("USE\n"); +#endif + return USE; +} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 124 "./config_scanner.l" +{ + yylval.ival = TCP; +#ifdef DEBUG + printf("TCP\n"); +#endif + return TCP; +} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 132 "./config_scanner.l" +{ + yylval.ival = SDP; +#ifdef DEBUG + printf("SDP\n"); +#endif + return SDP; +} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 140 "./config_scanner.l" +{ + yylval.ival = BOTH; +#ifdef DEBUG + printf("BOTH\n"); +#endif + return BOTH; +} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 148 "./config_scanner.l" +{ + yylval.ival = CLIENT; +#ifdef DEBUG + printf("CLIENT\n"); +#endif + BEGIN(CANNAME); + return CLIENT; +} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 157 "./config_scanner.l" +{ + yylval.ival = SERVER; +#ifdef DEBUG + printf("SERVER\n"); +#endif + BEGIN(CANNAME); + return SERVER; +} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 166 "./config_scanner.l" +{ + yylval.sval = (char *)malloc(strlen(yytext) + 1); + strcpy(yylval.sval, yytext); +#ifdef DEBUG + printf("NAME:%s\n",yylval.sval); +#endif + BEGIN(0); + return (NAME); +} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 176 "./config_scanner.l" +{ + __sdp_config_line_num++; +#ifdef DEBUG + printf("LINE\n"); +#endif + yylval.ival = LINE; + return(LINE); +} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 185 "./config_scanner.l" +{ + __sdp_config_line_num++; +} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 189 "./config_scanner.l" +{} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 191 "./config_scanner.l" +{ +#ifdef DEBUG + printf("CHAR:%c\n",yytext[0]); +#endif + return(yytext[0]); +} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 198 "./config_scanner.l" +ECHO; + YY_BREAK +#line 994 "lex.libsdp_yy.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(CANNAME): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 171 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 171 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 170); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + yy_current_buffer->yy_at_bol = (c == '\n'); + + return c; + } +#endif /* YY_NO_INPUT */ + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 198 "./config_scanner.l" + + +int yywrap () +{ + return (1); +} + diff --git a/contrib/ofed/libsdp/src/libsdp.h b/contrib/ofed/libsdp/src/libsdp.h new file mode 100644 index 0000000..0402d55 --- /dev/null +++ b/contrib/ofed/libsdp/src/libsdp.h @@ -0,0 +1,131 @@ +/* + This software is available to you under a choice of one of two + licenses. You may choose to be licensed under the terms of the GNU + General Public License (GPL) Version 2, available at + <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD + license, available in the LICENSE.TXT file accompanying this + software. These details are also available at + <http://openib.org/license.html>. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Copyright (c) 2004 Topspin Communications. All rights reserved. + Copyright (c) 2005-2006 Mellanox Technologies Ltd. All rights reserved. + + $Id$ +*/ + +#include <netinet/in.h> + +/* + * SDP specific includes + */ +#include "linux/sdp_inet.h" + +/* --------------------------------------------------------------------- */ +/* library static and global variables */ +/* --------------------------------------------------------------------- */ + +/* max string length to store any IPv4/IPv6 address */ +#define MAX_ADDR_STR_LEN 49 + +typedef enum +{ + USE_TCP = 1, + USE_SDP, + USE_BOTH, +} use_family_t; + +/* some state to string functions */ +static inline char * +__sdp_get_family_str( + use_family_t family ) +{ + switch ( family ) { + case USE_TCP: + return "tcp"; + break; + case USE_SDP: + return "sdp"; + break; + case USE_BOTH: + return "both"; + break; + } + return ( "unknown-family" ); +} + +/* data structure for holding address family mapoping rules */ +/* note we filter non relevant programs during parsing ... */ +struct use_family_rule +{ + struct use_family_rule *prev, *next; + int match_by_addr; /* if 0 ignore address match */ + struct in_addr ipv4; /* IPv4 address for mapping */ + unsigned char prefixlen; /* length of CIDR prefix (ie /24) */ + int match_by_port; /* if 0 ignore port match */ + unsigned short sport, eport; /* start port - end port, inclusive */ + use_family_t target_family; /* if match - use this family */ + char *prog_name_expr; /* expression for program name */ +}; + +extern struct use_family_rule *__sdp_clients_family_rules_head; +extern struct use_family_rule *__sdp_clients_family_rules_tail; +extern struct use_family_rule *__sdp_servers_family_rules_head; +extern struct use_family_rule *__sdp_servers_family_rules_tail; + +#define SDP_NETMASK(n) ((n == 0) ? 0 : ~((1UL<<(32 - n)) - 1)) + +/* match.c */ +use_family_t __sdp_match_connect( + const struct sockaddr *sin, + const socklen_t addrlen ); + +use_family_t __sdp_match_listen( + const struct sockaddr *sin, + const socklen_t addrlen ); + +/* config.c */ +int __sdp_config_empty( + void ); + +int __sdp_parse_config( + const char *config_file ); + +use_family_t __sdp_match_by_program( + ); + +/* log.c */ +void __sdp_log( + int level, + char *format, + ... ); + +int __sdp_log_get_level( + void ); + +void __sdp_log_set_min_level( + int level ); + +int __sdp_log_set_log_stderr( + void ); + +int __sdp_log_set_log_syslog( + void ); + +int __sdp_log_set_log_file( + char *filename ); + +/* port.c */ +int __sdp_sockaddr_to_sdp( + const struct sockaddr *addr_in, + socklen_t addrlen, + struct sockaddr_in *addr_out, + int *was_ipv6 ); diff --git a/contrib/ofed/libsdp/src/linux/sdp_inet.h b/contrib/ofed/libsdp/src/linux/sdp_inet.h new file mode 100644 index 0000000..fde347f --- /dev/null +++ b/contrib/ofed/libsdp/src/linux/sdp_inet.h @@ -0,0 +1,52 @@ +/* + This software is available to you under a choice of one of two + licenses. You may choose to be licensed under the terms of the GNU + General Public License (GPL) Version 2, available at + <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD + license, available in the LICENSE.TXT file accompanying this + software. These details are also available at + <http://openib.org/license.html>. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Copyright (c) 2004 Topspin Communications. All rights reserved. + + $Id$ +*/ + +#ifndef _SDP_INET_H +#define _SDP_INET_H + +/* + * constants shared between user and kernel space. + */ + +#ifndef SOLARIS_BUILD +#define AF_INET_SDP 27 /* SDP socket protocol family */ +#define AF_INET6_SDP 28 /* SDP socket protocol family */ +#else +#define AF_INET_SDP 31 /* This is an invalid family on native solaris + * and will only work using QuickTransit */ +//TODO XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx +#define AF_INET6_SDP 32 /* SDP socket protocol family */ +#endif + +#define AF_INET_STR "AF_INET_SDP" /* SDP enabled environment variable */ +#define AF_INET6_STR "AF_INET6_SDP" /* SDP enabled environment variable */ + +#ifndef SDP_ZCOPY_THRESH +#define SDP_ZCOPY_THRESH 80 +#endif + +#ifndef SDP_LAST_BIND_ERR +#define SDP_LAST_BIND_ERR 81 +#endif + +#endif /* _SDP_INET_H */ diff --git a/contrib/ofed/libsdp/src/log.c b/contrib/ofed/libsdp/src/log.c new file mode 100644 index 0000000..c98ee46 --- /dev/null +++ b/contrib/ofed/libsdp/src/log.c @@ -0,0 +1,236 @@ +/* + This software is available to you under a choice of one of two + licenses. You may choose to be licensed under the terms of the GNU + General Public License (GPL) Version 2, available at + <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD + license, available in the LICENSE.TXT file accompanying this + software. These details are also available at + <http://openib.org/license.html>. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Copyright (c) 2004 Topspin Communications. All rights reserved. + Copyright (c) 2006 Mellanox Technologies Ltd. All rights reserved. + + $Id$ +*/ + +/* + * system includes + */ +#if HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <limits.h> + +/* + * SDP specific includes + */ +#include "libsdp.h" + +extern char *program_invocation_short_name; + +typedef enum +{ + SDP_LOG_FILE, + SDP_LOG_SYSLOG, +} __sdp_log_type_t; + +/* --------------------------------------------------------------------- */ +/* library static and global variables */ +/* --------------------------------------------------------------------- */ +int __sdp_min_level = 9; +static __sdp_log_type_t __sdp_log_type = SDP_LOG_FILE; +static FILE *__sdp_log_file = NULL; + +void +__sdp_log( + int level, + char *format, + ... ) +{ + va_list ap; + char extra_format[512]; + time_t timeval; + char timestr[32]; + + if ( level < __sdp_min_level ) { + return; + } + + va_start( ap, format ); + switch ( __sdp_log_type ) { + case SDP_LOG_SYSLOG: + sprintf( extra_format, "%s[%d] libsdp %s ", + program_invocation_short_name, getpid( ), format ); + vsyslog( LOG_USER | LOG_NOTICE, extra_format, ap ); + break; + case SDP_LOG_FILE: + timeval = time(NULL); +#ifdef SOLARIS_BUILD + ctime_r(&timeval, timestr, sizeof timestr); +#else + ctime_r(&timeval, timestr); +#endif + timestr[strlen(timestr)-1] = '\0'; + sprintf( extra_format, "%s %s[%d] libsdp %s ", + timestr, program_invocation_short_name, + getpid( ), format ); + if ( __sdp_log_file == NULL ) { + vfprintf( stderr, extra_format, ap ); +#if 0 /* might slow everything too much? */ + ( void )fflush( stderr ); +#endif + } else { + vfprintf( __sdp_log_file, extra_format, ap ); +#if 0 /* might slow everything too much? */ + ( void )fflush( __sdp_log_file ); +#endif + } + break; + } + va_end( ap ); +} + +int +__sdp_log_get_level( + void ) +{ + return ( __sdp_min_level ); +} + +void +__sdp_log_set_min_level( + int level ) +{ + __sdp_min_level = level; +} + +static void +__sdp_log_set_log_type( + __sdp_log_type_t type ) +{ + if ( __sdp_log_file != NULL ) { + fclose( __sdp_log_file ); + __sdp_log_file = NULL; + } + + __sdp_log_type = type; +} + +int +__sdp_log_set_log_stderr( + void ) +{ + __sdp_log_set_log_type( SDP_LOG_FILE ); + /* NULL means stderr */ + + return 1; +} + +int +__sdp_log_set_log_syslog( + void ) +{ + __sdp_log_set_log_type( SDP_LOG_SYSLOG ); + + return 1; +} + +int +__sdp_log_set_log_file( + char *filename ) +{ + FILE *f; + uid_t uid; + struct stat lstat_res; + int status; + + char *p, tfilename[PATH_MAX + 1]; + + /* Strip off any paths from the filename */ + p = strrchr( filename, '/' ); + + /* + base on the active user ID we either use /var/log for root or + append the uid to the name + */ + uid = geteuid(); + if (uid == 0) { + if ( p ) + filename = p + 1; + snprintf( tfilename, sizeof(tfilename), "/var/log/%s", filename ); + } else { + char tdir[PATH_MAX + 1]; + /* + for regular user, allow log file to be placed in a user + requested path. If no path is requested the log file is + placed in /tmp/ + */ + if ( p ) + snprintf(tdir, sizeof(tdir), "%s.%d", filename, uid ); + else + snprintf(tdir, sizeof(tdir ), "/tmp/%s.%d", filename, uid ); + + if (mkdir(tdir, 0700)) { + struct stat stat; + + if (errno != EEXIST) { + __sdp_log( 9, "Couldn't create directory '%s' for logging (%m)\n", tdir ); + return 0; + } + + if (lstat(tdir, &stat)) { + __sdp_log(9, "Couldn't lstat directory %s\n", tdir); + return 0; + } + + if (!S_ISDIR(stat.st_mode) || stat.st_uid != uid || + (stat.st_mode & ~(S_IFMT | S_IRWXU))) { + __sdp_log( 9, "Cowardly refusing to log into directory:'%s'. " + "Make sure it is not: (1) link, (2) other uid, (3) bad permissions." + "thus is a security issue.\n", tdir ); + return 0; + } + } + + snprintf(tfilename, sizeof(tfilename), "%s/log", tdir); + printf("dir: %s file: %s\n", tdir, tfilename); + } + + /* double check the file is not a link */ + status = lstat(tfilename, &lstat_res); + if ( (status == 0) && S_ISLNK(lstat_res.st_mode) ) { + __sdp_log( 9, "Cowardly refusing to log into:'%s'. " + "It is a link - thus is a security issue.\n", tfilename ); + return 0; + } + + f = fopen( tfilename, "a" ); + if ( !f ) { + __sdp_log( 9, "Couldn't open '%s' for logging (%m)\n", tfilename ); + return 0; + } + + __sdp_log_set_log_type( SDP_LOG_FILE ); + __sdp_log_file = f; + + return 1; +} diff --git a/contrib/ofed/libsdp/src/match.c b/contrib/ofed/libsdp/src/match.c new file mode 100644 index 0000000..fe981b2 --- /dev/null +++ b/contrib/ofed/libsdp/src/match.c @@ -0,0 +1,296 @@ +/* + This software is available to you under a choice of one of two + licenses. You may choose to be licensed under the terms of the GNU + General Public License (GPL) Version 2, available at + <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD + license, available in the LICENSE.TXT file accompanying this + software. These details are also available at + <http://openib.org/license.html>. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Copyright (c) 2004 Topspin Communications. All rights reserved. + Copyright (c) 2005-2006 Mellanox Technologies Ltd. All rights reserved. + + $Id$ +*/ + +/* + * system includes + */ +#if HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fnmatch.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +/* + * SDP specific includes + */ +#include "libsdp.h" + +/* --------------------------------------------------------------------- */ +/* library static and global variables */ +/* --------------------------------------------------------------------- */ +extern char *program_invocation_name, *program_invocation_short_name; + +static void +get_rule_str( + struct use_family_rule *rule, + char *buf, + size_t len ) +{ + char addr_buf[MAX_ADDR_STR_LEN]; + char ports_buf[16]; + char *target = __sdp_get_family_str( rule->target_family ); + char *prog = rule->prog_name_expr; + + /* TODO: handle IPv6 in rule */ + if ( rule->match_by_addr ) { + if ( rule->prefixlen != 32 ) + sprintf( addr_buf, "%s/%d", inet_ntoa( rule->ipv4 ), + rule->prefixlen ); + else + sprintf( addr_buf, "%s", inet_ntoa( rule->ipv4 ) ); + } else { + strcpy( addr_buf, "*" ); + } + + if ( rule->match_by_port ) + if ( rule->eport > rule->sport ) + sprintf( ports_buf, "%d", rule->sport ); + else + sprintf( ports_buf, "%d-%d", rule->sport, rule->eport ); + else + sprintf( ports_buf, "*" ); + + snprintf( buf, len, "use %s %s %s:%s", target, prog, addr_buf, ports_buf ); +} + +/* return 0 if the addresses match */ +static inline int +match_ipv4_addr( + struct use_family_rule *rule, + const struct sockaddr_in *sin ) +{ + return ( rule->ipv4.s_addr != + ( sin->sin_addr. + s_addr & htonl( SDP_NETMASK( rule->prefixlen ) ) ) ); +} + +static int +match_ip_addr_and_port( + struct use_family_rule *rule, + const struct sockaddr *addr_in, + const socklen_t addrlen ) +{ + const struct sockaddr_in *sin = ( const struct sockaddr_in * )addr_in; + const struct sockaddr_in6 *sin6 = ( const struct sockaddr_in6 * )addr_in; + struct sockaddr_in tmp_sin; + unsigned short port; + int match = 1; + char addr_buf[MAX_ADDR_STR_LEN]; + const char *addr_str; + char rule_str[512]; + + if ( __sdp_log_get_level( ) <= 3 ) { + if ( sin6->sin6_family == AF_INET6 ) { + addr_str = + inet_ntop( AF_INET6, ( void * )&( sin6->sin6_addr ), addr_buf, + MAX_ADDR_STR_LEN ); + port = ntohs( sin6->sin6_port ); + } else { + addr_str = + inet_ntop( AF_INET, ( void * )&( sin->sin_addr ), addr_buf, + MAX_ADDR_STR_LEN ); + port = ntohs( sin->sin_port ); + } + if ( addr_str == NULL ) + addr_str = "INVALID_ADDR"; + + get_rule_str( rule, rule_str, sizeof( rule_str ) ); + + __sdp_log( 3, "MATCH: matching %s:%d to %s => \n", addr_str, port, + rule_str ); + } + + /* We currently only support IPv4 and IPv4 embedded in IPv6 */ + if ( rule->match_by_port ) { + if ( sin6->sin6_family == AF_INET6 ) + port = ntohs( sin6->sin6_port ); + else + port = ntohs( sin->sin_port ); + + if ( ( port < rule->sport ) || ( port > rule->eport ) ) { + __sdp_log( 3, "NEGATIVE by port range\n" ); + match = 0; + } + } + + if ( match && rule->match_by_addr ) { + if ( __sdp_sockaddr_to_sdp( addr_in, addrlen, &tmp_sin, NULL ) || + match_ipv4_addr( rule, &tmp_sin ) ) { + __sdp_log( 3, "NEGATIVE by address\n" ); + match = 0; + } + } + + if ( match ) + __sdp_log( 3, "POSITIVE\n" ); + + return match; +} + +/* return 1 on match */ +static int +match_program_name( + struct use_family_rule *rule ) +{ + return !fnmatch( rule->prog_name_expr, program_invocation_short_name, 0 ); +} + +static use_family_t +get_family_by_first_matching_rule( + const struct sockaddr *sin, + const socklen_t addrlen, + struct use_family_rule *rules ) +{ + struct use_family_rule *rule; + + for ( rule = rules; rule != NULL; rule = rule->next ) { + /* skip if not our program */ + if ( !match_program_name( rule ) ) + continue; + + /* first rule wins */ + if ( match_ip_addr_and_port( rule, sin, addrlen ) ) + return ( rule->target_family ); + } + + return ( USE_BOTH ); +} + +/* return the result of the first matching rule found */ +use_family_t +__sdp_match_listen( + const struct sockaddr * sin, + const socklen_t addrlen ) +{ + use_family_t target_family; + + /* if we do not have any rules we use sdp */ + if ( __sdp_config_empty( ) ) + target_family = USE_SDP; + else + target_family = + get_family_by_first_matching_rule( sin, addrlen, + __sdp_servers_family_rules_head ); + + __sdp_log( 4, "MATCH LISTEN: => %s\n", + __sdp_get_family_str( target_family ) ); + + return ( target_family ); +} + +use_family_t +__sdp_match_connect( + const struct sockaddr * sin, + const socklen_t addrlen ) +{ + use_family_t target_family; + + /* if we do not have any rules we use sdp */ + if ( __sdp_config_empty( ) ) + target_family = USE_SDP; + else + target_family = + get_family_by_first_matching_rule( sin, addrlen, + __sdp_clients_family_rules_head ); + + __sdp_log( 4, "MATCH CONNECT: => %s\n", + __sdp_get_family_str( target_family ) ); + + return ( target_family ); +} + +/* given a set of rules see if there is a global match for current program */ +static use_family_t +match_by_all_rules_program( + struct use_family_rule *rules ) +{ + int any_sdp = 0; + int any_tcp = 0; + use_family_t target_family = USE_BOTH; + struct use_family_rule *rule; + + for ( rule = rules; ( rule != NULL ) && ( target_family == USE_BOTH ); + rule = rule->next ) { + /* skip if not our program */ + if ( !match_program_name( rule ) ) + continue; + + /* + * to declare a dont care we either have a dont care address and port + * or the previous non global rules use the same target family as the + * global rule + */ + if ( rule->match_by_addr || rule->match_by_port ) { + /* not a glocal match rule - just track the target family */ + if ( rule->target_family == USE_SDP ) + any_sdp++; + else if ( rule->target_family == USE_TCP ) + any_tcp++; + } else { + /* a global match so we can declare a match by program */ + if ( ( rule->target_family == USE_SDP ) && ( any_tcp == 0 ) ) + target_family = USE_SDP; + else if ( ( rule->target_family == USE_TCP ) && ( any_sdp == 0 ) ) + target_family = USE_TCP; + } + } + return ( target_family ); +} + +/* return tcp or sdp if the port and role are dont cares */ +use_family_t +__sdp_match_by_program( + ) +{ + use_family_t server_target_family; + use_family_t client_target_family; + use_family_t target_family = USE_BOTH; + + if ( __sdp_config_empty( ) ) { + target_family = USE_SDP; + } else { + /* need to try both server and client rules */ + server_target_family = + match_by_all_rules_program( __sdp_servers_family_rules_head ); + client_target_family = + match_by_all_rules_program( __sdp_clients_family_rules_head ); + + /* only if both agree */ + if ( server_target_family == client_target_family ) + target_family = server_target_family; + } + + __sdp_log( 4, "MATCH PROGRAM: => %s\n", + __sdp_get_family_str( target_family ) ); + + return ( target_family ); +} diff --git a/contrib/ofed/libsdp/src/port.c b/contrib/ofed/libsdp/src/port.c new file mode 100644 index 0000000..26bcf7c --- /dev/null +++ b/contrib/ofed/libsdp/src/port.c @@ -0,0 +1,2629 @@ +/* + This software is available to you under a choice of one of two + licenses. You may choose to be licensed under the terms of the GNU + General Public License (GPL) Version 2, available at + <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD + license, available in the LICENSE.TXT file accompanying this + software. These details are also available at + <http://openib.org/license.html>. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Copyright (c) 2004 Topspin Communications. All rights reserved. + Copyright (c) 2005-2006 Mellanox Technologies Ltd. All rights reserved. + + $Id$ +*/ + +/* + * system includes + */ +#if HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +#ifdef SOLARIS_BUILD +/* Our prototypes for ioctl, get*name and accept do not strictly + match the headers - we use the following lines to move the header + versions 'out of the way' temporarily. */ +#define ioctl __real_ioctl +#define getsockname __real_getsockname +#define getpeername __real_getpeername +#define accept __real_accept +#define FASYNC 0 +#include <libgen.h> +#endif +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#define __USE_GNU +#define _GNU_SOURCE /* define RTLD_NEXT */ +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <stdarg.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/poll.h> +#ifdef __linux__ +#include <sys/epoll.h> +#endif + +#ifdef SOLARIS_BUILD +/* We're done protecting ourselves from the header prototypes */ +#undef ioctl +#undef getsockname +#undef getpeername +#undef accept +#endif + +/* + * SDP specific includes + */ +#include "libsdp.h" + +/* We can not use sizeof(sockaddr_in6) as the extra scope_id field is not a must have */ +#define IPV6_ADDR_IN_MIN_LEN 24 + +/* setsockopt() level and optname declarations */ +#define SOL_SDP 1025 +#define SDP_UNBIND 259 /* Unbind socket */ + +/* Solaris has two entry socket creation functions */ +#define SOCKET_SEMANTIC_DEFAULT 0 +#define SOCKET_SEMANTIC_XNET 1 + +/* HACK: filter ioctl errors for FIONREAD */ +#define FIONREAD 0x541B + +void __attribute__ ((constructor)) __sdp_init(void); +void __attribute__ ((destructor)) __sdp_fini(void); + +/* --------------------------------------------------------------------- */ +/* library type definitions. */ +/* --------------------------------------------------------------------- */ + +typedef int (*ioctl_func_t) (int fd, + int request, + void *arg0, + void *arg1, + void *arg2, + void *arg3, + void *arg4, void *arg5, void *arg6, void *arg7); + +typedef int (*fcntl_func_t) (int fd, int cmd, ...); + +typedef int (*socket_func_t) (int domain, int type, int protocol); + +typedef int (*setsockopt_func_t) (int s, + int level, + int optname, + const void *optval, socklen_t optlen); + +typedef int (*connect_func_t) (int sockfd, + const struct sockaddr * serv_addr, + socklen_t addrlen); + +typedef int (*listen_func_t) (int s, int backlog); + +typedef int (*bind_func_t) (int sockfd, + const struct sockaddr * my_addr, socklen_t addrlen); + +typedef int (*close_func_t) (int fd); + +typedef int (*dup_func_t) (int fd); + +typedef int (*dup2_func_t) (int oldfd, int newfd); + +typedef int (*getsockname_func_t) (int fd, + struct sockaddr * name, socklen_t * namelen); + +typedef int (*getpeername_func_t) (int fd, + struct sockaddr * name, socklen_t * namelen); + +typedef int (*accept_func_t) (int fd, + struct sockaddr * addr, socklen_t * addrlen); + +typedef int (*select_func_t) (int n, + fd_set * readfds, + fd_set * writefds, + fd_set * exceptfds, struct timeval * timeout); + +typedef int (*pselect_func_t) (int n, + fd_set * readfds, + fd_set * writefds, + fd_set * exceptfds, + const struct timespec * timeout, + const sigset_t * sigmask); + +typedef int (*poll_func_t) (struct pollfd * ufds, + unsigned long int nfds, int timeout); + +#ifdef __linux__ +typedef int (*epoll_create_func_t) (int size); + +typedef int (*epoll_ctl_func_t) (int epfd, + int op, int fd, struct epoll_event * event); + +typedef int (*epoll_wait_func_t) (int epfd, + struct epoll_event * events, + int maxevents, int timeout); + +typedef int (*epoll_pwait_func_t) (int epfd, + struct epoll_event * events, + int maxevents, + int timeout, const sigset_t * sigmask); +#endif + + +struct socket_lib_funcs { + ioctl_func_t ioctl; + fcntl_func_t fcntl; + socket_func_t socket; + setsockopt_func_t setsockopt; + connect_func_t connect; + listen_func_t listen; + bind_func_t bind; + close_func_t close; + dup_func_t dup; + dup2_func_t dup2; + getpeername_func_t getpeername; + getsockname_func_t getsockname; + accept_func_t accept; + select_func_t select; + pselect_func_t pselect; + poll_func_t poll; +#ifdef __linux__ + epoll_create_func_t epoll_create; + epoll_ctl_func_t epoll_ctl; + epoll_wait_func_t epoll_wait; + epoll_pwait_func_t epoll_pwait; +#endif +}; /* socket_lib_funcs */ + +#ifdef SOLARIS_BUILD +/* Solaris has another interface to socket functions prefixed with __xnet_ */ +struct socket_lib_xnet_funcs { + socket_func_t socket; + connect_func_t connect; + listen_func_t listen; + bind_func_t bind; +}; +#endif + +static int simple_sdp_library; +static int max_file_descriptors; +static int dev_null_fd; +volatile static int init_status = 0; /* 0: idle, 1:during, 2:ready */ + +/* --------------------------------------------------------------------- */ +/* library static and global variables */ +/* --------------------------------------------------------------------- */ + +/* glibc provides these symbols - for Solaris builds we fake them + * until _init is called, at which point we quiz libdl.. */ +#ifdef SOLARIS_BUILD +char *program_invocation_name = "[progname]", *program_invocation_short_name = + "[short_progname]"; +#else +extern char *program_invocation_name, *program_invocation_short_name; +#endif + +#ifdef RTLD_NEXT +static void *__libc_dl_handle = RTLD_NEXT; +#else +static void *__libc_dl_handle; +#endif + +/* extra fd attributes we need for our algorithms */ +struct sdp_extra_fd_attributes { + int shadow_fd; /* file descriptor of shadow sdp socket */ + short last_accept_was_tcp; /* used by accept to alternate tcp and sdp */ + short is_sdp; /* 1 if the fd represents an sdp socket */ +}; /* sdp_extra_fd_attributes */ + +/* stores the extra attributes struct by fd */ +static struct sdp_extra_fd_attributes *libsdp_fd_attributes; + +static struct socket_lib_funcs _socket_funcs = { + .socket = NULL, + /* Automatically sets all other elements to NULL */ +}; /* _socket_funcs */ + +#ifdef SOLARIS_BUILD +static struct socket_lib_xnet_funcs _socket_xnet_funcs = { + .socket = NULL, + /* Automatically sets all other elements to NULL */ +}; +#endif + +/* --------------------------------------------------------------------- */ +/* Prototypes */ +/* --------------------------------------------------------------------- */ +void __sdp_init(void); + +/* --------------------------------------------------------------------- */ +/* */ +/* local static functions. */ +/* */ +/* --------------------------------------------------------------------- */ + +/* ========================================================================= */ +/*..init_extra_attribute -- initialize the set of extra attributes for a fd */ +static void init_extra_attribute(int fd) +{ + if ((0 <= fd) && (max_file_descriptors > fd)) { + libsdp_fd_attributes[fd].shadow_fd = -1; + libsdp_fd_attributes[fd].is_sdp = 0; + libsdp_fd_attributes[fd].last_accept_was_tcp = -1; + } +} + +static inline int is_valid_fd(int fd) +{ + return (0 <= fd) && (fd < max_file_descriptors); +} + +/* ========================================================================= */ +/*..get_shadow_fd_by_fd -- given an fd return its shadow fd if exists */ +static inline int get_shadow_fd_by_fd(int fd) +{ + if (is_valid_fd(fd)) + return libsdp_fd_attributes[fd].shadow_fd; + else + return -1; +} + +/* ========================================================================= */ +/*..set_shadow_for_fd -- */ +static inline void set_shadow_for_fd(int fd, int shadow_fd) +{ + if (is_valid_fd(fd)) + libsdp_fd_attributes[fd].shadow_fd = shadow_fd; +} + +/* ========================================================================= */ +/*..set_is_sdp_socket -- */ +static inline void set_is_sdp_socket(int fd, short is_sdp) +{ + if (is_valid_fd(fd)) + libsdp_fd_attributes[fd].is_sdp = is_sdp; +} + +/* ========================================================================= */ +/*..get_is_sdp_socket -- given an fd return 1 if it is an SDP socket */ +static inline int get_is_sdp_socket(int fd) +{ + if (is_valid_fd(fd)) + return libsdp_fd_attributes[fd].is_sdp; + else + return 0; +} + +/* ========================================================================= */ +/*..last_accept_was_tcp -- given an fd return 1 if last accept was tcp */ +static inline int last_accept_was_tcp(int fd) +{ + if (is_valid_fd(fd)) + return libsdp_fd_attributes[fd].last_accept_was_tcp; + else + return 0; +} + +/* ========================================================================= */ +/*..set_last_accept -- given an fd set last accept was tcp */ +static inline void set_last_accept(int fd, int was_tcp) +{ + if (is_valid_fd(fd)) + libsdp_fd_attributes[fd].last_accept_was_tcp = was_tcp; +} + +/* ========================================================================= */ +/*..cleanup_shadow -- an error occured on an SDP socket, cleanup */ +static int cleanup_shadow(int fd) +{ + int shadow_fd = get_shadow_fd_by_fd(fd); + + if (shadow_fd == -1) + return 0; + libsdp_fd_attributes[fd].shadow_fd = -1; + libsdp_fd_attributes[fd].last_accept_was_tcp = 0; + return (_socket_funcs.close(shadow_fd)); +} /* cleanup_shadow */ + +/* ========================================================================= */ +/*..replace_fd_with_its_shadow -- perform all required for such promotion */ +static int replace_fd_with_its_shadow(int fd) +{ + int shadow_fd = libsdp_fd_attributes[fd].shadow_fd; + + if (shadow_fd == -1) { + __sdp_log(9, "Error replace_fd_with_its_shadow: no shadow for fd:%d\n", + fd); + return EINVAL; + } + + /* copy the attributes of the shadow before we clean them up */ + libsdp_fd_attributes[fd] = libsdp_fd_attributes[shadow_fd]; + libsdp_fd_attributes[fd].shadow_fd = -1; + if (_socket_funcs.dup2(shadow_fd, fd) < 0) { + init_extra_attribute(fd); + _socket_funcs.close(shadow_fd); + return EINVAL; + } + _socket_funcs.close(shadow_fd); + return 0; +} + +static sa_family_t get_sdp_domain(int domain) +{ + if (AF_INET_SDP == domain || AF_INET6_SDP == domain) + return domain; + + if (AF_INET == domain) + return AF_INET_SDP; + else if (AF_INET6 == domain) + return AF_INET6_SDP; + + __sdp_log(9, "Error %s: unknown TCP domain: %d\n", __func__, domain); + + return -1; +} + +static int get_sock_domain(int sd) +{ + struct sockaddr_storage tmp_sin; + socklen_t tmp_sinlen = sizeof(tmp_sin); + + if (_socket_funcs.getsockname(sd, (struct sockaddr *) &tmp_sin, &tmp_sinlen) < 0) { + __sdp_log(9, "Error %s: getsockname return <%d> for socket\n", __func__, errno); + return -1; + } + + return ((struct sockaddr *)&tmp_sin)->sa_family; +} + +/* ========================================================================= */ +/*..is_filtered_unsuported_sockopt -- return 1 if to filter sockopt failure */ +static inline int is_filtered_unsuported_sockopt(int level, int optname) +{ + /* + * TODO: until we know exactly which unsupported opts are really + * a don't care we always pass the error + */ + return 0; +#if 0 + /* these are the SOL_TCP OPTS we should consider filterring */ + TCP_NODELAY 1 /* Don't delay send to coalesce packets */ + TCP_MAXSEG 2 /* Set maximum segment size */ + TCP_CORK 3 /* Control sending of partial frames */ + TCP_KEEPIDLE 4 /* Start keeplives after this period */ + TCP_KEEPINTVL 5 /* Interval between keepalives */ + TCP_KEEPCNT 6 /* Number of keepalives before death */ + TCP_SYNCNT 7 /* Number of SYN retransmits */ + TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */ + TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */ + TCP_WINDOW_CLAMP 10 /* Bound advertised window */ + TCP_INFO 11 /* Information about this connection. */ + TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */ +#endif +} + +/* ========================================================================= */ +/*..is_invalid_addr -- return 1 if given pointer is not valid */ +/* NOTE: invalidation of the size is going to happen during actual call */ +static inline int is_invalid_addr(const void *p) +{ + /* HACK: on some systems we can not write to check for pointer validity */ + size_t ret = fcntl(dev_null_fd, F_GETLK, p); + + ret = (errno == EFAULT); + errno = 0; + return ret; +} + +/* ========================================================================= */ +/*..get_addr_str -- fill in the given buffer with addr str or return 1 */ +static int get_addr_str(const struct sockaddr *addr, char *buf, size_t len) +{ + const struct sockaddr_in *sin = (struct sockaddr_in *) addr; + const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr; + char const *conv_res; + + if (sin->sin_family == AF_INET) { + conv_res = inet_ntop(AF_INET, (void *) &(sin->sin_addr), buf, len); + } else if (sin6->sin6_family == AF_INET6) { + conv_res = inet_ntop(AF_INET6, (void *) &sin6->sin6_addr, buf, len); + } else { + strncpy(buf, "unknown address family", len); + conv_res = (char *) 1; + } + return conv_res == NULL; +} + +/* --------------------------------------------------------------------- */ +/* */ +/* Socket library function overrides. */ +/* */ +/* --------------------------------------------------------------------- */ + +/* ========================================================================= */ +/*..ioctl -- replacement ioctl call. */ +int +ioctl(int fd, + int request, + void *arg0, + void *arg1, + void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7) +{ + int shadow_fd; + int sret = 0; + int ret = 0; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.ioctl) { + __sdp_log(9, "Error ioctl: no implementation for ioctl found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + + __sdp_log(2, "IOCTL: <%s:%d:%d> request <%d>\n", + program_invocation_short_name, fd, shadow_fd, request); + + ret = _socket_funcs.ioctl(fd, request, + arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + + /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */ + if ((ret < 0) && get_is_sdp_socket(fd) && (request == FIONREAD)) { + __sdp_log(8, "Warning ioctl: " + "Ignoring FIONREAD error for SDP socket.\n"); + ret = 0; + } + + /* if shadow and no error on tcp */ + if ((ret >= 0) && (-1 != shadow_fd)) { + sret = _socket_funcs.ioctl(shadow_fd, request, + arg0, arg1, arg2, arg3, arg4, arg5, arg6, + arg7); + /* HACK: avoid failing on FIONREAD error as SDP does not support it at the moment */ + if ((sret < 0) && (request == FIONREAD)) { + __sdp_log(8, "Warning ioctl: " + "Ignoring FIONREAD error for shadow SDP socket.\n"); + sret = 0; + } + + if (sret < 0) { + __sdp_log(9, "Error ioctl: " + "<%d> calling ioctl for SDP socket, closing it.\n", + errno); + cleanup_shadow(fd); + } + } + + __sdp_log(2, "IOCTL: <%s:%d:%d> result <%d:%d>\n", + program_invocation_short_name, fd, shadow_fd, ret, sret); + + return ret; +} /* ioctl */ + +/* ========================================================================= */ +/*..fcntl -- replacement fcntl call. */ +int fcntl(int fd, int cmd, ...) +{ + int shadow_fd; + int sret = 0; + int ret = 0; + + void *arg; + va_list ap; + + va_start(ap, cmd); + arg = va_arg(ap, void *); + va_end(ap); + + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.fcntl) { + __sdp_log(9, "Error fcntl: no implementation for fcntl found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + + __sdp_log(2, "FCNTL: <%s:%d:%d> command <%d> argument <%p>\n", + program_invocation_short_name, fd, shadow_fd, cmd, arg); + + ret = _socket_funcs.fcntl(fd, cmd, arg); + if ((ret >= 0) && (-1 != shadow_fd)) { + sret = _socket_funcs.fcntl(shadow_fd, cmd, arg); + if (sret < 0) { + __sdp_log(9, "Error fcntl:" + " <%d> calling fcntl(%d, %d, %p) for SDP socket. Closing it.\n", + shadow_fd, cmd, arg, errno); + cleanup_shadow(fd); + } + } + + __sdp_log(2, "FCNTL: <%s:%d:%d> result <%d:%d>\n", + program_invocation_short_name, fd, shadow_fd, ret, sret); + + return ret; +} /* fcntl */ + +/* ========================================================================= */ +/*..setsockopt -- replacement setsockopt call. */ +int +setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen) +{ + int shadow_fd; + int sret = 0; + int ret = 0; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.setsockopt) { + __sdp_log(9, "Error setsockopt:" + " no implementation for setsockopt found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + + __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> level <%d> name <%d>\n", + program_invocation_short_name, fd, shadow_fd, level, optname); + + if (level == SOL_SOCKET && optname == SO_KEEPALIVE && get_is_sdp_socket(fd)) { + level = AF_INET_SDP; + __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n", + program_invocation_short_name, fd, shadow_fd, level); + } + + ret = _socket_funcs.setsockopt(fd, level, optname, optval, optlen); + if ((ret >= 0) && (shadow_fd != -1)) { + if (level == SOL_SOCKET && optname == SO_KEEPALIVE && + get_is_sdp_socket(shadow_fd)) { + level = AF_INET_SDP; + __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> substitute level %d\n", + program_invocation_short_name, fd, shadow_fd, level); + } + + sret = _socket_funcs.setsockopt(shadow_fd, level, optname, optval, optlen); + if (sret < 0) { + __sdp_log(8, "Warning sockopts:" + " ignoring error on shadow SDP socket fd:<%d>\n", fd); + /* + * HACK: we should allow some errors as some sock opts are unsupported + * __sdp_log(9, "Error %d calling setsockopt for SDP socket, closing\n", errno); + * cleanup_shadow(fd); + */ + } + } + + /* Due to SDP limited implmentation of sockopts we ignore some errors */ + if ((ret < 0) && get_is_sdp_socket(fd) && + is_filtered_unsuported_sockopt(level, optname)) { + __sdp_log(8, "Warning sockopts: " + "ignoring error on non implemented sockopt on SDP socket" + " fd:<%d> level:<%d> opt:<%d>\n", fd, level, optval); + ret = 0; + } + + __sdp_log(2, "SETSOCKOPT: <%s:%d:%d> result <%d:%d>\n", + program_invocation_short_name, fd, shadow_fd, ret, sret); + + return ret; +} /* setsockopt */ + +/* ========================================================================= */ +/*..socket -- replacement socket call. */ + +static inline int __create_socket_semantic(int domain, + int type, + int protocol, int semantics) +{ + return +#ifdef SOLARIS_BUILD + (semantics == SOCKET_SEMANTIC_XNET) ? + _socket_xnet_funcs.socket(domain, type, protocol) : +#endif + _socket_funcs.socket(domain, type, protocol); +} + +/* Contains the main logic for creating shadow SDP sockets */ +static int __create_socket(int domain, int type, int protocol, int semantics) +{ + int s = -1; + int shadow_fd = -1; + use_family_t family_by_prog; + int sdp_domain; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.socket) { + __sdp_log(9, "Error socket: no implementation for socket found\n"); + return -1; + } + + __sdp_log(2, "SOCKET: <%s> domain <%d> type <%d> protocol <%d>\n", + program_invocation_short_name, domain, type, protocol); + + sdp_domain = get_sdp_domain(domain); + if (sdp_domain < 0) { + errno = EAFNOSUPPORT; + s = -1; + goto done; + } + + /* check to see if we can skip the shadow */ + if ((AF_INET == domain || AF_INET6 == domain) && (SOCK_STREAM == type)) + if (simple_sdp_library) + family_by_prog = USE_SDP; + else + family_by_prog = __sdp_match_by_program(); + else if (AF_INET_SDP == domain || AF_INET6_SDP == domain) + family_by_prog = USE_SDP; + else + family_by_prog = USE_TCP; + + if (family_by_prog == USE_TCP) { + __sdp_log(1, "SOCKET: making TCP only socket (no shadow)\n"); + s = __create_socket_semantic(domain, type, protocol, semantics); + init_extra_attribute(s); + set_is_sdp_socket(s, 0); + goto done; + } + + if (family_by_prog == USE_SDP) { + /* HACK: convert the protocol if IPPROTO_IP */ + if (protocol == 0) + protocol = IPPROTO_TCP; + + __sdp_log(1, "SOCKET: making SDP socket type:%d proto:%d\n", + type, protocol); + s = __create_socket_semantic(sdp_domain, type, protocol, semantics); + init_extra_attribute(s); + set_is_sdp_socket(s, 1); + goto done; + } + + /* HACK: if we fail creating the TCP socket should we abort ? */ + __sdp_log(1, "SOCKET: making TCP socket\n"); + s = __create_socket_semantic(domain, type, protocol, semantics); + init_extra_attribute(s); + set_is_sdp_socket(s, 0); + if (is_valid_fd(s)) { + if (((AF_INET == domain) || (AF_INET6 == domain)) && + (SOCK_STREAM == type)) { + + if (protocol == 0) + protocol = IPPROTO_TCP; + __sdp_log(1, "SOCKET: making SDP shadow socket type:%d proto:%d\n", + type, protocol); + shadow_fd = + __create_socket_semantic(sdp_domain, type, protocol, + semantics); + if (is_valid_fd(shadow_fd)) { + init_extra_attribute(shadow_fd); + if (libsdp_fd_attributes[s].shadow_fd != -1) { + __sdp_log(8, "Warning socket: " + "overriding existing shadow fd:%d for fd:%d\n", + libsdp_fd_attributes[s].shadow_fd, s); + } + set_is_sdp_socket(shadow_fd, 1); + set_shadow_for_fd(s, shadow_fd); + } else { + __sdp_log(9, + "Error socket: <%d> calling socket for SDP socket\n", + errno); + /* fail if we did not make the SDP socket */ + __sdp_log(1, "SOCKET: closing TCP socket:<%d>\n", s); + _socket_funcs.close(s); + s = -1; + } + } + } else { + __sdp_log(9, "Error socket: " + "ignoring SDP socket since TCP fd:%d out of range\n", s); + } + +done: + __sdp_log(2, "SOCKET: <%s:%d:%d>\n", + program_invocation_short_name, s, shadow_fd); + + return s; +} /* socket */ + +int socket(int domain, int type, int protocol) +{ + return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_DEFAULT); +} + +#ifdef SOLARIS_BUILD +int __xnet_socket(int domain, int type, int protocol) +{ + return __create_socket(domain, type, protocol, SOCKET_SEMANTIC_XNET); +} +#endif + +/* ========================================================================= */ +/*..get_fd_addr_port_num - obtain the port the fd is attached to */ +static int get_fd_addr_port_num(int sd) +{ + struct sockaddr_storage addr; + int ret; + const struct sockaddr_in *sin; + socklen_t addrlen = sizeof(addr); + + ret = _socket_funcs.getsockname(sd, (struct sockaddr *) &addr, &addrlen); + + if (ret) { + __sdp_log(9, "Error: in get_fd_addr_port_num - Failed to get getsockname\n"); + return -1; + } + + /* port num is in same location for IPv4 and IPv6 */ + sin = (const struct sockaddr_in *) &addr; + return ntohs(sin->sin_port); +} + +/* ========================================================================= */ +/*..set_addr_port_num - sets the port in the given address */ +static int set_addr_port_num(const struct sockaddr *addr, int port) +{ + struct sockaddr_in *sin = (struct sockaddr_in *) addr; + + /* port num is in same location for IPv4 and IPv6 */ + sin->sin_port = htons(port); + return 0; +} + +/* ========================================================================= */ +/* perform a bind with the given socket semantics */ +static inline int +__bind_semantics(int fd, + const struct sockaddr *my_addr, + socklen_t addrlen, int semantics) +{ + return +#ifdef SOLARIS_BUILD + (semantics == SOCKET_SEMANTIC_XNET) ? + _socket_xnet_funcs.bind(fd, my_addr, addrlen) : +#endif + _socket_funcs.bind(fd, my_addr, addrlen); +} + +/* ========================================================================= */ +/*..find_free_port - find same free port on both TCP and SDP */ +#define MAX_BIND_ANY_PORT_TRIES 20000 +static int +find_free_port(const struct sockaddr *sin_addr, + const socklen_t addrlen, + int orig_sd, + int *sdp_sd, int *tcp_sd, int semantics) +{ + static int tcp_turn = 1; + int tmp_turn = tcp_turn; + int num_of_loops = 0; + int port = -1; + int tmp_sd[2]; + unsigned int yes = 1; + int ret; + int domain, sdp_domain; + + __sdp_log(2, "find_free_port: starting search for common free port\n"); + + /* need to obtain the address family from the fd */ + domain = get_sock_domain(orig_sd); + if (domain == -1) { + errno = EFAULT; + goto done; + } + + sdp_domain = get_sdp_domain(domain); + if (sdp_domain < 0) { + errno = EFAULT; + goto done; + } + + do { + __sdp_log(1, "find_free_port: taking loop (%d)\n", ++num_of_loops); + + __sdp_log(1, "find_free_port: creating the two sockets\n"); + tmp_sd[0] = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP); + if (tmp_sd[0] < 0) { + __sdp_log(8, "Warning find_free_port: creating first socket failed\n"); + goto done; + } + + _socket_funcs.setsockopt(tmp_sd[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + + tmp_sd[1] = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP); + if (tmp_sd[1] < 0) { + __sdp_log(8, "Warning find_free_port: creating second socket failed\n"); + _socket_funcs.close(tmp_sd[0]); + goto done; + } + + _socket_funcs.setsockopt(tmp_sd[1], SOL_SOCKET, SO_REUSEADDR, &yes, + sizeof(yes)); + + __sdp_log(1, "find_free_port: binding first %s socket\n", + tmp_turn ? "tcp" : "sdp"); + ret = __bind_semantics(tmp_sd[tmp_turn], sin_addr, addrlen, semantics); + if (ret < 0) { + __sdp_log(8, + "Warning find_free_port: binding first socket failed:%s\n", + strerror(errno)); + _socket_funcs.close(tmp_sd[0]); + _socket_funcs.close(tmp_sd[1]); + goto done; + } + + __sdp_log(1, "find_free_port: listening on first socket\n"); + ret = _socket_funcs.listen(tmp_sd[tmp_turn], 5); + if (ret < 0) { + __sdp_log(8, "Warning find_free_port: listening on first socket failed:%s\n", + strerror(errno)); + _socket_funcs.close(tmp_sd[0]); + _socket_funcs.close(tmp_sd[1]); + goto done; + } + + port = get_fd_addr_port_num(tmp_sd[tmp_turn]); + if (port < 0) { + __sdp_log(8, "Warning find_free_port: first socket port:%d < 0\n", + port); + _socket_funcs.close(tmp_sd[0]); + _socket_funcs.close(tmp_sd[1]); + goto done; + } + __sdp_log(1, "find_free_port: first socket port:%u\n", port); + + set_addr_port_num(sin_addr, port); + + __sdp_log(1, "find_free_port: binding second socket\n"); + ret = __bind_semantics(tmp_sd[1 - tmp_turn], sin_addr, addrlen, semantics); + if (ret < 0) { + /* bind() for sdp socket failed. It is acceptable only + * if the IP is not part of IB network. */ + + if (errno != EADDRINUSE) { + __sdp_log(8, "Warning find_free_port: " + "binding second socket failed with %s\n", + strerror(errno)); + goto close_and_mark; + } else { + int err; +#ifdef __linux__ + socklen_t len = sizeof(int); + + ret = getsockopt(tmp_sd[1 - tmp_turn], SOL_TCP, + SDP_LAST_BIND_ERR, &err, &len); + if (-1 == ret) { + __sdp_log(9, "Error %s:getsockopt: %s\n", + __func__, strerror(errno)); + goto close_and_mark; + } +#else + err = -errno; +#endif + if (-ENOENT == err || -EADDRINUSE != err) { + /* bind() failed due to either: + * 1. IP is ETH, not IB, so can't bind() to sdp socket. + * 2. real error. + * Continue only with TCP */ + goto close_and_mark; + } + __sdp_log(1, "find_free_port: %s port %u was busy\n", + 1 - tmp_turn ? "tcp" : "sdp", + ntohs(((const struct sockaddr_in *)sin_addr)->sin_port)); + } + + /* close the sockets - we will need new ones ... */ + __sdp_log(1, + "find_free_port: closing the two sockets before next loop\n"); + _socket_funcs.close(tmp_sd[0]); + _socket_funcs.close(tmp_sd[1]); + + port = -1; + /* we always start with tcp so we keep the original setting for now */ + /* tmp_turn = 1 - tmp_turn; */ + } + + } while ((port < 0) && (num_of_loops < MAX_BIND_ANY_PORT_TRIES)); + +setfds: + tcp_turn = tmp_turn; + *sdp_sd = tmp_sd[0]; + *tcp_sd = tmp_sd[1]; + +done: + __sdp_log(2, "find_free_port: return port:<%d>\n", port); + return port; + +close_and_mark: + _socket_funcs.close(tmp_sd[0]); + tmp_sd[0] = -1; /* mark with error */ + goto setfds; + +} + +/* ========================================================================= */ +/*..check_legal_bind - check if given address is okay for both TCP and SDP */ +static int +check_legal_bind(const struct sockaddr *sin_addr, + const socklen_t addrlen, + int orig_sd, + int *sdp_sd, int *tcp_sd, int semantics) +{ + unsigned int yes = 1; + int ret = -1; + int sret = -1; + int domain, sdp_domain; + + /* need to obtain the address family from the fd */ + domain = get_sock_domain(orig_sd); + if (domain == -1) { + errno = EFAULT; + ret = -1; + goto done; + } + + sdp_domain = get_sdp_domain(domain); + if (sdp_domain < 0) { + errno = EFAULT; + goto done; + } + + __sdp_log(2, "check_legal_bind: binding two temporary sockets\n"); + *sdp_sd = _socket_funcs.socket(sdp_domain, SOCK_STREAM, IPPROTO_TCP); + if (*sdp_sd < 0) { + __sdp_log(9, "Error check_legal_bind: " "creating SDP socket failed\n"); + goto done; + } + + __sdp_log(2, "check_legal_bind: reusing <%d> \n", *sdp_sd); + sret = + _socket_funcs.setsockopt(*sdp_sd, SOL_SOCKET, SO_REUSEADDR, &yes, + sizeof(yes)); + if (sret < 0) { + __sdp_log(9, "Error bind: Could not setsockopt sdp_sd\n"); + } + + *tcp_sd = _socket_funcs.socket(domain, SOCK_STREAM, IPPROTO_TCP); + if (*tcp_sd < 0) { + __sdp_log(9, "Error check_legal_bind: " + "creating second socket failed:%s\n", strerror(errno)); + _socket_funcs.close(*sdp_sd); + goto done; + } + + __sdp_log(2, "check_legal_bind: reusing <%d> \n", *tcp_sd); + sret = + _socket_funcs.setsockopt(*tcp_sd, SOL_SOCKET, SO_REUSEADDR, &yes, + sizeof(yes)); + if (sret < 0) { + __sdp_log(9, "Error bind: Could not setsockopt tcp_sd\n"); + } + + __sdp_log(1, "check_legal_bind: binding SDP socket\n"); + ret = __bind_semantics(*sdp_sd, sin_addr, addrlen, semantics); + if (ret < 0) { + /* bind() for sdp socket failed. It is acceptable only if + * the IP is not part of IB network. */ + int err; + socklen_t len = sizeof(int); + + if (EADDRINUSE != errno) + goto done; +#ifdef __linux__ + if (-1 == getsockopt(*sdp_sd, SOL_TCP, SDP_LAST_BIND_ERR, &err, &len)) { + __sdp_log(9, "Error check_legal_bind:getsockopt: %s\n", + strerror(errno)); + goto done; + } +#else + err = -errno; +#endif + if (-ENOENT != err) { + /* bind() failed due to real error. Can't continue */ + __sdp_log(9, "Error check_legal_bind: " + "binding SDP socket failed:%s\n", strerror(errno)); + _socket_funcs.close(*sdp_sd); + _socket_funcs.close(*tcp_sd); + + /* TCP and SDP without library return EINVAL */ + if (errno == EADDRINUSE) + errno = EINVAL; + + goto done; + } + /* IP is ETH, not IB, so can't bind() to sdp socket */ + /* Continue only with TCP */ + _socket_funcs.close(*sdp_sd); + *sdp_sd = -1; + } + + __sdp_log(1, "check_legal_bind: binding TCP socket\n"); + ret = __bind_semantics(*tcp_sd, sin_addr, addrlen, semantics); + if (ret < 0) { + __sdp_log(9, "Error check_legal_bind: " + "binding TCP socket failed:%s\n", strerror(errno)); + if (-1 != *sdp_sd) + _socket_funcs.close(*sdp_sd); + _socket_funcs.close(*tcp_sd); + goto done; + } + ret = 0; + __sdp_log(2, "check_legal_bind: result:<%d>\n", ret); +done: + return ret; +} + +/* ========================================================================= */ +/*..close_and_bind - close an open fd and bind another one immediately */ +static int +close_and_bind(int old_sd, + int new_sd, + const struct sockaddr *addr, socklen_t addrlen, int semantics) +{ + int ret; + + __sdp_log(2, "close_and_bind: closing <%d> binding <%d>\n", old_sd, new_sd); + ret = _socket_funcs.close(old_sd); + if (ret < 0) { + __sdp_log(9, "Error bind: Could not close old_sd\n"); + goto done; + } + + ret = __bind_semantics(new_sd, addr, addrlen, semantics); + if (ret < 0) + __sdp_log(9, "Error bind: Could not bind new_sd\n"); + +done: + __sdp_log(2, "close_and_bind: returning <%d>\n", ret); + return ret; +} + +/* ========================================================================= */ +/*..bind -- replacement bind call. */ +/* + As we do not know the role of this socket yet so we cannot choose AF. + We need to be able to handle shadow too. + SDP sockets (may be shadow or not) must be using converted address + + Since there is no way to "rebind" a socket we have to avoid "false" bind: + 1. When the given address for the bind includes a port we need to + guarantee the port is free on both address families. We do that + by creating temporary sockets and biding them first. Then we close and + re-use the address on the real sockets. + 2. When ANY_PORT is requested we need to make sure the port we obtain from + the first address family is also free on the second one. We use temporary + sockets for that task too. We loop several times to find such common + available socket +*/ +static int +__perform_bind(int fd, + const struct sockaddr *addr, socklen_t addrlen, int semantics) +{ + int shadow_fd; + struct sockaddr_in *sin_addr = (struct sockaddr_in *) addr; + int ret, sret = -1; + char buf[MAX_ADDR_STR_LEN]; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.bind) { + __sdp_log(9, "Error bind: no implementation for bind found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + + if ((addr == NULL) || is_invalid_addr(addr)) { + errno = EFAULT; + __sdp_log(9, "Error bind: illegal address provided\n"); + return -1; + } + + if (get_addr_str(addr, buf, MAX_ADDR_STR_LEN)) { + __sdp_log(9, "Error bind: provided illegal address: %s\n", + strerror(errno)); + return -1; + } + + __sdp_log(2, "BIND: <%s:%d:%d> type <%d> IP <%s> port <%d>\n", + program_invocation_short_name, fd, shadow_fd, + sin_addr->sin_family, buf, ntohs(sin_addr->sin_port)); + + if (get_is_sdp_socket(fd)) { + __sdp_log(1, "BIND: binding SDP socket:<%d>\n", fd); + ret = __bind_semantics(fd, addr, addrlen, semantics); + goto done; + } else if (shadow_fd != -1) { + /* has shadow */ + /* we need to validate the given address or find a common port + * so we use the following tmp address and sockets */ + struct sockaddr_storage tmp_addr; + int sdp_sd = -1, tcp_sd = -1, port; + + memcpy(&tmp_addr, addr, addrlen); + ret = 0; + if (ntohs(sin_addr->sin_port) == 0) { + /* When we get ANY_PORT we need to make sure that both TCP + * and SDP sockets will use the same port */ + + port = find_free_port(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics); + if (port < 0) { + ret = -1; + __sdp_log(9, "BIND: Failed to find common free port\n"); + /* We cannot bind both tcp and sdp on the same port, we will close + * the sdp and continue with tcp only */ + goto done; + } else { + /* copy the port to the tmp address */ + set_addr_port_num((struct sockaddr *) &tmp_addr, port); + } + } else { + /* have a shadow but requested specific port - check that we + * can actually bind the two addresses and then reuse */ + ret = check_legal_bind(addr, addrlen, fd, &sdp_sd, &tcp_sd, semantics); + if (ret < 0) { + __sdp_log(9, "Error bind: " + "Provided address can not bind on the two sockets\n"); + } + } + + /* if we fail to find a common port or given address can not be used + * we return error */ + if (ret < 0) { + /* Temporary sockets already closed by check_legal_bind or + * find_free_port */ + errno = EADDRINUSE; + goto done; + } + + /* close temporary sockets and reuse their address */ + /* HACK: close_and_bind might race with other applications. */ + /* When the race occur we return EADDRINUSE */ + ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) &tmp_addr, + addrlen, semantics); + if (ret < 0) { + __sdp_log(9, "Error bind: " "Could not close_and_bind TCP side\n"); + if (-1 != sdp_sd) + _socket_funcs.close(sdp_sd); + goto done; + } + + if (-1 != sdp_sd) { + ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) &tmp_addr, + addrlen, semantics); + + if (ret < 0) { + __sdp_log(9, + "Error bind: " "Could not close_and_bind sdp side\n"); + goto done; + } + } + goto done; + } + + /* we can only get here on single TCP socket */ + __sdp_log(1, "BIND: binding TCP socket:<%d>\n", fd); + ret = __bind_semantics(fd, addr, addrlen, semantics); + +done: + __sdp_log(2, "BIND: <%s:%d:%d> result <%d:%d>\n", + program_invocation_short_name, fd, shadow_fd, ret, sret); + + return ret; +} /* bind */ + + +int bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen) +{ + return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_DEFAULT); +} + +#ifdef SOLARIS_BUILD +int __xnet_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen) +{ + return __perform_bind(fd, my_addr, addrlen, SOCKET_SEMANTIC_XNET); +} +#endif + + +/* ========================================================================= */ +/*..connect -- replacement connect call. */ +/* + Given the connect address we can take out AF decision + if target AF == both it means SDP and fall back to TCP + if any connect worked we are fine +*/ +static inline int +__connect_semantics(int fd, + const struct sockaddr *serv_addr, + socklen_t addrlen, int semantics) +{ + return +#ifdef SOLARIS_BUILD + (semantics == SOCKET_SEMANTIC_XNET) ? + _socket_xnet_funcs.connect(fd, serv_addr, addrlen) : +#endif + _socket_funcs.connect(fd, serv_addr, addrlen); +} + +static int +__perform_connect(int fd, const struct sockaddr *serv_addr, + socklen_t addrlen, int semantics) +{ + struct sockaddr_in *serv_sin = (struct sockaddr_in *) serv_addr; + char buf[MAX_ADDR_STR_LEN]; + int shadow_fd; + int ret = -1, dup_ret; + use_family_t target_family; + int fopts; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.connect) { + __sdp_log(9, "Error connect: no implementation for connect found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + + if ((serv_addr == NULL) || is_invalid_addr(serv_addr)) { + errno = EFAULT; + __sdp_log(9, "Error connect: illegal address provided\n"); + return -1; + } + + if (get_addr_str(serv_addr, buf, MAX_ADDR_STR_LEN)) { + __sdp_log(9, "Error connect: provided illegal address: %s\n", + strerror(errno)); + return EADDRNOTAVAIL; + } + + __sdp_log(2, "CONNECT: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n", + program_invocation_short_name, fd, shadow_fd, + serv_sin->sin_family, buf, ntohs(serv_sin->sin_port)); + + + /* obtain the target address family */ + target_family = __sdp_match_connect(serv_addr, addrlen); + + /* if we do not have a shadow - just do the work */ + if (shadow_fd == -1) { + __sdp_log(1, "CONNECT: connectingthrough %s\n", + get_is_sdp_socket(fd) ? "SDP" : "TCP"); + ret = __connect_semantics(fd, serv_addr, addrlen, semantics); + if ((ret == 0) || (errno == EINPROGRESS)) { + __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n", + fd, buf, ntohs(serv_sin->sin_port)); + } + goto done; + } + + if ((target_family == USE_SDP) || (target_family == USE_BOTH)) { + /* NOTE: the entire if sequence is negative logic */ + __sdp_log(1, "CONNECT: connecting SDP fd:%d\n", shadow_fd); + + /* make the socket blocking on shadow SDP */ + fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL); + if ((target_family == USE_BOTH) && (fopts & O_NONBLOCK)) { + __sdp_log(1, + "CONNECT: shadow_fd <%d> will be blocking during connect\n", + shadow_fd); + _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts & (~O_NONBLOCK)); + } + + ret = __connect_semantics(shadow_fd, serv_addr, addrlen, semantics); + if ((ret < 0) && (errno != EINPROGRESS)) { + __sdp_log(9, "Error connect: " + "failed for SDP fd:%d with error:%m\n", shadow_fd); + } else { + __sdp_log(7, "CONNECT: connected SDP fd:%d to:%s port %d\n", + fd, buf, ntohs(serv_sin->sin_port)); + } + + /* restore socket options */ + _socket_funcs.fcntl(shadow_fd, F_SETFL, fopts); + + /* if target is SDP or we succeeded we need to dup SDP fd into TCP fd */ + if ((target_family == USE_SDP) || (ret >= 0)) { + dup_ret = replace_fd_with_its_shadow(fd); + if (dup_ret < 0) { + __sdp_log(9, "Error connect: " + "failed to dup2 shadow into orig fd:%d\n", fd); + ret = dup_ret; + } else { + /* we can skip the TCP option if we are done */ + __sdp_log(1, "CONNECT: " + "matched SDP fd:%d so shadow dup into TCP\n", fd); + goto done; + } + } + } + + if ((target_family == USE_TCP) || (target_family == USE_BOTH)) { + __sdp_log(1, "CONNECT: connecting TCP fd:%d\n", fd); + ret = __connect_semantics(fd, serv_addr, addrlen, semantics); + if ((ret < 0) && (errno != EINPROGRESS)) + __sdp_log(9, "Error connect: for TCP fd:%d failed with error:%m\n", + fd); + else + __sdp_log(7, "CONNECT: connected TCP fd:%d to:%s port %d\n", + fd, buf, ntohs(serv_sin->sin_port)); + + if ((target_family == USE_TCP) || (ret >= 0) || (errno == EINPROGRESS)) { + if (cleanup_shadow(fd) < 0) + __sdp_log(9, + "Error connect: failed to cleanup shadow for fd:%d\n", + fd); + } + } + +done: + __sdp_log(2, "CONNECT: <%s:%d:%d> result <%d>\n", + program_invocation_short_name, fd, shadow_fd, ret); + + return ret; +} /* connect */ + +int connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_DEFAULT); +} + +#if defined( SOLARIS_BUILD ) +int __xnet_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + return __perform_connect(fd, serv_addr, addrlen, SOCKET_SEMANTIC_XNET); +} +#endif + +/* ========================================================================= */ +/*..listen -- replacement listen call. */ +/* + Now we know our role (passive/server) and our address so we can get AF. + If both we should try listening on both +*/ + +static inline int __listen_semantics(int fd, int backlog, int semantics) +{ + return +#ifdef SOLARIS_BUILD + (semantics == SOCKET_SEMANTIC_XNET) ? + _socket_xnet_funcs.listen(fd, backlog) : +#endif + _socket_funcs.listen(fd, backlog); +} + +static int __perform_listen(int fd, int backlog, int semantics) +{ + use_family_t target_family; + int shadow_fd; + int ret = 0, sret = 0; + struct sockaddr_storage tmp_sin; + socklen_t tmp_sinlen = sizeof(tmp_sin); + struct sockaddr_in *sin4 = (struct sockaddr_in *) &tmp_sin; + char buf[MAX_ADDR_STR_LEN]; + int actual_port; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.listen) { + __sdp_log(9, "Error listen: no implementation for listen found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + __sdp_log(2, "LISTEN: <%s:%d:%d>\n", + program_invocation_short_name, fd, shadow_fd); + + /* if there is no shadow - simply call listen */ + if (shadow_fd == -1) { + __sdp_log(1, "LISTEN: calling listen on fd:%d\n", fd); + ret = __listen_semantics(fd, backlog, semantics); + goto done; + } + + /* we need to obtain the address from the fd */ + if (_socket_funcs.getsockname(fd, (struct sockaddr *) &tmp_sin, &tmp_sinlen) + < 0) { + __sdp_log(9, "Error listen: getsockname return <%d> for TCP socket\n", + errno); + errno = EADDRNOTAVAIL; + sret = -1; + goto done; + } + + if (get_addr_str((struct sockaddr *) &tmp_sin, buf, MAX_ADDR_STR_LEN)) { + __sdp_log(9, "Error listen: provided illegal address: %s\n", + strerror(errno)); + } + + __sdp_log(2, "LISTEN: <%s:%d:%d> domain <%d> IP <%s> port <%d>\n", + program_invocation_short_name, fd, shadow_fd, + sin4->sin_family, buf, ntohs(sin4->sin_port)); + + target_family = + __sdp_match_listen((struct sockaddr *) &tmp_sin, sizeof(tmp_sin)); + + /* + * in case of an implicit bind and "USE_BOTH" rule we need to first bind the + * two sockets to the same port number + */ + actual_port = ntohs(sin4->sin_port); + + /* do we need to implicit bind both */ + if ((actual_port == 0) && (target_family == USE_BOTH)) { + int sdp_sd = -1, tcp_sd = -1; + + actual_port = find_free_port((struct sockaddr *) &tmp_sin, tmp_sinlen, + fd, &sdp_sd, &tcp_sd, semantics); + if (actual_port < 0) { + ret = -1; + __sdp_log(8, "LISTEN: Failed to find common free port. Only TCP will be used.\n"); + target_family = USE_TCP; + } else { + /* copy the port to the tmp address */ + set_addr_port_num((struct sockaddr *) sin4, actual_port); + + __sdp_log(2, "LISTEN: BOTH on IP <%s> port <%d>\n", + buf, actual_port); + /* perform the bind */ + ret = close_and_bind(tcp_sd, fd, (struct sockaddr *) sin4, + tmp_sinlen, semantics); + if (ret < 0) { + __sdp_log(9, "Error listen: " + "Could not close_and_bind TCP side\n"); + } + + ret = close_and_bind(sdp_sd, shadow_fd, (struct sockaddr *) sin4, + tmp_sinlen, semantics); + if (ret < 0) { + __sdp_log(9, "Error listen: " + "Could not close_and_bind SDP side\n"); + } + } + } + + if ((target_family == USE_TCP) || (target_family == USE_BOTH)) { + __sdp_log(1, "LISTEN: calling listen on TCP fd:%d\n", fd); + ret = __listen_semantics(fd, backlog, semantics); + if (ret < 0) { + __sdp_log(9, "Error listen: failed with code <%d> on TCP fd:<%d>\n", + errno, fd); + } else { + __sdp_log(7, "LISTEN: fd:%d listening on TCP bound to:%s port:%d\n", + fd, buf, actual_port); + } + } + + if ((target_family == USE_SDP) || (target_family == USE_BOTH)) { + __sdp_log(1, "LISTEN: calling listen on SDP fd:<%d>\n", shadow_fd); + sret = __listen_semantics(shadow_fd, backlog, semantics); + if (sret < 0) { + __sdp_log(9, "Error listen: failed with code <%d> SDP fd:<%d>\n", + errno, shadow_fd); + } else { + __sdp_log(7, "LISTEN: fd:%d listening on SDP bound to:%s port:%d\n", + fd, buf, actual_port); + } + } + + /* cleanup the un-needed shadow if TCP and did not fail */ + if ((target_family == USE_TCP) && (ret >= 0)) { + __sdp_log(1, "LISTEN: cleaning up shadow SDP\n"); + if (cleanup_shadow(fd) < 0) + __sdp_log(9, "Error listen: failed to cleanup shadow for fd:%d\n", + fd); + } + + /* cleanup the TCP socket and replace with SDP */ + if ((target_family == USE_SDP) && (sret >= 0)) { + __sdp_log(1, "LISTEN: cleaning TCP socket and dup2 SDP into it\n"); + if (0 > (sret = replace_fd_with_its_shadow(fd))) + __sdp_log(9, "Error listen: " + "failed to dup2 shadow into orig fd:%d\n", fd); + } + +done: + __sdp_log(2, "LISTEN: <%s:%d:%d> result <%d>\n", + program_invocation_short_name, fd, shadow_fd, ret); + /* its a success only if both are ok */ + if (ret < 0) + return (ret); + if (sret < 0) + return (sret); + return 0; +} /* listen */ + +int listen(int fd, int backlog) +{ + return __perform_listen(fd, backlog, SOCKET_SEMANTIC_DEFAULT); +} + +#ifdef SOLARIS_BUILD +int __xnet_listen(int fd, int backlog) +{ + return __perform_listen(fd, backlog, SOCKET_SEMANTIC_XNET); +} +#endif + +/* ========================================================================= */ +/*..close -- replacement close call. */ +int close(int fd) +{ + int shadow_fd; + int ret; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.close) { + __sdp_log(9, "Error close: no implementation for close found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + + __sdp_log(2, "CLOSE: <%s:%d:%d>\n", + program_invocation_short_name, fd, shadow_fd); + + if (shadow_fd != -1) { + __sdp_log(1, "CLOSE: closing shadow fd:<%d>\n", shadow_fd); + if (cleanup_shadow(fd) < 0) + __sdp_log(9, "Error close: failed to cleanup shadow for fd:%d\n", + fd); + } + + init_extra_attribute(fd); + ret = _socket_funcs.close(fd); + __sdp_log(2, "CLOSE: <%s:%d:%d> result <%d>\n", + program_invocation_short_name, fd, shadow_fd, ret); + return ret; +} /* close */ + +/* ========================================================================= */ +/*..dup -- replacement dup call. */ +/* we duplicate the fd and its shadow if exists - ok if the main worked */ +int dup(int fd) +{ + int newfd, new_shadow_fd = -1; + int shadow_fd; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.dup) { + __sdp_log(9, "Error dup: no implementation for dup found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + + __sdp_log(2, "DUP: <%s:%d:%d>\n", + program_invocation_short_name, fd, shadow_fd); + + __sdp_log(1, "DUP: duplication fd:<%d>\n", fd); + newfd = _socket_funcs.dup(fd); + + if (newfd == fd) + return (fd); + + if (!is_valid_fd(newfd)) { + __sdp_log(9, "Error dup: new fd <%d> out of range.\n", newfd); + } else { + /* copy attributes from old fd */ + libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd]; + libsdp_fd_attributes[newfd].shadow_fd = -1; + + if (shadow_fd != -1) { + __sdp_log(1, "DUP: duplication shadow fd:<%d>\n", shadow_fd); + new_shadow_fd = _socket_funcs.dup(shadow_fd); + if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) { + __sdp_log(9, "Error dup: new shadow fd <%d> out of range.\n", + new_shadow_fd); + } else { + libsdp_fd_attributes[new_shadow_fd] = + libsdp_fd_attributes[shadow_fd]; + libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd; + } + } /* shadow exists */ + } + + __sdp_log(2, "DUP: <%s:%d:%d> return <%d:%d>\n", + program_invocation_short_name, fd, shadow_fd, newfd, + new_shadow_fd); + + return newfd; +} /* dup */ + +/* ========================================================================= */ +/*..dup2 -- replacement dup2 call. */ +/* since only the main new fd is given we only move the shadow if exists */ +int dup2(int fd, int newfd) +{ + int shadow_fd; + int shadow_newfd; + int new_shadow_fd = -1; + int ret = 0; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.dup2) { + __sdp_log(9, "Error dup2: no implementation for dup2 found\n"); + return -1; + } + + shadow_fd = get_shadow_fd_by_fd(fd); + shadow_newfd = get_shadow_fd_by_fd(newfd); + + __sdp_log(2, "DUP2: <%s:%d:%d>\n", + program_invocation_short_name, fd, shadow_fd); + + if (newfd == fd) { + __sdp_log(1, "DUP2: skip duplicating fd:<%d> into:<%d>\n", fd, newfd); + goto done; + } + + /* dup2 closes the target file desc if it is a valid fd */ + if (shadow_newfd != -1) { + __sdp_log(1, "DUP2: closing newfd:<%d> shadow:<%d>\n", newfd, + shadow_newfd); + ret = _socket_funcs.close(shadow_newfd); + if (ret != 0) { + __sdp_log(9, + "DUP2: fail to close newfd:<%d> shadow:<%d> with: %d %s\n", + newfd, shadow_newfd, ret, strerror(errno)); + } + } + + __sdp_log(1, "DUP2: duplicating fd:<%d> into:<%d>\n", fd, newfd); + newfd = _socket_funcs.dup2(fd, newfd); + if ((newfd > max_file_descriptors) || (newfd < 0)) { + __sdp_log(9, "Error dup2: new fd <%d> out of range.\n", newfd); + } else { + /* copy attributes from old fd */ + libsdp_fd_attributes[fd].shadow_fd = -1; + libsdp_fd_attributes[newfd] = libsdp_fd_attributes[fd]; + + /* if it had a shadow create a new shadow */ + if (shadow_fd != -1) { + __sdp_log(1, "DUP2: duplication shadow fd:<%d>\n", shadow_fd); + new_shadow_fd = _socket_funcs.dup(shadow_fd); + if ((new_shadow_fd > max_file_descriptors) || (new_shadow_fd < 0)) { + __sdp_log(9, "Error dup2: new shadow fd <%d> out of range.\n", + new_shadow_fd); + } else { + libsdp_fd_attributes[new_shadow_fd] = + libsdp_fd_attributes[shadow_fd]; + libsdp_fd_attributes[newfd].shadow_fd = new_shadow_fd; + } + } /* newfd is ok */ + } + +done: + __sdp_log(2, "DUP2: <%s:%d:%d> return <%d:%d>\n", + program_invocation_short_name, fd, shadow_fd, newfd, + new_shadow_fd); + + return newfd; +} /* dup */ + +/* ========================================================================= */ +/*..getsockname -- replacement getsocknanme call. */ +int getsockname(int fd, struct sockaddr *name, socklen_t * namelen) +{ + int ret = 0; + char buf[MAX_ADDR_STR_LEN]; + + if (init_status == 0) + __sdp_init(); + + /* + * ensure the SDP protocol family is not exposed to the user, since + * this is meant to be a transparency layer. + */ + if (NULL == _socket_funcs.getsockname) { + __sdp_log(9, + "Error getsockname: no implementation for getsockname found\n"); + return -1; + } + + /* double check provided pointers */ + if ((name == NULL) || is_invalid_addr(name)) { + errno = EFAULT; + __sdp_log(9, "Error getsockname: illegal address provided\n"); + return -1; + } + + if ((namelen != NULL) && is_invalid_addr(namelen)) { + errno = EFAULT; + __sdp_log(9, "Error getsockname: illegal address length pointer provided\n"); + return -1; + } + + __sdp_log(2, "GETSOCKNAME <%s:%d>\n", program_invocation_short_name, fd); + + ret = _socket_funcs.getsockname(fd, name, namelen); + + if (__sdp_log_get_level() <= 1) { + if (get_addr_str(name, buf, MAX_ADDR_STR_LEN)) { + __sdp_log(1, "GETSOCKNAME: " "address is illegal\n"); + } else { + __sdp_log(1, "GETSOCKNAME: address is:%s port:%d\n", buf, + ntohs(((struct sockaddr_in *) name)->sin_port)); + } + } + __sdp_log(2, "GETSOCKNAME <%s:%d> result <%d>\n", + program_invocation_short_name, fd, ret); + + return ret; +} /* getsockname */ + +/* ========================================================================= */ +/*..getpeername -- replacement getpeername call. */ +int getpeername(int fd, struct sockaddr *name, socklen_t * namelen) +{ + int ret = 0; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.getpeername) { + __sdp_log(9, "Error getpeername: " + "no implementation for getpeername found\n"); + return -1; + } + + /* double check provided pointers */ + if ((name == NULL) || is_invalid_addr(name)) { + errno = EFAULT; + __sdp_log(9, "Error getsockname: illegal address provided\n"); + return -1; + } + + if ((namelen != NULL) && is_invalid_addr(namelen)) { + errno = EFAULT; + __sdp_log(9, + "Error getsockname: illegal address length pointer provided\n"); + return -1; + } + + __sdp_log(2, "GETPEERNAME <%s:%d>\n", program_invocation_short_name, fd); + + ret = _socket_funcs.getpeername(fd, name, namelen); + + __sdp_log(2, "GETPEERNAME <%s:%d> result <%d:%d> family=%d s_addr=%d\n", + program_invocation_short_name, fd, ret, + (!(0 > ret) ? 0 : -1), name->sa_family, + ((struct sockaddr_in *) name)->sin_addr.s_addr); + + return ret; +} /* getpeername */ + + + +/* ========================================================================= */ +/*..accept -- replacement accept call. */ +/* + If we have a shadow we need to decide which socket we want to accept on + so we select first and then give priority based on previous selection +*/ +int accept(int fd, struct sockaddr *addr, socklen_t * addrlen) +{ + int shadow_fd; + int ret = 0; + fd_set fds; + socklen_t saved_addrlen = 0; + int fopts; + char buf[MAX_ADDR_STR_LEN]; + + if (init_status == 0) + __sdp_init(); + + shadow_fd = get_shadow_fd_by_fd(fd); + + /* + * ensure the SDP protocol family is not exposed to the user, since + * this is meant to be a transparency layer. + */ + if (NULL == _socket_funcs.accept) { + __sdp_log(9, "Error accept: no implementation for accept found\n"); + return -1; + } + + /* double check provided pointers */ + if ((addr != NULL) && is_invalid_addr(addr)) { + errno = EINVAL; + __sdp_log(9, "Error accept: illegal address provided\n"); + return -1; + } + + if ((addrlen != NULL) && is_invalid_addr(addrlen)) { + errno = EINVAL; + __sdp_log(9, "Error accept: illegal address length pointer provided\n"); + return -1; + } + + if (addr && addrlen) + saved_addrlen = *addrlen; + + __sdp_log(2, "ACCEPT: <%s:%d>\n", program_invocation_short_name, fd); + + if (shadow_fd == -1) { + fopts = _socket_funcs.fcntl(fd, F_GETFL); + __sdp_log(1, "ACCEPT: fd <%d> opts are <0x%x>\n", fd, fopts); + + __sdp_log(7, "ACCEPT: accepting on single fd:<%d>\n", fd); + ret = _socket_funcs.accept(fd, addr, addrlen); + if (ret < 0) { + if (!(fopts & O_NONBLOCK && errno == EWOULDBLOCK)) + __sdp_log(9, "Error accept: accept returned :<%d> %s\n", + ret, strerror(errno)); + } else { + set_is_sdp_socket(ret, get_is_sdp_socket(fd)); + } + } else { + + fopts = _socket_funcs.fcntl(shadow_fd, F_GETFL); + __sdp_log(1, "ACCEPT: shadow_fd <%d> opts are <0x%x>\n", + shadow_fd, fopts); + + /* we need different behavior for NONBLOCK or signal IO and BLOCK */ + if ((fopts > 0) && (fopts & (O_NONBLOCK | FASYNC))) { + __sdp_log(1, "ACCEPT: accepting (nonblock) on SDP fd:<%d>\n", shadow_fd); + + ret = _socket_funcs.accept(shadow_fd, addr, addrlen); + if (ret >= 0) { + set_is_sdp_socket(ret, 1); + + __sdp_log(7, "ACCEPT: accepted (nonblock) SDP fd:<%d>\n", + shadow_fd); + } else { + __sdp_log(1, "ACCEPT: accept on SDP fd:<%d> return:%d errno:%d\n", + shadow_fd, ret, errno); + + __sdp_log(1, "ACCEPT: accepting (nonblock) on TCP fd:<%d>\n", fd); + ret = _socket_funcs.accept(fd, addr, addrlen); + if (ret >= 0) { + __sdp_log(7, "ACCEPT: accepted (nonblock) TCP fd:<%d>\n", + shadow_fd); + } else { + __sdp_log(1, "ACCEPT: accept on TCP fd:<%d> " + "return:%d errno:%d\n", fd, ret, errno); + } + } + } else { + __sdp_log(1, "ACCEPT: selecting both fd:<%d> and shadow:<%d>\n", + fd, shadow_fd); + FD_ZERO(&fds); + FD_SET(fd, &fds); + FD_SET(shadow_fd, &fds); + ret = + _socket_funcs.select(1 + ((fd > shadow_fd) ? fd : shadow_fd), + &fds, NULL, NULL, NULL); + if (ret >= 0) { + if (last_accept_was_tcp(fd) == 0) { + if (FD_ISSET(fd, &fds)) { + set_last_accept(fd, 1); + __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd); + ret = _socket_funcs.accept(fd, addr, addrlen); + } else { + __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n", + shadow_fd); + ret = _socket_funcs.accept(shadow_fd, addr, addrlen); + if (ret >= 0) + set_is_sdp_socket(ret, 1); + } + } else { + if (FD_ISSET(shadow_fd, &fds)) { + set_last_accept(fd, 1); + __sdp_log(7, "ACCEPT: accepting on SDP fd:<%d>\n", + shadow_fd); + ret = _socket_funcs.accept(shadow_fd, addr, addrlen); + if (ret >= 0) + set_is_sdp_socket(ret, 1); + } else { + __sdp_log(7, "ACCEPT: accepting on TCP fd:<%d>\n", fd); + ret = _socket_funcs.accept(fd, addr, addrlen); + } + } + } else { + if (errno != EINTR) { + __sdp_log(9, + "Error accept: select returned :<%d> (%d) %s\n", + ret, errno, strerror(errno)); + } else { + __sdp_log(1, "ACCEPT: select returned :<%d> (%d) %s\n", + ret, errno, strerror(errno)); + } + } + } /* blocking mode */ + } /* shadow fd */ + + if ((__sdp_log_get_level() <= 1) && (ret >= 0) && addr && addrlen) { + get_addr_str(addr, buf, *addrlen); + __sdp_log(1, "ACCEPT: accepted from:%s port:%d into fd:%d\n", + buf, ntohs(((struct sockaddr_in *) addr)->sin_port), ret); + } + __sdp_log(2, "ACCEPT: <%s:%d> return <%d>\n", + program_invocation_short_name, fd, ret); + + return ret; +} /* accept */ + +/* ========================================================================= */ +/*..select -- replacement socket call. */ +/* + if we have shadow we must select on it too - which requires a hack back + and forth +*/ +int +select(int n, + fd_set * readfds, + fd_set * writefds, fd_set * exceptfds, struct timeval *timeout) +{ + int shadow_fd; + int ret; + int current; + int maxi = 0; + fd_set new_fds; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.select) { + __sdp_log(9, "Error select: no implementation for select found\n"); + return -1; + } + + __sdp_log(2, "SELECT: <%s:%d>\n", program_invocation_short_name, n); + + /* if we do not read - nothing to do */ + if (readfds == NULL) { + ret = _socket_funcs.select(n, readfds, writefds, exceptfds, timeout); + goto done; + } + + FD_ZERO(&new_fds); + if (n > 0) { + maxi = n - 1; + } + + /* add shadow bits */ + for (current = 0; current < n; current++) { + if (FD_ISSET(current, readfds)) { + FD_SET(current, &new_fds); + if (current > maxi) { + maxi = current; + } + shadow_fd = get_shadow_fd_by_fd(current); + if (shadow_fd != -1) { + __sdp_log(1, + "SELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n", + current, shadow_fd); + FD_SET(shadow_fd, &new_fds); + if (shadow_fd > maxi) { + maxi = shadow_fd; + } + } + } + } + + __sdp_log(1, "SELECT: invoking select n=<%d>\n", 1 + maxi); + ret = _socket_funcs.select(1 + maxi, + &new_fds, writefds, exceptfds, timeout); + + /* remove the count and bits of the shadows */ + if (ret >= 0) { + for (current = 0; current < n; current++) { + shadow_fd = get_shadow_fd_by_fd(current); + if (shadow_fd == -1) { + if (FD_ISSET(current, readfds) && + FD_ISSET(current, &new_fds) == 0) { + FD_CLR(current, readfds); + } + } else { + if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds) + && FD_ISSET(shadow_fd, &new_fds)) { + ret -= 1; + } + if (FD_ISSET(current, readfds) && + FD_ISSET(current, &new_fds) == 0 && + FD_ISSET(shadow_fd, &new_fds) == 0) { + FD_CLR(current, readfds); + } + } + } + } + +done: + + __sdp_log(2, "SELECT: <%s:%d> return <%d>\n", + program_invocation_short_name, n, ret); + return ret; +} /* select */ + +/* ========================================================================= */ +/*..pselect -- replacement socket call. */ +/* + if we have shadow we must pselect on it too - which requires a hack back + and forth +*/ +int +pselect(int n, + fd_set * readfds, + fd_set * writefds, + fd_set * exceptfds, + const struct timespec *timeout, const sigset_t * sigmask) +{ + int shadow_fd; + int ret; + int current; + int maxi = 0; + fd_set new_fds; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.pselect) { + __sdp_log(9, "Error pselect: no implementation for pselect found\n"); + return -1; + } + + __sdp_log(2, "PSELECT: <%s:%d>\n", program_invocation_short_name, n); + + /* if we do not read - nothing to do */ + if (readfds == NULL) { + ret = + _socket_funcs.pselect(n, readfds, writefds, exceptfds, timeout, + sigmask); + goto done; + } + + FD_ZERO(&new_fds); + if (n > 0) { + maxi = n - 1; + } + + /* add shadow bits */ + for (current = 0; current < n; current++) { + if (FD_ISSET(current, readfds)) { + FD_SET(current, &new_fds); + if (current > maxi) { + maxi = current; + } + shadow_fd = get_shadow_fd_by_fd(current); + if (shadow_fd != -1) { + __sdp_log(1, + "PSELECT: adding fd:<%d> shadow_fd:<%d> to readfs\n", + current, shadow_fd); + FD_SET(shadow_fd, &new_fds); + if (shadow_fd > maxi) { + maxi = shadow_fd; + } + } + } + } + + __sdp_log(1, "PSELECT: invoking pselect n=<%d>\n", 1 + maxi); + ret = _socket_funcs.pselect(1 + maxi, + &new_fds, writefds, exceptfds, + timeout, sigmask); + + /* remove the count and bits of the shadows */ + if (ret >= 0) { + for (current = 0; current < n; current++) { + shadow_fd = get_shadow_fd_by_fd(current); + if (shadow_fd == -1) { + if (FD_ISSET(current, readfds) && + FD_ISSET(current, &new_fds) == 0) { + FD_CLR(current, readfds); + } + } else { + if (FD_ISSET(current, readfds) && FD_ISSET(current, &new_fds) + && FD_ISSET(shadow_fd, &new_fds)) { + ret -= 1; + } + if (FD_ISSET(current, readfds) && + FD_ISSET(current, &new_fds) == 0 && + FD_ISSET(shadow_fd, &new_fds) == 0) { + FD_CLR(current, readfds); + } + } + } + } + +done: + + __sdp_log(2, "PSELECT: <%s:%d> return <%d>\n", + program_invocation_short_name, n, ret); + return ret; +} /* pselect */ + +/* ========================================================================= */ +/*..poll -- replacement socket call. */ +/* + if we have shadow we must poll on it too - which requires a hack back + and forth +*/ +int poll(struct pollfd *ufds, nfds_t nfds, int timeout) +{ + int ret; + int shadow_fd; + int current; + int extra = 0; + struct pollfd *poll_fds = NULL; + struct pollfd *poll_fd_ptr = NULL; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.poll) { + __sdp_log(9, "Error poll: no implementation for poll found\n"); + return -1; + } + + __sdp_log(2, "POLL: <%s:%d>\n", program_invocation_short_name, nfds); + + /* if we do not have any file desc - nothing to do */ + if (ufds == NULL) { + ret = _socket_funcs.poll(ufds, nfds, timeout); + goto done; + } + + /* scan for how many extra fds are required */ + for (current = 0; current < nfds; current++) { + shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); + if (shadow_fd != -1) + extra++; + } + + if (!extra) { + poll_fds = ufds; + } else { + poll_fds = + (struct pollfd *) malloc((nfds + extra) * sizeof(struct pollfd)); + if (!poll_fds) { + __sdp_log(9, + "Error poll: malloc of extended pollfd array failed\n"); + ret = -1; + errno = ENOMEM; + goto done; + } + poll_fd_ptr = poll_fds; + for (current = 0; current < nfds; current++) { + *poll_fd_ptr = ufds[current]; + poll_fd_ptr++; + shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); + if (shadow_fd != -1) { + __sdp_log(1, "POLL: adding fd:<%d> shadow_fd:<%d> to readfs\n", + current, shadow_fd); + *poll_fd_ptr = ufds[current]; + poll_fd_ptr->fd = shadow_fd; + poll_fd_ptr++; + } + } + } + + __sdp_log(1, "POLL: invoking poll nfds=<%d>\n", nfds + extra); + ret = _socket_funcs.poll(poll_fds, nfds + extra, timeout); + + /* refactor into original list if any events */ + if ((ret > 0) && extra) { + poll_fd_ptr = poll_fds; + for (current = 0; current < nfds; current++) { + shadow_fd = get_shadow_fd_by_fd(ufds[current].fd); + if (shadow_fd == -1) { + ufds[current] = *poll_fd_ptr; + } else { + ufds[current] = *poll_fd_ptr; + poll_fd_ptr++; + if (poll_fd_ptr->revents) { + if (ufds[current].revents) + ret--; + ufds[current].revents |= poll_fd_ptr->revents; + } + } + poll_fd_ptr++; + } + } + + if (extra) + free(poll_fds); +done: + + __sdp_log(2, "POLL: <%s:%d> return <%d>\n", + program_invocation_short_name, nfds, ret); + return ret; +} /* poll */ + +#ifdef __linux__ +/* ========================================================================= */ +/*..epoll_create -- replacement socket call. */ +/* + Need to make the size twice as large for shadow fds +*/ +int epoll_create(int size) +{ + int epfd; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.epoll_create) { + __sdp_log(9, + "Error epoll_create: no implementation for epoll_create found\n"); + return -1; + } + + __sdp_log(2, "EPOLL_CREATE: <%s:%d>\n", program_invocation_short_name, + size); + + epfd = _socket_funcs.epoll_create(size * 2); + + __sdp_log(2, "EPOLL_CREATE: <%s:%d> return %d\n", + program_invocation_short_name, size, epfd); + return epfd; +} /* epoll_create */ + +/* ========================================================================= */ +/*..epoll_ctl -- replacement socket call. */ +/* + Need to add/delete/modify shadow fds as well +*/ +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) +{ + int ret, shadow_fd, ret2; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.epoll_ctl) { + __sdp_log(9, + "Error epoll_ctl: no implementation for epoll_ctl found\n"); + return -1; + } + + __sdp_log(2, "EPOLL_CTL: <%s:%d> op <%d:%d>\n", + program_invocation_short_name, epfd, op, fd); + + ret = _socket_funcs.epoll_ctl(epfd, op, fd, event); + + shadow_fd = get_shadow_fd_by_fd(fd); + if (shadow_fd != -1) { + ret2 = _socket_funcs.epoll_ctl(epfd, op, shadow_fd, event); + if (ret2 < 0) { + __sdp_log(9, "Error epoll_ctl <%s:%d:%d>", + program_invocation_short_name, fd, shadow_fd); + return ret2; + } + } + + __sdp_log(2, "EPOLL_CTL: <%s:%d> return <%d>\n", + program_invocation_short_name, epfd, ret); + return ret; +} /* epoll_ctl */ + +/* ========================================================================= */ +/*..epoll_wait -- replacement socket call. */ +/* + We don't care who generated the event because all we get is user-context + values. +*/ +int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + int ret; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.epoll_wait) { + __sdp_log(9, + "Error epoll_wait: no implementation for epoll_wait found\n"); + return -1; + } + + __sdp_log(2, "EPOLL_WAIT: <%s:%d>\n", program_invocation_short_name, epfd); + + ret = _socket_funcs.epoll_wait(epfd, events, maxevents, timeout); + + __sdp_log(2, "EPOLL_WAIT: <%s:%d> return <%d>\n", + program_invocation_short_name, epfd, ret); + return ret; +} /* epoll_wait */ + +/* ========================================================================= */ +/*..epoll_pwait -- replacement socket call. */ +/* + We don't care who generated the event because all we get is user-context + values. +*/ +int +epoll_pwait(int epfd, + struct epoll_event *events, + int maxevents, int timeout, const sigset_t * sigmask) +{ + int ret; + + if (init_status == 0) + __sdp_init(); + + if (NULL == _socket_funcs.epoll_pwait) { + __sdp_log(9, + "Error epoll_pwait: no implementation for epoll_pwait found\n"); + return -1; + } + + __sdp_log(2, "EPOLL_PWAIT: <%s:%d>\n", program_invocation_short_name, epfd); + + ret = _socket_funcs.epoll_pwait(epfd, events, maxevents, timeout, sigmask); + + __sdp_log(2, "EPOLL_PWAIT: <%s:%d> return <%d>\n", + program_invocation_short_name, epfd, ret); + return ret; +} /* epoll_pwait */ +#endif + +/* ========================================================================= */ + +/* --------------------------------------------------------------------- */ +/* */ +/* Library load/unload initialization/cleanup */ +/* */ +/* --------------------------------------------------------------------- */ +/* ========================================================================= */ +/*..__sdp_init -- intialize the library */ +void __sdp_init(void) +{ + char *config_file, *error_str; + int fd; + struct rlimit nofiles_limit; + + /* HACK: races might apply here: can we assume init is happening + only within one thread ? */ + if (init_status != 0) + return; + init_status = 1; + + dev_null_fd = open("/dev/null", O_WRONLY); + + /* figure out the max number of file descriptors */ + if (getrlimit(RLIMIT_NOFILE, &nofiles_limit)) + max_file_descriptors = 1024; + else + max_file_descriptors = nofiles_limit.rlim_cur; + + /* allocate and initialize the shadow sdp sockets array */ + libsdp_fd_attributes = + (struct sdp_extra_fd_attributes *) calloc(max_file_descriptors, + sizeof(struct + sdp_extra_fd_attributes)); + for (fd = 0; fd < max_file_descriptors; fd++) + init_extra_attribute(fd); + +#ifndef RTLD_NEXT + /* + * open libc for original socket call. + * Solaris relies on RTLD next - since the socket calls are + * actually in libsocket rather than libc. + */ + __libc_dl_handle = dlopen("/lib64/libc.so.6", RTLD_LAZY); + if (NULL == __libc_dl_handle) { + __libc_dl_handle = dlopen("/lib/libc.so.6", RTLD_LAZY); + if (NULL == __libc_dl_handle) { + fprintf(stderr, "%s\n", dlerror()); + return; + } + } +#endif + + /* + * Get the original functions + */ + _socket_funcs.ioctl = dlsym(__libc_dl_handle, "ioctl"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.fcntl = dlsym(__libc_dl_handle, "fcntl"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.socket = dlsym(__libc_dl_handle, "socket"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.setsockopt = dlsym(__libc_dl_handle, "setsockopt"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.connect = dlsym(__libc_dl_handle, "connect"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.listen = dlsym(__libc_dl_handle, "listen"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.bind = dlsym(__libc_dl_handle, "bind"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.close = dlsym(__libc_dl_handle, "close"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.dup = dlsym(__libc_dl_handle, "dup"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.dup2 = dlsym(__libc_dl_handle, "dup2"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.getpeername = dlsym(__libc_dl_handle, "getpeername"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.getsockname = dlsym(__libc_dl_handle, "getsockname"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.accept = dlsym(__libc_dl_handle, "accept"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.select = dlsym(__libc_dl_handle, "select"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.pselect = dlsym(__libc_dl_handle, "pselect"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.poll = dlsym(__libc_dl_handle, "poll"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + +#ifdef __linux__ + _socket_funcs.epoll_create = dlsym(__libc_dl_handle, "epoll_create"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.epoll_ctl = dlsym(__libc_dl_handle, "epoll_ctl"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.epoll_wait = dlsym(__libc_dl_handle, "epoll_wait"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_funcs.epoll_pwait = dlsym(__libc_dl_handle, "epoll_pwait"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } +#endif +#ifdef SOLARIS_BUILD + _socket_xnet_funcs.socket = dlsym(__libc_dl_handle, "__xnet_socket"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_xnet_funcs.connect = dlsym(__libc_dl_handle, "__xnet_connect"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_xnet_funcs.listen = dlsym(__libc_dl_handle, "__xnet_listen"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + _socket_xnet_funcs.bind = dlsym(__libc_dl_handle, "__xnet_bind"); + if (NULL != (error_str = dlerror())) { + fprintf(stderr, "%s\n", error_str); + } + + /* Determine program name by asking libdl */ + Dl_argsinfo args_info; + if (NULL != dlinfo(RTLD_SELF, RTLD_DI_ARGSINFO, &args_info)) { + fprintf(stderr, "args_info: %s\n", dlerror()); + } else { + program_invocation_name = args_info.dla_argv[0]; + program_invocation_short_name = basename(args_info.dla_argv[0]); + } +#endif + + if (getenv("SIMPLE_LIBSDP") != NULL) { + simple_sdp_library = 1; + } + + if (getenv("ALWAYS_USE_SDP") != NULL) { + simple_sdp_library = 1; + } +#define LIBSDP_DEFAULT_CONFIG_FILE SYSCONFDIR "/libsdp.conf" + if (!simple_sdp_library) { + config_file = getenv("LIBSDP_CONFIG_FILE"); + if (!config_file) + config_file = LIBSDP_DEFAULT_CONFIG_FILE; + + if (__sdp_parse_config(config_file)) { + fprintf(stderr, + "libsdp Error: failed to parse config file:%s. Using defaults.\n", + config_file); + } + } + + __sdp_log(1, "Max file descriptors:%d\n", max_file_descriptors); + init_status = 2; + +} /* __sdp_init */ + +/* ========================================================================= */ +/*..__sdp_fini -- when the library is unloaded this is called */ +void __sdp_fini(void) +{ + struct use_family_rule *rule; + for (rule = __sdp_clients_family_rules_head; rule != NULL; + rule = rule->next) + free(rule->prog_name_expr); + for (rule = __sdp_servers_family_rules_head; rule != NULL; + rule = rule->next) + free(rule->prog_name_expr); + + free(libsdp_fd_attributes); + +#ifndef RTLD_NEXT + dlclose(__libc_dl_handle); +#endif +} /* _fini */ diff --git a/contrib/ofed/libsdp/src/socket.c b/contrib/ofed/libsdp/src/socket.c new file mode 100644 index 0000000..d40265b --- /dev/null +++ b/contrib/ofed/libsdp/src/socket.c @@ -0,0 +1,167 @@ +/* + This software is available to you under a choice of one of two + licenses. You may choose to be licensed under the terms of the GNU + General Public License (GPL) Version 2, available at + <http://www.fsf.org/copyleft/gpl.html>, or the OpenIB.org BSD + license, available in the LICENSE.TXT file accompanying this + software. These details are also available at + <http://openib.org/license.html>. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Copyright (c) 2004 Topspin Communications. All rights reserved. + Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. + + $Id$ +*/ + +/* + * system includes + */ +#if HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +/* + For non-i386 systems, we pass socket() through to library code using + dlsym() instead of trying to make the system call directly. This + may cause problems if this library is LD_PRELOADed before the real C + library is available. Eventually we may want to add the same type + of system call assembly code as i386 has for IA64 and AMD64, but for + now.... +*/ +#ifndef i386 +#define _GNU_SOURCE /* Get RTLD_NEXT */ +#include <dlfcn.h> +#else +#include <sys/syscall.h> +#endif + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <string.h> +/* + * SDP specific includes + */ +#include "linux/sdp_inet.h" + +#if 0 +#define _SDP_VERBOSE_PRELOAD +#endif + +#define SOCKOP_socket 1 +#define SOCKOP_bind 2 +#define SOCKOP_connect 3 +#define SOCKOP_listen 4 +#define SOCKOP_accept 5 +#define SOCKOP_getsockname 6 +#define SOCKOP_getpeername 7 +#define SOCKOP_socketpair 8 +#define SOCKOP_send 9 +#define SOCKOP_recv 10 +#define SOCKOP_sendto 11 +#define SOCKOP_recvfrom 12 +#define SOCKOP_shutdown 13 +#define SOCKOP_setsockopt 14 +#define SOCKOP_getsockopt 15 +#define SOCKOP_sendmsg 16 +#define SOCKOP_recvmsg 17 + +extern char * program_invocation_name; +extern char * program_invocation_short_name; +extern char ** const environ; + +/* ========================================================================= */ +/*..socket -- replacment socket call. */ +int socket +( + int domain, + int type, + int protocol +) +{ +#ifdef i386 + long __ret; + void *__scratch; + int call[3]; +#endif + char *test; + char *inet; + char **tenviron; + +#ifdef _SDP_VERBOSE_PRELOAD + FILE *fd; +#endif + /* + * check for magic enviroment variable + */ + if ((AF_INET == domain || AF_INET6 == domain) && + SOCK_STREAM == type) { + + if (environ) { + tenviron = environ; + for (test = *tenviron; NULL != test; test = *++tenviron) { + + inet = AF_INET_STR; + + while (*inet == *test && '\0' != *inet) { + + inet++; + test++; + } /* while */ + + if ('\0' == *inet && '=' == *test) { + + domain = AF_INET_SDP; + break; + } /* if */ + } /* for */ + } /* if */ + } /* if */ + +#ifdef _SDP_VERBOSE_PRELOAD + fd = fopen("/tmp/libsdp.log.txt", "a+"); + + fprintf(fd, "SOCKET: <%s> domain <%d> type <%d> protocol <%d>\n", + program_invocation_short_name, domain, type, protocol); + + fclose(fd); +#endif + +#ifdef i386 + /* Make the socket() system call directly, as described above */ + call[0] = domain; + call[1] = type; + call[2] = protocol; + + __asm__ __volatile__("movl %%ebx, %1\n" /* save %ebx */ + "movl %3, %%ebx\n" /* put sockopt in %ebx as arg */ + "int $0x80\n" /* do syscall */ + "movl %1, %%ebx\n" /* restore %ebx */ + : "=a" (__ret), "=r" (__scratch) + : "0" (__NR_socketcall), + "g" (SOCKOP_socket), + "c" (call)); + return __ret; +#else /* i386 */ + /* Use the standard library socket() to pass through the call */ + { + static int (*orig_socket)(int, int, int); + + if (!orig_socket) { + orig_socket = dlsym(RTLD_NEXT, "socket"); + } + + return orig_socket(domain, type, protocol); + } +#endif /* i386 */ +} /* socket */ |