ruli-0.33/0000755000177100017710000000000010254521423013152 5ustar labratlabrat00000000000000ruli-0.33/Makefile0000644000177100017710000000106510066460140014613 0ustar labratlabrat00000000000000# # $Id: Makefile,v 1.9 2004/06/24 05:02:24 evertonm Exp $ # # This is a Debian-friendly top-level Makefile. # .PHONY: default default: $(MAKE) -C src $(MAKE) -C sample .PHONY: clean clean: $(MAKE) -C src clean $(MAKE) -C sample clean .PHONY: install install: $(MAKE) -C src install $(MAKE) -C sample install .PHONY: dpkg dpkg: dpkg-buildpackage -rfakeroot .PHONY: dpkg-clean dpkg-clean: fakeroot debian/rules clean .PHONY: release-clean release-clean: rm -rf debian install doc/rfc ruli-mta test tube \ `find . -name CVS -o -name "*~"` ruli-0.33/COPYING0000644000177100017710000004312707571434661014233 0ustar labratlabrat00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ruli-0.33/README0000644000177100017710000001056310063355276014050 0ustar labratlabrat00000000000000# # $Id: README,v 1.18 2004/06/14 17:05:02 evertonm Exp $ # LICENSE RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. LINKING RULI AGAINST SOFTWARE DISTRIBUTED UNDER PHP LICENSE Additional to those permissions granted by the GNU Public License, permission is given to distribute copies of this work linked to software licenced under the terms of the PHP licence, Version 3.0 INTRODUCTION RULI stands for Resolver User Layer Interface. It's a library built on top of an asynchronous DNS stub resolver. RULI provides an easy-to-use interface for querying DNS SRV resource records. The goal is to promote the wide deployment of SRV-cognizant client programs. RULI aims to fully support SRV-related standards. HOMEPAGE http://www.nongnu.org/ruli/ SUPPORT SITE http://savannah.nongnu.org/projects/ruli/ PLATFORMS RULI main development is performed under Debian GNU/Linux. Efforts are made to keep the library portable to major POSIX systems, such as Solaris and FreeBSD. If you need assistance to port RULI to your system, please feel free to contact me. REQUIREMENTS RULI depends on Liboop (0.9 or higher), available at: http://liboop.org/ BUILD AND INSTALL 1. Install Liboop on your system 2. Compile and install RULI library cd ruli/src # Point OOP_BASE_DIR to the location of # Liboop on your system, then run 'make build' make OOP_BASE_DIR=/usr/local/oop build # Optionally, strip the objects make strip # Point INSTALL_BASE_DIR to location where you want # to install RULI library, then run 'make install' make INSTALL_BASE_DIR=/usr/local/ruli install 3. Tell the dynamic loader about RULI # Add INSTALL_BASE_DIR/lib path to # /etc/ld.so.conf ldconfig 4. Compile and install RULI sample programs (optional) cd ruli/sample # Point OOP_BASE_DIR to the location of # Liboop on your system, then run 'make build' make OOP_BASE_DIR=/usr/local/oop build # Optionally, strip the objects make strip # Point INSTALL_BASE_DIR to location where you want # to install RULI sample programs, then run 'make install' make INSTALL_BASE_DIR=/usr/local/ruli install 5. Compile and install RULI testing tools (optional) cd ruli/tools # Point OOP_BASE_DIR to the location of # Liboop on your system, then run 'make build' make OOP_BASE_DIR=/usr/local/oop build # Optionally, strip the objects make strip # Point INSTALL_BASE_DIR to location where you want # to install RULI testing tools, then run 'make install' make INSTALL_BASE_DIR=/usr/local/ruli install SAMPLE PROGRAMS Use the programs in 'sample' directory to test RULI. They are also good introductory examples of how to use RULI APIs. The sync_srvsearch program uses the synchronous API. This is an example session: $ echo _smtp._tcp.domain.tld | ./sync_srvsearch _smtp._tcp.domain.tld target=phantom.domain.tld. priority=5 weight=0 port=25 addresses=IPv4/1.2.3.4 _smtp._tcp.domain.tld target=sitemail.host.tld. priority=10 weight=0 port=25 addresses=IPv4/4.3.2.1 The srvsearch program uses the asynchronous API. This is an example session: $ echo _smtp._tcp.domain.tld | ./srvsearch _smtp._tcp.domain.tld target=phantom.domain.tld. priority=5 weight=0 port=25 addresses=IPv4/1.2.3.4 _smtp._tcp.domain.tld target=sitemail.host.tld. priority=10 weight=0 port=25 addresses=IPv4/4.3.2.1 The ruli-getaddrinfo uses the the getaddrinfo() interface to lookup SRV records, based on ruliwrap from http://weinholt.se/hacks/. This is an usage example: $ echo _telnet._tcp.bogus.tld | ./ruli-getaddrinfo _telnet._tcp.bogus.tld canon=mud.bogus.tld. port=6789 IPv4/5.6.7.8 FREE SOFTWARE RULI is Free Software (TM). For more nice Free Software, visit: http://nucleo.freeservers.com/ceosp/ -x- ruli-0.33/TODO0000644000177100017710000002354210254425551013655 0ustar labratlabrat00000000000000# # $Id: TODO,v 1.131 2005/06/17 01:46:17 evertonm Exp $ # Legend: - = todo / = in progress + = done ...................................................................... Wishlist: - Would handling of exceptional events on sockets add any benefit? - Actually fix the FIXMEs in the code. - Non-standard HTTP with SRV/_http._tcp.domain, A/domain? - Use garbage collection for memory management? As build-time option? Keep the application in charge of it? Anyone? - Launch auxiliary queries to follow CNAME chains? I believe we don't need to use extra queries for CNAME chains, because the recursive name server is supposed to fetch the whole chain for us. Not sure, though. - Use round-trip times to better distribute load among recursive name servers? - Add an reverse-lookup layer to the raw resolver in order to fetch IN PTR records across CNAME chains? - Add a CNAME-aware layer to the raw resolver in order to fetch arbitrary record types across CNAME chains? - ruli_txt: Recognize rfc1035-quoting (section 5.1) slash"\.".org slash"\046".org This will require a variable max-length for txt dst decoding buffer. Relatively hard at first. - Use EDNS0 to support larger UDP segments. - Special behavior (smtp, http, ...) under ruli_getaddrinfo(). - check packaging against Debian Library Packaging Guide: http://www.netfort.gr.jp/~dancer/column/libpkg-guide/ -x- Changes: ...................................................................... 0.35 - New: Autoconf/automake/libtool support. - Rgr: Regression test cases for special SRV behavior. (SMTP, HTTP, ...) - Rgr: Basic regression test cases for synchronous API. ...................................................................... 0.34 - New: Add optional logging for RULI major events and/or errors. - New: Permit the user to limit the number of concurrent queries thus preventing accidental overload of the library. - New: ruli_sync: Periodically (or on usage threshold) reload config: /etc/resolv.conf. - New: ruli_res: Periodically (or on usage threshold) refresh config: nameserver list & search list. ...................................................................... 0.33 + Fix: ruli_getaddrinfo: Mikael Magnusson patch to respect address family specified in hints. + Fix: Support for RFC3484 - destination address selection. + New: SONAME increased to reflect ABI change. ...................................................................... 0.32 + Fix: Sort MX records by priority. + Fix: Sort addresses by family, delivering IPv6 first, if any. + Fix: ruli_http: Support for specific srv-based queries for http. + New: Binding for Lua language. ...................................................................... 0.31 + Cln: Minor clean-ups. + New: Perl module 0.02: namespace "Net::RULI". + New: Java native interface. ...................................................................... 0.30 + Fix: Compilation fix for gcc 3.4. + Fix: Better error code reporting for Guile extension. + Fix: Solaris port. ...................................................................... 0.29 + New: Guile extension. ...................................................................... 0.28 + Cln: Use ruli_host for all address lookups. + walk: + Use ruli_host for address lookups. + Major clean-up. + fall: + Use ruli_host for address lookups. + Major clean-up. + Fix: Increase SONAME due to ABI changes (changed struct's members). API remains though. ...................................................................... 0.27 + Fix: Removed INSTALL_DIR from compiler/linker search path. + New: Resolver options. + uri_port + nowalk + nofall + New: ruli_host: CNAME-aware, family-agnostic, address lookup layer. ...................................................................... 0.26 + Fix: ruli_smtp: Perform extra "walk" queries for MX exchange which has no corresponding address record in the additional section? Shouldn't MX additional processing handle this for us in the recursive resolver? It seems MX TTL > MX target TTL partially defeats "MX additional processing", unfortunately. Thus we actually need to to work-around this issue by issuing queries for address records. + New: Symbol versioning in shared library. + Fix: Solaris port. + Fix: ruli_addr: Better IPv6 print helper. + Cln: Prefix internal non-static functions with '_'. ...................................................................... 0.25 + Fix: ruli_srv: Perform 2 separate queries for addresses (IN_AAAA, IN_A), instead of a single IN_ANY query. + walk_query + fall_query + Fix: Debian compiler warning for m68k, powerpc, hppa. ...................................................................... 0.24 + New: IPv6 support: AAAA resource records. + Fix: Better portability for ruli_getaddrinfo(). ...................................................................... 0.23 + Fix: Add IPv6 support for 'tools'. + Fix: Perl binding updated to new address-family-aware API. + Fix: PHP binding updated to new address-family-aware API. + Fix: Incorrect pointer arithmetic in ruli_getaddrinfo(). ...................................................................... 0.22 + New: IPv6 support: PF_INET6 protocol family as transport. + New: Change fsm to use IPv6 UDP sockets. TCP is for free. + New: load IPv6 nameserver addresses. + New: API changed to support IPv6. + New: ruli_inet6_ntoa(): detect valid IPv6 address. + New: Added ruliwrap wrapper (from http://weinholt.se/hacks/) as ruli_getaddrinfo(). ...................................................................... 0.21 + Fix: 'class' replaced by 'qclass' to avoid clash with c++ keyword. + Cln: Better support for Debian packaging. + Cln: Better portability. ...................................................................... 0.20 + New: Example programs for the Perl module. + New: Minimal man pages for sample programs. + New: Debian binary package 'libruli-bin' for sample programs. ...................................................................... 0.19 + New: Binding for Perl. ...................................................................... 0.18 + Cln: More friendly to Debian packaging. + New: Added bogus manpage for Debian. + New: Added 'debian' directory for package debianization. + Fix: Retrieve MX Exchange (in place of MX Owner) as SRV target. + New: Binding for PHP4. ...................................................................... 0.17 + Cln: Compatibility with newer gcc. + Fix: Better handling of remotely closed connection. + New: Better internal array structure. ...................................................................... 0.16 + Fix: Default config unloader was being improperly called. + New: Return priority/weight values in high-level interfaces. + New: Non-standard SMTP with SRV/_smtp._tcp.domain, MX/domain, A/domain. ...................................................................... 0.15 + Fix: Server round-robin scanning is reset for every suffix of the search list. + Cln: More ISAAC name space clean-ups. + New: ruli_search: Simpler, higher-level API for SRV queries. Previous RULI's standard SRV API (ruli_srv) seemed too complex for simple queries with trivial behavior. + Fix: Sample tools have been using incorrect buffer sizes for domain names in textual form. This limited the maximum domain name length to 252 characters instead of 253. + New: Sample programs under 'sample' directory show how to write SRV-aware applications. + Cln: ruli_sync based on ruli_search. + New: ruli_search: Higher-level API for easy resolver creation. + Fix: Regression errors. ...................................................................... 0.14 + ruli_txt: Clean-up label handling API: ruli_txt. + ruli_res: Implement search list. + ruli_sync: Use a search list as defined by 'search'/'domain' clauses of /etc/resolv.conf. + Code clean-up. ...................................................................... 0.13 + ruli_rand: Use random generator with explicit state: ISAAC. + Clean up of ISAAC name space. + Follow CNAME chains while falling back to IN A queries. Would require loop detection or limit the max chain depth. + Basic regression test cases for SRV API. + Clean up of obsolete domain comparisson code. + Fixed possible memory leaking in fallback answer processing. + Fixed possible memory leaking in "walk" answer processing. ...................................................................... 0.12 + Code clean-up. + Comprehensive, automated regression test cases for underlying resolver. + Stricter (paranoid) checking of servers answers for flags, opcode. ...................................................................... 0.11 + ruli_srv: Better RCODE kind semantics. + Report timeout (alarm) condition on sample tools. + Checking of target-walk and fallback answer IN A records. + Code clean-up. + Stricter compiler warnings. + Minor bugfix: ruli_srv_t.qdomain_len was not being initialized. + ruli_srv: Check owner match. + ruli_txt: Detect name compression loop. ...................................................................... 0.10 + Return error when fallback IN A query can't find any address. + Portability fixes for Solaris 7. + Synchronization with HTML documentation. + syncsolver: Minor fix for stdin parsing. ...................................................................... 0.9 + Fixed assert() triggered by late UDP answers reaching us when we have switched to another state due to timeout. + Better checks of function return results for ruli_list_new(), ruli_list_parse(), ruli_list_push(). -x- ruli-0.33/doc/0000755000177100017710000000000010254521423013717 5ustar labratlabrat00000000000000ruli-0.33/doc/man/0000755000177100017710000000000010254521423014472 5ustar labratlabrat00000000000000ruli-0.33/doc/man/srvsearch.10000644000177100017710000000536110161560676016573 0ustar labratlabrat00000000000000.\" Hey, EMACS: -*- nroff -*- .\" $Id: srvsearch.1,v 1.6 2004/12/20 14:29:18 evertonm Exp $ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH RULI 1 "October 08, 2004" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME srvsearch, sync_srvsearch, smtpsearch, sync_smtpsearch, httpsearch, sync_httpsearch, ruli\-getaddrinfo .br \- Sample programs for RULI Library (RFC 2782) .SH SYNOPSIS echo _service._protocol.nongnu.org | .B ruli-getaddrinfo .br echo _service._protocol.nongnu.org | .B srvsearch [ options ] .br echo _service._protocol.nongnu.org | .B sync_srvsearch [ options ] .br echo nongnu.org | .B smtpsearch [ options ] .br echo nongnu.org | .B sync_smtpsearch [ options ] .br echo nongnu.org | .B httpsearch [ options ] .br echo nongnu.org | .B sync_httpsearch [ options ] .br .SH DESCRIPTION This manual page documents briefly sample programs for the .B ruli(3) library. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBruli\fP is a library aimed at querying DNS SRV resource records. .SH OPTIONS .TP For http searches, one can force the port number by specifying it as the first option. .TP .BR search Use the resolver search list defined in \'/etc/resolv.conf\'. .TP .BR need_ra Require RA (Recursion Available) bit in the name server answer. .TP .BR noinet Don\'t fetch IPv4 addresses. .TP .BR noinet6 Don\'t fetch IPv6 addresses. .TP .BR uri_port Assume the specified default port was forced by the user-supplied URI. .TP .BR nowalk Don\'t search addresses missing from the name server answer. .TP .BR nofall Don\'t launch fallback queries for addresses, if the SRV query fails. .TP .BR nosort6 Don\'t sort the address list to give preference to IPv6 addresses. .SH EXAMPLES echo _telnet._tcp.nongnu.org | ruli-getaddrinfo .br echo _smtp._tcp.nongnu.org | srvsearch search .br echo _smtp._tcp.nongnu.org | sync_srvsearch search noinet6 .br echo nongnu.org | smtpsearch noinet .br echo nongnu.org | sync_smtpsearch nowalk nofall .br echo nongnu.org | httpsearch noinet6 .br echo nongnu.org | sync_httpsearch 80 .br .SH SEE ALSO ruli(3) .SH AUTHOR This manual page was written by Everton da Silva Marques . ruli-0.33/doc/man/ruli.30000644000177100017710000000262110031070706015526 0ustar labratlabrat00000000000000.\" Hey, EMACS: -*- nroff -*- .\" $Id: ruli.3,v 1.2 2004/03/26 18:09:10 evertonm Exp $ .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH RULI 3 "March 26, 2004" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME ruli \- Library for querying DNS SRV resource records (RFC 2782) .SH SYNOPSIS .B ruli .SH DESCRIPTION This manual page documents briefly the .B ruli library. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBruli\fP is a library aimed at querying DNS SRV resource records. .SH SEE ALSO The library is documented fully by .IR "The RULI Tutorial" , available at http://www.nongnu.org/ruli/. .br RFC 2782 - A DNS RR for specifying the location of services (DNS SRV) .SH AUTHOR This manual page was written by Everton da Silva Marques . ruli-0.33/doc/RELEASING0000644000177100017710000000156610073034221015155 0ustar labratlabrat00000000000000# # $Id: RELEASING,v 1.2 2004/07/07 17:53:21 evertonm Exp $ # a) Get CVS snapshot: CVS snapshot is ruli b) Create a clean source tree: cp -a ruli ruli- cd ruli- make release-clean cd .. tar czf ruli_.orig.tar.gz ruli- rm -r ruli- c) Add 'debian' directory: tar xzf ruli_.orig.tar.gz cd ruli- cp -a ../ruli/debian . rm -r `find debian -name CVS` d) Tweak things for Debian: Add DESTDIR to src/Makefile, sample/Makefile Remove OOP_* from src/Makefile, sample/Makefile Remove -Werror from src/Makefile e) Update Debian changelog: cd debian dch -i cd .. f) Create package: make dpkg g) Test package: cd .. linda -i *.dsc linda -i *.changes lintian *.dsc lintian *.changes dpkg -i *.deb dpkg -P ruli-bin libruli2 libruli2-dev h) Install previous package i) Upgrade to current package j) Remove current package ruli-0.33/guile/0000755000177100017710000000000010254521423014257 5ustar labratlabrat00000000000000ruli-0.33/guile/Makefile0000644000177100017710000000136010137536753015733 0ustar labratlabrat00000000000000# # $Id: Makefile,v 1.6 2004/10/26 21:13:15 evertonm Exp $ # INCLUDES = -I../src -I/usr/local/ruli/include LIBS = -L../src -L/usr/local/ruli/lib WARN = -pedantic -ansi -Wshadow -Wpointer-arith -Wcast-qual \ -Wcast-align -Wwrite-strings -Wstrict-prototypes \ -Wmissing-prototypes -Wredundant-decls \ -Wall \ # -Werror CFLAGS = $(WARN) -O2 -pipe -g -shared -D_REENTRANT -D__USE_GNU \ -fPIC $(shell guile-config compile) $(INCLUDES) $(LIBS) LDFLAGS = $(LIBS) -lruli $(shell guile-config link) CC = gcc .PHONY: default default: ruli-guile .PHONY: clean clean: rm -f *.o *.so *~ ruli-guile .PHONY: build build: clean default ruli-guile: ruli-guile.o libguile-ruli.so libguile-ruli.so: guile_ruli.o gcc -shared -o $@ $< $(LDFLAGS) ruli-0.33/guile/README0000644000177100017710000000501110137512373015140 0ustar labratlabrat00000000000000# # $Id: README,v 1.5 2004/10/26 18:18:35 evertonm Exp $ # COPYRIGHT AND LICENCE Copyright (C) 2004 by Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. INTRODUCTION This file provides introductory notes about the Guile/Scheme extension for RULI, a library for easily querying DNS SRV resource records (RFC 2782). This module requires the RULI library, available from: http://www.nongnu.org/ruli/ You'll need RULI 0.32 or higher. INSTALLATION 1) Make sure you have, at least, both Guile and RULI properly installed on your system. 2) Compile this Guile extension for RULI (libguile-ruli.so): make 3) Put libguile-ruli.so in the dynamic loader path and ruli.scm in the Guile autoload path. See the comments in the file ruli.scm, if you need more detailed instructions. USAGE In the Guile interpreter, you can load the ruli module (extension) with: (use-modules (ruli)) SCHEME FUNCTIONS This module provides the following functions: (ruli-sync-query service domain fallback_port [options]) (ruli-sync-smtp-query domain [options]) (ruli-sync-http-query domain [force-port [options]]) Possible results are: 1) Symbol 'timeout' 2) Symbol 'unavailable' 3) List of errors: ( (srv-code ) [(rcode )] ) 4) List of SRV records, possibly empty, as in this example: ( ( (target "host1.domain") (priority 0) (weight 10) (port 25) (addresses "1.1.1.1" "2.2.2.2") ) ( (target "host2.domain") (priority 0) (weight 0) (port 80) (addresses "3.3.3.3" "4.4.4.4") ) ) EXAMPLES These are examples of invokation for the functions provided in this module: (ruli-sync-query "_sip._udp" "sip-domain.tld" -1) (ruli-sync-smtp-query "mail-domain.tld") (ruli-sync-http-query "web-domain.tld") -x- ruli-0.33/guile/guile_ruli.c0000644000177100017710000002032610133272322016563 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: guile_ruli.c,v 1.6 2004/10/13 18:32:50 evertonm Exp $ */ #include #include "guile_ruli.h" #include #include extern char *gh_scm2newstr(SCM str, size_t *lenp); const char * const RULI_SYNC_QUERY = "ruli-sync-query"; const char * const RULI_SYNC_SMTP_QUERY = "ruli-sync-smtp-query"; const char * const RULI_SYNC_HTTP_QUERY = "ruli-sync-http-query"; const char * const SYMB_TIMEOUT = "timeout"; const char * const SYMB_UNAVAILABLE = "unavailable"; const char * const SYMB_SRV_CODE = "srv-code"; const char * const SYMB_RCODE = "rcode"; const char * const SYMB_TARGET = "target"; const char * const SYMB_PRIORITY = "priority"; const char * const SYMB_WEIGHT = "weight"; const char * const SYMB_PORT = "port"; const char * const SYMB_ADDRESSES = "addresses"; void ruli_guile_init(void) { scm_c_define_gsubr(RULI_SYNC_QUERY, 3, 1, 0, scm_ruli_sync_query); scm_c_define_gsubr(RULI_SYNC_SMTP_QUERY, 1, 1, 0, scm_ruli_sync_smtp_query); scm_c_define_gsubr(RULI_SYNC_HTTP_QUERY, 1, 2, 0, scm_ruli_sync_http_query); } static SCM scan_sync_srv_list(ruli_sync_t *sync_query) { SCM result = SCM_EOL; int srv_list_size; const ruli_list_t *srv_list; int srv_code; int i; SCM symb_target; SCM symb_priority; SCM symb_weight; SCM symb_port; SCM symb_addresses; assert(sync_query); srv_code = ruli_sync_srv_code(sync_query); assert(srv_code != RULI_SRV_CODE_VOID); /* if lookup times out, return 'timeout' symbol */ if (srv_code == RULI_SRV_CODE_ALARM) return scm_string_to_symbol(scm_mem2string(SYMB_TIMEOUT, strlen(SYMB_TIMEOUT))); /* if service is not available, return 'unavailable' symbol */ if (srv_code == RULI_SRV_CODE_UNAVAILABLE) return scm_string_to_symbol(scm_mem2string(SYMB_UNAVAILABLE, strlen(SYMB_UNAVAILABLE))); /* if srv error code, return (srv-code ) */ if (srv_code) { int rcode; const char *srv_msg = ruli_srv_errstr(srv_code); SCM symb_srv_code = scm_string_to_symbol(scm_mem2string(SYMB_SRV_CODE, strlen(SYMB_SRV_CODE))); SCM s_srv_code = scm_int2num(srv_code); SCM s_srv_msg = scm_mem2string(srv_msg, strlen(srv_msg)); result = scm_append(scm_list_2(result, scm_list_1(scm_list_3(symb_srv_code, s_srv_code, s_srv_msg)))); /* if rcode, return (rcode ) */ rcode = ruli_sync_rcode(sync_query); if (rcode) { SCM symb_rcode = scm_string_to_symbol(scm_mem2string(SYMB_RCODE, strlen(SYMB_RCODE))); SCM s_rcode = scm_int2num(rcode); result = scm_append(scm_list_2(result, scm_list_1(scm_list_2(symb_rcode, s_rcode)))); } return result; } srv_list = ruli_sync_srv_list(sync_query); assert(srv_list); srv_list_size = ruli_list_size(srv_list); assert(srv_list_size >= 0); if (srv_list_size < 1) return SCM_EOL; symb_target = scm_string_to_symbol(scm_mem2string(SYMB_TARGET, strlen(SYMB_TARGET))); symb_priority = scm_string_to_symbol(scm_mem2string(SYMB_PRIORITY, strlen(SYMB_PRIORITY))); symb_weight = scm_string_to_symbol(scm_mem2string(SYMB_WEIGHT, strlen(SYMB_WEIGHT))); symb_port = scm_string_to_symbol(scm_mem2string(SYMB_PORT, strlen(SYMB_PORT))); symb_addresses = scm_string_to_symbol(scm_mem2string(SYMB_ADDRESSES, strlen(SYMB_ADDRESSES))); /* * Scan list of SRV records */ for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); int j; SCM s_srv = SCM_EOL; SCM s_addr_list = scm_list_1(symb_addresses); /* * target host */ { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; SCM s_target; if (ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, entry->target, entry->target_len)) continue; s_target = scm_list_2(symb_target, scm_mem2string(txt_dname_buf, txt_dname_len)); s_srv = scm_append(scm_list_2(s_srv, scm_list_1(s_target))); } /* * priority, weight, port */ s_srv = scm_append(scm_list_2(s_srv, scm_list_1( scm_list_2(symb_priority, scm_int2num(entry->priority)) ))); s_srv = scm_append(scm_list_2(s_srv, scm_list_1( scm_list_2(symb_weight, scm_int2num(entry->weight)) ))); s_srv = scm_append(scm_list_2(s_srv, scm_list_1( scm_list_2(symb_port, scm_int2num(entry->port)) ))); /* * addresses */ for (j = 0; j < addr_list_size; ++j) { char buf[40]; ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, j); int len = ruli_addr_snprint(buf, sizeof(buf), addr); assert(len > 0); assert(len < sizeof(buf)); s_addr_list = scm_append(scm_list_2(s_addr_list, scm_list_1(scm_mem2string(buf, len)) )); } s_srv = scm_append(scm_list_2(s_srv, scm_list_1(s_addr_list))); result = scm_append(scm_list_2(result, scm_list_1(s_srv))); } /* scan srv records */ return result; } SCM scm_ruli_sync_query(SCM s_service, SCM s_domain, SCM s_fallback_port, SCM s_options) { SCM result = SCM_EOL; char *service; size_t service_len; char *domain; size_t domain_len; int fallback_port; int options; SCM_ASSERT(SCM_STRINGP(s_service), s_service, SCM_ARG1, RULI_SYNC_QUERY); SCM_ASSERT(SCM_STRINGP(s_domain), s_domain, SCM_ARG2, RULI_SYNC_QUERY); SCM_ASSERT(SCM_NUMBERP(s_fallback_port), s_fallback_port, SCM_ARG3, RULI_SYNC_QUERY); service = gh_scm2newstr(s_service, &service_len); domain = gh_scm2newstr(s_domain, &domain_len); fallback_port = SCM_INUM(s_fallback_port); options = SCM_UNBNDP(s_options) ? 0 : SCM_INUM(s_options); { ruli_sync_t *sync_query; sync_query = ruli_sync_query(service, domain, fallback_port, options); if (!sync_query) goto exit; result = scan_sync_srv_list(sync_query); ruli_sync_delete(sync_query); } exit: free(service); free(domain); return result; } SCM scm_ruli_sync_smtp_query(SCM s_domain, SCM s_options) { SCM result = SCM_EOL; char *domain; size_t domain_len; int options; SCM_ASSERT(SCM_STRINGP(s_domain), s_domain, SCM_ARG1, RULI_SYNC_SMTP_QUERY); domain = gh_scm2newstr(s_domain, &domain_len); options = SCM_UNBNDP(s_options) ? 0 : SCM_INUM(s_options); { ruli_sync_t *sync_query; sync_query = ruli_sync_smtp_query(domain, options); if (!sync_query) goto exit; result = scan_sync_srv_list(sync_query); ruli_sync_delete(sync_query); } exit: free(domain); return result; } SCM scm_ruli_sync_http_query(SCM s_domain, SCM s_force_port, SCM s_options) { SCM result = SCM_EOL; char *domain; size_t domain_len; int force_port; int options; SCM_ASSERT(SCM_STRINGP(s_domain), s_domain, SCM_ARG1, RULI_SYNC_SMTP_QUERY); domain = gh_scm2newstr(s_domain, &domain_len); force_port = SCM_UNBNDP(s_force_port) ? -1 : SCM_INUM(s_force_port); options = SCM_UNBNDP(s_options) ? 0 : SCM_INUM(s_options); { ruli_sync_t *sync_query; sync_query = ruli_sync_http_query(domain, force_port, options); if (!sync_query) goto exit; result = scan_sync_srv_list(sync_query); ruli_sync_delete(sync_query); } exit: free(domain); return result; } ruli-0.33/guile/guile_ruli.h0000644000177100017710000000227610133272322016574 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: guile_ruli.h,v 1.6 2004/10/13 18:32:50 evertonm Exp $ */ #ifndef GUILE_RULI_H #define GUILE_RULI_H #include void ruli_guile_init(void); SCM scm_ruli_sync_query(SCM service, SCM domain, SCM fallback_port, SCM options); SCM scm_ruli_sync_smtp_query(SCM domain, SCM options); SCM scm_ruli_sync_http_query(SCM domain, SCM force_port, SCM options); #endif /* GUILE_RULI_H */ ruli-0.33/guile/ruli-guile.c0000644000177100017710000000217610107600371016504 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli-guile.c,v 1.3 2004/08/15 06:21:45 evertonm Exp $ */ #include #include "guile_ruli.h" static void inner_main(void *closure, int argc, char **argv) { ruli_guile_init(); scm_shell(argc, argv); } int main(int argc, char **argv) { scm_boot_guile(argc, argv, inner_main, 0); exit(0); /* UNREACHEABLE */ } ruli-0.33/guile/ruli-test.scm0000644000177100017710000000147710113414533016721 0ustar labratlabrat00000000000000; $Id: ruli-test.scm,v 1.3 2004/08/26 17:09:47 evertonm Exp $ ; with optional argument (ruli-sync-query "_http._tcp" "isc.org" -1 0) (ruli-sync-smtp-query "isc.org" 0) ; without optional argument (ruli-sync-query "_http._tcp" "isc.org" -1) (ruli-sync-smtp-query "isc.org") (define sample-srv-list '( ( (target "host1.domain") (priority 0) (weight 10) (port 25) (addresses "1.1.1.1" "2.2.2.2") ) ( (target "host2.domain") (priority 0) (weight 0) (port 80) (addresses "3.3.3.3" "4.4.4.4") ) ) ) ; activate readline support (use-modules (ice-9 readline)) (activate-readline) ; write query result to file (define result '()) (define out '()) (set! result (ruli-sync-smtp-query "aol.com")) (set! out (open-output-file "result.txt")) (write-line result out) (close out) ruli-0.33/guile/ruli.scm0000644000177100017710000000475310166547546015767 0ustar labratlabrat00000000000000; RULI - Resolver User Layer Interface - Querying DNS SRV records ; Copyright (C) 2004 Everton da Silva Marques ; ; RULI 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. ; ; RULI 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 RULI; see the file COPYING. If not, write to the Free ; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ; 02111-1307, USA. ; ; $Id: ruli.scm,v 1.4 2005/01/04 17:16:22 evertonm Exp $ ; ; This is the Guile autoload file for the RULI extension. ; ; INSTALLATION: ; ; 1) Compile the library 'libguile-ruli.so'. ; ; See the file README for details. ; ; 2) Put libguile-ruli.so in the dynamic loader path. ; ; Under Linux, see the file /etc/ld.so.conf ; or the LD_LIBRARY_PATH environment variable. ; ; 3) Put this file (ruli.scm) in the Guile autoload path. ; ; See the GUILE_LOAD_PATH environment variable. ; ; Run this shell command to find out the current ; autoload path: ; ; guile -c '(write %load-path) (newline)' ; ; 4) In the Guile interpreter, you can load the ruli module with: ; ; (use-modules (ruli)) ; ; USAGE: ; ; (ruli-sync-query service domain fallback_port [options]) ; ; (ruli-sync-smtp-query domain [options]) ; ; Possible results are: ; ; 1) Symbol 'timeout' ; 2) Symbol 'unavailable' ; 3) List of errors: ( (srv-code ) [(rcode )] ) ; 4) List of SRV records, possibly empty, as in this example: ; ; ( ; ( ; (target "host1.domain") ; (priority 0) ; (weight 10) ; (port 25) ; (addresses "1.1.1.1" "2.2.2.2") ; ) ; ( ; (target "host2.domain") ; (priority 0) ; (weight 0) ; (port 80) ; (addresses "3.3.3.3" "4.4.4.4") ; ) ; ) ; ; EXAMPLES: ; ; (ruli-sync-query "_http._tcp" "web-domain.tld" -1) ; ; (ruli-sync-smtp-query "mail-domain.tld") ; Module name ; (define-module (ruli)) ; Public symbols ; (export ruli-sync-query) (export ruli-sync-smtp-query) (export ruli-sync-http-query) ; Initialize module from library (extension) ; (load-extension "libguile-ruli" "ruli_guile_init") ; EOF ruli-0.33/java/0000755000177100017710000000000010254521423014073 5ustar labratlabrat00000000000000ruli-0.33/java/src/0000755000177100017710000000000010254521423014662 5ustar labratlabrat00000000000000ruli-0.33/java/src/jni/0000755000177100017710000000000010254521423015442 5ustar labratlabrat00000000000000ruli-0.33/java/src/jni/Makefile0000644000177100017710000000101710137540065017104 0ustar labratlabrat00000000000000# # $Id: Makefile,v 1.2 2004/10/26 21:23:01 evertonm Exp $ # INCLUDES=-I/usr/local/j2sdk/include \ -I/usr/local/j2sdk/include/linux \ -I/usr/local/ruli/include LIBS=-L/usr/local/ruli/lib CFLAGS = -Wall -O2 -pipe -g -shared -D_REENTRANT -D__USE_GNU \ -fPIC $(INCLUDES) $(LIBS) LDFLAGS = -lruli $(LIBS) CC = gcc .PHONY: default default: java-ruli .PHONY: clean clean: rm -f *.o *.so *~ .PHONY: build build: clean default java-ruli: libjava-ruli.so libjava-ruli.so: ruli_RuliSyncImp.o gcc -shared -o $@ $< $(LDFLAGS) ruli-0.33/java/src/jni/ruli_RuliSyncImp.c0000644000177100017710000001472610131556040021066 0ustar labratlabrat00000000000000 #include #include #include "ruli_RuliSyncImp.h" const char * const STR_TARGET = "target"; const char * const STR_PRIORITY = "priority"; const char * const STR_WEIGHT = "weight"; const char * const STR_PORT = "port"; const char * const STR_ADDRESSES = "addresses"; static jobjectArray scan_sync_srv_list(JNIEnv *env, ruli_sync_t *sync_query) { jobjectArray result = 0; jclass hashmapClass; jmethodID hashmapNew; jmethodID hashmapPut; jclass integerClass; jmethodID integerNew; jclass stringClass; int srv_list_size; const ruli_list_t *srv_list; int srv_code; int i; jstring str_target; jstring str_priority; jstring str_weight; jstring str_port; jstring str_addresses; assert(sync_query); srv_code = ruli_sync_srv_code(sync_query); assert(srv_code != RULI_SRV_CODE_VOID); if (srv_code) return result; srv_list = ruli_sync_srv_list(sync_query); assert(srv_list); srv_list_size = ruli_list_size(srv_list); assert(srv_list_size >= 0); if (srv_list_size < 1) return result; hashmapClass = (*env)->FindClass(env, "java/util/HashMap"); assert(hashmapClass); result = (*env)->NewObjectArray(env, srv_list_size, hashmapClass, 0); assert(result); str_target = (*env)->NewStringUTF(env, STR_TARGET); str_priority = (*env)->NewStringUTF(env, STR_PRIORITY); str_weight = (*env)->NewStringUTF(env, STR_WEIGHT); str_port = (*env)->NewStringUTF(env, STR_PORT); str_addresses = (*env)->NewStringUTF(env, STR_ADDRESSES); assert(str_target); assert(str_priority); assert(str_weight); assert(str_port); assert(str_addresses); hashmapNew = (*env)->GetMethodID(env, hashmapClass, "", "()V"); assert(hashmapNew); hashmapPut = (*env)->GetMethodID(env, hashmapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); assert(hashmapPut); integerClass = (*env)->FindClass(env, "java/lang/Integer"); assert(integerClass); integerNew = (*env)->GetMethodID(env, integerClass, "", "(I)V"); assert(integerNew); stringClass = (*env)->FindClass(env, "java/lang/String"); assert(stringClass); /* * Scan list of SRV records */ for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); int j; /* create java record */ jobject hashmap = (*env)->NewObject(env, hashmapClass, hashmapNew); assert(hashmap); (*env)->SetObjectArrayElement(env, result, i, hashmap); /* target host */ { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; jstring hostname; if (ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, entry->target, entry->target_len)) continue; hostname = (*env)->NewStringUTF(env, txt_dname_buf); assert(hostname); (*env)->CallVoidMethod(env, hashmap, hashmapPut, str_target, hostname); } /* priority, weight, port */ { jobject int_priority = (*env)->NewObject(env, integerClass, integerNew, entry->priority); jobject int_weight = (*env)->NewObject(env, integerClass, integerNew, entry->weight); jobject int_port = (*env)->NewObject(env, integerClass, integerNew, entry->port); assert(int_priority); assert(int_weight); assert(int_port); (*env)->CallVoidMethod(env, hashmap, hashmapPut, str_priority, int_priority); (*env)->CallVoidMethod(env, hashmap, hashmapPut, str_weight, int_weight); (*env)->CallVoidMethod(env, hashmap, hashmapPut, str_port, int_port); } /* create addr list and add to hashmap */ jobjectArray addr_array = (*env)->NewObjectArray(env, addr_list_size, stringClass, 0); assert(addr_array); (*env)->CallVoidMethod(env, hashmap, hashmapPut, str_addresses, addr_array); /* * scan record addresses */ for (j = 0; j < addr_list_size; ++j) { char buf[40]; jstring str_addr; ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, j); int len = ruli_addr_snprint(buf, sizeof(buf), addr); assert(len > 0); assert(len < sizeof(buf)); /* add addr to addr_list */ str_addr = (*env)->NewStringUTF(env, buf); assert(str_addr); (*env)->SetObjectArrayElement(env, addr_array, j, str_addr); } } /* scan srv records */ return result; } JNIEXPORT jobjectArray JNICALL Java_ruli_RuliSyncImp_srvQuery (JNIEnv *env, jclass obj, jstring service, jstring domain, jint fallback_port, jint options) { const char *c_service; const char *c_domain; jobjectArray srv_list = 0; c_service = (*env)->GetStringUTFChars(env, service, 0); c_domain = (*env)->GetStringUTFChars(env, domain, 0); { ruli_sync_t *sync_query; sync_query = ruli_sync_query(c_service, c_domain, fallback_port, options); if (!sync_query) goto exit; srv_list = scan_sync_srv_list(env, sync_query); ruli_sync_delete(sync_query); } exit: (*env)->ReleaseStringUTFChars(env, service, c_service); (*env)->ReleaseStringUTFChars(env, domain, c_domain); return srv_list; } JNIEXPORT jobjectArray JNICALL Java_ruli_RuliSyncImp_smtpQuery (JNIEnv *env, jclass obj, jstring domain, jint options) { const char *c_domain; jobjectArray srv_list = 0; c_domain = (*env)->GetStringUTFChars(env, domain, 0); { ruli_sync_t *sync_query; sync_query = ruli_sync_smtp_query(c_domain, options); if (!sync_query) goto exit; srv_list = scan_sync_srv_list(env, sync_query); ruli_sync_delete(sync_query); } exit: (*env)->ReleaseStringUTFChars(env, domain, c_domain); return srv_list; } /* * Class: ruli_RuliSyncImp * Method: httpQuery * Signature: (Ljava/lang/String;II)[Ljava/lang/Object; */ JNIEXPORT jobjectArray JNICALL Java_ruli_RuliSyncImp_httpQuery (JNIEnv *env, jclass obj, jstring domain, jint port, jint options) { const char *c_domain; jobjectArray srv_list = 0; c_domain = (*env)->GetStringUTFChars(env, domain, 0); { ruli_sync_t *sync_query; sync_query = ruli_sync_http_query(c_domain, port, options); if (!sync_query) goto exit; srv_list = scan_sync_srv_list(env, sync_query); ruli_sync_delete(sync_query); } exit: (*env)->ReleaseStringUTFChars(env, domain, c_domain); return srv_list; } ruli-0.33/java/src/jni/ruli_RuliSyncImp.h0000644000177100017710000000166510131556040021071 0ustar labratlabrat00000000000000/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class ruli_RuliSyncImp */ #ifndef _Included_ruli_RuliSyncImp #define _Included_ruli_RuliSyncImp #ifdef __cplusplus extern "C" { #endif /* * Class: ruli_RuliSyncImp * Method: srvQuery * Signature: (Ljava/lang/String;Ljava/lang/String;II)[Ljava/lang/Object; */ JNIEXPORT jobjectArray JNICALL Java_ruli_RuliSyncImp_srvQuery (JNIEnv *, jclass, jstring, jstring, jint, jint); /* * Class: ruli_RuliSyncImp * Method: smtpQuery * Signature: (Ljava/lang/String;I)[Ljava/lang/Object; */ JNIEXPORT jobjectArray JNICALL Java_ruli_RuliSyncImp_smtpQuery (JNIEnv *, jclass, jstring, jint); /* * Class: ruli_RuliSyncImp * Method: httpQuery * Signature: (Ljava/lang/String;II)[Ljava/lang/Object; */ JNIEXPORT jobjectArray JNICALL Java_ruli_RuliSyncImp_httpQuery (JNIEnv *, jclass, jstring, jint, jint); #ifdef __cplusplus } #endif #endif ruli-0.33/java/src/ruli/0000755000177100017710000000000010254521423015635 5ustar labratlabrat00000000000000ruli-0.33/java/src/ruli/sample/0000755000177100017710000000000010254521423017116 5ustar labratlabrat00000000000000ruli-0.33/java/src/ruli/sample/RuliSyncHttpSearch.java0000644000177100017710000000151410131556040023515 0ustar labratlabrat00000000000000 package ruli.sample; import java.util.Map; import ruli.RuliSync; import ruli.RuliUtil; public class RuliSyncHttpSearch { private static void usage() { System.err.println("usage: RuliSyncHttpSearch domain [forcePort [options]]"); System.err.println("example: RuliSyncHttpSearch web-domain.tld 80"); System.exit(1); } public static void main(String[] args) { if ((args.length < 1) || (args.length > 3)) usage(); String domain = args[0]; int forcePort = (args.length > 1) ? Integer.parseInt(args[1]) : -1; int options = (args.length > 2) ? Integer.parseInt(args[2]) : 0; Map[] srvList = RuliSync.httpQuery(domain, forcePort, options); System.out.print(domain); if (forcePort > 0) System.out.print(":" + forcePort); System.out.println(); RuliUtil.dumpSrvList(System.out, srvList); } } ruli-0.33/java/src/ruli/sample/RuliSyncSmtpSearch.java0000644000177100017710000000122610131556040023521 0ustar labratlabrat00000000000000 package ruli.sample; import java.util.Map; import ruli.RuliSync; import ruli.RuliUtil; public class RuliSyncSmtpSearch { private static void usage() { System.err.println("usage: RuliSyncSmtpSearch domain [options]"); System.err.println("example: RuliSyncSmtpSearch mail-domain.tld"); System.exit(1); } public static void main(String[] args) { if ((args.length < 1) || (args.length > 2)) usage(); String domain = args[0]; int options = (args.length > 1) ? Integer.parseInt(args[1]) : 0; Map[] srvList = RuliSync.smtpQuery(domain, options); System.out.println(domain); RuliUtil.dumpSrvList(System.out, srvList); } } ruli-0.33/java/src/ruli/sample/RuliSyncSrvSearch.java0000644000177100017710000000150510131556040023350 0ustar labratlabrat00000000000000 package ruli.sample; import java.util.Map; import ruli.RuliSync; import ruli.RuliUtil; public class RuliSyncSrvSearch { private static void usage() { System.err.println("usage: RuliSyncSrvSearch service domain [fallbackPort [options]]"); System.err.println("example: RuliSyncSrvSearch _http._tcp web-domain.tld"); System.exit(1); } public static void main(String[] args) { if ((args.length < 2) || (args.length > 4)) usage(); String service = args[0]; String domain = args[1]; int fallbackPort = (args.length > 2) ? Integer.parseInt(args[2]) : -1; int options = (args.length > 3) ? Integer.parseInt(args[3]) : 0; Map[] srvList = RuliSync.srvQuery(service, domain, fallbackPort, options); System.out.println(service + "." + domain); RuliUtil.dumpSrvList(System.out, srvList); } } ruli-0.33/java/src/ruli/RuliSync.java0000644000177100017710000000077510131556040020256 0ustar labratlabrat00000000000000 package ruli; import java.util.Map; public class RuliSync { public static Map[] srvQuery(String service, String domain, int fallbackPort, int options) { return RuliSyncImp.srvQuery(service, domain, fallbackPort, options); } public static Map[] smtpQuery(String domain, int options) { return RuliSyncImp.smtpQuery(domain, options); } public static Map[] httpQuery(String domain, int forcePort, int options) { return RuliSyncImp.httpQuery(domain, forcePort, options); } } ruli-0.33/java/src/ruli/RuliSyncImp.java0000644000177100017710000000056010131556040020714 0ustar labratlabrat00000000000000 package ruli; import java.util.Map; class RuliSyncImp { static native Map[] srvQuery(String service, String domain, int fallbackPort, int options); static native Map[] smtpQuery(String domain, int options); static native Map[] httpQuery(String domain, int forcePort, int options); static { System.loadLibrary("java-ruli"); } } ruli-0.33/java/src/ruli/RuliUtil.java0000644000177100017710000000137410131556040020253 0ustar labratlabrat00000000000000 package ruli; import java.util.Map; import java.io.PrintStream; public class RuliUtil { public static void dumpSrvList(PrintStream out, Map[] srvList) { for (int i = 0; i < srvList.length; ++i) { Map srv = srvList[i]; String target = (String) srv.get("target"); int priority = ((Integer) srv.get("priority")).intValue(); int weight = ((Integer) srv.get("weight")).intValue(); int port = ((Integer) srv.get("port")).intValue(); out.print(" target=" + target + " priority=" + priority + " weight=" + weight + " port=" + port + " addresses="); String[] addrList = (String[]) srv.get("addresses"); for (int j = 0; j < addrList.length; ++j) out.print(addrList[j] + " "); out.println(); } } } ruli-0.33/java/Makefile0000644000177100017710000000222410130415023015522 0ustar labratlabrat00000000000000# # $Id: Makefile,v 1.5 2004/10/05 03:50:43 evertonm Exp $ # JAVAC = javac JAVAH = javah JAR = jar SRC_DIR = src BUILD_DIR = build INSTALL_DIR = install JNI_DIR = $(SRC_DIR)/jni BUILT_STAMP = $(BUILD_DIR)/built SRC_FILES = $(shell find $(SRC_DIR) -name "*.java") JAVA_RULI_SO = $(JNI_DIR)/libjava-ruli.so .PHONY: default .PHONY: clean .PHONY: build .PHONY: install default: $(BUILT_STAMP) $(JAVA_RULI_SO) clean: $(MAKE) -C $(JNI_DIR) clean rm -rf $(BUILD_DIR) rm -f `find . -name '*~'` build: clean default $(BUILT_STAMP): $(SRC_FILES) mkdir -p $(BUILD_DIR) $(JAVAC) -d $(BUILD_DIR) $(SRC_FILES) touch $@ $(JNI_DIR)/ruli_RuliSyncImp.h: $(JAVAH) -classpath $(BUILD_DIR) -d $(JNI_DIR) ruli.RuliSyncImp $(JAVA_RULI_SO): $(JNI_DIR)/ruli_RuliSyncImp.h $(MAKE) -C $(JNI_DIR) install: $(BUILT_STAMP) $(JAVA_RULI_SO) mkdir -p $(INSTALL_DIR)/lib cp src/jni/libjava-ruli.so $(INSTALL_DIR)/lib mkdir -p $(INSTALL_DIR)/classes $(JAR) cf $(INSTALL_DIR)/classes/java-ruli.jar -C $(BUILD_DIR) ruli @echo 'export LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:$(INSTALL_DIR)/lib' @echo 'export CLASSPATH=$$CLASSPATH:$(INSTALL_DIR)/classes/java-ruli.jar' ruli-0.33/java/README0000644000177100017710000000514210137512373014761 0ustar labratlabrat00000000000000# # $Id: README,v 1.8 2004/10/26 18:18:35 evertonm Exp $ # COPYRIGHT AND LICENCE Copyright (C) 2004 by Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. INTRODUCTION This file provides introductory notes about the Java native interface for RULI, a library for easily querying DNS SRV resource records (RFC 2782). This module requires the RULI library, available from: http://www.nongnu.org/ruli/ You'll need RULI 0.32 or higher. COMPILE You must properly install the RULI library on your system before trying to use this module. Type: make The compilation process issues the libjava-ruli.so library into src/jni directory. INSTALL Choose the installation directory, say '/usr/local/java-ruli'. Type: make INSTALL_DIR=/usr/local/java-ruli install Add /usr/local/java-ruli/lib to your dynamic loader search path: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/java-ruli/lib Add /usr/local/java-ruli/classes/java-ruli.jar to your system classpath: export CLASSPATH=$CLASSPATH:/usr/local/java-ruli/classes/java-ruli.jar TEST Run some tests: java ruli.sample.RuliSyncSmtpSearch registro.br java ruli.sample.RuliSyncSrvSearch _http._tcp registro.br java ruli.sample.RuliSyncHttpSearch registro.br 80 USAGE Import the RuliSync class into your java program: import ruli.RuliSync; Use these class (static) methods for querying SRV records: Map[] RuliSync.srvQuery(String service, String domain, int fallbackPort, int options); Map[] RuliSync.smtpQuery(String domain, int options); Examples: Map[] srvList = RuliSync.srvQuery("_ftp._tcp", "ftp-domain.tld", 21, 0); Map[] srvList = RuliSync.smtpQuery("mail-domain.tld", 0); SAMPLE PROGRAMS These simple java programs show how to use the native interface: src/ruli/sample/RuliSyncSrvSearch.java src/ruli/sample/RuliSyncSmtpSearch.java src/ruli/sample/RuliSyncHttpSearch.java ruli-0.33/lua/0000755000177100017710000000000010254521423013733 5ustar labratlabrat00000000000000ruli-0.33/lua/Makefile0000644000177100017710000000124410137540556015404 0ustar labratlabrat00000000000000# # $Id: Makefile,v 1.2 2004/10/26 21:28:14 evertonm Exp $ # INCLUDES=-I../src -I/usr/local/ruli/include LIBS=-L../src -L/usr/local/ruli/lib WARN = -pedantic -ansi -Wshadow -Wpointer-arith -Wcast-qual \ -Wcast-align -Wwrite-strings -Wstrict-prototypes \ -Wmissing-prototypes -Wredundant-decls \ -Wall \ # -Werror CFLAGS = $(WARN) -O2 -pipe -g -shared -D_REENTRANT -D__USE_GNU \ -fPIC $(shell lua-config --include) $(INCLUDES) $(LIBS) LDFLAGS = $(LIBS) -lruli -llua50 CC = gcc .PHONY: default default: liblua-ruli.so .PHONY: clean clean: rm -f *.o *.so *~ .PHONY: build build: clean default liblua-ruli.so: lua_ruli.o gcc -shared -o $@ $< $(LDFLAGS) ruli-0.33/lua/README0000644000177100017710000000274310137512373014625 0ustar labratlabrat00000000000000# # $Id: README,v 1.4 2004/10/26 18:18:35 evertonm Exp $ # COPYRIGHT AND LICENCE Copyright (C) 2004 by Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. INTRODUCTION This file provides introductory notes about the Lua extension for RULI, a library for easily querying DNS SRV resource records (RFC 2782). This module requires the RULI library, available from: http://www.nongnu.org/ruli/ You'll need RULI 0.32 or higher. Lua site is at: http://www.lua.org/ INSTRUCTIONS 0) Install RULI and Lua in your system 1) Compile this binding: type 'make' 2) Put liblua-ruli.so in the dynamic loader search path (See variable LD_LIBRARY_PATH, or the file /etc/ld.so.conf) 3) Put ruli.lua in the lua interpreter search path (See variable LUA_PATH) 4) Test: see the file test.lua $ lua test.lua -x- ruli-0.33/lua/lua_ruli.c0000644000177100017710000001462410137512454015726 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: lua_ruli.c,v 1.9 2004/10/26 18:19:24 evertonm Exp $ */ #include #include #include #include "lua_ruli.h" static void scan_sync_srv_list(lua_State *L, int result_index, ruli_sync_t *sync_query) { ruli_list_t *srv_list; int srv_list_size; int srv_code; int i; assert(sync_query); srv_code = ruli_sync_srv_code(sync_query); assert(srv_code != RULI_SRV_CODE_VOID); if (srv_code == RULI_SRV_CODE_ALARM) { return; } if (srv_code == RULI_SRV_CODE_UNAVAILABLE) { return; } if (srv_code) { int rcode = ruli_sync_rcode(sync_query); if (rcode) { return; } return; } srv_list = ruli_sync_srv_list(sync_query); assert(srv_list); srv_list_size = ruli_list_size(srv_list); assert(srv_list_size >= 0); if (srv_list_size < 1) { return; } /* * Scan list of SRV records */ for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); int j; int srv_index; int addr_index; /* * target host */ { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; if (ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, entry->target, entry->target_len)) continue; /* create srv table */ lua_newtable(L); srv_index = lua_gettop(L); /* add srv record to result table */ lua_pushvalue(L, srv_index); /* value=srv table */ lua_rawseti(L, result_index, i + 1); /* key=i+1, store at result table, pop value */ /* add target=>hostname to srv table */ lua_pushstring(L, "target"); /* key */ lua_pushlstring(L, txt_dname_buf, txt_dname_len); /* value=hostname */ lua_settable(L, srv_index); /* store at srv table, pop key/value */ } /* * priority */ lua_pushstring(L, "priority"); /* key */ lua_pushnumber(L, entry->priority); /* value */ lua_settable(L, srv_index); /* store at srv table, pop key/value */ /* * weight */ lua_pushstring(L, "weight"); /* key */ lua_pushnumber(L, entry->weight); /* value */ lua_settable(L, srv_index); /* store at srv table, pop key/value */ /* * port */ lua_pushstring(L, "port"); /* key */ lua_pushnumber(L, entry->port); /* value */ lua_settable(L, srv_index); /* store at srv table, pop key/value */ /* * addresses */ /* create addr table */ lua_newtable(L); addr_index = lua_gettop(L); /* add addr table to srv table */ lua_pushstring(L, "addresses"); /* key */ lua_pushvalue(L, addr_index); /* value=addr table */ lua_settable(L, srv_index); /* store at srv table, pop key/value */ for (j = 0; j < addr_list_size; ++j) { char buf[40]; ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, j); int len = ruli_addr_snprint(buf, sizeof(buf), addr); assert(len > 0); assert(len < sizeof(buf)); /* add to addr table */ lua_pushstring(L, buf); /* value=addr string */ lua_rawseti(L, addr_index, j + 1); /* key=j+1, store at addr table, pop value */ } lua_pop(L, 2); /* remove srv and addr tables from stack */ } /* scan srv records */ } static int lua_ruli_sync_query(lua_State *L) { const char *service; const char *domain; int fallback_port; long options; int result_index; lua_newtable(L); result_index = lua_gettop(L); service = lua_tostring(L, 1); domain = lua_tostring(L, 2); fallback_port = lua_tonumber(L, 3); options = lua_tonumber(L, 4); { ruli_sync_t *sync_query; sync_query = ruli_sync_query(service, domain, fallback_port, options); if (!sync_query) goto exit; scan_sync_srv_list(L, result_index, sync_query); ruli_sync_delete(sync_query); } exit: return 1; /* number of results */ } static int lua_ruli_sync_smtp_query(lua_State *L) { const char *domain; long options; int result_index; lua_newtable(L); result_index = lua_gettop(L); domain = lua_tostring(L, 1); options = lua_tonumber(L, 2); { ruli_sync_t *sync_query; sync_query = ruli_sync_smtp_query(domain, options); if (!sync_query) goto exit; scan_sync_srv_list(L, result_index, sync_query); ruli_sync_delete(sync_query); } exit: return 1; /* number of results */ } static int lua_ruli_sync_http_query(lua_State *L) { const char *domain; int force_port; long options; int result_index; lua_newtable(L); result_index = lua_gettop(L); domain = lua_tostring(L, 1); force_port = lua_tonumber(L, 2); options = lua_tonumber(L, 3); { ruli_sync_t *sync_query; sync_query = ruli_sync_http_query(domain, force_port, options); if (!sync_query) goto exit; scan_sync_srv_list(L, result_index, sync_query); ruli_sync_delete(sync_query); } exit: return 1; /* number of results */ } static const struct luaL_reg ruli_calls[] = { {"ruli_sync_query", lua_ruli_sync_query}, {"ruli_sync_smtp_query", lua_ruli_sync_smtp_query}, {"ruli_sync_http_query", lua_ruli_sync_http_query}, {NULL, NULL} }; int luaopen_ruli(lua_State *L) { luaL_openlib(L, "ruli", ruli_calls, 0); return 1; } ruli-0.33/lua/lua_ruli.h0000644000177100017710000000174010137512454015726 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: lua_ruli.h,v 1.5 2004/10/26 18:19:24 evertonm Exp $ */ #ifndef LUA_RULI_H #define LUA_RULI_H #include int luaopen_ruli(lua_State *L); #endif /* LUA_RULI_H */ ruli-0.33/lua/ruli.lua0000644000177100017710000000076610137300406015416 0ustar labratlabrat00000000000000-- $Id: ruli.lua,v 1.4 2004/10/25 22:41:10 evertonm Exp $ -- -- This is the load file for the RULI extension for -- the Lua language. -- -- RULI site is at: http://www.nongnu.org/ruli/ -- Lua site is at: http://www.lua.org/ -- -- This file is usually stored under the search -- path of Lua interpreter. See the lua manual -- for details. -- -- See the README file from the tarball distribution -- for detailed installation instructions. local r = assert(loadlib("liblua-ruli.so", "luaopen_ruli")) r() ruli-0.33/lua/test.lua0000644000177100017710000000154610137512373015427 0ustar labratlabrat00000000000000#! /usr/bin/env lua -- -- $Id: test.lua,v 1.6 2004/10/26 18:18:35 evertonm Exp $ function dump_srv_list(t) for i,v in ipairs(t) do print(string.format(' %d:', i)) for j,w in pairs(v) do if (type(w) == "table") then print(string.format(' %s =>', j)) for k,addr in ipairs(w) do print(string.format(' %s', addr)) end else print(string.format(' %s => %s', j, w)) end end end end function show(label, srv_list) print(label) dump_srv_list(srv_list) end require("ruli") t = ruli.ruli_sync_query("_sip._tcp", "gnu.org", -1, 0) show("SIP: gnu.org", t) t = ruli.ruli_sync_smtp_query("registro.br", 0) show("SMTP: registro.br", t) t = ruli.ruli_sync_http_query("6bone.net", -1, 0) show("HTTP: 6bone.net", t) t = ruli.ruli_sync_http_query("bad.tld", -1, 0) show("HTTP: bad.tld", t) ruli-0.33/lua/toy.lua0000644000177100017710000000054210137465126015261 0ustar labratlabrat00000000000000#! /usr/bin/env lua -- -- $Id: toy.lua,v 1.2 2004/10/26 15:16:38 evertonm Exp $ function dump_srv_list(t) for i,v in ipairs(t) do print(i, ":") for j,w in pairs(v) do print(j, "=>", w) end end end t = {} s = {} s["target"] = "host1" s["port"] = 25 t[1] = s s = {} s["target"] = "host2" s["port"] = 80 t[2] = s dump_srv_list(t) ruli-0.33/perl/0000755000177100017710000000000010254521423014114 5ustar labratlabrat00000000000000ruli-0.33/perl/RULI/0000755000177100017710000000000010254521423014667 5ustar labratlabrat00000000000000ruli-0.33/perl/RULI/MANIFEST0000644000177100017710000000025610125074101016014 0ustar labratlabrat00000000000000Changes Makefile.PL MANIFEST ppport.h README RULI.xs t/RULI.t fallback/const-c.inc fallback/const-xs.inc lib/Net/RULI.pm examples/ruli-sync-smtp.pl examples/ruli-sync-srv.pl ruli-0.33/perl/RULI/Changes0000644000177100017710000000043110133305756016165 0ustar labratlabrat00000000000000Revision history for Perl extension RULI. 0.01 Fri Mar 19 18:27:52 2004 - original version; created by h2xs 1.23 with options -n RULI /usr/include/ruli.h 0.02 Fri Sep 24 01:02:59 2004 - moved to namespace Net::RULI 0.03 Tue Oct 12 03:01:44 2004 - http-specific support ruli-0.33/perl/RULI/examples/0000755000177100017710000000000010254521423016505 5ustar labratlabrat00000000000000ruli-0.33/perl/RULI/examples/ruli-sync-http.pl0000755000177100017710000000153110133305757021755 0ustar labratlabrat00000000000000#! /usr/bin/perl -w # # $Id: ruli-sync-http.pl,v 1.1 2004/10/13 20:11:27 evertonm Exp $ use strict; use Net::RULI; if (($#ARGV < 0) || ($#ARGV > 1)) { die <<__EOF__; usage: $0 domain [force_port] example: $0 registro.br __EOF__ } my ($domain, $force_port) = @ARGV; if (!defined($force_port)) { $force_port = -1; } my $srv_list_ref = Net::RULI::ruli_sync_http_query($domain, $force_port, 0); if (!defined($srv_list_ref)) { warn "$domain query failed\n"; exit(1); } print $domain, "\n"; foreach (@$srv_list_ref) { my $target = $_->{target}; my $priority = $_->{priority}; my $weight = $_->{weight}; my $port = $_->{port}; my $addr_list_ref = $_->{addr_list}; print " target=$target priority=$priority weight=$weight port=$port addresses="; { $, = ","; print @$addr_list_ref; } print "\n"; } ruli-0.33/perl/RULI/examples/ruli-sync-smtp.pl0000755000177100017710000000135210125074101021745 0ustar labratlabrat00000000000000#! /usr/bin/perl -w # # $Id: ruli-sync-smtp.pl,v 1.3 2004/09/24 19:40:49 evertonm Exp $ use strict; use Net::RULI; if ($#ARGV != 0) { die <<__EOF__; usage: $0 domain example: $0 gnu.org __EOF__ } my ($domain) = @ARGV; my $srv_list_ref = Net::RULI::ruli_sync_smtp_query($domain, 0); if (!defined($srv_list_ref)) { warn "$domain query failed\n"; exit(1); } print $domain, "\n"; foreach (@$srv_list_ref) { my $target = $_->{target}; my $priority = $_->{priority}; my $weight = $_->{weight}; my $port = $_->{port}; my $addr_list_ref = $_->{addr_list}; print " target=$target priority=$priority weight=$weight port=$port addresses="; { $, = ","; print @$addr_list_ref; } print "\n"; } ruli-0.33/perl/RULI/examples/ruli-sync-srv.pl0000755000177100017710000000145510125074101021600 0ustar labratlabrat00000000000000#! /usr/bin/perl -w # # $Id: ruli-sync-srv.pl,v 1.3 2004/09/24 19:40:49 evertonm Exp $ use strict; use Net::RULI; if ($#ARGV != 1) { die <<__EOF__; usage: $0 service domain example: $0 _http._tcp gnu.org __EOF__ } my ($service, $domain) = @ARGV; my $srv_list_ref = Net::RULI::ruli_sync_query($service, $domain, -1, 0); if (!defined($srv_list_ref)) { warn "$service.$domain query failed\n"; exit(1); } print "$service.$domain\n"; foreach (@$srv_list_ref) { my $target = $_->{target}; my $priority = $_->{priority}; my $weight = $_->{weight}; my $port = $_->{port}; my $addr_list_ref = $_->{addr_list}; print " target=$target priority=$priority weight=$weight port=$port addresses="; { $, = ","; print @$addr_list_ref; } print "\n"; } ruli-0.33/perl/RULI/Makefile.PL0000644000177100017710000000355210125074101016637 0ustar labratlabrat00000000000000use 5.008003; use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( NAME => 'Net::RULI', VERSION_FROM => 'lib/Net/RULI.pm', # finds $VERSION PREREQ_PM => {}, # e.g., Module::Name => 1.1 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 (ABSTRACT_FROM => 'lib/Net/RULI.pm', # retrieve abstract from module AUTHOR => 'Everton da Silva Marques ') : ()), LIBS => ['-L/usr/local/ruli/lib -L/usr/local/oop/lib -lruli -loop'], # e.g., '-lm' DEFINE => '', # e.g., '-DHAVE_SOMETHING' INC => '-I. -I/usr/local/ruli/include -I/usr/local/oop/include', # e.g., '-I. -I/usr/include/other' # Un-comment this if you add C files to link with later: # OBJECT => '$(O_FILES)', # link all the C files too ); if (eval {require ExtUtils::Constant; 1}) { # If you edit these definitions to change the constants used by this module, # you will need to use the generated const-c.inc and const-xs.inc # files to replace their "fallback" counterparts before distributing your # changes. my @names = (qw()); ExtUtils::Constant::WriteConstants( NAME => 'Net::RULI', NAMES => \@names, DEFAULT_TYPE => 'IV', C_FILE => 'const-c.inc', XS_FILE => 'const-xs.inc', ); } else { use File::Copy; use File::Spec; foreach my $file ('const-c.inc', 'const-xs.inc') { my $fallback = File::Spec->catfile('fallback', $file); copy ($fallback, $file) or die "Can't copy $fallback to $file: $!"; } } ruli-0.33/perl/RULI/README0000644000177100017710000000267110137512373015561 0ustar labratlabrat00000000000000Perl binding for RULI version 0.03 ================================== DEPENDENCIES This module requires these other modules and libraries: RULI - Resolver User Layer Interface http://www.nongnu.org/ruli/ Please install the RULI library before installing this module. You'll need RULI 0.32 or higher. INSTALLATION To install this module type the following: perl Makefile.PL make make test make install USAGE See "perldoc Net::RULI" for usage information. EXAMPLES See the directory "examples" for basic programs using this module: ./examples/ruli-sync-smtp.pl registro.br ./examples/ruli-sync-http.pl registro.br ./examples/ruli-sync-srv.pl _sip._tcp gnu.org COPYRIGHT AND LICENCE Copyright (C) 2004 by Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ruli-0.33/perl/RULI/RULI.xs0000644000177100017710000001044610133305756016030 0ustar labratlabrat00000000000000#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include #include "const-c.inc" static void push_ruli_addr(AV *srv_addrs, const ruli_addr_t *addr) { SV *address; char buf[40]; if (ruli_addr_snprint(buf, 40, addr) < 0) return; address = newSVpv(buf, strlen(buf)); av_push(srv_addrs, address); } static SV *scan_srv_list(ruli_sync_t *sync_query) { int srv_code; ruli_list_t *srv_list; int srv_list_size; int i; AV* srv_array; SV* srv_array_ref; const char *label_target = "target"; const char *label_priority = "priority"; const char *label_weight = "weight"; const char *label_port = "port"; const char *label_addr_list = "addr_list"; SV* key_target = newSVpv(label_target, strlen(label_target)); SV* key_priority = newSVpv(label_priority, strlen(label_priority)); SV* key_weight = newSVpv(label_weight, strlen(label_weight)); SV* key_port = newSVpv(label_port, strlen(label_port)); SV* key_addr_list = newSVpv(label_addr_list, strlen(label_addr_list)); /* Underlying SRV query failure? */ srv_code = ruli_sync_srv_code(sync_query); if (srv_code == RULI_SRV_CODE_ALARM) return 0; /* Service provided? */ if (srv_code == RULI_SRV_CODE_UNAVAILABLE) return 0; /* Server RCODE? */ if (srv_code) { int rcode = ruli_sync_rcode(sync_query); if (rcode) return 0; return 0; } srv_list = ruli_sync_srv_list(sync_query); srv_list_size = ruli_list_size(srv_list); srv_array = newAV(); srv_array_ref = newRV_inc((SV*) srv_array); /* Scan list of SRV records */ for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; int j; HV* srv; SV* srv_ref; SV* target; SV* priority; SV* weight; SV* port; AV* srv_addrs; SV* srv_addrs_ref; if (ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, entry->target, entry->target_len)) continue; target = newSVpv(txt_dname_buf, txt_dname_len); priority = newSViv(entry->priority); weight = newSViv(entry->weight); port = newSViv(entry->port); srv = newHV(); srv_ref = newRV_inc((SV*) srv); av_push(srv_array, srv_ref); hv_store_ent(srv, key_target, target, 0); hv_store_ent(srv, key_priority, priority, 0); hv_store_ent(srv, key_weight, weight, 0); hv_store_ent(srv, key_port, port, 0); srv_addrs = newAV(); srv_addrs_ref = newRV_inc((SV*) srv_addrs); hv_store_ent(srv, key_addr_list, srv_addrs_ref, 0); for (j = 0; j < addr_list_size; ++j) { ruli_addr_t *addr = ruli_list_get(addr_list, j); push_ruli_addr(srv_addrs, addr); } } return srv_array_ref; } MODULE = Net::RULI PACKAGE = Net::RULI INCLUDE: const-xs.inc PROTOTYPES: ENABLE SV * ruli_sync_query(service, domain, fallback_port, options) const char * service const char * domain int fallback_port long options CODE: ruli_sync_t *sync_query; SV* srv_array_ref; /* Submit query */ sync_query = ruli_sync_query(service, domain, fallback_port, options); if (!sync_query) XSRETURN_UNDEF; srv_array_ref = scan_srv_list(sync_query); ruli_sync_delete(sync_query); if (!srv_array_ref) XSRETURN_UNDEF; RETVAL = srv_array_ref; OUTPUT: RETVAL SV * ruli_sync_smtp_query(domain, options) const char * domain long options CODE: ruli_sync_t *sync_query; SV* srv_array_ref; /* Submit query */ sync_query = ruli_sync_smtp_query(domain, options); if (!sync_query) XSRETURN_UNDEF; srv_array_ref = scan_srv_list(sync_query); ruli_sync_delete(sync_query); if (!srv_array_ref) XSRETURN_UNDEF; RETVAL = srv_array_ref; OUTPUT: RETVAL SV * ruli_sync_http_query(domain, force_port, options) const char * domain int force_port long options CODE: ruli_sync_t *sync_query; SV* srv_array_ref; /* Submit query */ sync_query = ruli_sync_http_query(domain, force_port, options); if (!sync_query) XSRETURN_UNDEF; srv_array_ref = scan_srv_list(sync_query); ruli_sync_delete(sync_query); if (!srv_array_ref) XSRETURN_UNDEF; RETVAL = srv_array_ref; OUTPUT: RETVAL ruli-0.33/perl/RULI/ppport.h0000644000177100017710000007214110027507513016373 0ustar labratlabrat00000000000000 /* ppport.h -- Perl/Pollution/Portability Version 2.011 * * Automatically Created by Devel::PPPort on Fri Mar 19 18:27:51 2004 * * Do NOT edit this file directly! -- Edit PPPort.pm instead. * * Version 2.x, Copyright (C) 2001, Paul Marquess. * Version 1.x, Copyright (C) 1999, Kenneth Albanowski. * This code may be used and distributed under the same license as any * version of Perl. * * This version of ppport.h is designed to support operation with Perl * installations back to 5.004, and has been tested up to 5.8.1. * * If this version of ppport.h is failing during the compilation of this * module, please check if a newer version of Devel::PPPort is available * on CPAN before sending a bug report. * * If you are using the latest version of Devel::PPPort and it is failing * during compilation of this module, please send a report to perlbug@perl.com * * Include all following information: * * 1. The complete output from running "perl -V" * * 2. This file. * * 3. The name & version of the module you were trying to build. * * 4. A full log of the build that failed. * * 5. Any other information that you think could be relevant. * * * For the latest version of this code, please retreive the Devel::PPPort * module from CPAN. * */ /* * In order for a Perl extension module to be as portable as possible * across differing versions of Perl itself, certain steps need to be taken. * Including this header is the first major one, then using dTHR is all the * appropriate places and using a PL_ prefix to refer to global Perl * variables is the second. * */ /* If you use one of a few functions that were not present in earlier * versions of Perl, please add a define before the inclusion of ppport.h * for a static include, or use the GLOBAL request in a single module to * produce a global definition that can be referenced from the other * modules. * * Function: Static define: Extern define: * newCONSTSUB() NEED_newCONSTSUB NEED_newCONSTSUB_GLOBAL * */ /* To verify whether ppport.h is needed for your module, and whether any * special defines should be used, ppport.h can be run through Perl to check * your source code. Simply say: * * perl -x ppport.h *.c *.h *.xs foo/bar*.c [etc] * * The result will be a list of patches suggesting changes that should at * least be acceptable, if not necessarily the most efficient solution, or a * fix for all possible problems. It won't catch where dTHR is needed, and * doesn't attempt to account for global macro or function definitions, * nested includes, typemaps, etc. * * In order to test for the need of dTHR, please try your module under a * recent version of Perl that has threading compiled-in. * */ /* #!/usr/bin/perl @ARGV = ("*.xs") if !@ARGV; %badmacros = %funcs = %macros = (); $replace = 0; foreach () { $funcs{$1} = 1 if /Provide:\s+(\S+)/; $macros{$1} = 1 if /^#\s*define\s+([a-zA-Z0-9_]+)/; $replace = $1 if /Replace:\s+(\d+)/; $badmacros{$2}=$1 if $replace and /^#\s*define\s+([a-zA-Z0-9_]+).*?\s+([a-zA-Z0-9_]+)/; $badmacros{$1}=$2 if /Replace (\S+) with (\S+)/; } foreach $filename (map(glob($_),@ARGV)) { unless (open(IN, "<$filename")) { warn "Unable to read from $file: $!\n"; next; } print "Scanning $filename...\n"; $c = ""; while () { $c .= $_; } close(IN); $need_include = 0; %add_func = (); $changes = 0; $has_include = ($c =~ /#.*include.*ppport/m); foreach $func (keys %funcs) { if ($c =~ /#.*define.*\bNEED_$func(_GLOBAL)?\b/m) { if ($c !~ /\b$func\b/m) { print "If $func isn't needed, you don't need to request it.\n" if $changes += ($c =~ s/^.*#.*define.*\bNEED_$func\b.*\n//m); } else { print "Uses $func\n"; $need_include = 1; } } else { if ($c =~ /\b$func\b/m) { $add_func{$func} =1 ; print "Uses $func\n"; $need_include = 1; } } } if (not $need_include) { foreach $macro (keys %macros) { if ($c =~ /\b$macro\b/m) { print "Uses $macro\n"; $need_include = 1; } } } foreach $badmacro (keys %badmacros) { if ($c =~ /\b$badmacro\b/m) { $changes += ($c =~ s/\b$badmacro\b/$badmacros{$badmacro}/gm); print "Uses $badmacros{$badmacro} (instead of $badmacro)\n"; $need_include = 1; } } if (scalar(keys %add_func) or $need_include != $has_include) { if (!$has_include) { $inc = join('',map("#define NEED_$_\n", sort keys %add_func)). "#include \"ppport.h\"\n"; $c = "$inc$c" unless $c =~ s/#.*include.*XSUB.*\n/$&$inc/m; } elsif (keys %add_func) { $inc = join('',map("#define NEED_$_\n", sort keys %add_func)); $c = "$inc$c" unless $c =~ s/^.*#.*include.*ppport.*$/$inc$&/m; } if (!$need_include) { print "Doesn't seem to need ppport.h.\n"; $c =~ s/^.*#.*include.*ppport.*\n//m; } $changes++; } if ($changes) { open(OUT,">/tmp/ppport.h.$$"); print OUT $c; close(OUT); open(DIFF, "diff -u $filename /tmp/ppport.h.$$|"); while () { s!/tmp/ppport\.h\.$$!$filename.patched!; print STDOUT; } close(DIFF); unlink("/tmp/ppport.h.$$"); } else { print "Looks OK\n"; } } __DATA__ */ #ifndef _P_P_PORTABILITY_H_ #define _P_P_PORTABILITY_H_ #ifndef PERL_REVISION # ifndef __PATCHLEVEL_H_INCLUDED__ # define PERL_PATCHLEVEL_H_IMPLICIT # include # endif # if !(defined(PERL_VERSION) || (defined(SUBVERSION) && defined(PATCHLEVEL))) # include # endif # ifndef PERL_REVISION # define PERL_REVISION (5) /* Replace: 1 */ # define PERL_VERSION PATCHLEVEL # define PERL_SUBVERSION SUBVERSION /* Replace PERL_PATCHLEVEL with PERL_VERSION */ /* Replace: 0 */ # endif #endif #define PERL_BCDVERSION ((PERL_REVISION * 0x1000000L) + (PERL_VERSION * 0x1000L) + PERL_SUBVERSION) /* It is very unlikely that anyone will try to use this with Perl 6 (or greater), but who knows. */ #if PERL_REVISION != 5 # error ppport.h only works with Perl version 5 #endif /* PERL_REVISION != 5 */ #ifndef ERRSV # define ERRSV perl_get_sv("@",FALSE) #endif #if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 5)) /* Replace: 1 */ # define PL_Sv Sv # define PL_compiling compiling # define PL_copline copline # define PL_curcop curcop # define PL_curstash curstash # define PL_defgv defgv # define PL_dirty dirty # define PL_dowarn dowarn # define PL_hints hints # define PL_na na # define PL_perldb perldb # define PL_rsfp_filters rsfp_filters # define PL_rsfpv rsfp # define PL_stdingv stdingv # define PL_sv_no sv_no # define PL_sv_undef sv_undef # define PL_sv_yes sv_yes /* Replace: 0 */ #endif #ifdef HASATTRIBUTE # if (defined(__GNUC__) && defined(__cplusplus)) || defined(__INTEL_COMPILER) # define PERL_UNUSED_DECL # else # define PERL_UNUSED_DECL __attribute__((unused)) # endif #else # define PERL_UNUSED_DECL #endif #ifndef dNOOP # define NOOP (void)0 # define dNOOP extern int Perl___notused PERL_UNUSED_DECL #endif #ifndef dTHR # define dTHR dNOOP #endif #ifndef dTHX # define dTHX dNOOP # define dTHXa(x) dNOOP # define dTHXoa(x) dNOOP #endif #ifndef pTHX # define pTHX void # define pTHX_ # define aTHX # define aTHX_ #endif #ifndef dAX # define dAX I32 ax = MARK - PL_stack_base + 1 #endif #ifndef dITEMS # define dITEMS I32 items = SP - MARK #endif /* IV could also be a quad (say, a long long), but Perls * capable of those should have IVSIZE already. */ #if !defined(IVSIZE) && defined(LONGSIZE) # define IVSIZE LONGSIZE #endif #ifndef IVSIZE # define IVSIZE 4 /* A bold guess, but the best we can make. */ #endif #ifndef UVSIZE # define UVSIZE IVSIZE #endif #ifndef NVTYPE # if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) # define NVTYPE long double # else # define NVTYPE double # endif typedef NVTYPE NV; #endif #ifndef INT2PTR #if (IVSIZE == PTRSIZE) && (UVSIZE == PTRSIZE) # define PTRV UV # define INT2PTR(any,d) (any)(d) #else # if PTRSIZE == LONGSIZE # define PTRV unsigned long # else # define PTRV unsigned # endif # define INT2PTR(any,d) (any)(PTRV)(d) #endif #define NUM2PTR(any,d) (any)(PTRV)(d) #define PTR2IV(p) INT2PTR(IV,p) #define PTR2UV(p) INT2PTR(UV,p) #define PTR2NV(p) NUM2PTR(NV,p) #if PTRSIZE == LONGSIZE # define PTR2ul(p) (unsigned long)(p) #else # define PTR2ul(p) INT2PTR(unsigned long,p) #endif #endif /* !INT2PTR */ #ifndef boolSV # define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no) #endif #ifndef gv_stashpvn # define gv_stashpvn(str,len,flags) gv_stashpv(str,flags) #endif #ifndef newSVpvn # define newSVpvn(data,len) ((len) ? newSVpv ((data), (len)) : newSVpv ("", 0)) #endif #ifndef newRV_inc /* Replace: 1 */ # define newRV_inc(sv) newRV(sv) /* Replace: 0 */ #endif /* DEFSV appears first in 5.004_56 */ #ifndef DEFSV # define DEFSV GvSV(PL_defgv) #endif #ifndef SAVE_DEFSV # define SAVE_DEFSV SAVESPTR(GvSV(PL_defgv)) #endif #ifndef newRV_noinc # ifdef __GNUC__ # define newRV_noinc(sv) \ ({ \ SV *nsv = (SV*)newRV(sv); \ SvREFCNT_dec(sv); \ nsv; \ }) # else # if defined(USE_THREADS) static SV * newRV_noinc (SV * sv) { SV *nsv = (SV*)newRV(sv); SvREFCNT_dec(sv); return nsv; } # else # define newRV_noinc(sv) \ (PL_Sv=(SV*)newRV(sv), SvREFCNT_dec(sv), (SV*)PL_Sv) # endif # endif #endif /* Provide: newCONSTSUB */ /* newCONSTSUB from IO.xs is in the core starting with 5.004_63 */ #if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION < 63)) #if defined(NEED_newCONSTSUB) static #else extern void newCONSTSUB(HV * stash, char * name, SV *sv); #endif #if defined(NEED_newCONSTSUB) || defined(NEED_newCONSTSUB_GLOBAL) void newCONSTSUB(stash,name,sv) HV *stash; char *name; SV *sv; { U32 oldhints = PL_hints; HV *old_cop_stash = PL_curcop->cop_stash; HV *old_curstash = PL_curstash; line_t oldline = PL_curcop->cop_line; PL_curcop->cop_line = PL_copline; PL_hints &= ~HINT_BLOCK_SCOPE; if (stash) PL_curstash = PL_curcop->cop_stash = stash; newSUB( #if (PERL_VERSION < 3) || ((PERL_VERSION == 3) && (PERL_SUBVERSION < 22)) /* before 5.003_22 */ start_subparse(), #else # if (PERL_VERSION == 3) && (PERL_SUBVERSION == 22) /* 5.003_22 */ start_subparse(0), # else /* 5.003_23 onwards */ start_subparse(FALSE, 0), # endif #endif newSVOP(OP_CONST, 0, newSVpv(name,0)), newSVOP(OP_CONST, 0, &PL_sv_no), /* SvPV(&PL_sv_no) == "" -- GMB */ newSTATEOP(0, Nullch, newSVOP(OP_CONST, 0, sv)) ); PL_hints = oldhints; PL_curcop->cop_stash = old_cop_stash; PL_curstash = old_curstash; PL_curcop->cop_line = oldline; } #endif #endif /* newCONSTSUB */ #ifndef START_MY_CXT /* * Boilerplate macros for initializing and accessing interpreter-local * data from C. All statics in extensions should be reworked to use * this, if you want to make the extension thread-safe. See ext/re/re.xs * for an example of the use of these macros. * * Code that uses these macros is responsible for the following: * 1. #define MY_CXT_KEY to a unique string, e.g. "DynaLoader_guts" * 2. Declare a typedef named my_cxt_t that is a structure that contains * all the data that needs to be interpreter-local. * 3. Use the START_MY_CXT macro after the declaration of my_cxt_t. * 4. Use the MY_CXT_INIT macro such that it is called exactly once * (typically put in the BOOT: section). * 5. Use the members of the my_cxt_t structure everywhere as * MY_CXT.member. * 6. Use the dMY_CXT macro (a declaration) in all the functions that * access MY_CXT. */ #if defined(MULTIPLICITY) || defined(PERL_OBJECT) || \ defined(PERL_CAPI) || defined(PERL_IMPLICIT_CONTEXT) /* This must appear in all extensions that define a my_cxt_t structure, * right after the definition (i.e. at file scope). The non-threads * case below uses it to declare the data as static. */ #define START_MY_CXT #if (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION < 68 )) /* Fetches the SV that keeps the per-interpreter data. */ #define dMY_CXT_SV \ SV *my_cxt_sv = perl_get_sv(MY_CXT_KEY, FALSE) #else /* >= perl5.004_68 */ #define dMY_CXT_SV \ SV *my_cxt_sv = *hv_fetch(PL_modglobal, MY_CXT_KEY, \ sizeof(MY_CXT_KEY)-1, TRUE) #endif /* < perl5.004_68 */ /* This declaration should be used within all functions that use the * interpreter-local data. */ #define dMY_CXT \ dMY_CXT_SV; \ my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*,SvUV(my_cxt_sv)) /* Creates and zeroes the per-interpreter data. * (We allocate my_cxtp in a Perl SV so that it will be released when * the interpreter goes away.) */ #define MY_CXT_INIT \ dMY_CXT_SV; \ /* newSV() allocates one more than needed */ \ my_cxt_t *my_cxtp = (my_cxt_t*)SvPVX(newSV(sizeof(my_cxt_t)-1));\ Zero(my_cxtp, 1, my_cxt_t); \ sv_setuv(my_cxt_sv, PTR2UV(my_cxtp)) /* This macro must be used to access members of the my_cxt_t structure. * e.g. MYCXT.some_data */ #define MY_CXT (*my_cxtp) /* Judicious use of these macros can reduce the number of times dMY_CXT * is used. Use is similar to pTHX, aTHX etc. */ #define pMY_CXT my_cxt_t *my_cxtp #define pMY_CXT_ pMY_CXT, #define _pMY_CXT ,pMY_CXT #define aMY_CXT my_cxtp #define aMY_CXT_ aMY_CXT, #define _aMY_CXT ,aMY_CXT #else /* single interpreter */ #define START_MY_CXT static my_cxt_t my_cxt; #define dMY_CXT_SV dNOOP #define dMY_CXT dNOOP #define MY_CXT_INIT NOOP #define MY_CXT my_cxt #define pMY_CXT void #define pMY_CXT_ #define _pMY_CXT #define aMY_CXT #define aMY_CXT_ #define _aMY_CXT #endif #endif /* START_MY_CXT */ #ifndef IVdf # if IVSIZE == LONGSIZE # define IVdf "ld" # define UVuf "lu" # define UVof "lo" # define UVxf "lx" # define UVXf "lX" # else # if IVSIZE == INTSIZE # define IVdf "d" # define UVuf "u" # define UVof "o" # define UVxf "x" # define UVXf "X" # endif # endif #endif #ifndef NVef # if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \ defined(PERL_PRIfldbl) /* Not very likely, but let's try anyway. */ # define NVef PERL_PRIeldbl # define NVff PERL_PRIfldbl # define NVgf PERL_PRIgldbl # else # define NVef "e" # define NVff "f" # define NVgf "g" # endif #endif #ifndef AvFILLp /* Older perls (<=5.003) lack AvFILLp */ # define AvFILLp AvFILL #endif #ifdef SvPVbyte # if PERL_REVISION == 5 && PERL_VERSION < 7 /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */ # undef SvPVbyte # define SvPVbyte(sv, lp) \ ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \ ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp)) static char * my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp) { sv_utf8_downgrade(sv,0); return SvPV(sv,*lp); } # endif #else # define SvPVbyte SvPV #endif #ifndef SvPV_nolen # define SvPV_nolen(sv) \ ((SvFLAGS(sv) & (SVf_POK)) == SVf_POK \ ? SvPVX(sv) : sv_2pv_nolen(sv)) static char * sv_2pv_nolen(pTHX_ register SV *sv) { STRLEN n_a; return sv_2pv(sv, &n_a); } #endif #ifndef get_cv # define get_cv(name,create) perl_get_cv(name,create) #endif #ifndef get_sv # define get_sv(name,create) perl_get_sv(name,create) #endif #ifndef get_av # define get_av(name,create) perl_get_av(name,create) #endif #ifndef get_hv # define get_hv(name,create) perl_get_hv(name,create) #endif #ifndef call_argv # define call_argv perl_call_argv #endif #ifndef call_method # define call_method perl_call_method #endif #ifndef call_pv # define call_pv perl_call_pv #endif #ifndef call_sv # define call_sv perl_call_sv #endif #ifndef eval_pv # define eval_pv perl_eval_pv #endif #ifndef eval_sv # define eval_sv perl_eval_sv #endif #ifndef PERL_SCAN_GREATER_THAN_UV_MAX # define PERL_SCAN_GREATER_THAN_UV_MAX 0x02 #endif #ifndef PERL_SCAN_SILENT_ILLDIGIT # define PERL_SCAN_SILENT_ILLDIGIT 0x04 #endif #ifndef PERL_SCAN_ALLOW_UNDERSCORES # define PERL_SCAN_ALLOW_UNDERSCORES 0x01 #endif #ifndef PERL_SCAN_DISALLOW_PREFIX # define PERL_SCAN_DISALLOW_PREFIX 0x02 #endif #if (PERL_VERSION > 6) || ((PERL_VERSION == 6) && (PERL_SUBVERSION >= 1)) #define I32_CAST #else #define I32_CAST (I32*) #endif #ifndef grok_hex static UV _grok_hex (char *string, STRLEN *len, I32 *flags, NV *result) { NV r = scan_hex(string, *len, I32_CAST len); if (r > UV_MAX) { *flags |= PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = r; return UV_MAX; } return (UV)r; } # define grok_hex(string, len, flags, result) \ _grok_hex((string), (len), (flags), (result)) #endif #ifndef grok_oct static UV _grok_oct (char *string, STRLEN *len, I32 *flags, NV *result) { NV r = scan_oct(string, *len, I32_CAST len); if (r > UV_MAX) { *flags |= PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = r; return UV_MAX; } return (UV)r; } # define grok_oct(string, len, flags, result) \ _grok_oct((string), (len), (flags), (result)) #endif #if !defined(grok_bin) && defined(scan_bin) static UV _grok_bin (char *string, STRLEN *len, I32 *flags, NV *result) { NV r = scan_bin(string, *len, I32_CAST len); if (r > UV_MAX) { *flags |= PERL_SCAN_GREATER_THAN_UV_MAX; if (result) *result = r; return UV_MAX; } return (UV)r; } # define grok_bin(string, len, flags, result) \ _grok_bin((string), (len), (flags), (result)) #endif #ifndef IN_LOCALE # define IN_LOCALE \ (PL_curcop == &PL_compiling ? IN_LOCALE_COMPILETIME : IN_LOCALE_RUNTIME) #endif #ifndef IN_LOCALE_RUNTIME # define IN_LOCALE_RUNTIME (PL_curcop->op_private & HINT_LOCALE) #endif #ifndef IN_LOCALE_COMPILETIME # define IN_LOCALE_COMPILETIME (PL_hints & HINT_LOCALE) #endif #ifndef IS_NUMBER_IN_UV # define IS_NUMBER_IN_UV 0x01 # define IS_NUMBER_GREATER_THAN_UV_MAX 0x02 # define IS_NUMBER_NOT_INT 0x04 # define IS_NUMBER_NEG 0x08 # define IS_NUMBER_INFINITY 0x10 # define IS_NUMBER_NAN 0x20 #endif #ifndef grok_numeric_radix # define GROK_NUMERIC_RADIX(sp, send) grok_numeric_radix(aTHX_ sp, send) #define grok_numeric_radix Perl_grok_numeric_radix bool Perl_grok_numeric_radix(pTHX_ const char **sp, const char *send) { #ifdef USE_LOCALE_NUMERIC #if (PERL_VERSION > 6) || ((PERL_VERSION == 6) && (PERL_SUBVERSION >= 1)) if (PL_numeric_radix_sv && IN_LOCALE) { STRLEN len; char* radix = SvPV(PL_numeric_radix_sv, len); if (*sp + len <= send && memEQ(*sp, radix, len)) { *sp += len; return TRUE; } } #else /* pre5.6.0 perls don't have PL_numeric_radix_sv so the radix * must manually be requested from locale.h */ #include struct lconv *lc = localeconv(); char *radix = lc->decimal_point; if (radix && IN_LOCALE) { STRLEN len = strlen(radix); if (*sp + len <= send && memEQ(*sp, radix, len)) { *sp += len; return TRUE; } } #endif /* PERL_VERSION */ #endif /* USE_LOCALE_NUMERIC */ /* always try "." if numeric radix didn't match because * we may have data from different locales mixed */ if (*sp < send && **sp == '.') { ++*sp; return TRUE; } return FALSE; } #endif /* grok_numeric_radix */ #ifndef grok_number #define grok_number Perl_grok_number int Perl_grok_number(pTHX_ const char *pv, STRLEN len, UV *valuep) { const char *s = pv; const char *send = pv + len; const UV max_div_10 = UV_MAX / 10; const char max_mod_10 = UV_MAX % 10; int numtype = 0; int sawinf = 0; int sawnan = 0; while (s < send && isSPACE(*s)) s++; if (s == send) { return 0; } else if (*s == '-') { s++; numtype = IS_NUMBER_NEG; } else if (*s == '+') s++; if (s == send) return 0; /* next must be digit or the radix separator or beginning of infinity */ if (isDIGIT(*s)) { /* UVs are at least 32 bits, so the first 9 decimal digits cannot overflow. */ UV value = *s - '0'; /* This construction seems to be more optimiser friendly. (without it gcc does the isDIGIT test and the *s - '0' separately) With it gcc on arm is managing 6 instructions (6 cycles) per digit. In theory the optimiser could deduce how far to unroll the loop before checking for overflow. */ if (++s < send) { int digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { digit = *s - '0'; if (digit >= 0 && digit <= 9) { value = value * 10 + digit; if (++s < send) { /* Now got 9 digits, so need to check each time for overflow. */ digit = *s - '0'; while (digit >= 0 && digit <= 9 && (value < max_div_10 || (value == max_div_10 && digit <= max_mod_10))) { value = value * 10 + digit; if (++s < send) digit = *s - '0'; else break; } if (digit >= 0 && digit <= 9 && (s < send)) { /* value overflowed. skip the remaining digits, don't worry about setting *valuep. */ do { s++; } while (s < send && isDIGIT(*s)); numtype |= IS_NUMBER_GREATER_THAN_UV_MAX; goto skip_value; } } } } } } } } } } } } } } } } } } numtype |= IS_NUMBER_IN_UV; if (valuep) *valuep = value; skip_value: if (GROK_NUMERIC_RADIX(&s, send)) { numtype |= IS_NUMBER_NOT_INT; while (s < send && isDIGIT(*s)) /* optional digits after the radix */ s++; } } else if (GROK_NUMERIC_RADIX(&s, send)) { numtype |= IS_NUMBER_NOT_INT | IS_NUMBER_IN_UV; /* valuep assigned below */ /* no digits before the radix means we need digits after it */ if (s < send && isDIGIT(*s)) { do { s++; } while (s < send && isDIGIT(*s)); if (valuep) { /* integer approximation is valid - it's 0. */ *valuep = 0; } } else return 0; } else if (*s == 'I' || *s == 'i') { s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; if (s == send || (*s != 'F' && *s != 'f')) return 0; s++; if (s < send && (*s == 'I' || *s == 'i')) { s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; if (s == send || (*s != 'I' && *s != 'i')) return 0; s++; if (s == send || (*s != 'T' && *s != 't')) return 0; s++; if (s == send || (*s != 'Y' && *s != 'y')) return 0; s++; } sawinf = 1; } else if (*s == 'N' || *s == 'n') { /* XXX TODO: There are signaling NaNs and quiet NaNs. */ s++; if (s == send || (*s != 'A' && *s != 'a')) return 0; s++; if (s == send || (*s != 'N' && *s != 'n')) return 0; s++; sawnan = 1; } else return 0; if (sawinf) { numtype &= IS_NUMBER_NEG; /* Keep track of sign */ numtype |= IS_NUMBER_INFINITY | IS_NUMBER_NOT_INT; } else if (sawnan) { numtype &= IS_NUMBER_NEG; /* Keep track of sign */ numtype |= IS_NUMBER_NAN | IS_NUMBER_NOT_INT; } else if (s < send) { /* we can have an optional exponent part */ if (*s == 'e' || *s == 'E') { /* The only flag we keep is sign. Blow away any "it's UV" */ numtype &= IS_NUMBER_NEG; numtype |= IS_NUMBER_NOT_INT; s++; if (s < send && (*s == '-' || *s == '+')) s++; if (s < send && isDIGIT(*s)) { do { s++; } while (s < send && isDIGIT(*s)); } else return 0; } } while (s < send && isSPACE(*s)) s++; if (s >= send) return numtype; if (len == 10 && memEQ(pv, "0 but true", 10)) { if (valuep) *valuep = 0; return IS_NUMBER_IN_UV; } return 0; } #endif /* grok_number */ #ifndef PERL_MAGIC_sv # define PERL_MAGIC_sv '\0' #endif #ifndef PERL_MAGIC_overload # define PERL_MAGIC_overload 'A' #endif #ifndef PERL_MAGIC_overload_elem # define PERL_MAGIC_overload_elem 'a' #endif #ifndef PERL_MAGIC_overload_table # define PERL_MAGIC_overload_table 'c' #endif #ifndef PERL_MAGIC_bm # define PERL_MAGIC_bm 'B' #endif #ifndef PERL_MAGIC_regdata # define PERL_MAGIC_regdata 'D' #endif #ifndef PERL_MAGIC_regdatum # define PERL_MAGIC_regdatum 'd' #endif #ifndef PERL_MAGIC_env # define PERL_MAGIC_env 'E' #endif #ifndef PERL_MAGIC_envelem # define PERL_MAGIC_envelem 'e' #endif #ifndef PERL_MAGIC_fm # define PERL_MAGIC_fm 'f' #endif #ifndef PERL_MAGIC_regex_global # define PERL_MAGIC_regex_global 'g' #endif #ifndef PERL_MAGIC_isa # define PERL_MAGIC_isa 'I' #endif #ifndef PERL_MAGIC_isaelem # define PERL_MAGIC_isaelem 'i' #endif #ifndef PERL_MAGIC_nkeys # define PERL_MAGIC_nkeys 'k' #endif #ifndef PERL_MAGIC_dbfile # define PERL_MAGIC_dbfile 'L' #endif #ifndef PERL_MAGIC_dbline # define PERL_MAGIC_dbline 'l' #endif #ifndef PERL_MAGIC_mutex # define PERL_MAGIC_mutex 'm' #endif #ifndef PERL_MAGIC_shared # define PERL_MAGIC_shared 'N' #endif #ifndef PERL_MAGIC_shared_scalar # define PERL_MAGIC_shared_scalar 'n' #endif #ifndef PERL_MAGIC_collxfrm # define PERL_MAGIC_collxfrm 'o' #endif #ifndef PERL_MAGIC_tied # define PERL_MAGIC_tied 'P' #endif #ifndef PERL_MAGIC_tiedelem # define PERL_MAGIC_tiedelem 'p' #endif #ifndef PERL_MAGIC_tiedscalar # define PERL_MAGIC_tiedscalar 'q' #endif #ifndef PERL_MAGIC_qr # define PERL_MAGIC_qr 'r' #endif #ifndef PERL_MAGIC_sig # define PERL_MAGIC_sig 'S' #endif #ifndef PERL_MAGIC_sigelem # define PERL_MAGIC_sigelem 's' #endif #ifndef PERL_MAGIC_taint # define PERL_MAGIC_taint 't' #endif #ifndef PERL_MAGIC_uvar # define PERL_MAGIC_uvar 'U' #endif #ifndef PERL_MAGIC_uvar_elem # define PERL_MAGIC_uvar_elem 'u' #endif #ifndef PERL_MAGIC_vstring # define PERL_MAGIC_vstring 'V' #endif #ifndef PERL_MAGIC_vec # define PERL_MAGIC_vec 'v' #endif #ifndef PERL_MAGIC_utf8 # define PERL_MAGIC_utf8 'w' #endif #ifndef PERL_MAGIC_substr # define PERL_MAGIC_substr 'x' #endif #ifndef PERL_MAGIC_defelem # define PERL_MAGIC_defelem 'y' #endif #ifndef PERL_MAGIC_glob # define PERL_MAGIC_glob '*' #endif #ifndef PERL_MAGIC_arylen # define PERL_MAGIC_arylen '#' #endif #ifndef PERL_MAGIC_pos # define PERL_MAGIC_pos '.' #endif #ifndef PERL_MAGIC_backref # define PERL_MAGIC_backref '<' #endif #ifndef PERL_MAGIC_ext # define PERL_MAGIC_ext '~' #endif #endif /* _P_P_PORTABILITY_H_ */ /* End of File ppport.h */ ruli-0.33/perl/RULI/fallback/0000755000177100017710000000000010254521423016426 5ustar labratlabrat00000000000000ruli-0.33/perl/RULI/fallback/const-c.inc0000644000177100017710000000322510027507513020473 0ustar labratlabrat00000000000000#define PERL_constant_NOTFOUND 1 #define PERL_constant_NOTDEF 2 #define PERL_constant_ISIV 3 #define PERL_constant_ISNO 4 #define PERL_constant_ISNV 5 #define PERL_constant_ISPV 6 #define PERL_constant_ISPVN 7 #define PERL_constant_ISSV 8 #define PERL_constant_ISUNDEF 9 #define PERL_constant_ISUV 10 #define PERL_constant_ISYES 11 #ifndef NVTYPE typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it. */ #endif #ifndef aTHX_ #define aTHX_ /* 5.6 or later define this for threading support. */ #endif #ifndef pTHX_ #define pTHX_ /* 5.6 or later define this for threading support. */ #endif static int constant (pTHX_ const char *name, STRLEN len) { /* Initially switch on the length of the name. */ /* When generated this function returned values for the list of names given in this section of perl code. Rather than manually editing these functions to add or remove constants, which would result in this comment and section of code becoming inaccurate, we recommend that you edit this section of code, and use it to regenerate a new set of constant functions which you then use to replace the originals. Regenerate these constant functions by feeding this entire source file to perl -x #!/usr/bin/perl -w use ExtUtils::Constant qw (constant_types C_constant XS_constant); my $types = {map {($_, 1)} qw()}; my @names = (qw()); print constant_types(); # macro defs foreach (C_constant ("RULI", 'constant', 'IV', $types, undef, 3, @names) ) { print $_, "\n"; # C constant subs } print "#### XS Section:\n"; print XS_constant ("RULI", $types); __END__ */ switch (len) { } return PERL_constant_NOTFOUND; } ruli-0.33/perl/RULI/fallback/const-xs.inc0000644000177100017710000000506510027507513020707 0ustar labratlabrat00000000000000void constant(sv) PREINIT: #ifdef dXSTARG dXSTARG; /* Faster if we have it. */ #else dTARGET; #endif STRLEN len; int type; /* IV iv; Uncomment this if you need to return IVs */ /* NV nv; Uncomment this if you need to return NVs */ /* const char *pv; Uncomment this if you need to return PVs */ INPUT: SV * sv; const char * s = SvPV(sv, len); PPCODE: type = constant(aTHX_ s, len); /* Return 1 or 2 items. First is error message, or undef if no error. Second, if present, is found value */ switch (type) { case PERL_constant_NOTFOUND: sv = sv_2mortal(newSVpvf("%s is not a valid RULI macro", s)); PUSHs(sv); break; case PERL_constant_NOTDEF: sv = sv_2mortal(newSVpvf( "Your vendor has not defined RULI macro %s, used", s)); PUSHs(sv); break; /* Uncomment this if you need to return IVs case PERL_constant_ISIV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHi(iv); break; */ /* Uncomment this if you need to return NOs case PERL_constant_ISNO: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHs(&PL_sv_no); break; */ /* Uncomment this if you need to return NVs case PERL_constant_ISNV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHn(nv); break; */ /* Uncomment this if you need to return PVs case PERL_constant_ISPV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHp(pv, strlen(pv)); break; */ /* Uncomment this if you need to return PVNs case PERL_constant_ISPVN: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHp(pv, iv); break; */ /* Uncomment this if you need to return SVs case PERL_constant_ISSV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHs(sv); break; */ /* Uncomment this if you need to return UNDEFs case PERL_constant_ISUNDEF: break; */ /* Uncomment this if you need to return UVs case PERL_constant_ISUV: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHu((UV)iv); break; */ /* Uncomment this if you need to return YESs case PERL_constant_ISYES: EXTEND(SP, 1); PUSHs(&PL_sv_undef); PUSHs(&PL_sv_yes); break; */ default: sv = sv_2mortal(newSVpvf( "Unexpected return type %d while processing RULI macro %s, used", type, s)); PUSHs(sv); } ruli-0.33/perl/RULI/lib/0000755000177100017710000000000010254521423015435 5ustar labratlabrat00000000000000ruli-0.33/perl/RULI/lib/Net/0000755000177100017710000000000010254521423016163 5ustar labratlabrat00000000000000ruli-0.33/perl/RULI/lib/Net/RULI.pm0000644000177100017710000001103610133335300017266 0ustar labratlabrat00000000000000package Net::RULI; use 5.008003; use strict; use warnings; use Carp; require Exporter; use AutoLoader; our @ISA = qw(Exporter); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. # This allows declaration use RULI ':all'; # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( ); our $VERSION = '0.03'; sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. my $constname; our $AUTOLOAD; ($constname = $AUTOLOAD) =~ s/.*:://; croak "&RULI::constant not defined" if $constname eq 'constant'; my ($error, $val) = constant($constname); if ($error) { croak $error; } { no strict 'refs'; # Fixed between 5.005_53 and 5.005_61 #XXX if ($] >= 5.00561) { #XXX *$AUTOLOAD = sub () { $val }; #XXX } #XXX else { *$AUTOLOAD = sub { $val }; #XXX } } goto &$AUTOLOAD; } require XSLoader; XSLoader::load('Net::RULI', $VERSION); # Preloaded methods go here. # Autoload methods go after =cut, and are processed by the autosplit program. 1; __END__ # Stub documentation for RULI module. =head1 NAME Net::RULI - Perl extension for RULI, a library for easily querying DNS SRV resource records =head1 SYNOPSIS use Net::RULI; my $srv_list_ref = Net::RULI::ruli_sync_query($service, $domain, $fallback_port, $options); my $srv_list_ref = Net::RULI::ruli_sync_smtp_query($domain, $options); my $srv_list_ref = Net::RULI::ruli_sync_http_query($domain, $force_port, $options); =head1 DESCRIPTION RULI performs DNS queries for SRV records. The result is a ready-to-use list of SRV records. The whole logic demanded by SRV standards is already performed. It's the application role to try to contact every address in the given order. This function performs a query for a generic service: my $srv_list_ref = Net::RULI::ruli_sync_query($service, $domain, $fallback_port, $options); This function performs a query for the SMTP service: my $srv_list_ref = Net::RULI::ruli_sync_smtp_query($domain, $options); This function performs a query for the HTTP service: my $srv_list_ref = Net::RULI::ruli_sync_http_query($domain, $force_port, $options); The $options field is currently unused and should be set to 0 (zero). If the query fails for any reason, undef is returned by those functions. =head1 EXAMPLES =head2 Example 1 This example submits a generic query for FTP over TCP. my $srv_list_ref = Net::RULI::ruli_sync_query("_ftp._tcp", "bogus.tld", 21, 0); =head2 Example 2 This example submits a specific query for SMTP. my $srv_list_ref = Net::RULI::ruli_sync_smtp_query("bogus.tld", 0); =head2 Example 3 This example submits a specific query for HTTP. my $srv_list_ref = Net::RULI::ruli_sync_http_query("bogus.tld", -1, 0); =head2 Example 4 This example scans the list of SRV records returned by successful calls to RULI functions. foreach (@$srv_list_ref) { my $target = $_->{target}; my $priority = $_->{priority}; my $weight = $_->{weight}; my $port = $_->{port}; my $addr_list_ref = $_->{addr_list}; print " target=$target priority=$priority weight=$weight port=$port addresses="; foreach (@$addr_list_ref) { print $_, " "; } print "\n"; } =head1 SEE ALSO RFC 2782 - A DNS RR for specifying the location of services (DNS SRV) RULI Web Site: http://www.nongnu.org/ruli/ =head1 AUTHOR Everton da Silva Marques =head1 COPYRIGHT AND LICENSE Copyright (C) 2004 by Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =cut ruli-0.33/perl/RULI/t/0000755000177100017710000000000010254521423015132 5ustar labratlabrat00000000000000ruli-0.33/perl/RULI/t/RULI.t0000644000177100017710000000412510133305757016102 0ustar labratlabrat00000000000000# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl RULI.t' ######################### use Test::More tests => 12; BEGIN { use_ok('Net::RULI'); }; ######################### # Insert your test code below, the Test::More module is use()ed here so read # its man page ( perldoc Test::More ) for help writing this test script. sub dump_srv_list { my ($query, $srv_list_ref) = @_; diag("$query\n"); foreach (@$srv_list_ref) { my $target = $_->{target}; my $priority = $_->{priority}; my $weight = $_->{weight}; my $port = $_->{port}; my $addr_list_ref = $_->{addr_list}; diag(" target=$target priority=$priority weight=$weight port=$port addresses="); foreach (@$addr_list_ref) { diag("$_ "); } diag("\n"); } } ok(!defined(Net::RULI::ruli_sync_query('xxx', 'xxx', -1, 0))); my $service = "_http._tcp"; my $domain = "bocaaberta.com.br"; my $srv_list_ref = Net::RULI::ruli_sync_query($service, $domain, -1, 0); ok(defined($srv_list_ref)); ok(ref($srv_list_ref)); &dump_srv_list("ruli_sync_query: service=$service domain=$domain\n", $srv_list_ref); $service = "_http._tcp"; $domain = "uol.com.br"; $srv_list_ref = Net::RULI::ruli_sync_query($service, $domain, -1, 0); ok(defined($srv_list_ref)); ok(ref($srv_list_ref)); &dump_srv_list("ruli_sync_query: service=$service domain=$domain\n", $srv_list_ref); $domain = "aol.com"; $srv_list_ref = Net::RULI::ruli_sync_smtp_query($domain, 0); ok(defined($srv_list_ref)); ok(ref($srv_list_ref)); &dump_srv_list("ruli_sync_smtp_query: domain=$domain\n", $srv_list_ref); $domain = "kensingtonlabs.com"; $srv_list_ref = Net::RULI::ruli_sync_smtp_query($domain, 0); ok(defined($srv_list_ref)); ok(ref($srv_list_ref)); &dump_srv_list("ruli_sync_smtp_query: domain=$domain\n", $srv_list_ref); $domain = "registro.br"; $srv_list_ref = Net::RULI::ruli_sync_http_query($domain, -1, 0); ok(defined($srv_list_ref)); ok(ref($srv_list_ref)); &dump_srv_list("ruli_sync_http_query: domain=$domain\n", $srv_list_ref); ruli-0.33/php/0000755000177100017710000000000010254521423013741 5ustar labratlabrat00000000000000ruli-0.33/php/ruli/0000755000177100017710000000000010254521423014714 5ustar labratlabrat00000000000000ruli-0.33/php/ruli/EXPERIMENTAL0000644000177100017710000000000010026160022016511 0ustar labratlabrat00000000000000ruli-0.33/php/ruli/CREDITS0000644000177100017710000000000410026160022015715 0ustar labratlabrat00000000000000ruliruli-0.33/php/ruli/tests/0000755000177100017710000000000010254521423016056 5ustar labratlabrat00000000000000ruli-0.33/php/ruli/tests/001.phpt0000644000177100017710000000105610026160022017244 0ustar labratlabrat00000000000000--TEST-- Check for ruli presence --SKIPIF-- --POST-- --GET-- --INI-- --FILE-- --EXPECT-- ruli extension is available ruli-0.33/php/ruli/config.m40000644000177100017710000000315010026160022016411 0ustar labratlabrat00000000000000dnl $Id: config.m4,v 1.1 2004/03/17 23:32:34 evertonm Exp $ dnl config.m4 for extension ruli PHP_ARG_WITH(ruli, for ruli support, Make sure that the comment is aligned: [ --with-ruli Include ruli support]) if test "$PHP_RULI" != "no"; then # --with-ruli -> check with-path SEARCH_PATH="/usr/local/ruli /usr/local /usr" SEARCH_FOR="/include/ruli.h" if test -r $PHP_RULI/; then # path given as parameter RULI_DIR=$PHP_RULI if test -r $RULI_DIR/$SEARCH_FOR; then dnl AC_MSG_RESULT(found in $RULI_DIR) : else AC_MSG_RESULT(not found in $RULI_DIR) AC_MSG_ERROR([Please reinstall the ruli distribution]) fi else # search default path list AC_MSG_CHECKING([for ruli files in default path]) for i in $SEARCH_PATH ; do if test -r $i/$SEARCH_FOR; then RULI_DIR=$i AC_MSG_RESULT(found in $i) fi done fi if test -z "$RULI_DIR"; then AC_MSG_RESULT([not found]) AC_MSG_ERROR([Please reinstall the ruli distribution]) fi # --with-ruli -> add include path PHP_ADD_INCLUDE($RULI_DIR/include) # --with-ruli -> check for lib and symbol presence LIBNAME=ruli LIBSYMBOL=ruli_sync_query PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, [ PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $RULI_DIR/lib, RULI_SHARED_LIBADD) AC_DEFINE(HAVE_RULILIB,1,[ ]) ],[ AC_MSG_ERROR([wrong ruli lib version or lib not found]) ],[ -L$RULI_DIR/lib -loop ]) PHP_SUBST(RULI_SHARED_LIBADD) PHP_ADD_LIBRARY_WITH_PATH(oop, /usr/lib, OOP_SHARED_LIBADD) PHP_SUBST(OOP_SHARED_LIBADD) PHP_NEW_EXTENSION(ruli, php_ruli.c, $ext_shared) fi ruli-0.33/php/ruli/php_ruli.c0000644000177100017710000001774210137111544016714 0ustar labratlabrat00000000000000/* $Id: php_ruli.c,v 1.6 2004/10/25 05:47:16 evertonm Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_ruli.h" /* If you declare any globals in php_ruli.h uncomment this: ZEND_DECLARE_MODULE_GLOBALS(ruli) */ #if 0 /* True global resources - no need for thread safety here */ static int le_ruli; #endif /* {{{ ruli_functions[] * * Every user visible function must have an entry in ruli_functions[]. */ function_entry ruli_functions[] = { PHP_FE(confirm_ruli_compiled, NULL) /* For testing, remove later. */ PHP_FE(ruli_sync_query, NULL) PHP_FE(ruli_sync_smtp_query, NULL) PHP_FE(ruli_sync_http_query, NULL) {NULL, NULL, NULL} /* Must be the last line in ruli_functions[] */ }; /* }}} */ /* {{{ ruli_module_entry */ zend_module_entry ruli_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "ruli", ruli_functions, PHP_MINIT(ruli), PHP_MSHUTDOWN(ruli), PHP_RINIT(ruli), /* Replace with NULL if there's nothing to do at request start */ PHP_RSHUTDOWN(ruli), /* Replace with NULL if there's nothing to do at request end */ PHP_MINFO(ruli), #if ZEND_MODULE_API_NO >= 20010901 "0.2", /* Replace with version number for your extension */ #endif STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_RULI ZEND_GET_MODULE(ruli) #endif /* {{{ PHP_INI */ /* Remove comments and fill if you need to have entries in php.ini PHP_INI_BEGIN() STD_PHP_INI_ENTRY("ruli.global_value", "42", PHP_INI_ALL, OnUpdateInt, global_value, zend_ruli_globals, ruli_globals) STD_PHP_INI_ENTRY("ruli.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_ruli_globals, ruli_globals) PHP_INI_END() */ /* }}} */ /* {{{ php_ruli_init_globals */ /* Uncomment this function if you have INI entries static void php_ruli_init_globals(zend_ruli_globals *ruli_globals) { ruli_globals->global_value = 0; ruli_globals->global_string = NULL; } */ /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(ruli) { /* If you have INI entries, uncomment these lines ZEND_INIT_MODULE_GLOBALS(ruli, php_ruli_init_globals, NULL); REGISTER_INI_ENTRIES(); */ return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(ruli) { /* uncomment this line if you have INI entries UNREGISTER_INI_ENTRIES(); */ return SUCCESS; } /* }}} */ /* Remove if there's nothing to do at request start */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(ruli) { return SUCCESS; } /* }}} */ /* Remove if there's nothing to do at request end */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(ruli) { return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(ruli) { php_info_print_table_start(); php_info_print_table_header(2, "ruli support", "enabled"); php_info_print_table_end(); /* Remove comments if you have entries in php.ini DISPLAY_INI_ENTRIES(); */ } /* }}} */ /* Remove the following function when you have succesfully modified config.m4 so that your module can be compiled into PHP, it exists only for testing purposes. */ /* Every user-visible function in PHP should document itself in the source */ /* {{{ proto string confirm_ruli_compiled(string arg) Return a string to confirm that the module is compiled in */ PHP_FUNCTION(confirm_ruli_compiled) { char *arg = NULL; int arg_len, len; char string[256]; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) { return; } len = sprintf(string, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "ruli", arg); RETURN_STRINGL(string, len, 1); } /* }}} */ /* The previous line is meant for vim and emacs, so it can correctly fold and unfold functions in source code. See the corresponding marks just before function definition, where the functions purpose is also documented. Please follow this convention for the convenience of others editing your code. */ static int scan_srv_list(zval *return_value, ruli_sync_t *sync_query) { int srv_code; ruli_list_t *srv_list; int srv_list_size; int i; /* * Underlying SRV query failure? */ srv_code = ruli_sync_srv_code(sync_query); if (srv_code == RULI_SRV_CODE_ALARM) return -1; /* * Service provided? */ if (srv_code == RULI_SRV_CODE_UNAVAILABLE) return -1; /* * Server RCODE? */ if (srv_code) { int rcode = ruli_sync_rcode(sync_query); if (rcode) return -1; return -1; } srv_list = ruli_sync_srv_list(sync_query); srv_list_size = ruli_list_size(srv_list); /* * Scan list of SRV records */ array_init(return_value); for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; int j; zval *srv; zval *srv_addrs; if (ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, entry->target, entry->target_len)) continue; MAKE_STD_ZVAL(srv); array_init(srv); add_index_zval(return_value, i, srv); add_assoc_string(srv, "target", txt_dname_buf, 1); add_assoc_long(srv, "priority", entry->priority); add_assoc_long(srv, "weight", entry->weight); add_assoc_long(srv, "port", entry->port); MAKE_STD_ZVAL(srv_addrs); array_init(srv_addrs); add_assoc_zval(srv, "addr_list", srv_addrs); for (j = 0; j < addr_list_size; ++j) { ruli_addr_t *addr = ruli_list_get(addr_list, j); char buf[40]; if (ruli_addr_snprint(buf, 40, addr) < 0) continue; add_index_string(srv_addrs, j, buf, 1); } } return 0; } /* {{{ proto array ruli_sync_query(string service, string domain, int fallback_port, long options) query SRV records synchronously */ PHP_FUNCTION(ruli_sync_query) { char *service = NULL; char *domain = NULL; int argc = ZEND_NUM_ARGS(); int service_len; int domain_len; long fallback_port; long options; ruli_sync_t *sync_query; if (zend_parse_parameters(argc TSRMLS_CC, "ssll", &service, &service_len, &domain, &domain_len, &fallback_port, &options) == FAILURE) return; /* * Submit query */ sync_query = ruli_sync_query(service, domain, fallback_port, options); if (!sync_query) { RETURN_FALSE; } { int result; result = scan_srv_list(return_value, sync_query); ruli_sync_delete(sync_query); if (result) { RETURN_FALSE; } } } /* }}} */ /* {{{ proto array ruli_sync_smtp_query(string domain, long options) query SRV records synchronously for _smtp._tcp service */ PHP_FUNCTION(ruli_sync_smtp_query) { char *domain = NULL; int argc = ZEND_NUM_ARGS(); int domain_len; long options; ruli_sync_t *sync_query; if (zend_parse_parameters(argc TSRMLS_CC, "sl", &domain, &domain_len, &options) == FAILURE) return; /* * Submit query */ sync_query = ruli_sync_smtp_query(domain, options); if (!sync_query) { RETURN_FALSE; } { int result; result = scan_srv_list(return_value, sync_query); ruli_sync_delete(sync_query); if (result) { RETURN_FALSE; } } } /* }}} */ /* {{{ proto array ruli_sync_http_query(string domain, int force_port, long options) query SRV records synchronously for _http._tcp service */ PHP_FUNCTION(ruli_sync_http_query) { char *domain = NULL; int argc = ZEND_NUM_ARGS(); int domain_len; long force_port; long options; ruli_sync_t *sync_query; if (zend_parse_parameters(argc TSRMLS_CC, "sll", &domain, &domain_len, &force_port, &options) == FAILURE) return; /* * Submit query */ sync_query = ruli_sync_http_query(domain, force_port, options); if (!sync_query) { RETURN_FALSE; } { int result; result = scan_srv_list(return_value, sync_query); ruli_sync_delete(sync_query); if (result) { RETURN_FALSE; } } } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ ruli-0.33/php/ruli/php_ruli.h0000644000177100017710000000324010133335300016677 0ustar labratlabrat00000000000000/* $Id: php_ruli.h,v 1.3 2004/10/13 23:31:12 evertonm Exp $ */ #ifndef PHP_RULI_H #define PHP_RULI_H #include #include #include #include "ruli.h" extern zend_module_entry ruli_module_entry; #define phpext_ruli_ptr &ruli_module_entry #ifdef PHP_WIN32 #define PHP_RULI_API __declspec(dllexport) #else #define PHP_RULI_API #endif #ifdef ZTS #include "TSRM.h" #endif PHP_MINIT_FUNCTION(ruli); PHP_MSHUTDOWN_FUNCTION(ruli); PHP_RINIT_FUNCTION(ruli); PHP_RSHUTDOWN_FUNCTION(ruli); PHP_MINFO_FUNCTION(ruli); PHP_FUNCTION(confirm_ruli_compiled); /* For testing, remove later. */ PHP_FUNCTION(ruli_sync_query); PHP_FUNCTION(ruli_sync_smtp_query); PHP_FUNCTION(ruli_sync_http_query); /* Declare any global variables you may need between the BEGIN and END macros here: ZEND_BEGIN_MODULE_GLOBALS(ruli) long global_value; char *global_string; ZEND_END_MODULE_GLOBALS(ruli) */ /* In every utility function you add that needs to use variables in php_ruli_globals, call TSRMLS_FETCH(); after declaring other variables used by that function, or better yet, pass in TSRMLS_CC after the last function argument and declare your utility function with TSRMLS_DC after the last declared argument. Always refer to the globals in your function as RULI_G(variable). You are encouraged to rename these macros something shorter, see examples in any other php module directory. */ #ifdef ZTS #define RULI_G(v) TSRMG(ruli_globals_id, zend_ruli_globals *, v) #else #define RULI_G(v) (ruli_globals.v) #endif #endif /* PHP_RULI_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * indent-tabs-mode: t * End: */ ruli-0.33/php/ruli/php_ruli.make0000644000177100017710000000074110057674530017410 0ustar labratlabrat00000000000000# # $Id: php_ruli.make,v 1.2 2004/06/03 19:17:44 evertonm Exp $ # .PHONY: default default: php_ruli.so .PHONY: clean clean: rm -f *.o *.so *.lo .PHONY: build build: clean default php_ruli.o: php_ruli.c gcc -Wall -fPIC -DCOMPILE_DL_RULI=1 -I/usr/local/ruli/include -I/usr/local/include -I. -I.. -I../.. -I../../Zend -I../../main -I../../TSRM -c php_ruli.c php_ruli.so: php_ruli.o gcc -Wall -shared -L/usr/local/ruli/lib -L/usr/local/lib -rdynamic -o php_ruli.so php_ruli.o ruli-0.33/php/ruli/ruli.php0000644000177100017710000000070610026160022016372 0ustar labratlabrat00000000000000\n"; foreach($functions as $func) { echo $func."
\n"; } echo "
\n"; $function = 'confirm_' . $module . '_compiled'; if (extension_loaded($module)) { $str = $function($module); } else { $str = "Module $module is not compiled into PHP"; } echo "$str\n"; ?> ruli-0.33/php/ruli/ruli_php_proto0000644000177100017710000000054410133335300017700 0ustar labratlabrat00000000000000array ruli_sync_query(string service, string domain, int fallback_port, long options) query SRV records synchronously array ruli_sync_smtp_query(string domain, long options) query SRV records synchronously for _smtp._tcp service array ruli_sync_http_query(string domain, int force_port, long options) query SRV records synchronously for _http._tcp service ruli-0.33/php/ruli/ruli_sync_http_query.php0000644000177100017710000000070510137543266021733 0ustar labratlabrat00000000000000 ruli-0.33/php/ruli/ruli_sync_query.php0000644000177100017710000000077610026160022020662 0ustar labratlabrat00000000000000 ruli-0.33/php/ruli/ruli_sync_smtp_query.php0000644000177100017710000000065010026160022021714 0ustar labratlabrat00000000000000 ruli-0.33/php/README0000644000177100017710000000367010137512373014633 0ustar labratlabrat00000000000000# # $Id: README,v 1.7 2004/10/26 18:18:35 evertonm Exp $ # LICENSE Copyright (C) 2004 by Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. LINKING RULI AGAINST SOFTWARE DISTRIBUTED UNDER PHP LICENSE Additional to those permissions granted by the GNU Public License, permission is given to distribute copies of this work linked to software licenced under the terms of the PHP licence, Version 3.0 INTRODUCTION This is a PHP binding for RULI, a library for easily querying DNS SRV resource records. Please install the RULI library before installing this module. RULI is available from: http://www.nongnu.org/ruli/ You'll need RULI 0.32 or higher. Usage: 1) INSTALL RULI 2) GET PHP4 wget http://downloads.php.net/ilia/php-4.3.9.tar.gz 3) PUT RULI-PHP BINDING UNDER PHP4 SOURCE TREE tar xzf php-4.3.9.tar.gz cd php-4.3.9 cp -r $RULI_HOME/php/ruli ext 4) BUILD PHP4 ./buildconf --force ./configure --with-ruli make 5) TEST RULI-PHP BINDING # Test 1: ./sapi/cli/php -f ext/ruli/ruli.php # Test 2: ./sapi/cli/php -r 'print_r(ruli_sync_smtp_query("registro.br", 0));' # Test 3: ./sapi/cli/php -f ext/ruli/ruli_sync_query.php # Test 4: ./sapi/cli/php -f ext/ruli/ruli_sync_smtp_query.php # Test 5: ./sapi/cli/php -f ext/ruli/ruli_sync_http_query.php ruli-0.33/sample/0000755000177100017710000000000010254521423014433 5ustar labratlabrat00000000000000ruli-0.33/sample/Makefile0000644000177100017710000000461210131412767016102 0ustar labratlabrat00000000000000 # # $Id: Makefile,v 1.17 2004/10/08 04:22:15 evertonm Exp $ # # # OOP_INCLUDE_DIR points the location of # Liboop headers in your system # # OOP_LIB_DIR points the location of # Liboop libraries in your system # # Debian packaging likes this: OOP_BASE_DIR = /usr # OOP_BASE_DIR = /usr/local/oop OOP_INCLUDE_DIR = $(OOP_BASE_DIR)/include OOP_LIB_DIR = $(OOP_BASE_DIR)/lib # # INSTALL_BASE_DIR indicates where RULI # is to be installed in your system # # Debian packaging likes this: INSTALL_BASE_DIR = $(DESTDIR)/usr # INSTALL_BASE_DIR = ../install/ruli INSTALL_INCLUDE_DIR = $(INSTALL_BASE_DIR)/include INSTALL_LIB_DIR = $(INSTALL_BASE_DIR)/lib INSTALL_BIN_DIR = $(INSTALL_BASE_DIR)/bin INSTALL_MAN_DIR = $(INSTALL_BASE_DIR)/share/man INSTALL_MAN1_DIR = $(INSTALL_MAN_DIR)/man1 PLATFORM=$(shell uname) ifeq ($(PLATFORM),SunOS) SOLARIS_LIBS = -lresolv -lnsl -lsocket endif CC = gcc CFLAGS = -O2 -pipe -Wall -g -I../src -I$(OOP_INCLUDE_DIR) LDFLAGS = -L../src -L$(OOP_LIB_DIR) $(SOLARIS_LDFLAGS) LIBS = -lruli -loop $(SOLARIS_LIBS) LINK = $(CC) $(ARCH) $(LDFLAGS) -o $@ $^ $(LIBS) TARGETS = srvsearch sync_srvsearch smtpsearch sync_smtpsearch \ sync_httpsearch httpsearch ruli-getaddrinfo SHARED_OBJS = stdout_srv_list.o parse_options.o .PHONY: default default: $(TARGETS) .PHONY: clean clean: rm -f *~ .*~ *.o $(TARGETS) .PHONY: build build: clean default .PHONY: strip strip: $(TARGETS) strip $(TARGETS) .PHONY: install install: $(TARGETS) mkdir -p $(INSTALL_BIN_DIR) $(INSTALL_MAN1_DIR) cp $(TARGETS) $(INSTALL_BIN_DIR) cp ../doc/man/*.1 $(INSTALL_MAN1_DIR) cd $(INSTALL_MAN_DIR)/man1 && ln -s srvsearch.1 smtpsearch.1 cd $(INSTALL_MAN_DIR)/man1 && ln -s srvsearch.1 httpsearch.1 cd $(INSTALL_MAN_DIR)/man1 && ln -s srvsearch.1 sync_srvsearch.1 cd $(INSTALL_MAN_DIR)/man1 && ln -s srvsearch.1 sync_smtpsearch.1 cd $(INSTALL_MAN_DIR)/man1 && ln -s srvsearch.1 sync_httpsearch.1 cd $(INSTALL_MAN_DIR)/man1 && ln -s srvsearch.1 ruli-getaddrinfo.1 %.o: %.c $(CC) $(ARCH) $(CPPFLAGS) $(CFLAGS) -c $< srvsearch: srvsearch.o $(SHARED_OBJS) $(LINK) sync_srvsearch: sync_srvsearch.o $(SHARED_OBJS) $(LINK) smtpsearch: smtpsearch.o $(SHARED_OBJS) $(LINK) sync_smtpsearch: sync_smtpsearch.o $(SHARED_OBJS) $(LINK) httpsearch: httpsearch.o $(SHARED_OBJS) $(LINK) sync_httpsearch: sync_httpsearch.o $(SHARED_OBJS) $(LINK) ruli-getaddrinfo: ruli-getaddrinfo.o $(SHARED_OBJS) $(LINK) ruli-0.33/sample/httpsearch.c0000644000177100017710000001476010131412767016760 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: httpsearch.c,v 1.1 2004/10/08 04:22:15 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "parse_options.h" #include "stdout_srv_list.h" const char *prog_name; #define QBUFSZ RULI_LIMIT_DNAME_TEXT_BUFSZ /* * Store query buffers */ typedef struct { char txt_domain[QBUFSZ]; int txt_domain_len; } srv_qbuf_t; const int QBUF_SIZE = sizeof(srv_qbuf_t); static void release_query(ruli_search_srv_t *search, srv_qbuf_t *qbuf) { ruli_search_srv_delete(search); ruli_free(qbuf); } static void *on_search_answer(ruli_search_srv_t *search, void *search_arg) { srv_qbuf_t *qbuf = (srv_qbuf_t *) search_arg; int code; assert(search); code = ruli_search_srv_code(search); assert(code != RULI_SRV_CODE_VOID); /* * Timeout? */ if (code == RULI_SRV_CODE_ALARM) { printf("%s timeout\n", qbuf->txt_domain); release_query(search, qbuf); return OOP_CONTINUE; } /* * Service is not provided by that domain? */ if (code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s http-service-not-provided\n", qbuf->txt_domain); release_query(search, qbuf); return OOP_CONTINUE; } /* * Other error? */ if (code) { int rcode = ruli_search_srv_rcode(search); printf("%s srv-failure code=%d rcode=%d\n", qbuf->txt_domain, code, rcode); release_query(search, qbuf); return OOP_CONTINUE; } /* * Query successful */ show_srv_list(qbuf->txt_domain, ruli_search_srv_answer_list(search)); release_query(search, qbuf); return OOP_CONTINUE; } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef SRVSEARCH_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static void do_query(ruli_res_t *res_ctx, const char *domain, int port, long options) { srv_qbuf_t *qbuf; /* Allocate qbuf */ qbuf = (srv_qbuf_t *) ruli_malloc(QBUF_SIZE); if (!qbuf) { fprintf(stderr, "%s: do_query(): could not allocate srv_qbuf_t: ruli_malloc(%d) failed\n", prog_name, QBUF_SIZE); return; } qbuf->txt_domain_len = strlen(domain); assert(qbuf->txt_domain_len < QBUFSZ); strcpy(qbuf->txt_domain, domain); /* * Send query */ { ruli_search_srv_t *search = ruli_search_http_submit(res_ctx, on_search_answer, qbuf, port, options, qbuf->txt_domain); if (!search) { fprintf(stderr, "%s: do_query(): could not send SRV query\n", prog_name); ruli_free(qbuf); return; } } /* * Submitted */ } static void go(int port, long options) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_search_res_t *search_res; ruli_res_t *res; int retry = 2; int timeout = 10; /* seconds */ /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ search_res = ruli_search_res_new(source, retry, timeout); if (!search_res) { fprintf(stderr, "%s: can't create ruli resolver\n", prog_name); exit(1); } assert(search_res); res = ruli_search_resolver(search_res); assert(res); for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(res, tok, port, options); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ /* * Run event loop */ { void *oop_result = run_event_loop(source_sys); if (oop_result != OOP_CONTINUE) break; } } /* for */ /* * Destroy resolver */ ruli_search_res_delete(search_res); /* * Destroy event source */ oop_sys_delete(source_sys); } int main(int argc, const char **argv) { long options; prog_name = argv[0]; int i = 1; int port = -1; if (argc > 1) { port = atoi(argv[1]); if (port) ++i; } options = parse_options(argc, argv, i); go(port, options); exit(0); } ruli-0.33/sample/parse_options.c0000644000177100017710000000413610130624174017470 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: parse_options.c,v 1.2 2004/10/05 23:04:28 evertonm Exp $ */ #include #include #include #include "parse_options.h" struct opt_map { const char *name; long option; } opt_table[] = { { "search", RULI_RES_OPT_SEARCH }, { "need_ra", RULI_RES_OPT_NEED_RA }, { "noinet", RULI_RES_OPT_SRV_NOINET }, { "noinet6", RULI_RES_OPT_SRV_NOINET6 }, { "uri_port", RULI_RES_OPT_SRV_URI_PORT }, { "nowalk", RULI_RES_OPT_SRV_NOWALK }, { "nofall", RULI_RES_OPT_SRV_NOFALL }, { "nosort6", RULI_RES_OPT_SRV_NOSORT6 }, { 0, 0 } }; long parse_options(int argc, const char *argv[], int first) { long options = 0; int i; for (i = first; i < argc; ++i) { const char *arg = argv[i]; int j; if (!strncmp(arg, "h", 1) || !strncmp(arg, "-h", 2)) { printf("%s: available resolver options:", argv[0]); for (j = 0;; ++j) { struct opt_map opt = opt_table[j]; if (!opt.name) break; printf(" %s", opt.name); } printf("\n"); exit(0); } for (j = 0;; ++j) { struct opt_map opt = opt_table[j]; if (!opt.name) { fprintf(stderr, "%s: ignoring unknown resolver option: %s\n", argv[0], arg); break; } if (!strcmp(arg, opt.name)) { options |= opt.option; break; } } } return options; } ruli-0.33/sample/parse_options.h0000644000177100017710000000177710065427763017521 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: parse_options.h,v 1.1 2004/06/21 00:46:43 evertonm Exp $ */ #ifndef PARSE_OPTIONS_H #define PARSE_OPTIONS_H long parse_options(int argc, const char *argv[], int first); #endif /* PARSE_OPTIONS_H */ ruli-0.33/sample/ruli-getaddrinfo.c0000644000177100017710000001241210064101512020026 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli-getaddrinfo.c,v 1.6 2004/06/16 17:28:42 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "stdout_srv_list.h" const int INBUFSZ = 1024; const char *prog_name; static void solve(const char *fullname) { int name_len = strlen(fullname); char name[name_len + 1]; char *txt_service; int txt_service_len; char *txt_domain; int txt_domain_len; memcpy(name, fullname, name_len + 1); /* * Split full domain name in service + domain * Example: _http._tcp.domain => _http._tcp + domain */ { int name_len = strlen(name); char *past_end = name + name_len; char *i = name; assert(name_len > 0); assert(name_len < INBUFSZ); if (*i != '_') { fprintf(stderr, "%s: solve(): could not match _service\n", prog_name); return; } /* * Find domain */ for (; i < past_end; ++i) { if (*i == '.') { ++i; if (i < past_end) { if (*i != '_') break; } } } if (i >= past_end) { fprintf(stderr, "%s: solve(): could not split service/domain\n", prog_name); return; } txt_service = name; txt_service_len = i - name - 1; txt_domain = i; txt_domain_len = past_end - i; txt_service[txt_service_len] = '\0'; } /* * Submit query */ { const int BUFSZ = RULI_LIMIT_LABEL_HIGH + 1; /* = 64 */ struct addrinfo hints; struct addrinfo *ai_res; char service[BUFSZ]; struct protoent *pe; char *i, *j; int result; /* * from: txt_service = "_smtp._tcp" * make: service = "smtp" */ i = txt_service; assert(*i == '_'); ++i; assert(i < (txt_service + txt_service_len)); j = (char *) memchr(i, '.', txt_service_len - (i - txt_service)); assert(j); assert(*j == '.'); memcpy(service, i, j - i); service[j - i] = '\0'; /* * j = "._tcp"; */ if (!strcasecmp(j, "._tcp")) hints.ai_socktype = SOCK_STREAM; else if (!strcasecmp(j, "._udp")) hints.ai_socktype = SOCK_DGRAM; else { printf("%s bad-socket-type: %s\n", fullname, j); return; } j += 2; assert(j < (txt_service + txt_service_len)); /* * j = "tcp"; */ pe = getprotobyname(j); if (!pe) { printf("%s bad-protocol: %s\n", fullname, j); return; } hints.ai_protocol = pe->p_proto; hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_addrlen = 0; hints.ai_addr = 0; hints.ai_canonname = 0; result = ruli_getaddrinfo(txt_domain, service, &hints, &ai_res); if (result) { printf("%s getaddrinfo-failed: %s\n", fullname, gai_strerror(result)); return; } /* show addresses */ { struct addrinfo *ai; for (ai = ai_res; ai; ai = ai->ai_next) { printf(fullname); switch (ai->ai_family) { case PF_INET: { struct sockaddr_in *sa = (struct sockaddr_in *) ai->ai_addr; assert(sizeof(*sa) <= ai->ai_addrlen); printf(" canon=%s port=%d IPv4/%s\n", ai->ai_canonname, ntohs(sa->sin_port), inet_ntoa(sa->sin_addr)); } break; case PF_INET6: { struct sockaddr_in6 *sa = (struct sockaddr_in6 *) ai->ai_addr; assert(sizeof(*sa) <= ai->ai_addrlen); printf(" canon=%s port=%d IPv6/", ai->ai_canonname, ntohs(sa->sin6_port)); ruli_inet6_print(stdout, &sa->sin6_addr); printf("\n"); } break; default: assert(0); } } /* scan list */ } /* show addresses */ ruli_freeaddrinfo(ai_res); } /* submit query */ } static void go() { char inbuf[INBUFSZ]; /* * Scan stdin */ for (;;) { if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Make SRV query for token */ solve(tok); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ } } int main(int argc, char *argv[]) { prog_name = argv[0]; go(); exit(0); } ruli-0.33/sample/smtpsearch.c0000644000177100017710000001452310065425115016756 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: smtpsearch.c,v 1.3 2004/06/21 00:22:37 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "parse_options.h" #include "stdout_srv_list.h" const char *prog_name; #define QBUFSZ RULI_LIMIT_DNAME_TEXT_BUFSZ /* * Store query buffers */ typedef struct { char txt_domain[QBUFSZ]; int txt_domain_len; } srv_qbuf_t; const int QBUF_SIZE = sizeof(srv_qbuf_t); static void release_query(ruli_search_srv_t *search, srv_qbuf_t *qbuf) { ruli_search_srv_delete(search); ruli_free(qbuf); } static void *on_search_answer(ruli_search_srv_t *search, void *search_arg) { srv_qbuf_t *qbuf = (srv_qbuf_t *) search_arg; int code; assert(search); code = ruli_search_srv_code(search); assert(code != RULI_SRV_CODE_VOID); /* * Timeout? */ if (code == RULI_SRV_CODE_ALARM) { printf("%s timeout\n", qbuf->txt_domain); release_query(search, qbuf); return OOP_CONTINUE; } /* * Service is not provided by that domain? */ if (code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s smtp-service-not-provided\n", qbuf->txt_domain); release_query(search, qbuf); return OOP_CONTINUE; } /* * Other error? */ if (code) { int rcode = ruli_search_srv_rcode(search); printf("%s srv-failure code=%d rcode=%d\n", qbuf->txt_domain, code, rcode); release_query(search, qbuf); return OOP_CONTINUE; } /* * Query successful */ show_srv_list(qbuf->txt_domain, ruli_search_srv_answer_list(search)); release_query(search, qbuf); return OOP_CONTINUE; } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef SRVSEARCH_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static void do_query(ruli_res_t *res_ctx, const char *domain, long options) { srv_qbuf_t *qbuf; /* Allocate qbuf */ qbuf = (srv_qbuf_t *) ruli_malloc(QBUF_SIZE); if (!qbuf) { fprintf(stderr, "%s: do_query(): could not allocate srv_qbuf_t: ruli_malloc(%d) failed\n", prog_name, QBUF_SIZE); return; } qbuf->txt_domain_len = strlen(domain); assert(qbuf->txt_domain_len < QBUFSZ); strcpy(qbuf->txt_domain, domain); /* * Send query */ { ruli_search_srv_t *search = ruli_search_smtp_submit(res_ctx, on_search_answer, qbuf, options, qbuf->txt_domain); if (!search) { fprintf(stderr, "%s: do_query(): could not send SRV query\n", prog_name); ruli_free(qbuf); return; } } /* * Submitted */ } static void go(long options) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_search_res_t *search_res; ruli_res_t *res; int retry = 2; int timeout = 10; /* seconds */ /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ search_res = ruli_search_res_new(source, retry, timeout); if (!search_res) { fprintf(stderr, "%s: can't create ruli resolver\n", prog_name); exit(1); } assert(search_res); res = ruli_search_resolver(search_res); assert(res); for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(res, tok, options); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ /* * Run event loop */ { void *oop_result = run_event_loop(source_sys); if (oop_result != OOP_CONTINUE) break; } } /* for */ /* * Destroy resolver */ ruli_search_res_delete(search_res); /* * Destroy event source */ oop_sys_delete(source_sys); } int main(int argc, const char **argv) { long options; prog_name = argv[0]; options = parse_options(argc, argv, 1); go(options); exit(0); } ruli-0.33/sample/srvsearch.c0000644000177100017710000001773110065425115016611 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: srvsearch.c,v 1.8 2004/06/21 00:22:37 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "parse_options.h" #include "stdout_srv_list.h" const char *prog_name; #define QBUFSZ RULI_LIMIT_DNAME_TEXT_BUFSZ /* * Store query buffers */ typedef struct { char txt_service[QBUFSZ]; int txt_service_len; char txt_domain[QBUFSZ]; int txt_domain_len; } srv_qbuf_t; const int QBUF_SIZE = sizeof(srv_qbuf_t); static void release_query(ruli_search_srv_t *search, srv_qbuf_t *qbuf) { ruli_search_srv_delete(search); ruli_free(qbuf); } static void *on_search_answer(ruli_search_srv_t *search, void *search_arg) { srv_qbuf_t *qbuf = (srv_qbuf_t *) search_arg; int code; assert(search); code = ruli_search_srv_code(search); assert(code != RULI_SRV_CODE_VOID); /* * Timeout? */ if (code == RULI_SRV_CODE_ALARM) { printf("%s.%s timeout\n", qbuf->txt_service, qbuf->txt_domain); release_query(search, qbuf); return OOP_CONTINUE; } /* * Service is not provided by that domain? */ if (code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s.%s service-not-provided\n", qbuf->txt_service, qbuf->txt_domain); release_query(search, qbuf); return OOP_CONTINUE; } /* * Other error? */ if (code) { int rcode = ruli_search_srv_rcode(search); printf("%s.%s srv-failure code=%d rcode=%d\n", qbuf->txt_service, qbuf->txt_domain, code, rcode); release_query(search, qbuf); return OOP_CONTINUE; } /* * Query successful */ { char fullname[RULI_LIMIT_DNAME_TEXT_BUFSZ]; snprintf(fullname, RULI_LIMIT_DNAME_TEXT_BUFSZ, "%s.%s", qbuf->txt_service, qbuf->txt_domain); show_srv_list(fullname, ruli_search_srv_answer_list(search)); } release_query(search, qbuf); return OOP_CONTINUE; } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef SRVSEARCH_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static void do_query(ruli_res_t *res_ctx, const char *domain, long options) { srv_qbuf_t *qbuf; /* * Break full domain name in service + domain into qbuf */ { int domain_len = strlen(domain); const char *past_end = domain + domain_len; const char *i = domain; if (*i != '_') { fprintf(stderr, "%s: do_query(): could not match _service\n", prog_name); return; } for (; i < past_end; ++i) { if (*i == '.') { ++i; if (i < past_end) { if (*i != '_') break; } } } if (i >= past_end) { fprintf(stderr, "%s: do_query(): could not split service/domain\n", prog_name); return; } /* Allocate qbuf */ qbuf = (srv_qbuf_t *) ruli_malloc(QBUF_SIZE); if (!qbuf) { fprintf(stderr, "%s: do_query(): could not allocate srv_qbuf_t: ruli_malloc(%d) failed\n", prog_name, QBUF_SIZE); return; } qbuf->txt_service_len = i - domain - 1; assert(qbuf->txt_service_len < QBUFSZ); memcpy(qbuf->txt_service, domain, qbuf->txt_service_len); qbuf->txt_service[qbuf->txt_service_len] = '\0'; #ifdef SRVSEARCH_DEBUG debug_dump_buf(stderr, "do_query(): txt_service=%s txt_service_len=%d", qbuf->txt_service, qbuf->txt_service_len); #endif qbuf->txt_domain_len = past_end - i; assert(qbuf->txt_domain_len < QBUFSZ); memcpy(qbuf->txt_domain, i, qbuf->txt_domain_len); qbuf->txt_domain[qbuf->txt_domain_len] = '\0'; #ifdef SRVSEARCH_DEBUG debug_dump_buf(stderr, "do_query(): txt_domain=%s txt_domain_len=%d", qbuf->txt_domain, qbuf->txt_domain_len); #endif } /* Break full domain name in service + domain into qbuf */ /* * Send query */ { ruli_search_srv_t *search = ruli_search_srv_submit(res_ctx, on_search_answer, qbuf, options, qbuf->txt_service, qbuf->txt_domain, -1); if (!search) { fprintf(stderr, "%s: do_query(): could not send SRV query\n", prog_name); ruli_free(qbuf); return; } } /* * Submitted */ } static void go(long options) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_search_res_t *search_res; ruli_res_t *res; int retry = 2; int timeout = 10; /* seconds */ /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ search_res = ruli_search_res_new(source, retry, timeout); if (!search_res) { fprintf(stderr, "%s: can't create ruli resolver\n", prog_name); exit(1); } assert(search_res); res = ruli_search_resolver(search_res); assert(res); for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(res, tok, options); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ /* * Run event loop */ { void *oop_result = run_event_loop(source_sys); if (oop_result != OOP_CONTINUE) break; } } /* for */ /* * Destroy resolver */ ruli_search_res_delete(search_res); /* * Destroy event source */ oop_sys_delete(source_sys); } int main(int argc, const char **argv) { long options; prog_name = argv[0]; options = parse_options(argc, argv, 1); go(options); exit(0); } ruli-0.33/sample/stdout_srv_list.c0000644000177100017710000000505510055735137020063 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: stdout_srv_list.c,v 1.7 2004/05/28 22:17:03 evertonm Exp $ */ #include #include #include #include #include #include "stdout_srv_list.h" void show_srv_list(const char *fullname, const ruli_list_t *srv_list) { int srv_list_size = ruli_list_size(srv_list); int i; assert(srv_list_size >= 0); if (srv_list_size < 1) { printf("%s empty\n", fullname); return; } /* * Scan list of SRV records */ for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); int j; /* * Show original full query name */ printf("%s ", fullname); /* * Show target */ { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; if (ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, entry->target, entry->target_len)) { printf("target-decoding-failed\n"); continue; } printf("target=%s ", txt_dname_buf); } /* * Show port number and addresses */ printf("priority=%d weight=%d port=%d addresses=", entry->priority, entry->weight, entry->port); /* * Scan addresses */ for (j = 0; j < addr_list_size; ++j) { ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, j); switch (ruli_addr_family(addr)) { case PF_INET: printf("IPv4/"); break; case PF_INET6: printf("IPv6/"); break; default: printf("?/"); } ruli_addr_print(stdout, addr); printf(" "); } printf("\n"); } } ruli-0.33/sample/stdout_srv_list.h0000644000177100017710000000204507622362554020071 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: stdout_srv_list.h,v 1.1 2003/02/12 06:10:52 evertonm Exp $ */ #ifndef STDOUT_SRV_LIST_H #define STDOUT_SRV_LIST_H #include void show_srv_list(const char *fullname, const ruli_list_t *srv_list); #endif /* STDOUT_SRV_LIST_H */ ruli-0.33/sample/sync_httpsearch.c0000644000177100017710000000617710131351173020010 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: sync_httpsearch.c,v 1.1 2004/10/07 23:34:19 evertonm Exp $ */ #include #include #include #include #include #include #include #include "parse_options.h" #include "stdout_srv_list.h" const int INBUFSZ = 1024; const char *prog_name; static void solve(const char *fullname, int port, long options) { int srv_code; ruli_sync_t *sync_query = ruli_sync_http_query(fullname, port, options); /* * Sync query failure? */ if (!sync_query) { printf("%s could-not-submit-query\n", fullname); return; } /* * Underlying SRV query failure? */ srv_code = ruli_sync_srv_code(sync_query); assert(srv_code != RULI_SRV_CODE_VOID); /* Timeout ? */ if (srv_code == RULI_SRV_CODE_ALARM) { printf("%s timeout\n", fullname); ruli_sync_delete(sync_query); return; } /* Service provided ? */ if (srv_code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s srv-service-not-provided\n", fullname); ruli_sync_delete(sync_query); return; } if (srv_code) { int rcode = ruli_sync_rcode(sync_query); printf("%s srv-query-failed: srv_code=%d rcode=%d\n", fullname, srv_code, rcode); ruli_sync_delete(sync_query); return; } /* * Show the result */ show_srv_list(fullname, ruli_sync_srv_list(sync_query)); ruli_sync_delete(sync_query); } static void go(int port, long options) { char inbuf[INBUFSZ]; /* * Scan stdin */ for (;;) { if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Make SRV query for token */ solve(tok, port, options); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ } } int main(int argc, const char *argv[]) { long options; prog_name = argv[0]; int i = 1; int port = -1; if (argc > 1) { port = atoi(argv[1]); if (port) ++i; } options = parse_options(argc, argv, i); go(port, options); exit(0); } ruli-0.33/sample/sync_smtpsearch.c0000644000177100017710000000576110065425115020016 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: sync_smtpsearch.c,v 1.2 2004/06/21 00:22:37 evertonm Exp $ */ #include #include #include #include #include #include #include #include "parse_options.h" #include "stdout_srv_list.h" const int INBUFSZ = 1024; const char *prog_name; static void solve(const char *fullname, long options) { int srv_code; ruli_sync_t *sync_query = ruli_sync_smtp_query(fullname, options); /* * Sync query failure? */ if (!sync_query) { printf("%s could-not-submit-query\n", fullname); return; } /* * Underlying SRV query failure? */ srv_code = ruli_sync_srv_code(sync_query); assert(srv_code != RULI_SRV_CODE_VOID); /* Timeout ? */ if (srv_code == RULI_SRV_CODE_ALARM) { printf("%s timeout\n", fullname); ruli_sync_delete(sync_query); return; } /* Service provided ? */ if (srv_code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s srv-service-not-provided\n", fullname); ruli_sync_delete(sync_query); return; } if (srv_code) { int rcode = ruli_sync_rcode(sync_query); printf("%s srv-query-failed: srv_code=%d rcode=%d\n", fullname, srv_code, rcode); ruli_sync_delete(sync_query); return; } /* * Show the result */ show_srv_list(fullname, ruli_sync_srv_list(sync_query)); ruli_sync_delete(sync_query); } static void go(long options) { char inbuf[INBUFSZ]; /* * Scan stdin */ for (;;) { if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Make SRV query for token */ solve(tok, options); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ } } int main(int argc, const char *argv[]) { long options; prog_name = argv[0]; options = parse_options(argc, argv, 1); go(options); exit(0); } ruli-0.33/sample/sync_srvsearch.c0000644000177100017710000001027010065425115017634 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: sync_srvsearch.c,v 1.3 2004/06/21 00:22:37 evertonm Exp $ */ #include #include #include #include #include #include #include #include "parse_options.h" #include "stdout_srv_list.h" const int INBUFSZ = 1024; const char *prog_name; static void solve(const char *fullname, long options) { int name_len = strlen(fullname); char name[name_len + 1]; char *txt_service; int txt_service_len; char *txt_domain; int txt_domain_len; memcpy(name, fullname, name_len + 1); /* * Split full domain name in service + domain * Example: _http._tcp.domain => _http._tcp + domain */ { int name_len = strlen(name); char *past_end = name + name_len; char *i = name; assert(name_len > 0); assert(name_len < INBUFSZ); if (*i != '_') { fprintf(stderr, "%s: solve(): could not match _service\n", prog_name); return; } /* * Find domain */ for (; i < past_end; ++i) { if (*i == '.') { ++i; if (i < past_end) { if (*i != '_') break; } } } if (i >= past_end) { fprintf(stderr, "%s: solve(): could not split service/domain\n", prog_name); return; } txt_service = name; txt_service_len = i - name - 1; txt_domain = i; txt_domain_len = past_end - i; txt_service[txt_service_len] = '\0'; } /* * Submit synchronous query */ { ruli_sync_t *sync_query = ruli_sync_query(txt_service, txt_domain, -1, options); int srv_code; /* * Sync query failure? */ if (!sync_query) { printf("%s could-not-submit-query\n", fullname); return; } /* * Underlying SRV query failure? */ srv_code = ruli_sync_srv_code(sync_query); assert(srv_code != RULI_SRV_CODE_VOID); /* Timeout ? */ if (srv_code == RULI_SRV_CODE_ALARM) { printf("%s timeout\n", fullname); ruli_sync_delete(sync_query); return; } /* Service provided ? */ if (srv_code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s srv-service-not-provided\n", fullname); ruli_sync_delete(sync_query); return; } if (srv_code) { int rcode = ruli_sync_rcode(sync_query); printf("%s srv-query-failed: srv_code=%d rcode=%d\n", fullname, srv_code, rcode); ruli_sync_delete(sync_query); return; } /* * Show the result */ show_srv_list(fullname, ruli_sync_srv_list(sync_query)); ruli_sync_delete(sync_query); } } static void go(long options) { char inbuf[INBUFSZ]; /* * Scan stdin */ for (;;) { if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Make SRV query for token */ solve(tok, options); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ } } int main(int argc, const char *argv[]) { long options; prog_name = argv[0]; options = parse_options(argc, argv, 1); go(options); exit(0); } ruli-0.33/src/0000755000177100017710000000000010254521423013741 5ustar labratlabrat00000000000000ruli-0.33/src/Makefile0000644000177100017710000001010610253332655015405 0ustar labratlabrat00000000000000# # $Id: Makefile,v 1.57 2005/06/13 16:34:53 evertonm Exp $ # #DEBUG += -DRULI_SRV_DEBUG #DEBUG += -DRULI_HOST_DEBUG #DEBUG += -DRULI_RES_DEBUG #DEBUG += -DRULI_TXT_COMPARE_DEBUG #DEBUG += -DRULI_SYNC_DEBUG #DEBUG += -DRULI_SEARCH_DEBUG #DEBUG += -DRULI_MSG_DUMP_DEBUG -DRULI_SOCK_DUMP_DEBUG #DEBUG += -DRULI_SMTP_DEBUG #DEBUG += -DRULI_RFC3484_DEBUG # # OOP_INCLUDE_DIR points the location of # Liboop headers in your system # # Debian packaging likes this: OOP_BASE_DIR = /usr # OOP_BASE_DIR = /usr/local/oop OOP_INCLUDE_DIR = $(OOP_BASE_DIR)/include OOP_LIB_DIR = $(OOP_BASE_DIR)/lib # # INSTALL_BASE_DIR indicates where RULI # is to be installed in your system # # Example: INSTALL_BASE_DIR=/usr/local/ruli # # Debian packaging likes this: INSTALL_BASE_DIR = $(DESTDIR)/usr # INSTALL_BASE_DIR = ../install/ruli INSTALL_INCLUDE_DIR = $(INSTALL_BASE_DIR)/include INSTALL_LIB_DIR = $(INSTALL_BASE_DIR)/lib INSTALL_MAN_DIR = $(INSTALL_BASE_DIR)/share/man INSTALL_MAN3_DIR = $(INSTALL_MAN_DIR)/man3 # SunOS, Linux PLATFORM=$(shell uname) ifeq ($(PLATFORM),SunOS) DEFINE_SOLARIS = -D_RULI_SOLARIS_ endif WARN = -pedantic -ansi -Wshadow -Wpointer-arith -Wcast-qual \ -Wcast-align -Wwrite-strings -Wredundant-decls CC = gcc # gcc-specific options (not valid for g++) ifeq ($(CC),gcc) WARN += -Wnested-externs WARN += -Wmissing-prototypes WARN += -Wstrict-prototypes endif SHARED = -fPIC FLAGS = $(DEBUG) -O2 -pipe -Wall -g -shared -D_REENTRANT \ $(DEFINE_SOLARIS) -I. -I$(OOP_INCLUDE_DIR) SOFT_CFLAGS = $(WARN) $(FLAGS) CFLAGS = $(WARN) -Werror $(FLAGS) LIBOBJ = ruli_isaac.o ruli_mem.o ruli_rand.o ruli_util.o ruli_list.o \ ruli_addr.o ruli_sock.o ruli_txt.o ruli_msg.o ruli_fsm.o \ ruli_res.o ruli_parse.o ruli_host.o ruli_srv.o ruli_conf.o \ ruli_search.o ruli_http.o ruli_smtp.o ruli_sync.o \ ruli_getaddrinfo.o SHAREDOBJ = $(LIBOBJ:%.o=%.os) SONAME = libruli.so.4 LDFLAGS = -L$(OOP_LIB_DIR) COMPILE = $(CC) $(ARCH) $(CPPFLAGS) $(CFLAGS) -c SHARED_COMPILE = $(CC) $(ARCH) $(CPPFLAGS) $(SHARED) $(CFLAGS) -o $@ -c # no -Werror SOFT_COMPILE = $(CC) $(ARCH) $(CPPFLAGS) $(SOFT_CFLAGS) -c SHARED_SOFT_COMPILE = $(CC) $(ARCH) $(CPPFLAGS) $(SHARED) $(SOFT_CFLAGS) -o $@ -c .PHONY: default default: ruli .PHONY: clean clean: rm -f *~ .*~ *.o *.os *.so *.a *.so.* .PHONY: build build: clean default .PHONY: strip strip: ruli strip $(SONAME) libruli.a .PHONY: install install: ruli mkdir -p $(INSTALL_LIB_DIR) $(INSTALL_INCLUDE_DIR) $(INSTALL_MAN3_DIR) cp $(SONAME) libruli.a $(INSTALL_LIB_DIR) cp *.h $(INSTALL_INCLUDE_DIR) cp ../doc/man/*.3 $(INSTALL_MAN3_DIR) cd $(INSTALL_LIB_DIR) && ln -s $(SONAME) libruli.so @echo @echo "REMINDER:" @echo "Add $(INSTALL_LIB_DIR) to your dynamic loader path:" @echo "# echo $(INSTALL_LIB_DIR) >> /etc/ld.so.conf" @echo "# ldconfig" @echo .PHONY: ruli ruli: $(SONAME) libruli.a # # This "SOFT" section forces compiling of some # source files without the -Werror options. # ruli_util.o: ruli_util.c ruli_util.h $(SOFT_COMPILE) $< ruli_addr.o: ruli_addr.c ruli_addr.h $(SOFT_COMPILE) $< ruli_sock.o: ruli_sock.c ruli_sock.h $(SOFT_COMPILE) $< ruli_res.o: ruli_res.c ruli_res.h $(SOFT_COMPILE) $< ruli_getaddrinfo.o: ruli_getaddrinfo.c ruli_getaddrinfo.h $(SOFT_COMPILE) $< ruli_util.os: ruli_util.c ruli_util.h $(SHARED_SOFT_COMPILE) $< ruli_addr.os: ruli_addr.c ruli_addr.h $(SHARED_SOFT_COMPILE) $< ruli_sock.os: ruli_sock.c ruli_sock.h $(SHARED_SOFT_COMPILE) $< ruli_res.os: ruli_res.c ruli_res.h $(SHARED_SOFT_COMPILE) $< ruli_getaddrinfo.os: ruli_getaddrinfo.c ruli_getaddrinfo.h $(SHARED_SOFT_COMPILE) $< # # End of "SOFT" section # %.o: %.c %.h $(COMPILE) $< %.os: %.c %.h $(SHARED_COMPILE) $< libruli.so: $(SHAREDOBJ) ifdef DEFINE_SOLARIS $(CC) $(ARCH) $(CFLAGS) $(LDFLAGS) -Wl,-h,$(SONAME) -o $@ \ $(SHAREDOBJ) -loop -ldl -lsocket -lnsl else $(CC) $(ARCH) $(CFLAGS) $(LDFLAGS) -Wl,-soname,$(SONAME) \ -Wl,--version-script,libruli.ver -o $@ $(SHAREDOBJ) -loop -ldl endif $(SONAME): libruli.so cp libruli.so $(SONAME) libruli.a: $(LIBOBJ) ifdef DEFINE_SOLARIS ar -r -v $@ $(LIBOBJ) else ar rcv $@ $(LIBOBJ) ar sv $@ endif ruli-0.33/src/libruli.ver0000644000177100017710000000010010252463364016117 0ustar labratlabrat00000000000000HIDDEN { local: __*; _rest*; _save*; }; libruli4 { *; }; ruli-0.33/src/ruli.h0000644000177100017710000000240010131351173015056 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli.h,v 1.10 2004/10/07 23:34:19 evertonm Exp $ */ #ifndef RULI_H #define RULI_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif /* RULI_H */ ruli-0.33/src/ruli_addr.c0000644000177100017710000005252710254425551016072 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_addr.c,v 1.22 2005/06/17 01:46:17 evertonm Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE /* for GNU memrchr() */ #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void ruli_addr_init(ruli_addr_t *addr, int family) { addr->addr_family = family; addr->has_src = 0; /* false */ } ruli_addr_t *ruli_addr_inet_new(struct in_addr ia) { ruli_addr_t *addr = (ruli_addr_t *) ruli_malloc(sizeof(*addr)); if (!addr) return 0; ruli_addr_init(addr, PF_INET); addr->addr.ipv4 = ia; return addr; } ruli_addr_t *ruli_addr_inet6_new(struct in6_addr ia) { ruli_addr_t *addr = (ruli_addr_t *) ruli_malloc(sizeof(*addr)); if (!addr) return 0; ruli_addr_init(addr, PF_INET6); addr->addr.ipv6 = ia; return addr; } int ruli_addr_family(const ruli_addr_t *addr) { return addr->addr_family; } int ruli_addr_size(const ruli_addr_t *addr) { int size; switch (addr->addr_family) { case PF_INET: size = sizeof(addr->addr.ipv4); break; case PF_INET6: size = sizeof(addr->addr.ipv6); break; default: assert(0); } return size; } static void ruli_addr_find_source(ruli_addr_t *addr) { int fd; union { struct sockaddr_in inet; struct sockaddr_in6 inet6; } dst; int dst_len = sizeof(dst); socklen_t src_len; addr->has_src = 0; /* false */ fd = socket(addr->addr_family, SOCK_DGRAM, IPPROTO_IP); if (fd < 0) return; ruli_sock_set_sockaddr((struct sockaddr *) &dst, &dst_len, &addr->addr, addr->addr_family, 0); if (connect(fd, (const struct sockaddr *) &dst, dst_len)) { close(fd); return; } src_len = sizeof(addr->src_sock); if (getsockname(fd, (struct sockaddr *) &addr->src_sock, &src_len)) { close(fd); return; } close(fd); addr->src_family = addr->src_sock.sock.sin_family; assert(addr->src_family == addr->src_sock.sock6.sin6_family); addr->has_src = -1; /* true */ } int ruli_addr_src_get_family(const ruli_addr_t *addr) { assert(ruli_addr_has_source(addr)); return addr->src_family; } int ruli_addr_has_source(const ruli_addr_t *addr) { return addr->has_src; } _ruli_addr *ruli_addr_src_get_addr(const ruli_addr_t *addr) { _ruli_addr *ad; assert(ruli_addr_has_source(addr)); switch (ruli_addr_src_get_family(addr)) { case PF_INET: ad = (_ruli_addr *) &addr->src_sock.sock.sin_addr; break; case PF_INET6: ad = (_ruli_addr *) &addr->src_sock.sock6.sin6_addr; break; default: assert(0); } return ad; } struct in_addr ruli_addr_inet(const ruli_addr_t *addr) { assert(ruli_addr_family(addr) == PF_INET); assert(ruli_addr_size(addr) == sizeof(struct in_addr)); return addr->addr.ipv4; } struct in6_addr ruli_addr_inet6(const ruli_addr_t *addr) { assert(ruli_addr_family(addr) == PF_INET6); assert(ruli_addr_size(addr) == sizeof(struct in6_addr)); return addr->addr.ipv6; } #define RULI_WORD16_LEN ((int) sizeof(struct in6_addr) / 2) static int search_forward(const char *cp, const char *past_end, unsigned int *word16, int *wi, const char **wildcard) { const char *i; long w; *wi = 0; for (i = cp; i < past_end; ) { if (*i == ':') { ++i; if (*i == ':') { *wildcard = i; return 0; } /* can't start addr with : */ if (*wi == 0) return -1; } if (*wi >= RULI_WORD16_LEN) return -1; if (!isxdigit((int) *i)) return -1; w = strtol(i, 0, 16); if (w == LONG_MIN) return -1; if (w == LONG_MAX) return -1; if (w < 0) return -1; if (w > 0xFFFF) return -1; word16[*wi] = w; ++*wi; i = (const char *) memchr(i, ':', past_end - i); if (!i) break; } return 0; } static int search_backward(const char *cp, const char *past_end, unsigned int *word16, int *wj, const char **wildcard) { const char *i; long w; *wj = RULI_WORD16_LEN; for (i = past_end; i > cp; --i) { const char *j; i = (const char *) ruli_memrchr(cp, ':', i - cp); if (!i) return -1; if (*wj <= 0) return -1; j = i + 1; w = strtol(j, 0, 16); if (w == LONG_MIN) return -1; if (w == LONG_MAX) return -1; if (w < 0) return -1; if (w > 0xFFFF) return -1; word16[--*wj] = w; if (*(i - 1) == ':') { *wildcard = i; return 0; } if (!isxdigit((int) *j)) return -1; } return -1; } int ruli_inet6_aton(const char *cp, struct in6_addr *inp) { unsigned int word16[RULI_WORD16_LEN]; const char *past_end; const char *wildcard_fwd = 0; const char *wildcard_bwd; int wi, wj; /* locate end of string */ past_end = (const char *) memchr(cp, '\0', 40); if (!past_end) return 0; /* search from start up to :: or end */ if (search_forward(cp, past_end, word16, &wi, &wildcard_fwd)) return 0; if (wi < RULI_WORD16_LEN) { /* search from end up to :: */ if (search_backward(cp, past_end, word16, &wj, &wildcard_bwd)) return 0; /* wildcard :: was hit? */ if (wildcard_fwd) { /* forward found the same wildcard as backward? */ if (wildcard_fwd != wildcard_bwd) return 0; } /* clean unused slots */ { int i; for (i = wi; i < wj; ++i) word16[i] = 0; } } /* convert 2-byte host-order array to 1-byte net-order array */ { char *p = (char *) inp; for (wi = 0; wi < RULI_WORD16_LEN; ++wi) { unsigned int w = word16[wi]; *p = w >> 8; ++p; *p = w & 0xFF; ++p; } } return -1; } int ruli_addr_parse(const char *p, ruli_addr_t *addr) { if (ruli_inet6_aton(p, &addr->addr.ipv6)) { ruli_addr_init(addr, PF_INET6); return 0; } if (inet_aton(p, &addr->addr.ipv4)) { ruli_addr_init(addr, PF_INET); return 0; } ruli_addr_init(addr, PF_UNSPEC); return -1; } ruli_addr_t *ruli_addr_parse_new(const char *p) { struct in_addr addr; struct in6_addr addr6; if (ruli_inet6_aton(p, &addr6)) return ruli_addr_inet6_new(addr6); if (inet_aton(p, &addr)) return ruli_addr_inet_new(addr); return 0; } int ruli_inet6_printf(FILE *out, const char *fmt, const struct in6_addr *ia) { const unsigned char *begin = (const unsigned char *) ia; const unsigned char *past_end = begin + sizeof(*ia); int wr = 0; const unsigned char *i; unsigned int sum = 0; for (i = begin; i < past_end; ++i) { int j = i - begin; int w; assert(wr >= 0); sum <<= 8; sum += *i; assert(sum >= 0); assert(sum <= 0xFFFF); if (j) { if (!(j % 2)) { w = fprintf(out, ":"); if (w < 0) return w; wr += w; } if (!((j + 1) % 2)) { w = fprintf(out, fmt, sum); if (w < 0) return w; wr += w; sum = 0; } } } return wr; } int ruli_inet6_print(FILE *out, const struct in6_addr *ia) { return ruli_inet6_printf(out, "%x", ia); } int ruli_in_print(FILE *out, const _ruli_addr *addr, int family) { switch (family) { case PF_INET: return fprintf(out, inet_ntoa(addr->ipv4)); case PF_INET6: return ruli_inet6_print(out, &addr->ipv6); default: assert(0); } return -1; } int ruli_addr_print(FILE *out, const ruli_addr_t *addr) { return ruli_in_print(out, &addr->addr, addr->addr_family); } int ruli_inet6_snprintf(char *buf, size_t size, const char *fmt, const struct in6_addr *ia) { const unsigned char *begin = (const unsigned char *) ia; const unsigned char *past_end = begin + sizeof(*ia); int wr = 0; const unsigned char *i; unsigned int sum = 0; for (i = begin; i < past_end; ++i) { int j = i - begin; int w; assert(wr >= 0); assert((size_t) wr < size); sum <<= 8; sum += *i; assert(sum >= 0); assert(sum <= 0xFFFF); if (j) { if (!(j % 2)) { w = snprintf(buf + wr, size - wr, ":"); if (w < 0) return w; wr += w; if ((size_t) wr >= size) return wr; } if (!((j + 1) % 2)) { w = snprintf(buf + wr, size - wr, fmt, sum); if (w < 0) return w; wr += w; if ((size_t) wr >= size) return wr; sum = 0; } } } return wr; } int ruli_inet6_snprint(char *buf, size_t size, const struct in6_addr *ia) { return ruli_inet6_snprintf(buf, size, "%x", ia); } int ruli_in_snprint(char *buf, size_t size, const _ruli_addr *addr, int family) { switch (family) { case PF_INET: return snprintf(buf, size, inet_ntoa(addr->ipv4)); case PF_INET6: return ruli_inet6_snprint(buf, size, &addr->ipv6); default: assert(0); } return -1; } int ruli_addr_snprint(char *buf, size_t size, const ruli_addr_t *addr) { return ruli_in_snprint(buf, size, &addr->addr, addr->addr_family); } static int get_scope(const _ruli_addr *ad, int family) { switch (family) { case PF_INET: { const ruli_uint8_t *addr = (const ruli_uint8_t *) &ad->ipv4; /* 169.254/16, 127/8 are link-local */ if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127) return RULI_ADDR_SCOPE_LINK_LOCAL; /* 10/8, 192.168/16, 172.16/12 are site-local */ if (addr[0] == 10 || (addr[0] == 192 && addr[1] == 168) || (addr[0] == 172 && addr[1] >= 16 && addr[1] <= 31)) return RULI_ADDR_SCOPE_SITE_LOCAL; /* unspecified? */ if (ad->ipv4.s_addr == INADDR_ANY) return RULI_ADDR_SCOPE_UNSPEC; /* try to ignore */ } break; case PF_INET6: { const struct in6_addr *addr = (const struct in6_addr *) &ad->ipv6; if (IN6_IS_ADDR_MULTICAST(addr)) return addr->s6_addr[1] & 0xf; if (IN6_IS_ADDR_LINKLOCAL(addr)) return RULI_ADDR_SCOPE_LINK_LOCAL; if (IN6_IS_ADDR_LOOPBACK(addr)) return RULI_ADDR_SCOPE_LINK_LOCAL; if (IN6_IS_ADDR_SITELOCAL(addr)) return RULI_ADDR_SCOPE_SITE_LOCAL; if (IN6_IS_ADDR_UNSPECIFIED(addr)) return RULI_ADDR_SCOPE_UNSPEC; /* try to ignore */ } break; default: assert(0); } return RULI_ADDR_SCOPE_GLOBAL; } int ruli_addr_get_scope(const _ruli_addr *ad, int family) { int scope = get_scope(ad, family); #ifdef RULI_RFC3484_DEBUG fprintf(stderr, "DEBUG %s %s addr=", __FILE__, __PRETTY_FUNCTION__); ruli_in_print(stderr, ad, family); fprintf(stderr, " scope=%d\n", scope); #endif /* RULI_RFC3484_DEBUG */ return scope; } /* RFC 3484 Prefix Precedence Label ::1/128 50 0 ::/0 40 1 2002::/16 30 2 ::/96 20 3 ::ffff:0:0/96 10 4 */ static const struct prefixlist { struct in6_addr prefix; unsigned int bits; int val; } default_label[] = { { IN6ADDR_LOOPBACK_INIT, 128, 0 }, { { { { 0x20,0x02,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 } } }, 16, 2 }, { IN6ADDR_ANY_INIT, 96, 3 }, { { { { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0 } } }, 96, 4 }, { IN6ADDR_ANY_INIT, 0, 1 } }; static const struct prefixlist default_precedence[] = { { IN6ADDR_LOOPBACK_INIT, 128, 50 }, { { { { 0x20,0x02,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 } } }, 16, 30 }, { IN6ADDR_ANY_INIT, 96, 20 }, { { { { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0 } } }, 96, 10 }, { IN6ADDR_ANY_INIT, 0, 40 } }; /* does ADDRESS addr/addr_len belong to NETWORK net/prefix_len ? */ static int addr_in_net(const ruli_uint8_t *net, int prefix_len, const ruli_uint8_t *addr, int addr_len) { const ruli_uint8_t *net_pastend; char byte_len, left; /* * Compares all bytes, but the last one. */ byte_len = prefix_len >> 3; /* prefix_len / 8 */ net_pastend = net + byte_len; for (; net < net_pastend; ++net, ++addr) if (*net != *addr) return 0; /* * left = prefix_len % 8 = number of bits 1 at left */ left = prefix_len & 7; if (!left) return -1; /* * Compares last byte. * * 8 - () => number of bits 0 at right * 0xFF << () => insert bits 0 at right * *ip_a & () => ignore bits 0 */ return *net == (*addr & (char) (0xFF << (8 - left))); } static int match_prefix(const struct prefixlist *list, const _ruli_addr *ad, int family) { int i; struct in6_addr in6_mem; const struct in6_addr *in6; switch (family) { case PF_INET6: in6 = (const struct in6_addr *) &ad->ipv6; break; case PF_INET: { const struct in_addr *in = (const struct in_addr *) &ad->ipv4; /* Convert to IPv6 address */ if (in->s_addr == htonl(0)) { struct in6_addr tmp = IN6ADDR_ANY_INIT; memcpy(&in6_mem, &tmp, sizeof(tmp)); } else if (in->s_addr == htonl(0x7f000001)) { struct in6_addr tmp = IN6ADDR_LOOPBACK_INIT; memcpy(&in6_mem, &tmp, sizeof(tmp)); } else { /* Construct a V4-to-6 mapped address. */ memset(&in6_mem, '\0', sizeof(in6_mem)); in6_mem.s6_addr16[5] = 0xffff; in6_mem.s6_addr32[3] = in->s_addr; } in6 = &in6_mem; } break; default: assert(0); } for (i = 0; ; ++i) { unsigned int bits = list[i].bits; ruli_uint8_t *mask = list[i].prefix.s6_addr; #ifdef RULI_RFC3484_DEBUG fprintf(stderr, "DEBUG %s %s ad=", __FILE__, __PRETTY_FUNCTION__); ruli_in_print(stderr, ad, family); fprintf(stderr, " v6="); ruli_in_print(stderr, (const _ruli_addr *) in6, PF_INET6); fprintf(stderr, " prefix[%d]=", i); ruli_in_print(stderr, (const _ruli_addr *) mask, PF_INET6); fprintf(stderr, "/%d\n", bits); #endif /* RULI_RFC3484_DEBUG */ if (addr_in_net(mask, bits, (const ruli_uint8_t *) in6, sizeof(*in6))) return list[i].val; } assert(0); return -1; } int ruli_addr_get_label(const _ruli_addr *ad, int family) { int label = match_prefix(default_label, ad, family); #ifdef RULI_RFC3484_DEBUG fprintf(stderr, "DEBUG %s %s addr=", __FILE__, __PRETTY_FUNCTION__); ruli_in_print(stderr, ad, family); fprintf(stderr, " label=%d\n", label); #endif /* RULI_RFC3484_DEBUG */ return label; } int ruli_addr_get_precedence(const _ruli_addr *ad, int family) { int precedence = match_prefix(default_precedence, ad, family); #ifdef RULI_RFC3484_DEBUG fprintf(stderr, "DEBUG %s %s addr=", __FILE__, __PRETTY_FUNCTION__); ruli_in_print(stderr, ad, family); fprintf(stderr, " precedence=%d\n", precedence); #endif /* RULI_RFC3484_DEBUG */ return precedence; } int ruli_addr_get_common_prefix_bitlen(const ruli_uint8_t *a1, const ruli_uint8_t *a2, int byte_len) { const ruli_uint8_t *a1_pastend; int bitlen; assert(byte_len >= 0); assert(byte_len <= 32); bitlen = 0; for (a1_pastend = a1 + byte_len; ; ++a1, ++a2, bitlen += 8) { if (a1 >= a1_pastend) break; if (*a1 != *a2) { int mask; int match_bits = 8; for (mask = *a1 ^ *a2; mask; mask >>= 1) --match_bits; bitlen += match_bits; break; } } assert(bitlen >= 0); assert(bitlen <= 128); return bitlen; } static int rfc3484_cmp(const void *addr1, const void *addr2) { const ruli_addr_t *a1 = *(const ruli_addr_t * const *) addr1; const ruli_addr_t *a2 = *(const ruli_addr_t * const *) addr2; int a1_dst_scope; int a2_dst_scope; int a1_family; int a2_family; /* Rule 1: Avoid unusable destinations. */ if (a1->has_src && !a2->has_src) return -1; if (!a1->has_src && a2->has_src) return 1; /* Rule 2: Prefer matching scope. */ a1_family = ruli_addr_family(a1); a2_family = ruli_addr_family(a2); a1_dst_scope = ruli_addr_get_scope(&a1->addr, a1_family); a2_dst_scope = ruli_addr_get_scope(&a2->addr, a2_family); if (a1->has_src && a2->has_src) { _ruli_addr *a1_src = ruli_addr_src_get_addr(a1); _ruli_addr *a2_src = ruli_addr_src_get_addr(a2); int a1_src_family = ruli_addr_src_get_family(a1); int a2_src_family = ruli_addr_src_get_family(a2); int a1_src_scope = ruli_addr_get_scope(a1_src, a1_src_family); int a2_src_scope = ruli_addr_get_scope(a2_src, a2_src_family); if ((a1_dst_scope == a1_src_scope) && (a2_dst_scope != a2_src_scope)) return -1; if ((a1_dst_scope != a1_src_scope) && (a2_dst_scope == a2_src_scope)) return 1; } /* Rule 3: Avoid deprecated addresses. How?? FIXME */ /* Rule 4: Prefer home addresses. How?? FIXME */ /* Rule 5: Prefer matching label. */ if (a1->has_src && a2->has_src) { int a1_dst_label = ruli_addr_get_label(&a1->addr, a1_family); int a2_dst_label = ruli_addr_get_label(&a2->addr, a2_family); _ruli_addr *a1_src = ruli_addr_src_get_addr(a1); _ruli_addr *a2_src = ruli_addr_src_get_addr(a2); int a1_src_family = ruli_addr_src_get_family(a1); int a2_src_family = ruli_addr_src_get_family(a2); int a1_src_label = ruli_addr_get_label(a1_src, a1_src_family); int a2_src_label = ruli_addr_get_label(a2_src, a2_src_family); if ((a1_dst_label == a1_src_label) && (a2_dst_label != a2_src_label)) return -1; if ((a1_dst_label != a1_src_label) && (a2_dst_label == a2_src_label)) return 1; } /* Rule 6: Prefer higher precedence. */ { int a1_prec = ruli_addr_get_precedence(&a1->addr, a1_family); int a2_prec = ruli_addr_get_precedence(&a2->addr, a2_family); if (a1_prec > a2_prec) return -1; if (a1_prec < a2_prec) return 1; } /* Rule 7: Prefer native transport. How?? FIXME */ /* Rule 8: Prefer smaller scope. */ if (a1_dst_scope < a2_dst_scope) return -1; if (a1_dst_scope > a2_dst_scope) return 1; /* Rule 9: Use longest matching prefix. */ if (a1_family == a2_family) if (a1->has_src && a2->has_src) { _ruli_addr *a1_src = ruli_addr_src_get_addr(a1); _ruli_addr *a2_src = ruli_addr_src_get_addr(a2); int addr_size = ruli_addr_size(a1); int len1; int len2; assert(addr_size == ruli_addr_size(a2)); len1 = ruli_addr_get_common_prefix_bitlen((const ruli_uint8_t *) &a1->addr, (const ruli_uint8_t *) a1_src, addr_size); len2 = ruli_addr_get_common_prefix_bitlen((const ruli_uint8_t *) &a2->addr, (const ruli_uint8_t *) a2_src, addr_size); if (len1 > len2) return -1; if (len1 < len2) return 1; } /* Rule 10: Otherwise, leave the order unchanged. */ return 0; } static long addr_cmp_options; static int addr_cmp_preference(const void *addr1, const void *addr2) { const ruli_addr_t *a1 = *(const ruli_addr_t * const *) addr1; const ruli_addr_t *a2 = *(const ruli_addr_t * const *) addr2; int result; /* Apply RFC3484 destination address selection rules? */ if (addr_cmp_options & RULI_RES_OPT_SRV_RFC3484) { result = rfc3484_cmp(addr1, addr2); if (result) return result; } /* Give preference to IPv6 addresses over IPv4? */ if (!(addr_cmp_options & RULI_RES_OPT_SRV_NOSORT6)) { int f1 = ruli_addr_family(a1); int f2 = ruli_addr_family(a2); if ((f1 == PF_INET6) && (f2 == PF_INET)) return -1; if ((f1 == PF_INET) && (f2 == PF_INET6)) return 1; } /* Perform stable sorting */ if (addr1 < addr2) return -1; if (addr1 > addr2) return 1; return 0; } static void find_addr_src(ruli_list_t *addr_list) { int addr_list_size = ruli_list_size(addr_list); int j; for (j = 0; j < addr_list_size; ++j) { ruli_addr_t *addr = ruli_list_get(addr_list, j); ruli_addr_find_source(addr); #ifdef RULI_RFC3484_DEBUG fprintf(stderr, "DEBUG %s %s dst=", __FILE__, __PRETTY_FUNCTION__); ruli_addr_print(stderr, addr); fprintf(stderr, " has_src=%d src_family=%d src=", addr->has_src, addr->src_family); switch (addr->src_family) { case PF_INET: fprintf(stderr, inet_ntoa(addr->src_sock.sock.sin_addr)); break; case PF_INET6: ruli_inet6_print(stderr, &addr->src_sock.sock6.sin6_addr); break; default: fprintf(stderr, "?"); } fprintf(stderr, "\n"); #endif /* RULI_RFC3484_DEBUG */ } } void ruli_addr_rfc3484_sort(ruli_list_t *addr_list, long options) { /* solve source addresses for later RFC3484 destination address selection rules? */ if (options & RULI_RES_OPT_SRV_RFC3484) find_addr_src(addr_list); /* argument for addr_cmp_preference functor */ addr_cmp_options = options; /* sort address list */ qsort(addr_list->head, ruli_list_size(addr_list), sizeof(void*), addr_cmp_preference); } ruli-0.33/src/ruli_addr.h0000644000177100017710000000703410254520421016060 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_addr.h,v 1.16 2005/06/17 10:08:17 evertonm Exp $ */ #ifndef RULI_ADDR_H #define RULI_ADDR_H #include #include #include #include #include typedef enum { RULI_ADDR_SCOPE_INTERFACE_LOCAL = 0x1, RULI_ADDR_SCOPE_LINK_LOCAL = 0x2, RULI_ADDR_SCOPE_SUBNET_LOCAL = 0x3, RULI_ADDR_SCOPE_ADMIN_LOCAL = 0x4, RULI_ADDR_SCOPE_SITE_LOCAL = 0x5, RULI_ADDR_SCOPE_ORGANIZATION_LOCAL = 0x8, RULI_ADDR_SCOPE_GLOBAL = 0xE, RULI_ADDR_SCOPE_UNSPEC = 0x10 } ruli_addr_scope_t; typedef union { struct in_addr ipv4; struct in6_addr ipv6; } _ruli_addr; typedef struct { int addr_family; /* PF_INET, PF_INET6 */ _ruli_addr addr; /* The section below holds the source address for RFC3484 destination address selection. */ int has_src; /* boolean */ int src_family; /* PF_INET, PF_INET6 */ union { struct sockaddr_in sock; struct sockaddr_in6 sock6; } src_sock; } ruli_addr_t; void ruli_addr_init(ruli_addr_t *addr, int family); /* * constructors */ ruli_addr_t *ruli_addr_inet_new(struct in_addr ia); ruli_addr_t *ruli_addr_inet6_new(struct in6_addr ia); /* * access methods */ int ruli_addr_family(const ruli_addr_t *addr); int ruli_addr_size(const ruli_addr_t *addr); int ruli_addr_has_source(const ruli_addr_t *addr); int ruli_addr_src_get_family(const ruli_addr_t *addr); _ruli_addr *ruli_addr_src_get_addr(const ruli_addr_t *addr); struct in_addr ruli_addr_inet(const ruli_addr_t *addr); struct in6_addr ruli_addr_inet6(const ruli_addr_t *addr); /* * misc utilities */ int ruli_inet6_aton(const char *cp, struct in6_addr *inp); int ruli_addr_parse(const char *p, ruli_addr_t *addr); ruli_addr_t *ruli_addr_parse_new(const char *p); int ruli_inet6_printf(FILE *out, const char *fmt, const struct in6_addr *ia); int ruli_inet6_print(FILE *out, const struct in6_addr *ia); int ruli_in_print(FILE *out, const _ruli_addr *addr, int family); int ruli_addr_print(FILE *out, const ruli_addr_t *addr); int ruli_inet6_snprintf(char *buf, size_t size, const char *fmt, const struct in6_addr *ia); int ruli_inet6_snprint(char *buf, size_t size, const struct in6_addr *ia); int ruli_in_snprint(char *buf, size_t size, const _ruli_addr *addr, int family); int ruli_addr_snprint(char *buf, size_t size, const ruli_addr_t *addr); int ruli_addr_get_scope(const _ruli_addr *ad, int family); int ruli_addr_get_label(const _ruli_addr *ad, int family); int ruli_addr_get_precedence(const _ruli_addr *ad, int family); int ruli_addr_get_common_prefix_bitlen(const ruli_uint8_t *a1, const ruli_uint8_t *a2, int byte_len); void ruli_addr_rfc3484_sort(ruli_list_t *addr_list, long options); #endif /* RULI_ADDR_H */ ruli-0.33/src/ruli_conf.c0000644000177100017710000001553510113161267016076 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_conf.c,v 1.9 2004/08/25 19:04:23 evertonm Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE /* for GNU strtok_r(), inet_aton() */ #endif #include #include #include #include #include #include #include #include #include #include #define LOAD_SEARCH_LIST_INBUFSZ 1024 #define LOAD_NS_LIST_INBUFSZ 1024 static int conf_load_search_list(ruli_list_t *search_list) { const char *const RESOLV_CONF = "/etc/resolv.conf"; const char *const SEARCH = "search"; int list_size; list_size = ruli_list_size(search_list); assert(list_size == 0); /* * Parse resolv.conf */ { char inbuf[LOAD_SEARCH_LIST_INBUFSZ]; FILE *in; in = fopen(RESOLV_CONF, "r"); if (!in) return -1; /* * Scan file for 'search' */ for (;;) { if (!fgets(inbuf, LOAD_SEARCH_LIST_INBUFSZ, in)) { /* If EOF, exit nicely */ if (feof(in)) break; /* If error, exit nicely too */ break; } /* Make sure it's a null-terminated string */ if (!memchr(inbuf, '\0', LOAD_SEARCH_LIST_INBUFSZ)) continue; /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; if (strcmp(tok, SEARCH)) continue; /* * Parse domains */ for (;;) { ruli_domain_t *dom; char *i; /* Find domain name */ tok = strtok_r(0, SEP, &ptr); if (!tok) break; /* Allocate space for domain name */ dom = (ruli_domain_t *) ruli_malloc(sizeof(ruli_domain_t)); if (!dom) break; assert(sizeof(char) == sizeof(ruli_uint8_t)); /* Encode domain name into space */ i = ruli_dname_encode((char *) dom->domain_name, RULI_LIMIT_DNAME_ENCODED, tok, strlen(tok)); if (!i) { ruli_free(dom); break; } dom->domain_len = (ruli_uint8_t *) i - dom->domain_name; assert(dom->domain_len > 0); assert(dom->domain_len <= RULI_LIMIT_DNAME_ENCODED); /* Save space into search_list */ if (ruli_list_push(search_list, dom)) ruli_free(dom); } } } /* for */ fclose(in); } list_size = ruli_list_size(search_list); #ifdef RULI_CONF_DEBUG { int i; fprintf(stderr, "DEBUG: %s: %s(): loaded search list:", __FILE__, __PRETTY_FUNCTION__); for (i = 0; i < list_size; ++i) { ruli_domain_t *dom = ruli_list_get(search_list, i); char txt_domain[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_len; assert(sizeof(char) == sizeof(ruli_uint8_t)); { int result = ruli_decode_dname(txt_domain, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_len, (char *) dom->domain_name, dom->domain_len); assert(!result); } fprintf(stderr, " %s", txt_domain); } fprintf(stderr, "\n"); } #endif if (list_size < 1) return -1; return 0; } ruli_list_t *ruli_conf_load_search_list(ruli_conf_handler_t *bogus) { ruli_list_t *search_list = (ruli_list_t *) ruli_malloc(sizeof(ruli_list_t)); if (!search_list) return 0; if (ruli_list_new(search_list)) { ruli_free(search_list); return 0; } if (conf_load_search_list(search_list)) { assert(!ruli_list_size(search_list)); ruli_list_delete(search_list); ruli_free(search_list); return 0; } return search_list; } void ruli_conf_unload_search_list(ruli_conf_handler_t *bogus, ruli_list_t *search_list) { assert(search_list); ruli_list_dispose_trivial(search_list); ruli_free(search_list); } static int load_ns_list(ruli_list_t *ns_list) { const char *const RESOLV_CONF = "/etc/resolv.conf"; const char *const NAMESERVER = "nameserver"; int list_size; list_size = ruli_list_size(ns_list); assert(!list_size); /* * Parse resolv.conf */ { char inbuf[LOAD_NS_LIST_INBUFSZ]; FILE *in; in = fopen(RESOLV_CONF, "r"); if (!in) return -1; /* * Scan file for 'nameserver' */ for (;;) { if (!fgets(inbuf, LOAD_NS_LIST_INBUFSZ, in)) { /* If EOF, exit nicely */ if (feof(in)) break; /* If error, exit nicely too */ break; } /* Make sure it's a null-terminated string */ if (!memchr(inbuf, '\0', LOAD_NS_LIST_INBUFSZ)) continue; /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; if (strcmp(tok, NAMESERVER)) continue; /* * Parse addresses */ for (;;) { struct in_addr addr; struct in6_addr addr6; ruli_addr_t *ad = 0; tok = strtok_r(0, SEP, &ptr); if (!tok) break; /* IPv4 address? */ if (inet_aton(tok, &addr)) ad = ruli_addr_inet_new(addr); /* IPv6 address? */ if (!ad) if (ruli_inet6_aton(tok, &addr6)) ad = ruli_addr_inet6_new(addr6); if (!ad) break; if (ruli_list_push(ns_list, ad)) ruli_free(ad); } } } /* for */ fclose(in); } list_size = ruli_list_size(ns_list); #ifdef RULI_CONF_DEBUG { int i; fprintf(stderr, "DEBUG: %s: %s(): loaded ns list:" __FILE__, __PRETTY_FUNCTION__); for (i = 0; i < list_size; ++i) { ruli_addr_t *addr = ruli_list_get(ns_list, i); fprintf(stderr, " "); ruli_addr_print(stderr, addr); } fprintf(stderr, "\n"); } #endif if (list_size < 1) return -1; return 0; } ruli_list_t *ruli_conf_load_ns_list(ruli_conf_handler_t *bogus) { ruli_list_t *ns_list = (ruli_list_t *) ruli_malloc(sizeof(ruli_list_t)); if (!ns_list) return 0; if (ruli_list_new(ns_list)) { ruli_free(ns_list); return 0; } if (load_ns_list(ns_list)) { assert(!ruli_list_size(ns_list)); ruli_list_delete(ns_list); ruli_free(ns_list); return 0; } return ns_list; } void ruli_conf_unload_ns_list(ruli_conf_handler_t *bogus, ruli_list_t *ns_list) { assert(ns_list); ruli_list_dispose_trivial(ns_list); ruli_free(ns_list); } ruli-0.33/src/ruli_conf.h0000644000177100017710000000254607622575776016132 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_conf.h,v 1.2 2003/02/13 01:59:26 evertonm Exp $ */ #ifndef RULI_CONF_H #define RULI_CONF_H #include #include /* * Search list */ ruli_list_t *ruli_conf_load_search_list(ruli_conf_handler_t *bogus); void ruli_conf_unload_search_list(ruli_conf_handler_t *bogus, ruli_list_t *search_list); /* * Nameserver list */ ruli_list_t *ruli_conf_load_ns_list(ruli_conf_handler_t *bogus); void ruli_conf_unload_ns_list(ruli_conf_handler_t *bogus, ruli_list_t *ns_list); #endif /* RULI_CONF_H */ ruli-0.33/src/ruli_fsm.c0000644000177100017710000012034610064243135015733 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_fsm.c,v 1.26 2004/06/17 07:21:01 evertonm Exp $ TIMEOUT NOTES: The following operations are protected by explicit timeouts: - Waiting the answer for an UDP query - Waiting the answer for a TCP query Others are not subject to timeout restrictions. */ #include /* FIXME: remove me [used for fprintf() debug] */ #include /* FIXME: remove me [used for strerror() debug] */ #include /* FIXME: remove me [used for strerror() debug] */ #include #include #include #include #include #include #include /* Forward declarations */ static void query_switch_status(ruli_res_query_t *qry, int status); static void query_done_write_udp(ruli_res_query_t *qry); static void query_want_read_udp(ruli_res_query_t *qry); static void query_done_read_udp(ruli_res_query_t *qry); static void query_want_connect_tcp(ruli_res_query_t *qry); static void query_done_connect_tcp(ruli_res_query_t *qry); static void query_want_write_tcp(ruli_res_query_t *qry); static void query_done_write_tcp(ruli_res_query_t *qry); static void query_want_read_tcp_head(ruli_res_query_t *qry); static void query_done_read_tcp_head(ruli_res_query_t *qry); static void query_want_read_tcp_body(ruli_res_query_t *qry); static void query_done_read_tcp_body(ruli_res_query_t *qry); static void *on_udp_write(oop_source *oop_src, int udp_sd, oop_event event, void *res_qry); static void *on_udp_read(oop_source *oop_src, int udp_sd, oop_event event, void *res_qry); static void *on_tcp_connect(oop_source *oop_src, int tcp_sd, oop_event event, void *ctx); static void *on_tcp_write(oop_source *oop_src, int tcp_sd, oop_event event, void *ctx); static void *on_tcp_read(oop_source *oop_src, int tcp_sd, oop_event event, void *ctx); static void queries_tcp_connect2write(ruli_list_t *query_list, int tcp_sd); static int tcp_status(int status) { return (status >= RULI_QRY_TCP_STAT_MIN) && (status <= RULI_QRY_TCP_STAT_MAX); } /* fsm exit point */ static void *query_done(ruli_res_query_t *qry) { #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: fsm: query_done(): " "id=%d answer_code=%d, rcode=%d status=%d\n", qry->query_id, qry->answer_code, qry->answer_header.rcode, qry->status); #endif assert(qry->status == RULI_QRY_STAT_VOID); assert(qry->answer_code != RULI_CODE_VOID); assert(qry->answer_msg_len <= qry->answer_buf_size); /* * In case of truncated TCP response, panic */ if (!qry->answer_code) if (qry->answer_header.flags & RULI_MSG_MASK_TC) qry->answer_code = RULI_CODE_ANSWER_TRUNC; return _ruli_fsm_query_done(qry); } /* Used to schedule query_done() immediately */ static void *query_done_now(oop_source *oop_src, struct timeval sched_tv, void *res_qry) { return query_done((ruli_res_query_t *) res_qry); } static void schedule_immediate_query_done(oop_source *oop_src, ruli_res_query_t *qry) { oop_src->on_time(oop_src, OOP_TIME_NOW, query_done_now, qry); } /* Returns: -1: switch failed: finish scheduled with result 'code' 0: switch succeeded */ static int switch_else_schedule_finish(ruli_res_query_t *qry, int code) { assert(qry->status == RULI_QRY_STAT_VOID); assert(code != RULI_CODE_VOID); assert(code != RULI_CODE_OK); /* * Is it possible to switch to another server? */ if (ruli_res_switch_server(qry)) { /* * No: schedule finish */ assert(!qry->answer_buf); assert(qry->answer_code == RULI_CODE_VOID); qry->answer_code = code; schedule_immediate_query_done(qry->resolver->res_source, qry); return -1; } /* * Yes: switched */ return 0; } static void *on_udp_read_timeout(oop_source *oop_src, struct timeval sched_tv, void *res_qry) { ruli_res_query_t *qry = (ruli_res_query_t *) res_qry; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: on_udp_read_timeout(): id=%d " "udp_readers=%d udp6_readers=%d\n", qry->query_id, qry->resolver->udp_readers, qry->resolver->udp6_readers); #endif query_done_read_udp(qry); if (switch_else_schedule_finish(qry, RULI_CODE_TIMEOUT)) { /* * Switch failed, finish scheduled */ return OOP_CONTINUE; } /* * Switched */ _ruli_query_want_write_udp(qry); return OOP_CONTINUE; } static void *tcp_read_timeout(ruli_res_query_t *qry) { /* * Should we close the socket which * failed for reading right here? * * If we close the socket, we should * deal with all other queries using it, * naaahh... */ if (switch_else_schedule_finish(qry, RULI_CODE_TIMEOUT)) { /* * Switch failed, finish scheduled */ return OOP_CONTINUE; } /* * Switched */ query_want_connect_tcp(qry); return OOP_CONTINUE; } static void *on_tcp_read_head_timeout(oop_source *oop_src, struct timeval sched_tv, void *res_qry) { ruli_res_query_t *qry = (ruli_res_query_t *) res_qry; #ifdef RULI_RES_DEBUG fprintf(stderr, "on_tcp_read_timeout(): id=%d\n", qry->query_id); #endif query_done_read_tcp_head(qry); return tcp_read_timeout(qry); } static void *on_tcp_read_body_timeout(oop_source *oop_src, struct timeval sched_tv, void *res_qry) { ruli_res_query_t *qry = (ruli_res_query_t *) res_qry; query_done_read_tcp_body(qry); return tcp_read_timeout(qry); } static void query_switch_status(ruli_res_query_t *qry, int status) { #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: query_switch_status(id=%d index=%d): %d=>%d" " udp_writers=%d udp_readers=%d" " udp6_writers=%d udp6_readers=%d\n", qry->query_id, qry->resolver_index, qry->status, status, qry->resolver->udp_writers, qry->resolver->udp_readers, qry->resolver->udp6_writers, qry->resolver->udp6_readers); #endif qry->status = status; } void _ruli_query_want_write_udp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_addr_t *addr = ruli_res_get_curr_serv_addr(qry); assert(qry->status == RULI_QRY_STAT_VOID); /* * For each address family socket: * * Only one query registers the udp sd for event monitoring. * Many queries may later be waiting for write permission. * Thus we pass the resolver context to the on_udp_write event sink. * So any UDP_WANT_SEND-query can be selected in on_udp_write time. */ switch (addr->addr_family) { case PF_INET: assert(res_ctx->udp_writers >= 0); if (!res_ctx->udp_writers) oop_src->on_fd(oop_src, res_ctx->udp_sd, OOP_WRITE, on_udp_write, res_ctx); ++res_ctx->udp_writers; break; case PF_INET6: assert(res_ctx->udp6_writers >= 0); if (!res_ctx->udp6_writers) oop_src->on_fd(oop_src, res_ctx->udp6_sd, OOP_WRITE, on_udp_write, res_ctx); ++res_ctx->udp6_writers; break; default: assert(0); } query_switch_status(qry, RULI_QRY_STAT_UDP_WANT_SEND); } static void query_done_write_udp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_addr_t *addr = ruli_res_get_curr_serv_addr(qry); assert(qry->status == RULI_QRY_STAT_UDP_WANT_SEND); switch (addr->addr_family) { case PF_INET: assert(res_ctx->udp_writers > 0); --res_ctx->udp_writers; if (!res_ctx->udp_writers) oop_src->cancel_fd(oop_src, res_ctx->udp_sd, OOP_WRITE); break; case PF_INET6: assert(res_ctx->udp6_writers > 0); --res_ctx->udp6_writers; if (!res_ctx->udp6_writers) oop_src->cancel_fd(oop_src, res_ctx->udp6_sd, OOP_WRITE); break; default: assert(0); } query_switch_status(qry, RULI_QRY_STAT_VOID); } static void schedule_timeout(ruli_res_query_t *qry, oop_call_time *call) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; { int result = gettimeofday(&qry->tv, 0); assert(!result); } #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: schedule_timeout(): query_id=%d now_is=%ld/%ld ", qry->query_id, qry->tv.tv_sec, qry->tv.tv_usec); #endif qry->tv.tv_sec += res_ctx->res_timeout; #ifdef RULI_RES_DEBUG fprintf(stderr, "scheduling_for=%ld/%ld\n", qry->tv.tv_sec, qry->tv.tv_usec); #endif oop_src->on_time(oop_src, qry->tv, call, qry); } static void query_want_read_udp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_addr_t *addr = ruli_res_get_curr_serv_addr(qry); assert(qry->status == RULI_QRY_STAT_VOID); /* * For each socket address family: * * Only one query registers the sd for event monitoring. * Many queries may later be waiting for write permission. * Thus we pass the resolver context to the on_udp_write event sink. * So any UDP_WANT_SEND-query can be selected in on_udp_write time. */ switch (addr->addr_family) { case PF_INET: assert(res_ctx->udp_readers >= 0); if (!res_ctx->udp_readers) oop_src->on_fd(oop_src, res_ctx->udp_sd, OOP_READ, on_udp_read, res_ctx); ++res_ctx->udp_readers; break; case PF_INET6: assert(res_ctx->udp6_readers >= 0); if (!res_ctx->udp6_readers) oop_src->on_fd(oop_src, res_ctx->udp6_sd, OOP_READ, on_udp_read, res_ctx); ++res_ctx->udp6_readers; break; default: assert(0); } /* * Set a timeout specific for this query. * Each query has its own timeout event registered. * The timeval is stored in the query context for later removal. */ schedule_timeout(qry, on_udp_read_timeout); query_switch_status(qry, RULI_QRY_STAT_UDP_WANT_RECV); } static void query_done_read_udp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_addr_t *addr = ruli_res_get_curr_serv_addr(qry); assert(qry->status == RULI_QRY_STAT_UDP_WANT_RECV); switch (addr->addr_family) { case PF_INET: assert(res_ctx->udp_readers > 0); --res_ctx->udp_readers; oop_src->cancel_time(oop_src, qry->tv, on_udp_read_timeout, qry); if (!res_ctx->udp_readers) oop_src->cancel_fd(oop_src, res_ctx->udp_sd, OOP_READ); break; case PF_INET6: assert(res_ctx->udp6_readers > 0); --res_ctx->udp6_readers; oop_src->cancel_time(oop_src, qry->tv, on_udp_read_timeout, qry); if (!res_ctx->udp6_readers) oop_src->cancel_fd(oop_src, res_ctx->udp6_sd, OOP_READ); break; default: assert(0); } query_switch_status(qry, RULI_QRY_STAT_VOID); } static void query_want_write_tcp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server = ruli_res_get_curr_server(qry); assert(qry->status == RULI_QRY_STAT_VOID); assert(server->tcp_writers >= 0); /* * Only one query registers the sd for event monitoring. * Many queries may later be waiting for connection. * Thus we pass the resolver context to the on_tcp_write event sink. * So any TCP_WANT_SEND-query can be selected in on_tcp_write time. */ if (!server->tcp_writers) oop_src->on_fd(oop_src, server->tcp_sd, OOP_WRITE, on_tcp_write, res_ctx); ++server->tcp_writers; query_switch_status(qry, RULI_QRY_STAT_TCP_WANT_SEND); } static void query_done_write_tcp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server = ruli_res_get_curr_server(qry); assert(qry->status == RULI_QRY_STAT_TCP_WANT_SEND); assert(server->tcp_writers > 0); --server->tcp_writers; if (!server->tcp_writers) oop_src->cancel_fd(oop_src, server->tcp_sd, OOP_WRITE); query_switch_status(qry, RULI_QRY_STAT_VOID); } static void query_want_read_tcp_head(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server = ruli_res_get_curr_server(qry); assert(qry->status == RULI_QRY_STAT_VOID); assert(server->tcp_readers >= 0); /* * Only one query registers the sd for event monitoring. * Many queries may later be waiting for tcp read opportunity. * Thus we pass the resolver context to the on_tcp_read event sink. * So any TCP_WANT_READ-query can be selected in on_tcp_read time. */ if (!server->tcp_readers) oop_src->on_fd(oop_src, server->tcp_sd, OOP_READ, on_tcp_read, res_ctx); ++server->tcp_readers; /* Reset received length of TCP header */ server->tcp_head_len = 0; /* * Set a timeout specific for this query. * Each query has its own timeout event registered. * The timeval is stored in the query context for later removal. */ schedule_timeout(qry, on_tcp_read_head_timeout); query_switch_status(qry, RULI_QRY_STAT_TCP_WANT_RECV_HEAD); } static void query_done_read_tcp_head(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server = ruli_res_get_curr_server(qry); assert(qry->status == RULI_QRY_STAT_TCP_WANT_RECV_HEAD); assert(server->tcp_readers > 0); /* * Disable timeout */ oop_src->cancel_time(oop_src, qry->tv, on_tcp_read_head_timeout, qry); --server->tcp_readers; if (!server->tcp_readers) oop_src->cancel_fd(oop_src, server->tcp_sd, OOP_READ); query_switch_status(qry, RULI_QRY_STAT_VOID); } static void query_want_read_tcp_body(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server = ruli_res_get_curr_server(qry); assert(qry->status == RULI_QRY_STAT_VOID); assert(server->tcp_readers >= 0); assert(server->tcp_head_len == RULI_LIMIT_TCP_HEADER); /* * Only one query registers the sd for event monitoring. * Many queries may later be waiting for tcp read opportunity. * Thus we pass the resolver context to the on_tcp_read event sink. * So any TCP_WANT_READ-query can be selected in on_tcp_read time. */ if (!server->tcp_readers) oop_src->on_fd(oop_src, server->tcp_sd, OOP_READ, on_tcp_read, res_ctx); ++server->tcp_readers; /* * Set a timeout specific for this query. * Each query has its own timeout event registered. * The timeval is stored in the query context for later removal. */ schedule_timeout(qry, on_tcp_read_body_timeout); query_switch_status(qry, RULI_QRY_STAT_TCP_WANT_RECV_BODY); } static void query_done_read_tcp_body(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server = ruli_res_get_curr_server(qry); assert(qry->status == RULI_QRY_STAT_TCP_WANT_RECV_BODY); assert(server->tcp_readers > 0); /* * Disable timeout */ oop_src->cancel_time(oop_src, qry->tv, on_tcp_read_body_timeout, qry); --server->tcp_readers; if (!server->tcp_readers) oop_src->cancel_fd(oop_src, server->tcp_sd, OOP_READ); query_switch_status(qry, RULI_QRY_STAT_VOID); } static void query_want_connect_tcp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server; /* * Scan available servers */ for (;;) { ruli_addr_t *server_addr = ruli_res_get_curr_serv_addr(qry); int server_port = ruli_res_get_curr_serv_port(qry); int result; server = ruli_res_get_curr_server(qry); #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: query_want_connect_tcp(): trying "); ruli_addr_print(stderr, server_addr); fprintf(stderr, ":%d\n", server_port); #endif assert(qry->status == RULI_QRY_STAT_VOID); /* * Server already connected? */ if (server->tcp_sd != -1) { query_want_write_tcp(qry); break; } /* * Create socket */ server->tcp_sd = ruli_sock_create_tcp(server_addr->addr_family); if (server->tcp_sd == -1) { /* * Try to switch to next server. * If switched successfully, then loop. * * I'm not sure there is benefit in * switching server in this case. I * believe we could just schedule * query_done() immediately with * a failed result. */ if (switch_else_schedule_finish(qry, RULI_CODE_CONNECT)) { /* * Switch failed, finish scheduled: exit loop */ break; /* for */ } /* * Switched: loop to try new server */ continue; /* for */ } /* * Try to connect to server */ result = ruli_sock_connect(server->tcp_sd, server_addr, server_port); /* * If connected, exit loop */ if (!result) { /* * We got an immediate connection and * must wait opportunity to write * * Does this really happens on any OS? */ query_want_write_tcp(qry); /* * Switch OTHER wanna-connect queries on same socket * to wanna-write * * Otherwise they would miss the "connected" event, * which occurs only once per socket descriptor */ queries_tcp_connect2write(&res_ctx->query_list, server->tcp_sd); break; } /* * If connection is in progress, we'll wait * in wanna-connect mode */ if (result == RULI_SOCK_WOULD_BLOCK) { #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: query_want_connect_tcp(): would block\n"); #endif assert(server->tcp_connecters >= 0); /* * Only one query registers the sd for event monitoring. * Many queries may later be waiting for connection. * Thus we pass the resolver context to the on_tcp_connect event sink. * So any TCP_WANT_CONNECT-query can be selected in on_tcp_connect time. */ if (!server->tcp_connecters) oop_src->on_fd(oop_src, server->tcp_sd, OOP_WRITE, on_tcp_connect, res_ctx); ++server->tcp_connecters; query_switch_status(qry, RULI_QRY_STAT_TCP_WANT_CONNECT); break; } #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: query_want_connect_tcp(): connect failed\n"); #endif /* * Any other error, try to switch the server * * If switch fails, give up exiting the for-loop */ if (switch_else_schedule_finish(qry, RULI_CODE_CONNECT)) { /* * Switch failed, finish scheduled */ break; } /* * Switched: loop to try next server */ } /* for */ } static void query_done_connect_tcp(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; oop_source *oop_src = res_ctx->res_source; ruli_server_t *server = ruli_res_get_curr_server(qry); assert(qry->status == RULI_QRY_STAT_TCP_WANT_CONNECT); assert(server->tcp_connecters > 0); --server->tcp_connecters; if (!server->tcp_connecters) oop_src->cancel_fd(oop_src, server->tcp_sd, OOP_WRITE); query_switch_status(qry, RULI_QRY_STAT_VOID); } /* * Note: As there is no timeout for the wanna-write * condition, we don't need to disable the * timeout here. * * udp_sd family is either PF_INET or PF_INET6. */ static void *on_udp_write(oop_source *oop_src, int udp_sd, oop_event event, void *ctx) { ruli_res_t *res_ctx = (ruli_res_t *) ctx; ruli_addr_t *curr_server_addr; int curr_server_port; int result; ruli_res_query_t *qry = 0; /* picky compilers */ int i; int queries; assert(event == OOP_WRITE); /* * Now we can write to the socket. * * As many queries may be waiting to write, * we need to pick (any) one of them. * * Note: Other possible approach is to try all * udp-wanna-write queries, as long as they * don't block. We currently don't do this. */ queries = ruli_list_size(&res_ctx->query_list); /* There must exist at least one query */ assert(queries > 0); for (i = 0; i < queries; ++i) { qry = (ruli_res_query_t *) ruli_list_get(&res_ctx->query_list, i); if (qry->status == RULI_QRY_STAT_UDP_WANT_SEND) break; } /* At least one UDP_WANT_SEND query MUST have been found */ assert(i < queries); #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: on_udp_write(): id=%d index=%d resolver=%u query=%u\n", qry->query_id, qry->resolver_index, (unsigned int) ctx, (unsigned int) qry); #endif /* * Proceed to write to socket descriptor */ curr_server_addr = ruli_res_get_curr_serv_addr(qry); curr_server_port = ruli_res_get_curr_serv_port(qry); result = ruli_sock_sendto(udp_sd, curr_server_addr, curr_server_port, ruli_qry_udp_buf(qry), ruli_qry_udp_msg_len(qry)); if (result == RULI_SOCK_WOULD_BLOCK) return OOP_CONTINUE; if (result == RULI_SOCK_SEND_FAIL) { query_done_write_udp(qry); if (switch_else_schedule_finish(qry, RULI_CODE_SEND)) { /* * Switch failed, finish scheduled */ return OOP_CONTINUE; } /* * Switched */ _ruli_query_want_write_udp(qry); return OOP_CONTINUE; } /* We don't expect other failures */ assert(!result); /* * Change this query mode to read */ query_done_write_udp(qry); query_want_read_udp(qry); return OOP_CONTINUE; } static void *start_tcp_query(ruli_res_query_t *qry) { int tcp_sd = _ruli_get_curr_tcp_socket(qry); /* * If socket disconnected: Set wanna-connect mode */ if (tcp_sd == -1) { query_want_connect_tcp(qry); return OOP_CONTINUE; } /* * If socket connected: Set wanna-send mode */ query_want_write_tcp(qry); return OOP_CONTINUE; } static int check_answer_flags(ruli_uint16_t flags, long options) { /* We expect a query answer */ if (!(flags & RULI_MSG_MASK_QR)) return RULI_CODE_ANSWER_FLAG_QR; /* We expect an opcode for a standard query */ if ((flags & RULI_MSG_MASK_OPCODE) != RULI_OPCODE_QUERY) return RULI_CODE_ANSWER_OPCODE; /* We expect the server returns RD as we previously sent */ if (!(flags & RULI_MSG_MASK_RD)) return RULI_CODE_ANSWER_FLAG_RD; /* Require recursive service? */ if (options & RULI_RES_OPT_NEED_RA) if (!(flags & RULI_MSG_MASK_RA)) return RULI_CODE_ANSWER_FLAG_RA; /* RFC1035 states Z must be zero, so be it */ if (flags & RULI_MSG_MASK_Z) return RULI_CODE_ANSWER_FLAG_Z; return RULI_CODE_OK; } #define UDP_READ_BUFSZ 2048 /* udp_sd family is either PF_INET or PF_INET6. */ static void *on_udp_read(oop_source *oop_src, int udp_sd, oop_event event, void *ctx) { ruli_res_t *res_ctx = (ruli_res_t *) ctx; ruli_uint8_t buf[UDP_READ_BUFSZ]; struct sockaddr sa; socklen_t sa_len = sizeof(sa); int rd; int result; ruli_res_query_t *qry; ruli_msg_header_t msg_hdr; assert(event == OOP_READ); /* Ensure enough work space */ assert(UDP_READ_BUFSZ >= RULI_LIMIT_DATAGRAM_HIGH); /* * Receive message */ result = ruli_sock_recvfrom(udp_sd, buf, UDP_READ_BUFSZ, &rd, &sa, &sa_len); if (result == RULI_SOCK_WOULD_BLOCK) return OOP_CONTINUE; /* If we can't receive the message, we can't identify the query */ if (result == RULI_SOCK_RECV_FAIL) return OOP_CONTINUE; /* We don't expect other failures */ assert(!result); /* Ignore message too long for DNS protocol */ if (rd > RULI_LIMIT_DATAGRAM_HIGH) return OOP_CONTINUE; /* If we can't parse the header, ignore the message */ if (ruli_msg_parse_header(&msg_hdr, buf, rd)) return OOP_CONTINUE; /* If we can't find the query, ignore the message */ qry = ruli_res_find_query_by_id(&res_ctx->query_list, msg_hdr.id); if (!qry) return OOP_CONTINUE; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: on_udp_read(): " "id=%d index=%d resolver=%u qry=%u status=%d\n", qry->query_id, qry->resolver_index, (unsigned int) qry->resolver, (unsigned int) qry, qry->status); #endif /* * If the found query is not waiting for the answer, ignore the message. * One reason for this is: we may have switched to another server due * to timeout, then the previous server answer arrives. */ if (qry->status != RULI_QRY_STAT_UDP_WANT_RECV) return OOP_CONTINUE; /* Query must be attached to a resolver */ assert(qry->resolver); /* Query must be attached to right resolver */ assert(qry->resolver == res_ctx); #ifndef NDEBUG /* Make sure the query was waiting on the proper socket */ { ruli_addr_t *addr = ruli_res_get_curr_serv_addr(qry); switch (addr->addr_family) { case PF_INET: assert(udp_sd == qry->resolver->udp_sd); break; case PF_INET6: assert(udp_sd == qry->resolver->udp6_sd); break; default: assert(0); } } #endif /* assert() NDEBUG */ /* * Stop monitoring for reading and disable timeout */ query_done_read_udp(qry); /* * Check answer flags */ { int code = check_answer_flags(msg_hdr.flags, qry->q_options); if (code) { qry->answer_code = code; return query_done(qry); } } /* * In case of truncated UDP response, switch to TCP query */ if (msg_hdr.flags & RULI_MSG_MASK_TC) return start_tcp_query(qry); /* * Save the answer for user */ assert(!qry->answer_buf); assert(qry->answer_code == RULI_CODE_VOID); qry->answer_buf = (char *) ruli_malloc(rd); if (!qry->answer_buf) { qry->answer_code = RULI_CODE_MALLOC; return query_done(qry); } qry->answer_buf_size = rd; qry->answer_msg_len = rd; qry->answer_header = msg_hdr; qry->answer_code = RULI_CODE_OK; memcpy(qry->answer_buf, buf, rd); return query_done(qry); } /* If we don't want to use the failed_tcp_sd anymore, but still have work to do in TCP mode, we call this function to close the socket and switch to next server. Behavior: The failed tcp socket is closed here. Try to switch TCP queries to next server. Finish query if the server switch fails. For every query from query_list: If query is monitoring the failed_tcp_sd, Try to switch such query to the next server. */ static void queries_connect_next(oop_source *oop_src, ruli_list_t *query_list, int failed_tcp_sd) { ruli_server_t *failed_server = 0; int list_size; int i; ruli_list_t affected_list; /* list of ruli_res_query_t* */ /* There must exist at least one query */ list_size = ruli_list_size(query_list); assert(list_size > 0); /* * Before closing socket, we're going to unregister wanna-connect event */ { int result = ruli_list_new_cap(&affected_list, list_size); assert(!result); } /* * Scan queries, saving the TCP ones in affected_list */ for (i = 0; i < list_size; ++i) { ruli_res_query_t *qry = (ruli_res_query_t *) ruli_list_get(query_list, i); /* * Analyze only queries in TCP mode */ if (tcp_status(qry->status)) { ruli_server_t *server = ruli_res_get_curr_server(qry); assert(server); if (server->tcp_sd == failed_tcp_sd) { /* * Save the affected queries for processing below */ int result = ruli_list_push(&affected_list, qry); assert(!result); } } } /* * There must exist at least one affected query * * Otherwise, which query was using the failed socket? */ list_size = ruli_list_size(&affected_list); assert(list_size > 0); /* * Close the socket */ for (i = 0; i < list_size; ++i) { ruli_res_query_t *qry = (ruli_res_query_t *) ruli_list_get(&affected_list, i); ruli_server_t *server = ruli_res_get_curr_server(qry); if (server->tcp_sd != -1) { /* Close socket */ int result = close(server->tcp_sd); assert(!result); server->tcp_sd = -1; /* Remember server of failed connection */ assert(!failed_server); failed_server = server; break; } } /* * Try to switch affected queries to next server */ for (i = 0; i < list_size; ++i) { ruli_res_query_t *qry = (ruli_res_query_t *) ruli_list_get(&affected_list, i); ruli_server_t *server = ruli_res_get_curr_server(qry); /* * Switch off TCP mode */ assert(tcp_status(qry->status)); switch(qry->status) { case RULI_QRY_STAT_TCP_WANT_CONNECT: query_done_connect_tcp(qry); break; case RULI_QRY_STAT_TCP_WANT_SEND: query_done_write_tcp(qry); break; case RULI_QRY_STAT_TCP_WANT_RECV_HEAD: query_done_read_tcp_head(qry); break; case RULI_QRY_STAT_TCP_WANT_RECV_BODY: query_done_read_tcp_body(qry); break; default: assert(0); } assert(qry->status == RULI_QRY_STAT_VOID); assert(server); assert(failed_server); assert(server == failed_server); if (switch_else_schedule_finish(qry, RULI_CODE_CONNECT)) { /* * Switch failed, finish scheduled */ continue; } /* * Switched successfully, wait for TCP connection */ query_want_connect_tcp(qry); } ruli_list_delete(&affected_list); } static void queries_tcp_connect2write(ruli_list_t *query_list, int tcp_sd) { int list_size = ruli_list_size(query_list); int i; assert(tcp_sd != -1); /* * Scan the given query list * Wanna-connect queries monitoring tcp_sd are switched to wanna-write */ for (i = 0; i < list_size; ++i) { ruli_res_query_t *qry = (ruli_res_query_t *) ruli_list_get(query_list, i); if (qry->status == RULI_QRY_STAT_TCP_WANT_CONNECT) { ruli_server_t *server = ruli_res_get_curr_server(qry); assert(server); assert(server->tcp_sd != -1); if (server->tcp_sd == tcp_sd) { query_done_connect_tcp(qry); query_want_write_tcp(qry); } } } } static void *on_tcp_connect(oop_source *oop_src, int tcp_sd, oop_event event, void *ctx) { ruli_res_t *res_ctx = (ruli_res_t *) ctx; assert(event == OOP_WRITE); /* * If connection succeded, switch all wanna-connect queries * monitoring this tcp_sd socket to wanna-write mode. */ if (ruli_sock_has_connected(tcp_sd)) { /* There must exist at least one query */ assert(ruli_list_size(&res_ctx->query_list) > 0); queries_tcp_connect2write(&res_ctx->query_list, tcp_sd); return OOP_CONTINUE; } /* * Connection failed: switch queries on tcp_sd to next server. */ queries_connect_next(oop_src, &res_ctx->query_list, tcp_sd); return OOP_CONTINUE; } /* * Note: As there is no timeout for the wanna-write * condition, we don't need to disable the * timeout here. */ static void *on_tcp_write(oop_source *oop_src, int tcp_sd, oop_event event, void *ctx) { ruli_res_t *res_ctx = (ruli_res_t *) ctx; int result; ruli_res_query_t *qry = 0; /* picky compilers */ int i; int queries; assert(event == OOP_WRITE); /* * Now we can write to the socket. * * As many queries may be waiting to write, * we need to find one of them. */ queries = ruli_list_size(&res_ctx->query_list); /* There must exist at least one query */ assert(queries > 0); for (i = 0; i < queries; ++i) { qry = (ruli_res_query_t *) ruli_list_get(&res_ctx->query_list, i); if (qry->status == RULI_QRY_STAT_TCP_WANT_SEND) break; } /* At least one TCP_WANT_SEND query MUST have been found */ assert(i < queries); #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: on_tcp_write(): id=%d index=%d\n", qry->query_id, qry->resolver_index); #endif /* * Proceed to write to socket descriptor */ result = ruli_sock_send(tcp_sd, ruli_qry_tcp_buf(qry), ruli_qry_tcp_msg_len(qry)); if (result == RULI_SOCK_WOULD_BLOCK) return OOP_CONTINUE; if (result == RULI_SOCK_SEND_FAIL) { /* * Connection failed: switch queries on tcp_sd to next server * * FIXME: * * I believe it's not needed to switch other * wanna-send queries. Switching the current one * should be sufficient. Other queries would detect * the problem in their send event. But the * server-switching code is handy, so we use it. * */ queries_connect_next(oop_src, &res_ctx->query_list, tcp_sd); return OOP_CONTINUE; } /* We don't expect other failures */ assert(!result); /* * Change this query mode to read */ query_done_write_tcp(qry); query_want_read_tcp_head(qry); return OOP_CONTINUE; } static void *recv_tcp_head(ruli_res_t *ctx, int tcp_sd) { ruli_server_t *server; int rd; int result; int head_len; ruli_uint16_t msg_len; ruli_msg_header_t msg_hdr; ruli_res_query_t *qry; /* * Find the server */ server = ruli_res_find_server_by_sd(&ctx->server_list, tcp_sd); /* The server must have been found */ assert(server); head_len = server->tcp_head_len; /* Sanity of received part of header */ assert(head_len >= 0); /* We must be waiting some part of the header */ assert(head_len < RULI_LIMIT_TCP_HEADER); /* * Receive message */ result = ruli_sock_recv(tcp_sd, server->tcp_head_buf + head_len, RULI_LIMIT_TCP_HEADER - head_len, &rd); /* We don't block, so keep waiting */ if (result == RULI_SOCK_WOULD_BLOCK) return OOP_CONTINUE; /* Server closed connection */ if (result == RULI_SOCK_CLOSED) { queries_connect_next(ctx->res_source, &ctx->query_list, tcp_sd); return OOP_CONTINUE; } /* If we can't read the TCP socket, assume it's broken, and switch to next server */ if (result == RULI_SOCK_RECV_FAIL) { queries_connect_next(ctx->res_source, &ctx->query_list, tcp_sd); return OOP_CONTINUE; } /* We don't expect other failures */ assert(!result); /* * If we haven't filled a full header yet, just keep waiting. */ server->tcp_head_len += rd; if (server->tcp_head_len < RULI_LIMIT_TCP_HEADER) return OOP_CONTINUE; /* Get encoded message size */ msg_len = ruli_pack2(server->tcp_head_buf); #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: recv_tcp_head(): encoded_msg_len=%d\n", msg_len); #endif /* * If the encoded message size is too short, * surely there is some error. * * As we won't be able to delimit messages anymore, * the TCP socket is unusable. Give up on that socket. */ if (msg_len < RULI_LIMIT_MSG_LOW) { queries_connect_next(ctx->res_source, &ctx->query_list, tcp_sd); return OOP_CONTINUE; } /* Parse the message header */ result = ruli_msg_parse_header(&msg_hdr, server->tcp_head_buf + 2, server->tcp_head_len - 2); /* In this case, the header parsing can't fail */ assert(!result); /* * If we can't find the query, there must be some error. * Then TCP socket is unusable, drop it. */ qry = ruli_res_find_query_by_id(&ctx->query_list, msg_hdr.id); if (!qry) { queries_connect_next(ctx->res_source, &ctx->query_list, tcp_sd); return OOP_CONTINUE; } #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: recv_tcp_head(): id=%d index=%d\n", qry->query_id, qry->resolver_index); #endif /* Query must be attached to a resolver */ assert(qry->resolver); /* Query must be attached to right resolver */ assert(qry->resolver == ctx); /* * Stop monitoring for reading and disable timeout */ query_done_read_tcp_head(qry); /* * Check answer flags */ { int code = check_answer_flags(msg_hdr.flags, qry->q_options); if (code) { qry->answer_code = code; return query_done(qry); } } /* * Allocate buffer for whole answer */ assert(!qry->answer_buf); assert(qry->answer_code == RULI_CODE_VOID); qry->answer_buf = (char *) ruli_malloc(msg_len); if (!qry->answer_buf) { qry->answer_code = RULI_CODE_MALLOC; return query_done(qry); } /* * Save already-received header */ { int len = server->tcp_head_len - 2; assert(len == RULI_LIMIT_MSG_HEADER); qry->answer_buf_size = msg_len; qry->answer_msg_len = len; qry->answer_header = msg_hdr; memcpy(qry->answer_buf, server->tcp_head_buf + 2, len); } /* * Wait answer body */ query_want_read_tcp_body(qry); return OOP_CONTINUE; } static void *recv_tcp_body(ruli_res_query_t *qry, int tcp_sd) { int result; int rd; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: recv_tcp_body(): id=%d index=%d\n", qry->query_id, qry->resolver_index); #endif assert(_ruli_get_curr_tcp_socket(qry) == tcp_sd); assert(qry->answer_buf); assert(qry->answer_buf_size >= RULI_LIMIT_MSG_LOW); assert(qry->answer_msg_len >= RULI_LIMIT_MSG_HEADER); /* We are here because the body has not been finished */ assert(qry->answer_msg_len < qry->answer_buf_size); /* * Receive message */ assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_sock_recv(tcp_sd, (ruli_uint8_t *) (qry->answer_buf + qry->answer_msg_len), qry->answer_buf_size - qry->answer_msg_len, &rd); /* We never block, so keep waiting */ if (result == RULI_SOCK_WOULD_BLOCK) return OOP_CONTINUE; /* If we can't read the TCP socket, assume it's broken, and switch to next server */ if (result == RULI_SOCK_RECV_FAIL) { queries_connect_next(qry->resolver->res_source, &qry->resolver->query_list, tcp_sd); return OOP_CONTINUE; } /* We don't expect other failures */ assert(!result); assert(rd >= 0); assert(rd <= (qry->answer_buf_size - qry->answer_msg_len)); /* Update message received length */ qry->answer_msg_len += rd; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: recv_tcp_body(): id=%d index=%d answer_msg_len=%d\n", qry->query_id, qry->resolver_index, qry->answer_msg_len); #endif /* * Received whole TCP message? */ if (qry->answer_msg_len == qry->answer_buf_size) { /* * Yes, we received the whole TCP message */ query_done_read_tcp_body(qry); assert(qry->answer_buf_size == qry->answer_msg_len); assert(qry->answer_code == RULI_CODE_VOID); qry->answer_code = RULI_CODE_OK; return query_done(qry); } /* * No, keep waiting for more */ return OOP_CONTINUE; } static void *on_tcp_read(oop_source *oop_src, int tcp_sd, oop_event event, void *ctx) { ruli_res_t *res_ctx = (ruli_res_t *) ctx; ruli_list_t *query_list = &res_ctx->query_list; int list_size = ruli_list_size(query_list); ruli_res_query_t *qry; int i; assert(event == OOP_READ); /* At least one query must exist */ assert(list_size > 0); /* * Is there a query waiting the body of a * TCP answer on tcp_sd socket? * * Only one TCP query can exist in the * READ_BODY state for a given socket. * Other TCP queries on the socket remain * in READ_HEAD until the first is complete. */ for (i = 0; i < list_size; ++i) { qry = (ruli_res_query_t *) ruli_list_get(query_list, i); if (_ruli_get_curr_tcp_socket(qry) == tcp_sd) if (qry->status == RULI_QRY_STAT_TCP_WANT_RECV_BODY) break; } /* * Yes: Let's receive the remaining of the answer body. */ if (i < list_size) return recv_tcp_body(qry, tcp_sd); /* * No: Receive a new TCP answer. */ return recv_tcp_head(res_ctx, tcp_sd); } void _ruli_query_status_done(ruli_res_query_t *qry) { switch (qry->status) { case RULI_QRY_STAT_VOID: break; case RULI_QRY_STAT_UDP_WANT_SEND: query_done_write_udp(qry); break; case RULI_QRY_STAT_UDP_WANT_RECV: query_done_read_udp(qry); break; case RULI_QRY_STAT_TCP_WANT_CONNECT: query_done_connect_tcp(qry); break; case RULI_QRY_STAT_TCP_WANT_SEND: query_done_read_udp(qry); break; case RULI_QRY_STAT_TCP_WANT_RECV_HEAD: query_done_read_tcp_head(qry); break; case RULI_QRY_STAT_TCP_WANT_RECV_BODY: query_done_read_tcp_body(qry); break; default: assert(0); } assert(qry->status == RULI_QRY_STAT_VOID); } ruli-0.33/src/ruli_fsm.h0000644000177100017710000000275410063605302015737 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_fsm.h,v 1.4 2004/06/15 14:42:10 evertonm Exp $ */ #ifndef RULI_FSM_H #define RULI_FSM_H #include /* * Query status */ enum { RULI_QRY_STAT_VOID = 0, RULI_QRY_STAT_UDP_WANT_SEND = 1, RULI_QRY_STAT_UDP_WANT_RECV = 2, RULI_QRY_STAT_TCP_WANT_CONNECT = 3, RULI_QRY_STAT_TCP_WANT_SEND = 4, RULI_QRY_STAT_TCP_WANT_RECV_HEAD = 5, RULI_QRY_STAT_TCP_WANT_RECV_BODY = 6 }; enum { RULI_QRY_TCP_STAT_MIN = RULI_QRY_STAT_TCP_WANT_CONNECT, RULI_QRY_TCP_STAT_MAX = RULI_QRY_STAT_TCP_WANT_RECV_BODY }; void _ruli_query_want_write_udp(ruli_res_query_t *qry); void _ruli_query_status_done(ruli_res_query_t *qry); #endif /* RULI_FSM_H */ ruli-0.33/src/ruli_getaddrinfo.c0000644000177100017710000001615510251152276017441 0ustar labratlabrat00000000000000/* libruliwrap - wrapper for getaddrinfo using libruli * Copyright (C) 2004 Göran Weinholt * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: ruli_getaddrinfo.c,v 1.13 2005/06/06 22:57:02 evertonm Exp $ */ #ifndef __USE_GNU #define __USE_GNU #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifndef __USE_POSIX #define __USE_POSIX #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { struct addrinfo ai; union { struct sockaddr_in sa_inet; struct sockaddr_in6 sa_inet6; } sa; } _ruli_ai_addrbag; typedef int (*getaddrinfo_call)(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); getaddrinfo_call real_getaddrinfo = NULL; static int call_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **_res) { if (!real_getaddrinfo) real_getaddrinfo = (getaddrinfo_call) dlsym(RTLD_NEXT, "getaddrinfo"); if (!real_getaddrinfo) { errno = ENOTSUP; return EAI_SYSTEM; } return real_getaddrinfo(node, service, hints, _res); } int ruli_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **_res) { ruli_sync_t *query; const ruli_list_t *srv_list; struct addrinfo *res = NULL, *res0 = NULL, *res1 = NULL; char full_service[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int srv_code, srv_list_size, i; long options = RULI_RES_OPT_SEARCH | RULI_RES_OPT_SRV_RFC3484; if (!node || (node && !*node) || !service || (service && !*service) || !hints || !_res) return call_getaddrinfo(node, service, hints, _res); /* Can't SRV records for numeric hosts. */ if (hints->ai_flags & AI_NUMERICHOST) return call_getaddrinfo(node, service, hints, _res); /* No numeric services either. */ if (atoi(service) > 0 || *service == '0') return call_getaddrinfo(node, service, hints, _res); if (hints->ai_socktype == SOCK_STREAM) snprintf(full_service, RULI_LIMIT_DNAME_TEXT_BUFSZ, "_%s._tcp", service); else if (hints->ai_socktype == SOCK_DGRAM) snprintf(full_service, RULI_LIMIT_DNAME_TEXT_BUFSZ, "_%s._udp", service); else return call_getaddrinfo(node, service, hints, _res); if (hints->ai_family == AF_INET) options |= RULI_RES_OPT_SRV_NOINET6; else if (hints->ai_family == AF_INET6) options |= RULI_RES_OPT_SRV_NOINET; query = ruli_sync_query(full_service, node, -1, options); if (!query) return call_getaddrinfo(node, service, hints, _res); srv_code = ruli_sync_srv_code(query); if (srv_code) { ruli_sync_delete(query); return call_getaddrinfo(node, service, hints, _res); } srv_list = ruli_sync_srv_list(query); srv_list_size = ruli_list_size(srv_list); if (srv_list_size < 1) { ruli_sync_delete(query); return call_getaddrinfo(node, service, hints, _res); } /* scan srv list */ for (i = 0; i < srv_list_size; i++) { ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); int j; char canonname[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int canonlen; if (ruli_dname_decode(canonname, RULI_LIMIT_DNAME_TEXT_BUFSZ, &canonlen, entry->target, entry->target_len)) continue; if (entry->port == -1) { struct servent *serv = 0; if (hints->ai_socktype == SOCK_STREAM) serv = getservbyname(service, "tcp"); else if (hints->ai_socktype == SOCK_DGRAM) serv = getservbyname(service, "udp"); if (!serv) continue; entry->port = ntohs(serv->s_port); } /* scan addr list */ for (j = 0; j < addr_list_size; ++j) { ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, j); int sockaddr_size; switch (ruli_addr_family(addr)) { case PF_INET: sockaddr_size = sizeof(struct sockaddr_in); break; case PF_INET6: sockaddr_size = sizeof(struct sockaddr_in6); break; default: ruli_sync_delete(query); if (res0) { ruli_freeaddrinfo(res0); res0 = 0; } return EAI_FAMILY; } { const int SZ = sizeof(_ruli_ai_addrbag) + canonlen + 1; res1 = (struct addrinfo *) ruli_malloc(SZ); if (!res1) { ruli_sync_delete(query); return EAI_MEMORY; } memset(res1, 0, SZ); } if (!res0) res0 = res1; else res->ai_next = res1; res = res1; res->ai_family = ruli_addr_family(addr); res->ai_socktype = hints->ai_socktype; switch (hints->ai_socktype) { case SOCK_STREAM: res->ai_protocol = IPPROTO_TCP; break; case SOCK_DGRAM: res->ai_protocol = IPPROTO_UDP; break; default: ruli_sync_delete(query); if (res0) { ruli_freeaddrinfo(res0); res0 = 0; } return EAI_SOCKTYPE; } switch (ruli_addr_family(addr)) { case PF_INET: { struct sockaddr_in *ai_addr; ai_addr = &((_ruli_ai_addrbag *) res)->sa.sa_inet; ai_addr->sin_port = htons(entry->port); ai_addr->sin_addr = ruli_addr_inet(addr); ai_addr->sin_family = ruli_addr_family(addr); res->ai_addr = (struct sockaddr *) ai_addr; } break; case PF_INET6: { struct sockaddr_in6 *ai_addr; ai_addr = &((_ruli_ai_addrbag *) res)->sa.sa_inet6; ai_addr->sin6_port = htons(entry->port); ai_addr->sin6_addr = ruli_addr_inet6(addr); ai_addr->sin6_family = ruli_addr_family(addr); res->ai_addr = (struct sockaddr *) ai_addr; } break; default: ruli_sync_delete(query); if (res0) { ruli_freeaddrinfo(res0); res0 = 0; } return EAI_FAMILY; } res->ai_addrlen = sockaddr_size; if (hints->ai_flags & AI_CANONNAME) { res->ai_canonname = (char *) (((_ruli_ai_addrbag *) res) + 1); memcpy(res->ai_canonname, canonname, canonlen + 1); } } /* for addr list */ } /* for srv list */ ruli_sync_delete(query); /* Something went wrong and res0 isn't populated. */ if (!res0) return call_getaddrinfo(node, service, hints, _res); #if 0 /* Get the normal getaddrinfo() results if possible and put them at the end of the linked list.*/ if (!call_getaddrinfo(node, service, hints, &res1)) res->ai_next = res1; #endif *_res = res0; return 0; } void ruli_freeaddrinfo(struct addrinfo *res) { struct addrinfo *prev; while (res) { prev = res; res = res->ai_next; ruli_free(prev); } } ruli-0.33/src/ruli_getaddrinfo.h0000644000177100017710000000231710113210765017434 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_getaddrinfo.h,v 1.3 2004/08/25 22:25:57 evertonm Exp $ */ #ifndef RULI_GETADDRINFO #define RULI_GETADDRINFO #ifndef __USE_POSIX #define __USE_POSIX #endif #include #include #include int ruli_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **_res); void ruli_freeaddrinfo(struct addrinfo *res); #endif ruli-0.33/src/ruli_host.c0000644000177100017710000003243410130671727016131 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_host.c,v 1.6 2004/10/06 04:25:59 evertonm Exp $ */ #include #include #include #include #include const char *ruli_host_errstr(int result) { return "FIXME: ruli_host_errstr()"; } int ruli_host_answer_code(ruli_host_t *host_qry) { return host_qry->answer_code; } int ruli_host_rcode(ruli_host_t *host_qry) { return host_qry->host_query.answer_header.rcode; } static int _ruli_need_query_in_a(int qtype, long options) { /* can't disable all address families */ assert( !((options & RULI_RES_OPT_SRV_NOINET) && (options & RULI_RES_OPT_SRV_NOINET6)) ); return ( (qtype == RULI_RR_TYPE_AAAA) && !(options & RULI_RES_OPT_SRV_NOINET) ); } static int _ruli_reset_qtype(long options) { /* can't disable all address families */ assert( !((options & RULI_RES_OPT_SRV_NOINET) && (options & RULI_RES_OPT_SRV_NOINET6)) ); return (options & RULI_RES_OPT_SRV_NOINET6) ? RULI_RR_TYPE_A : RULI_RR_TYPE_AAAA; } /* This is an indirection to the user callback */ static void *query_done(ruli_host_t *host_qry, int result_code) { assert(host_qry->answer_code == RULI_HOST_CODE_VOID); assert(result_code != RULI_HOST_CODE_VOID); host_qry->answer_code = result_code; /* * Invoke user callback */ return host_qry->host_on_answer(host_qry, host_qry->host_on_answer_arg); } static void *query_resubmit(ruli_host_t *host_qry) { ruli_res_query_t *qry = &host_qry->host_query; #ifdef RULI_HOST_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: OLD query_id=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, qry->query_id); #endif /* RULI_HOST_DEBUG */ /* reset query, but do not dispose it */ ruli_res_query_delete(qry); assert(!_ruli_need_query_in_a(qry->q_type, host_qry->host_options)); if (ruli_res_query_submit(host_qry->host_resolver, qry)) return query_done(host_qry, RULI_HOST_CODE_QUERY); #ifdef RULI_HOST_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: NEW query_id=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, qry->query_id); #endif /* RULI_HOST_DEBUG */ return OOP_CONTINUE; } static void *on_host_answer(ruli_res_query_t *qry, void *qry_arg) { ruli_host_t *host_qry = (ruli_host_t *) qry_arg; int prev_addr_list_size = ruli_list_size(&host_qry->answer_addr_list); #ifdef RULI_HOST_DEBUG { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; int result; result = ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, (const char *) qry->full_dname, qry->full_dname_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): %d: domain=%s len=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, txt_dname_buf, txt_dname_len); fprintf(stderr, "DEBUG: %s: %s(): %d: " "query_id=%d qtype=%d answer_code=%d rcode=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, qry->query_id, qry->q_type, qry->answer_code, qry->answer_header.rcode); } #endif assert(qry->answer_code != RULI_CODE_VOID); /* * Query failed? */ if (qry->answer_code) { if (qry->answer_code == RULI_CODE_TIMEOUT) return query_done(host_qry, RULI_HOST_CODE_ALARM); return query_done(host_qry, RULI_HOST_CODE_QUERY); } /* * Bad RCODE ? */ { ruli_uint16_t rcode = qry->answer_header.rcode; if (rcode != RULI_RCODE_NOERROR) { if (_ruli_need_query_in_a(qry->q_type, host_qry->host_options)) { qry->q_type = RULI_RR_TYPE_A; return query_resubmit(host_qry); } return query_done(host_qry, RULI_HOST_CODE_RCODE); } } /* * Parse answer */ { ruli_uint8_t *wanted_owner; int wanted_owner_len; ruli_cname_rdata_t cname_rdata; int cname_found; /* boolean */ int remaining_cname_depth = host_qry->host_max_cname_depth; ruli_parse_t parse; if (ruli_parse_new(&parse)) return query_done(host_qry, RULI_HOST_CODE_OTHER); { int result; assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_parse_message(&parse, &qry->answer_header, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len); if (result) { ruli_parse_delete(&parse); return query_done(host_qry, RULI_HOST_CODE_PARSE); } } assert(sizeof(ruli_uint8_t) == sizeof(char)); wanted_owner = (ruli_uint8_t *) qry->full_dname; wanted_owner_len = qry->full_dname_len; /* * Search for Address records * * The following algorithm scans the answer section * for CNAME records: * * 1/3: We look for address records for the wanted_owner * 2/3: If at least one address record is found, we're done * 3/3: We search IN CNAME records for the wanted_owner * If a CNAME record is found, we make * wanted_owner <- cname_target and go to 1/3 * Otherwise, if no CNAME found, we quit */ for (;;) { ruli_list_t *an_list = &parse.answer_list; int an_list_size = ruli_list_size(an_list); int i; #ifdef RULI_HOST_DEBUG { char wanted_txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int wanted_txt_len; int result; assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_dname_decode(wanted_txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &wanted_txt_len, (const char *) wanted_owner, wanted_owner_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): %d: " "wanted owner=(%d)%s answer_list_len=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, wanted_txt_len, wanted_txt, an_list_size); } #endif /* * 1/3: Scan answer section for address records */ for (i = 0; i < an_list_size; ++i) { ruli_rr_t *rr = (ruli_rr_t *) ruli_list_get(an_list, i); if (rr->qclass != RULI_RR_CLASS_IN) continue; if (!ruli_rr_type_is_address(host_qry->host_options, rr->type)) continue; /* * Owner matches? */ if (ruli_dname_compare(rr->owner, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len, wanted_owner, wanted_owner_len)) continue; /* * Save address */ { ruli_addr_t *addr; /* Allocate space */ addr = (ruli_addr_t *) ruli_malloc(sizeof(*addr)); if (!addr) { ruli_parse_delete(&parse); return query_done(host_qry, RULI_HOST_CODE_OTHER); } /* Save space */ if (ruli_list_push(&host_qry->answer_addr_list, addr)) { ruli_free(addr); ruli_parse_delete(&parse); return query_done(host_qry, RULI_HOST_CODE_OTHER); } /* Write address into space */ ruli_parse_addr_rr(addr, rr, host_qry->host_options); #ifdef RULI_HOST_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: " "query_id=%d q_type=%d addr_pushed=", __FILE__, __PRETTY_FUNCTION__, __LINE__, qry->query_id, qry->q_type); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif } /* save address */ } /* for: scan answer section for addresses */ /* * 2/3: Done if at least one address record has been added */ { int addr_list_size = ruli_list_size(&host_qry->answer_addr_list); #ifdef RULI_HOST_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: " "query_id=%d q_type=%d addr_list_size=%d done=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, qry->query_id, qry->q_type, addr_list_size, addr_list_size > prev_addr_list_size); #endif if (addr_list_size > prev_addr_list_size) { ruli_parse_delete(&parse); if (_ruli_need_query_in_a(qry->q_type, host_qry->host_options)) { qry->q_type = RULI_RR_TYPE_A; return query_resubmit(host_qry); } return query_done(host_qry, RULI_HOST_CODE_OK); } } #ifdef RULI_HOST_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: " "query_id=%d qtype=%d answer_code=%d rcode=%d: " "BUT: no matching address record\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, qry->query_id, qry->q_type, qry->answer_code, qry->answer_header.rcode); #endif /* * 3/3: Scan answer section for IN CNAME records */ cname_found = 0; /* false */ for (i = 0; i < an_list_size; ++i) { ruli_rr_t *rr = (ruli_rr_t *) ruli_list_get(an_list, i); if (rr->qclass != RULI_RR_CLASS_IN) continue; if (rr->type != RULI_RR_TYPE_CNAME) continue; /* * Owner matches? */ if (ruli_dname_compare(rr->owner, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len, wanted_owner, wanted_owner_len)) continue; /* Get new owner from CNAME target */ assert(sizeof(ruli_uint8_t) == sizeof(char)); if (ruli_parse_rr_cname(&cname_rdata, rr->rdata, rr->rdlength, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len)) { ruli_parse_delete(&parse); return query_done(host_qry, RULI_HOST_CODE_PARSE); } #ifdef RULI_HOST_DEBUG { ruli_uint8_t cname_owner_txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int cname_owner_txt_len; char cname_trg_txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int cname_trg_txt_len; int result; assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_dname_extract((const ruli_uint8_t *) qry->answer_buf, (const ruli_uint8_t *) qry->answer_buf + qry->answer_msg_len, cname_owner_txt, cname_owner_txt + RULI_LIMIT_DNAME_TEXT_BUFSZ, rr->owner, &cname_owner_txt_len); assert(!result); result = ruli_dname_decode(cname_trg_txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &cname_trg_txt_len, (const char *) cname_rdata.cname, cname_rdata.cname_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): %d: " "CNAME owner=(%d)%s target=(%d)%s remaining=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, cname_owner_txt_len, cname_owner_txt, cname_trg_txt_len, cname_trg_txt, remaining_cname_depth); } #endif wanted_owner = cname_rdata.cname; wanted_owner_len = cname_rdata.cname_len; cname_found = 1; /* true */ break; } /* for: IN CNAME scan of answer section */ /* If no CNAME found, give up */ if (!cname_found) break; /* If CNAME found, check depth */ if (--remaining_cname_depth < 0) { ruli_parse_delete(&parse); return query_done(host_qry, RULI_HOST_CODE_CNAME); } /* Loop to find address for CNAME target */ } /* for: Address search */ ruli_parse_delete(&parse); } /* parsed answer context */ if (_ruli_need_query_in_a(qry->q_type, host_qry->host_options)) { qry->q_type = RULI_RR_TYPE_A; return query_resubmit(host_qry); } if (ruli_list_size(&host_qry->answer_addr_list)) return query_done(host_qry, RULI_HOST_CODE_OK); return query_done(host_qry, RULI_HOST_CODE_EMPTY); } int ruli_host_query_submit(ruli_host_t *host_qry) { ruli_res_query_t *query = &host_qry->host_query; /* * Initialize query */ if (ruli_list_new(&host_qry->answer_addr_list)) return RULI_HOST_SUBMIT_OTHER; host_qry->answer_code = RULI_HOST_CODE_VOID; /* * Define callback parameters */ query->q_on_answer = on_host_answer; query->q_on_answer_arg = host_qry; /* * Pass on arguments to underlying query */ query->q_domain = host_qry->host_domain; query->q_domain_len = host_qry->host_domain_len; query->q_class = RULI_RR_CLASS_IN; query->q_type = _ruli_reset_qtype(host_qry->host_options); query->q_options = host_qry->host_options; assert(host_qry->host_max_cname_depth >= 0); assert(host_qry->host_max_cname_depth <= RULI_LIMIT_CNAME_DEPTH); /* * Submit underlying query */ if (ruli_res_query_submit(host_qry->host_resolver, query)) { ruli_list_delete(&host_qry->answer_addr_list); return RULI_HOST_SUBMIT_OTHER; } return RULI_HOST_SUBMIT_OK; } /* This is an ugly hack: it detaches the addresses from the ruli_list_t container, so that the later call to ruli_host_query_delete won't dispose those addresses. */ void ruli_host_query_detach(ruli_host_t *host_qry) { ruli_list_prune(&host_qry->answer_addr_list, 0); } void ruli_host_query_delete(ruli_host_t *host_qry) { ruli_list_dispose_trivial(&host_qry->answer_addr_list); ruli_res_query_delete(&host_qry->host_query); } ruli-0.33/src/ruli_host.h0000644000177100017710000000574710070067501016135 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_host.h,v 1.3 2004/06/28 19:19:29 evertonm Exp $ */ #ifndef RULI_HOST_H #define RULI_HOST_H #include /* Return codes for ruli_host_query_submit() */ enum { RULI_HOST_SUBMIT_OK = 0, /* successful */ RULI_HOST_SUBMIT_OTHER /* could not sumit query */ }; /* Answer codes for ruli_host_t.answer_code */ enum { RULI_HOST_CODE_VOID = -1, /* no result yet */ RULI_HOST_CODE_OK = 0, /* good answer */ RULI_HOST_CODE_ALARM, /* underlying query timeout */ RULI_HOST_CODE_QUERY, /* underlying query unspecified error */ RULI_HOST_CODE_PARSE, /* underlying query parsing failed */ RULI_HOST_CODE_EMPTY, /* underlying query rcode==NOERROR, no records */ RULI_HOST_CODE_RCODE, /* underlying query rcode!=NOERROR, check rcode */ RULI_HOST_CODE_CNAME, /* underlying query cname chain too deep */ RULI_HOST_CODE_OTHER /* unspecified error, resources exhausted */ }; struct ruli_host_t; typedef struct ruli_host_t ruli_host_t; /* User callback function type */ typedef void *(*ruli_host_call_t)(ruli_host_t *host_qry, void *host_qry_arg); /* Query opaque context */ struct ruli_host_t { /* * private members */ ruli_res_query_t host_query; /* underlying query context */ /* * public members */ /* input */ ruli_res_t *host_resolver; /* resolver context */ ruli_host_call_t host_on_answer; /* user callback function */ void *host_on_answer_arg; /* user callback argument */ char *host_domain; /* encoded domain name */ int host_domain_len; /* length of above */ long host_options; /* query options */ int host_max_cname_depth; /* max cname chain depth */ /* output */ int answer_code; /* result code */ ruli_list_t answer_addr_list; /* list of ruli_addr_t* */ }; int ruli_host_query_submit(ruli_host_t *host_qry); void ruli_host_query_detach(ruli_host_t *host_qry); void ruli_host_query_delete(ruli_host_t *host_qry); const char *ruli_host_errstr(int result); int ruli_host_answer_code(ruli_host_t *host_qry); int ruli_host_rcode(ruli_host_t *host_qry); #endif /* RULI_HOST_H */ ruli-0.33/src/ruli_http.c0000644000177100017710000000342410133305757016130 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_http.c,v 1.3 2004/10/13 20:11:27 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #include #include #include ruli_search_srv_t *ruli_search_http_submit(ruli_res_t *resolver, void *(*call)(ruli_search_srv_t *search, void *arg), void *call_arg, int port, long options, const char *txt_domain) { /* * If the user passed a valid port number, * also assume that port number was forced in * the URI. Otherwise, use 80 as default * fallback port. */ if (port > 0) options |= RULI_RES_OPT_SRV_URI_PORT; else port = 80; /* * This query uses fallback to address * records as implicit fallback mechanism. */ return ruli_search_srv_submit(resolver, call, call_arg, options, "_http._tcp", txt_domain, port); } ruli-0.33/src/ruli_http.h0000644000177100017710000000227110131412767016132 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_http.h,v 1.2 2004/10/08 04:22:15 evertonm Exp $ */ #ifndef RULI_HTTP_H #define RULI_HTTP_H #include ruli_search_srv_t *ruli_search_http_submit(ruli_res_t *resolver, void *(*call) (ruli_search_srv_t *search, void *arg), void *call_arg, int port, long options, const char *txt_domain); #endif /* RULI_HTTP_H */ ruli-0.33/src/ruli_isaac.c0000644000177100017710000000737410053444466016243 0ustar labratlabrat00000000000000/* ISAAC: a fast cryptographic random number generator http://burtleburtle.net/bob/rand/isaacafa.html ------------------------------------------------------------------------------ rand.c: By Bob Jenkins. My random number generator, ISAAC. Public Domain MODIFIED: 960327: Creation (addition of randinit, really) 970719: use context, not global variables, for internal state 980324: make a portable version 010626: Note this is public domain ------------------------------------------------------------------------------ $Id: ruli_isaac.c,v 1.2 2004/05/21 18:23:50 evertonm Exp $ */ #include "ruli_isaac.h" #define isaac_ind(mm,x) ((mm)[(x>>2)&(ISAAC_RANDSIZ-1)]) #define isaac_rngstep(mix,a,b,mm,m,m2,r,x) \ { \ x = *m; \ a = ((a^(mix)) + *(m2++)) & 0xffffffff; \ *(m++) = y = (isaac_ind(mm,x) + a + b) & 0xffffffff; \ *(r++) = b = (isaac_ind(mm,y>>ISAAC_RANDSIZL) + x) & 0xffffffff; \ } void isaac(isaac_randctx *ctx) { register isaac_ub4 a,b,x,y,*m,*mm,*m2,*r,*mend; mm=ctx->randmem; r=ctx->randrsl; a = ctx->randa; b = (ctx->randb + (++ctx->randc)) & 0xffffffff; for (m = mm, mend = m2 = m+(ISAAC_RANDSIZ/2); m>6 , a, b, mm, m, m2, r, x); isaac_rngstep( a<<2 , a, b, mm, m, m2, r, x); isaac_rngstep( a>>16, a, b, mm, m, m2, r, x); } for (m2 = mm; m2>6 , a, b, mm, m, m2, r, x); isaac_rngstep( a<<2 , a, b, mm, m, m2, r, x); isaac_rngstep( a>>16, a, b, mm, m, m2, r, x); } ctx->randb = b; ctx->randa = a; } #define isaac_mix(a,b,c,d,e,f,g,h) \ { \ a^=b<<11; d+=a; b+=c; \ b^=c>>2; e+=b; c+=d; \ c^=d<<8; f+=c; d+=e; \ d^=e>>16; g+=d; e+=f; \ e^=f<<10; h+=e; f+=g; \ f^=g>>4; a+=f; g+=h; \ g^=h<<8; b+=g; h+=a; \ h^=a>>9; c+=h; a+=b; \ } /* if (flag==TRUE), then use the contents of randrsl[] to initialize mm[]. */ void isaac_randinit(isaac_randctx *ctx, isaac_word flag) { isaac_word i; isaac_ub4 a,b,c,d,e,f,g,h; isaac_ub4 *m,*r; ctx->randa = ctx->randb = ctx->randc = 0; m=ctx->randmem; r=ctx->randrsl; a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ for (i=0; i<4; ++i) /* scramble it */ { isaac_mix(a,b,c,d,e,f,g,h); } if (flag) { /* initialize using the contents of r[] as the seed */ for (i=0; irandcnt=ISAAC_RANDSIZ; /* prepare to use the first set of results */ } #ifdef NEVER int main() { isaac_ub4 i,j; isaac_randctx ctx; ctx.randa=ctx.randb=ctx.randc=(isaac_ub4)0; for (i=0; i<256; ++i) ctx.randrsl[i]=(isaac_ub4)0; isaac_randinit(&ctx, ISAAC_TRUE); for (i=0; i<2; ++i) { isaac(&ctx); for (j=0; j<256; ++j) { printf("%.8lx",ctx.randrsl[j]); if ((j&7)==7) printf("\n"); } } } #endif ruli-0.33/src/ruli_isaac.h0000644000177100017710000000565707656224342016256 0ustar labratlabrat00000000000000/* ISAAC: a fast cryptographic random number generator http://burtleburtle.net/bob/rand/isaacafa.html ------------------------------------------------------------------------------ rand.h: definitions for a random number generator By Bob Jenkins, 1996, Public Domain MODIFIED: 960327: Creation (addition of randinit, really) 970719: use context, not global variables, for internal state 980324: renamed seed to flag 980605: recommend RANDSIZL=4 for noncryptography. 010626: note this is public domain ------------------------------------------------------------------------------ $Id: ruli_isaac.h,v 1.1 2003/05/07 15:40:18 evertonm Exp $ */ typedef unsigned long int isaac_ub4; /* unsigned 4-byte quantities */ #define ISAAC_UB4MAXVAL 0xffffffff typedef signed long int isaac_sb4; #define ISAAC_UB4BITS 32 #define ISAAC_SB4MAXVAL 0x7fffffff typedef unsigned short int isaac_ub2; #define ISAAC_UB2MAXVAL 0xffff #define ISAAC_UB2BITS 16 typedef signed short int isaac_sb2; #define ISAAC_SB2MAXVAL 0x7fff typedef unsigned char isaac_ub1; #define ISAAC_UB1MAXVAL 0xff #define ISAAC_UB1BITS 8 typedef signed char isaac_sb1; /* signed 1-byte quantities */ #define ISAAC_SB1MAXVAL 0x7f typedef int isaac_word; /* fastest type available */ #define isaac_bis(target,mask) ((target) |= (mask)) #define isaac_bic(target,mask) ((target) &= ~(mask)) #define isaac_bit(target,mask) ((target) & (mask)) #ifndef min # define min(a,b) (((a)<(b)) ? (a) : (b)) #endif /* min */ #ifndef max # define max(a,b) (((a)<(b)) ? (b) : (a)) #endif /* max */ #ifndef align # define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1))) #endif /* align */ #ifndef abs # define abs(a) (((a)>0) ? (a) : -(a)) #endif #define ISAAC_TRUE 1 #define ISAAC_FALSE 0 #define ISAAC_SUCCESS 0 /* 1 on VAX */ #ifndef ISAAC_RAND #define ISAAC_RAND #define ISAAC_RANDSIZL (8) /* I recommend 8 for crypto, 4 for simulations */ #define ISAAC_RANDSIZ (1<randcnt-- ? \ (isaac(r), (r)->randcnt=ISAAC_RANDSIZ-1, (r)->randrsl[(r)->randcnt]) : \ (r)->randrsl[(r)->randcnt]) #endif /* RAND */ ruli-0.33/src/ruli_limits.h0000644000177100017710000000342507622362554016467 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_limits.h,v 1.7 2003/02/12 06:10:52 evertonm Exp $ */ #ifndef RULI_LIMITS_H #define RULI_LIMITS_H /* message sizing section size --------------- header 12 qname 1..255 [the ENCODED dname must fit into 255] qtype 2 qclass 2 --------------- total 17..271 */ enum { RULI_LIMIT_MSG_HEADER = 12, RULI_LIMIT_TCP_HEADER = RULI_LIMIT_MSG_HEADER + 2, /* 14 */ RULI_LIMIT_MSG_LOW = RULI_LIMIT_MSG_HEADER + 5, /* 17 */ RULI_LIMIT_MSG_HIGH = 271, RULI_LIMIT_DNAME_ENCODED = 255, /* bufsz can have same length */ RULI_LIMIT_DNAME_TEXT = RULI_LIMIT_DNAME_ENCODED - 2, /* 253 */ RULI_LIMIT_DNAME_TEXT_BUFSZ = RULI_LIMIT_DNAME_TEXT + 1, /* 253 + EOS */ RULI_LIMIT_DATAGRAM_HIGH = 512, RULI_LIMIT_LABEL_LOW = 1, RULI_LIMIT_LABEL_HIGH = 63, RULI_LIMIT_COMPRESSION_DEPTH = 20, /* arbitrary */ RULI_LIMIT_CNAME_DEPTH = 5 /* arbitrary */ }; #endif /* RULI_LIMITS_H */ ruli-0.33/src/ruli_list.c0000644000177100017710000001312410053444466016124 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_list.c,v 1.17 2004/05/21 18:23:50 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include void *(*ruli_list_malloc)(size_t) = ruli_mem_malloc; void *(*ruli_list_realloc)(void *,size_t) = ruli_mem_realloc; void (*ruli_list_free)(void *) = ruli_mem_free; const char *ruli_list_errstr(int result) { return "FIXME: ruli_list_errstr()"; } int ruli_list_new_cap(ruli_list_t *list, int cap) { void **head; assert(list); assert(cap > 0); head = (void **) ruli_list_malloc(cap * sizeof(void *)); if (!head) return RULI_LIST_MALLOC; list->head = head; list->capacity = cap; list->size = 0; return RULI_LIST_OK; } int ruli_list_new(ruli_list_t *list) { assert(list); return ruli_list_new_cap(list, 10); } void ruli_list_delete(ruli_list_t *list) { assert(list); assert(list->head); ruli_list_free(list->head); list->head = 0; assert(!list->head); } void ruli_list_clean(ruli_list_t *list, ruli_list_disposer_t cleaner) { assert(list); assert(list->head); { void **i = list->head; void **past_end = list->head + list->size; for (; i < past_end; ++i) cleaner(*i); } list->size = 0; assert(!list->size); assert(list->head); } void ruli_list_clean_trivial(ruli_list_t *list) { assert(list); assert(list->head); ruli_list_clean(list, ruli_list_free); assert(!list->size); } void ruli_list_dispose(ruli_list_t *list, ruli_list_disposer_t disposer) { assert(list); assert(list->head); assert(disposer); { void **i = list->head; void **past_end = list->head + list->size; for (; i < past_end; ++i) disposer(*i); } ruli_list_delete(list); assert(!list->head); } void ruli_list_dispose_trivial(ruli_list_t *list) { assert(list); assert(list->head); ruli_list_dispose(list, ruli_list_free); assert(!list->head); } int ruli_list_size(const ruli_list_t *list) { assert(list); assert(list->head); assert(list->size >= 0); return list->size; } int ruli_list_capacity(const ruli_list_t *list) { assert(list->head); return list->capacity; } static int list_grow(ruli_list_t *list) { int new_cap; void **new_head; assert(list); assert(list->head); new_cap = list->capacity << 1; assert(new_cap > 0); new_head = (void **) ruli_list_realloc(list->head, new_cap * sizeof(void *)); if (!new_head) return RULI_LIST_MALLOC; list->head = new_head; list->capacity = new_cap; return RULI_LIST_OK; } int ruli_list_push(ruli_list_t *list, void *item) { assert(list); assert(list->head); if (list->size >= list->capacity) { int result = list_grow(list); if (result) return result; } list->head[list->size] = item; ++list->size; return RULI_LIST_OK; } int ruli_list_insert_at(ruli_list_t *list, int idx, void *item) { assert(list); assert(list->head); assert(idx >= 0); assert(idx < list->size); if (list->size >= list->capacity) { int result = list_grow(list); if (result) return result; } { void **begin = list->head + idx; void **to = list->head + list->size; void **from = to - 1; for (; from >= begin; --from, --to) *to = *from; *begin = item; } ++list->size; return RULI_LIST_OK; } void *ruli_list_shift_at(ruli_list_t *list, int idx) { void *item; assert(list); assert(list->head); assert(idx >= 0); assert(idx < list->size); assert(list->size > 0); { void **past_end = list->head + list->size; void **to = list->head + idx; void **from = to + 1; item = *to; for (; from < past_end; ++from, ++to) *to = *from; } --list->size; return item; } void *ruli_list_top(const ruli_list_t *list) { assert(list); assert(list->head); assert(list->size > 0); return list->head[list->size - 1]; } void *ruli_list_pop(ruli_list_t *list) { assert(list); assert(list->head); assert(list->size > 0); --list->size; return list->head[list->size]; } void ruli_list_drop(ruli_list_t *list, int idx) { assert(list); assert(list->head); assert(idx >= 0); assert(idx < list->size); --list->size; if (idx == list->size) return; list->head[idx] = list->head[list->size]; } void *ruli_list_get(const ruli_list_t *list, int idx) { assert(list); assert(list->head); assert(idx >= 0); assert(idx < list->size); return list->head[idx]; } void ruli_list_set(ruli_list_t *list, int idx, void *item) { assert(list); assert(list->head); assert(idx >= 0); assert(idx < list->size); list->head[idx] = item; } void ruli_list_prune(ruli_list_t *list, int size) { assert(list); assert(list->head); assert(size >= 0); assert(size <= list->size); list->size = size; } ruli-0.33/src/ruli_list.h0000644000177100017710000000460107655017021016126 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_list.h,v 1.13 2003/05/03 19:52:49 evertonm Exp $ */ #ifndef RULI_LIST_H #define RULI_LIST_H enum { RULI_LIST_OK = 0, RULI_LIST_MALLOC /* malloc failed */ }; typedef struct { int size; int capacity; void **head; } ruli_list_t; typedef void (*ruli_list_disposer_t)(void *); extern void *(*ruli_list_malloc)(size_t len); extern void *(*ruli_list_realloc)(void *ptr, size_t len); extern void (*ruli_list_free)(void *ptr); const char *ruli_list_errstr(int result); int ruli_list_new_cap(ruli_list_t *list, int cap); int ruli_list_new(ruli_list_t *list); void ruli_list_delete(ruli_list_t *list); /* destroy list, keep contents */ /* clean list contents */ void ruli_list_clean(ruli_list_t *list, ruli_list_disposer_t cleaner); void ruli_list_clean_trivial(ruli_list_t *list); /* destroy list, apply disposer on contents */ void ruli_list_dispose(ruli_list_t *list, ruli_list_disposer_t disposer); /* destroy list, apply free() on contents */ void ruli_list_dispose_trivial(ruli_list_t *list); int ruli_list_size(const ruli_list_t *list); int ruli_list_capacity(const ruli_list_t *list); int ruli_list_push(ruli_list_t *list, void *item); int ruli_list_insert_at(ruli_list_t *list, int idx, void *item); void *ruli_list_shift_at(ruli_list_t *list, int idx); void *ruli_list_top(const ruli_list_t *list); void *ruli_list_pop(ruli_list_t *list); void ruli_list_drop(ruli_list_t *list, int idx); void *ruli_list_get(const ruli_list_t *list, int idx); void ruli_list_set(ruli_list_t *list, int idx, void *item); void ruli_list_prune(ruli_list_t *list, int size); #endif /* RULI_LIST_H */ ruli-0.33/src/ruli_mem.c0000644000177100017710000000253410064101513015713 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_mem.c,v 1.6 2004/06/16 17:28:43 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include void *(*ruli_malloc)(size_t) = ruli_mem_malloc; void *(*ruli_realloc)(void *,size_t) = ruli_mem_realloc; void (*ruli_free)(void *) = ruli_mem_free; void *ruli_mem_malloc(size_t len) { return oop_malloc(len); } void *ruli_mem_realloc(void *ptr, size_t len) { return oop_realloc(ptr, len); } void ruli_mem_free(void *ptr) { oop_free(ptr); } ruli-0.33/src/ruli_mem.h0000644000177100017710000000227707654642541015752 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_mem.h,v 1.8 2003/05/03 04:28:17 evertonm Exp $ */ #ifndef RULI_MEM_H #define RULI_MEM_H #include void *ruli_mem_malloc(size_t len); void *ruli_mem_realloc(void *ptr, size_t len); void ruli_mem_free(void *ptr); extern void *(*ruli_malloc)(size_t len); extern void *(*ruli_realloc)(void *ptr, size_t len); extern void (*ruli_free)(void *ptr); #endif /* RULI_MEM_H */ ruli-0.33/src/ruli_msg.c0000644000177100017710000001146107622631732015743 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_msg.c,v 1.8 2003/02/13 05:57:46 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #ifdef RULI_MSG_DUMP_DEBUG static void dump_buf(FILE *out, ruli_uint8_t *buf, int len) { int i; fprintf(out, " dump=%d @%u", len, (unsigned int) buf); for(i = 0; i < len; ++i) fprintf(out, " %02x", (unsigned char) buf[i]); } #endif static ruli_uint16_t build_options(ruli_uint16_t option_qr, ruli_uint16_t option_opcode, ruli_uint16_t option_aa, ruli_uint16_t option_tc, ruli_uint16_t option_rd, ruli_uint16_t option_ra, ruli_uint16_t option_z, ruli_uint16_t option_rcode) { return \ option_qr << RULI_MSG_OFFSET_QR | \ option_opcode << RULI_MSG_OFFSET_OPCODE | \ option_aa << RULI_MSG_OFFSET_AA | \ option_tc << RULI_MSG_OFFSET_TC | \ option_rd << RULI_MSG_OFFSET_RD | \ option_ra << RULI_MSG_OFFSET_RA | \ option_z << RULI_MSG_OFFSET_Z | \ option_rcode << RULI_MSG_OFFSET_RCODE; } int ruli_msg_build(ruli_uint8_t *buf, int buf_size, int *msg_len, ruli_uint16_t query_id, const ruli_uint8_t *dname, int dname_len, ruli_uint16_t qclass, ruli_uint16_t qtype) { ruli_uint8_t *i; ruli_uint16_t options; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: %s: %s(): buf_size=%d query_id=%d " "dname_from=%u dname_len=%d " "qclass=%d qtype=%d\n", __FILE__, __PRETTY_FUNCTION__, buf_size, query_id, (unsigned int) dname, dname_len, qclass, qtype); { char txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_len; int result; result = ruli_dname_decode(txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_len, (const char *) dname, dname_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): building name=%s len=%d\n", __FILE__, __PRETTY_FUNCTION__, txt, txt_len); } #endif /* RULI_RES_DEBUG */ /* Buffer must support largest possible message */ if (buf_size < RULI_LIMIT_MSG_HIGH) return RULI_MSG_SHORT_BUF; options = build_options(/* qr = query */ 0, \ /* opcode = standard */ RULI_OPCODE_QUERY, \ /* aa = don't care */ 0, \ /* tc = false */ 0, \ /* rd = true */ 1, \ /* ra = don't care */ 0, \ /* z = 0 */ 0, \ /* rcode = don't care */ 0); i = ruli_unpack2(buf, query_id); i = ruli_unpack2(i, options); i = ruli_unpack2(i, /* qdcount */ 1); i = ruli_unpack2(i, /* ancount */ 0); i = ruli_unpack2(i, /* nscount */ 0); i = ruli_unpack2(i, /* arcount */ 0); memcpy(i, dname, dname_len); i += dname_len; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: ruli_msg_build(): wrote_dname_len=%d at %u\n", dname_len, (unsigned int) (i - dname_len)); #endif i = ruli_unpack2(i, qtype); i = ruli_unpack2(i, qclass); /* * Message is finished, let's calculate its length */ { int len = i - buf; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: ruli_msg_build(): wrote_msg_len=%d at %u\n", len, (unsigned int) buf); #endif assert(len >= RULI_LIMIT_MSG_LOW); assert(len <= RULI_LIMIT_MSG_HIGH); assert(len <= buf_size); if (msg_len) *msg_len = len; #ifdef RULI_MSG_DUMP_DEBUG fprintf(stderr, "DEBUG: ruli_msg_build():"); dump_buf(stderr, buf, len); fprintf(stderr, "\n"); #endif } return RULI_MSG_OK; } int ruli_msg_parse_header(ruli_msg_header_t *msg_hdr, const ruli_uint8_t *msg, size_t msg_len) { /* Message too short? */ if (msg_len < RULI_LIMIT_MSG_HEADER) return RULI_MSG_PARSE_SHORT; msg_hdr->id = ruli_pack2(msg); msg_hdr->flags = ruli_pack2(msg + 2); msg_hdr->rcode = msg[3] & 0xF; msg_hdr->qdcount = ruli_pack2(msg + 4); msg_hdr->ancount = ruli_pack2(msg + 6); msg_hdr->nscount = ruli_pack2(msg + 8); msg_hdr->arcount = ruli_pack2(msg + 10); return RULI_MSG_OK; } ruli-0.33/src/ruli_msg.h0000644000177100017710000000575107621611552015752 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_msg.h,v 1.5 2003/02/10 02:50:18 evertonm Exp $ */ #ifndef RULI_MSG_H #define RULI_MSG_H #include #include enum { RULI_MSG_OK = 0, RULI_MSG_SHORT_BUF, RULI_MSG_PARSE_SHORT }; enum { RULI_MSG_OFFSET_QR = 15, /* 1 bit */ RULI_MSG_OFFSET_OPCODE = 11, /* 4 bits */ RULI_MSG_OFFSET_AA = 10, /* 1 bit */ RULI_MSG_OFFSET_TC = 9, /* 1 bit */ RULI_MSG_OFFSET_RD = 8, /* 1 bit */ RULI_MSG_OFFSET_RA = 7, /* 1 bit */ RULI_MSG_OFFSET_Z = 4, /* 1 bit */ RULI_MSG_OFFSET_RCODE = 0 /* 4 bits */ }; enum { RULI_MSG_OFFMASK_QR = 1, /* 1 bit */ RULI_MSG_OFFMASK_OPCODE = 7, /* 4 bits */ RULI_MSG_OFFMASK_AA = 1, /* 1 bit */ RULI_MSG_OFFMASK_TC = 1, /* 1 bit */ RULI_MSG_OFFMASK_RD = 1, /* 1 bit */ RULI_MSG_OFFMASK_RA = 1, /* 1 bit */ RULI_MSG_OFFMASK_Z = 1, /* 1 bit */ RULI_MSG_OFFMASK_RCODE = 7 /* 4 bits */ }; enum { RULI_MSG_MASK_QR = RULI_MSG_OFFMASK_QR << RULI_MSG_OFFSET_QR, RULI_MSG_MASK_OPCODE = RULI_MSG_OFFMASK_OPCODE << RULI_MSG_OFFSET_OPCODE, RULI_MSG_MASK_AA = RULI_MSG_OFFMASK_AA << RULI_MSG_OFFSET_AA, RULI_MSG_MASK_TC = RULI_MSG_OFFMASK_TC << RULI_MSG_OFFSET_TC, RULI_MSG_MASK_RD = RULI_MSG_OFFMASK_RD << RULI_MSG_OFFSET_RD, RULI_MSG_MASK_RA = RULI_MSG_OFFMASK_RA << RULI_MSG_OFFSET_RA, RULI_MSG_MASK_Z = RULI_MSG_OFFMASK_Z << RULI_MSG_OFFSET_Z, RULI_MSG_MASK_RCODE = RULI_MSG_OFFMASK_RCODE << RULI_MSG_OFFSET_RCODE }; enum { RULI_OPCODE_QUERY = 0, /* standard query */ RULI_OPCODE_IQUERY = 1, /* obsolete */ RULI_OPCODE_STATUS = 2 /* server status request */ }; typedef struct { ruli_uint16_t id; ruli_uint16_t flags; ruli_uint8_t rcode; ruli_uint16_t qdcount; ruli_uint16_t ancount; ruli_uint16_t nscount; ruli_uint16_t arcount; } ruli_msg_header_t; int ruli_msg_build(ruli_uint8_t *buf, int buf_size, int *msg_len, ruli_uint16_t query_id, const ruli_uint8_t *dname, int dname_len, ruli_uint16_t qclass, ruli_uint16_t qtype); int ruli_msg_parse_header(ruli_msg_header_t *msg_hdr, const ruli_uint8_t *msg, size_t msg_len); #endif /* RULI_MSG_H */ ruli-0.33/src/ruli_oop.h0000644000177100017710000000200410064101514015730 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_oop.h,v 1.1 2004/06/16 17:28:44 evertonm Exp $ */ #ifndef RULI_OOP_H #define RULI_OOP_H #ifdef __cplusplus extern "C" { #endif #include #ifdef __cplusplus } #endif #endif /* RULI_OOP_H */ ruli-0.33/src/ruli_parse.c0000644000177100017710000002661410251416417016266 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_parse.c,v 1.20 2005/06/07 22:17:51 evertonm Exp $ */ #include /* FIXME: remove me [fprintf() debug] */ #include #include #include #include #include #include #include int ruli_parse_new(ruli_parse_t *parse) { if (ruli_list_new(&parse->question_list)) return RULI_PARSE_LIST; if (ruli_list_new(&parse->answer_list)) { ruli_list_delete(&parse->question_list); return RULI_PARSE_LIST; } if (ruli_list_new(&parse->authority_list)) { ruli_list_delete(&parse->question_list); ruli_list_delete(&parse->answer_list); return RULI_PARSE_LIST; } if (ruli_list_new(&parse->additional_list)) { ruli_list_delete(&parse->question_list); ruli_list_delete(&parse->answer_list); ruli_list_delete(&parse->authority_list); return RULI_PARSE_LIST; } return RULI_PARSE_OK; } static const ruli_uint8_t *skip_rr_owner(const ruli_uint8_t *msg, const ruli_uint8_t *past_end) { int len; /* * Iterate over labels */ for (;;) { if (msg >= past_end) return 0; len = *msg; /* Last label? */ if (!len) { const ruli_uint8_t *next = msg + 1; if (next > past_end) return 0; return next; } /* Name compression? */ if ((len & 0xC0) == 0xC0) { const ruli_uint8_t *next = msg + 2; if (next > past_end) return 0; return next; } msg += len + 1; } /* * NOT REACHED */ assert(0); return 0; } typedef const ruli_uint8_t *(*rr_parser_t)(ruli_rr_t *rr, const ruli_uint8_t *msg, const ruli_uint8_t *past_end); static const ruli_uint8_t *parse_question(ruli_rr_t *rr, const ruli_uint8_t *msg, const ruli_uint8_t *past_end) { const ruli_uint8_t *m; assert(msg <= past_end); /* * Skip owner */ m = skip_rr_owner(msg, past_end); if (!m) return 0; assert(msg < m); assert(m < past_end); /* offset data size ------------------------ 0 type 2 2 class 2 4 next */ { const ruli_uint8_t *next = m + 4; if (next > past_end) return 0; rr->owner = msg; rr->owner_len = m - msg; rr->type = ruli_pack2(m); rr->qclass = ruli_pack2(m + 2); rr->ttl = 0; rr->rdlength = 0; rr->rdata = 0; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: parse_question(): owner_len=%d type=%d class=%d\n", rr->owner_len, rr->type, rr->qclass); #endif return next; } } static const ruli_uint8_t *parse_rr(ruli_rr_t *rr, const ruli_uint8_t *msg, const ruli_uint8_t *past_end) { const ruli_uint8_t *m; const ruli_uint8_t *rdata; const ruli_uint8_t *next; ruli_uint16_t rdlength; assert(msg <= past_end); /* * Skip owner */ m = skip_rr_owner(msg, past_end); if (!m) return 0; assert(msg < m); assert(m < past_end); /* offset data size ------------------------ 0 type 2 2 class 2 4 ttl 4 8 rdlength 2 10 rdata rdlength 10 + rdlength */ rdlength = ruli_pack2(m + 8); rdata = m + 10; /* RR data must fit */ next = rdata + rdlength; if (next > past_end) return 0; rr->owner = msg; rr->owner_len = m - msg; rr->type = ruli_pack2(m); rr->qclass = ruli_pack2(m + 2); rr->ttl = ruli_pack4(m + 4); rr->rdlength = rdlength; rr->rdata = rdata; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: parse_rr(): owner_len=%d type=%d class=%d ttl=%u " "rdlength=%d\n", rr->owner_len, rr->type, rr->qclass, rr->ttl, rdlength); #endif return next; } static const ruli_uint8_t *parse_section(rr_parser_t rr_parser, ruli_list_t *rr_list, const ruli_uint8_t *msg, const ruli_uint8_t *past_end, int rr_count) { int i; const ruli_uint8_t *m; assert(!ruli_list_size(rr_list)); assert(msg <= past_end); m = msg; /* * Scan msg for resource records */ for (i = 0; i < rr_count; ++i) { const ruli_uint8_t *p; ruli_rr_t *rr; /* Allocate space for RR */ rr = (ruli_rr_t *) ruli_malloc(sizeof(ruli_rr_t)); if (!rr) return 0; /* Effectively parse RR */ p = rr_parser(rr, m, past_end); if (!p) { ruli_free(rr); return 0; } assert(m < p); /* We MUST have found at least one RR */ assert(p <= past_end); /* Save reference for RR */ if (ruli_list_push(rr_list, rr)) { ruli_free(rr); return 0; } m = p; } #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: parse_section(): scanned_octets=%d RRs_found=%d\n", m - msg, ruli_list_size(rr_list)); #endif return m; } int ruli_parse_message(ruli_parse_t *parse, ruli_msg_header_t *msg_hdr, const ruli_uint8_t *msg, int msg_len) { const ruli_uint8_t *i; const ruli_uint8_t *j; const ruli_uint8_t *past_end; assert(!ruli_list_size(&parse->question_list)); assert(!ruli_list_size(&parse->answer_list)); assert(!ruli_list_size(&parse->authority_list)); assert(!ruli_list_size(&parse->additional_list)); parse->qdcount = msg_hdr->qdcount; parse->ancount = msg_hdr->ancount; parse->nscount = msg_hdr->nscount; parse->arcount = msg_hdr->arcount; /* Message too short? */ if (msg_len < RULI_LIMIT_MSG_HEADER) return RULI_PARSE_SHORT_MSG; /* Skip message header */ i = msg + RULI_LIMIT_MSG_HEADER; past_end = msg + msg_len; /* * Parse question section */ j = parse_section(parse_question, &parse->question_list, i, past_end, parse->qdcount); if (!j) return RULI_PARSE_QUESTION; assert(i <= j); assert(j <= past_end); assert(ruli_list_size(&parse->question_list) == parse->qdcount); /* * Parse answer section */ i = parse_section(parse_rr, &parse->answer_list, j, past_end, parse->ancount); if (!i) return RULI_PARSE_ANSWER; assert(j <= i); assert(i <= past_end); assert(ruli_list_size(&parse->answer_list) == parse->ancount); /* * Parse authority section */ j = parse_section(parse_rr, &parse->authority_list, i, past_end, parse->nscount); if (!j) return RULI_PARSE_AUTHORITY; assert(i <= j); assert(j <= past_end); assert(ruli_list_size(&parse->authority_list) == parse->nscount); /* * Parse additional section */ i = parse_section(parse_rr, &parse->additional_list, j, past_end, parse->arcount); if (!i) return RULI_PARSE_ADDITIONAL; assert(j <= i); assert(i <= past_end); assert(ruli_list_size(&parse->additional_list) == parse->arcount); if (i < past_end) return RULI_PARSE_LONG_MSG; return RULI_PARSE_OK; } void ruli_parse_delete(ruli_parse_t *parse) { /* * Free all ruli_rr_t structs, if any. */ ruli_list_dispose_trivial(&parse->question_list); ruli_list_dispose_trivial(&parse->answer_list); ruli_list_dispose_trivial(&parse->authority_list); ruli_list_dispose_trivial(&parse->additional_list); } int ruli_parse_rr_a(struct in_addr *addr, const ruli_uint8_t *rdata, ruli_uint16_t rdlength) { int in_addr_size = sizeof(*addr); if (rdlength != in_addr_size) return RULI_PARSE_RR_FAIL; memcpy(addr, rdata, rdlength); return RULI_PARSE_RR_OK; } int ruli_parse_rr_aaaa(struct in6_addr *addr, const ruli_uint8_t *rdata, ruli_uint16_t rdlength) { int in_addr_size = sizeof(*addr); if (rdlength != in_addr_size) return RULI_PARSE_RR_FAIL; memcpy(addr, rdata, rdlength); return RULI_PARSE_RR_OK; } int ruli_parse_rr_srv(ruli_srv_rdata_t *srv_rdata, const ruli_uint8_t *rdata, ruli_uint16_t rdlength) { const ruli_uint8_t *i; const ruli_uint8_t *past_end = rdata + rdlength; /* offset data size ------------------------ 0 priority 2 2 weight 2 4 port 2 6 target 1..255 */ if (rdlength < 7) return RULI_PARSE_RR_FAIL; if (rdlength > 261) return RULI_PARSE_RR_FAIL; srv_rdata->priority = ruli_pack2(rdata); srv_rdata->weight = ruli_pack2(rdata + 2); srv_rdata->port = ruli_pack2(rdata + 4); { const ruli_uint8_t *trg = rdata + 6; i = skip_rr_owner(trg, past_end); if (i != past_end) return RULI_PARSE_RR_FAIL; srv_rdata->target = trg; srv_rdata->target_len = past_end - trg; } assert(srv_rdata->target_len <= RULI_LIMIT_DNAME_ENCODED); return RULI_PARSE_RR_OK; } int ruli_parse_rr_cname(ruli_cname_rdata_t *cname_rdata, const ruli_uint8_t *rdata, ruli_uint16_t rdlength, const ruli_uint8_t *msg, size_t msg_len) { size_t len; if (ruli_dname_expand(msg, msg + msg_len, cname_rdata->cname, cname_rdata->cname + RULI_LIMIT_DNAME_ENCODED, rdata, &len)) return RULI_PARSE_RR_FAIL; assert(len > 0); assert(len <= RULI_LIMIT_DNAME_ENCODED); cname_rdata->cname_len = len; return RULI_PARSE_RR_OK; } int ruli_parse_rr_mx(ruli_mx_rdata_t *mx_rdata, const ruli_uint8_t *rdata, ruli_uint16_t rdlength, const ruli_uint8_t *msg, size_t msg_len) { size_t len; /* offset data size ------------------------ 0 preference 2 2 target 1..255 */ if (rdlength < 3) return RULI_PARSE_RR_FAIL; if (rdlength > 257) return RULI_PARSE_RR_FAIL; mx_rdata->preference = ruli_pack2(rdata); if (ruli_dname_expand(msg, msg + msg_len, mx_rdata->target, mx_rdata->target + RULI_LIMIT_DNAME_ENCODED, rdata + 2, &len)) return RULI_PARSE_RR_FAIL; assert(len > 0); assert(len <= RULI_LIMIT_DNAME_ENCODED); mx_rdata->target_len = len; return RULI_PARSE_RR_OK; } void ruli_parse_addr_rr(ruli_addr_t *addr, const ruli_rr_t *rr, long options) { assert(ruli_rr_type_is_address(options, rr->type)); switch (rr->type) { case RULI_RR_TYPE_A: { int result = ruli_parse_rr_a(&addr->addr.ipv4, rr->rdata, rr->rdlength); assert(!result); /* IN A parsing can't fail */ } ruli_addr_init(addr, PF_INET); break; case RULI_RR_TYPE_AAAA: { int result = ruli_parse_rr_aaaa(&addr->addr.ipv6, rr->rdata, rr->rdlength); assert(!result); /* IN AAAA parsing can't fail */ } ruli_addr_init(addr, PF_INET6); break; default: /* Previous ruli_rr_type_is_address() call ensures * RR type is either IN_A or IN_AAAA, thus we can * panic otherwise. */ assert(0); } #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: ruli_parse_addr_rr(): addr="); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif } ruli-0.33/src/ruli_parse.h0000644000177100017710000000677410060516504016274 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_parse.h,v 1.13 2004/06/06 04:27:48 evertonm Exp $ */ #ifndef RULI_PARSE_H #define RULI_PARSE_H #include #include #include #include #include enum { RULI_PARSE_OK = 0, RULI_PARSE_SHORT_MSG, RULI_PARSE_LONG_MSG, RULI_PARSE_QUESTION, RULI_PARSE_ANSWER, RULI_PARSE_AUTHORITY, RULI_PARSE_ADDITIONAL, RULI_PARSE_LIST }; enum { RULI_PARSE_RR_OK = 0, RULI_PARSE_RR_FAIL }; /* offset data size ------------------------ 0 type 2 2 class 2 4 ttl 4 8 rdlength 2 10 rdata rdlength 10 + rdlength */ typedef struct { /* * References owner in compressed format */ const ruli_uint8_t *owner; int owner_len; ruli_uint16_t type; ruli_uint16_t qclass; /* class is a C++ keyword */ ruli_uint32_t ttl; ruli_uint32_t rdlength; const ruli_uint8_t *rdata; } ruli_rr_t; typedef struct { ruli_uint16_t priority; ruli_uint16_t weight; ruli_uint16_t port; const ruli_uint8_t *target; int target_len; } ruli_srv_rdata_t; typedef struct { ruli_uint8_t cname[RULI_LIMIT_DNAME_ENCODED]; /* encoded, uncompressed */ int cname_len; } ruli_cname_rdata_t; typedef struct { ruli_uint16_t preference; ruli_uint8_t target[RULI_LIMIT_DNAME_ENCODED]; /* encoded, uncompressed */ int target_len; } ruli_mx_rdata_t; typedef struct { /* * input */ ruli_uint16_t qdcount; ruli_uint16_t ancount; ruli_uint16_t nscount; ruli_uint16_t arcount; /* * output: lists of ruli_rr_t* */ ruli_list_t question_list; ruli_list_t answer_list; ruli_list_t authority_list; ruli_list_t additional_list; } ruli_parse_t; int ruli_parse_new(ruli_parse_t *parse); int ruli_parse_message(ruli_parse_t *parse, ruli_msg_header_t *msg_hdr, const ruli_uint8_t *msg, int msg_len); void ruli_parse_delete(ruli_parse_t *parse); int ruli_parse_rr_a(struct in_addr *addr, const ruli_uint8_t *rdata, ruli_uint16_t rdlength); int ruli_parse_rr_aaaa(struct in6_addr *addr, const ruli_uint8_t *rdata, ruli_uint16_t rdlength); int ruli_parse_rr_srv(ruli_srv_rdata_t *srv_rdata, const ruli_uint8_t *rdata, ruli_uint16_t rdlength); int ruli_parse_rr_cname(ruli_cname_rdata_t *cname_rdata, const ruli_uint8_t *rdata, ruli_uint16_t rdlength, const ruli_uint8_t *msg, size_t msg_len); int ruli_parse_rr_mx(ruli_mx_rdata_t *mx_rdata, const ruli_uint8_t *rdata, ruli_uint16_t rdlength, const ruli_uint8_t *msg, size_t msg_len); void ruli_parse_addr_rr(ruli_addr_t *addr, const ruli_rr_t *rr, long options); #endif /* RULI_PARSE_H */ ruli-0.33/src/ruli_rand.c0000644000177100017710000000277310053444466016105 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_rand.c,v 1.7 2004/05/21 18:23:50 evertonm Exp $ */ #include #include void ruli_rand_init(ruli_rand_t *rand_ctx) { int i; rand_ctx->isaac_ctx.randa = 0; rand_ctx->isaac_ctx.randb = rand_ctx->isaac_ctx.randa; rand_ctx->isaac_ctx.randc = rand_ctx->isaac_ctx.randc; for (i = 0; i < 256; ++i) rand_ctx->isaac_ctx.randrsl[i] = 0; isaac_randinit(&rand_ctx->isaac_ctx, 1); } int ruli_rand_next(ruli_rand_t *rand_ctx, int min, int max) { int r; unsigned int u; assert(min <= max); u = isaac_rand(&rand_ctx->isaac_ctx); r = (int) ((float) (1.0 + max - min) * u / ISAAC_UB4MAXVAL + min); assert(min <= r); assert(r <= max); return r; } ruli-0.33/src/ruli_rand.h0000644000177100017710000000216007656224342016104 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_rand.h,v 1.6 2003/05/07 15:40:18 evertonm Exp $ */ #ifndef RULI_RAND_H #define RULI_RAND_H #include "ruli_isaac.h" typedef struct { isaac_randctx isaac_ctx; } ruli_rand_t; void ruli_rand_init(ruli_rand_t *rand_ctx); int ruli_rand_next(ruli_rand_t *rand_ctx, int min, int max); #endif /* RULI_RAND_H */ ruli-0.33/src/ruli_res.c0000644000177100017710000005067110130671727015750 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_res.c,v 1.36 2004/10/06 04:25:59 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * From RFC 1035 */ static const ruli_qtype_pair_t ruli_qtype_map[] = { { "a", RULI_RR_TYPE_A }, { "ns", RULI_RR_TYPE_NS }, { "md", RULI_RR_TYPE_MD }, { "mf", RULI_RR_TYPE_MF }, { "cname", RULI_RR_TYPE_CNAME }, { "soa", RULI_RR_TYPE_SOA }, { "mb", RULI_RR_TYPE_MB }, { "mg", RULI_RR_TYPE_MG }, { "mr", RULI_RR_TYPE_MR }, { "null", RULI_RR_TYPE_NULL }, { "wks", RULI_RR_TYPE_WKS }, { "ptr", RULI_RR_TYPE_PTR }, { "hinfo", RULI_RR_TYPE_HINFO }, { "minfo", RULI_RR_TYPE_MINFO }, { "mx", RULI_RR_TYPE_MX }, { "txt", RULI_RR_TYPE_TXT }, { "aaaa", RULI_RR_TYPE_AAAA }, { "srv", RULI_RR_TYPE_SRV }, { "axfr", RULI_RR_TYPE_AXFR }, { "mailb", RULI_RR_TYPE_MAILB }, { "maila", RULI_RR_TYPE_MAILA }, { "*", RULI_RR_TYPE_ANY }, { 0, 0 } }; /* * From RFC 1035 */ static const ruli_qclass_pair_t ruli_qclass_map[] = { { "in", RULI_RR_CLASS_IN }, { "cs", RULI_RR_CLASS_CS }, { "ch", RULI_RR_CLASS_CH }, { "hs", RULI_RR_CLASS_HS }, { "*", RULI_RR_CLASS_ANY }, { 0, 0 } }; int ruli_get_qtype_code(const char *qt_name) { int i; for (i = 0; ruli_qtype_map[i].qt_name; ++i) if (!strcasecmp(qt_name, ruli_qtype_map[i].qt_name)) return ruli_qtype_map[i].qt_code; return 0; } int ruli_get_qclass_code(const char *qc_name) { int i; for (i = 0; ruli_qclass_map[i].qc_name; ++i) if (!strcasecmp(qc_name, ruli_qclass_map[i].qc_name)) return ruli_qclass_map[i].qc_code; return 0; } const char *ruli_get_qtype_name(int qt_code) { int i; for (i = 0; ruli_qtype_map[i].qt_name; ++i) if (qt_code == ruli_qtype_map[i].qt_code) return ruli_qtype_map[i].qt_name; return 0; } const char *ruli_get_qclass_name(int qc_code) { int i; for (i = 0; ruli_qclass_map[i].qc_name; ++i) if (qc_code == ruli_qclass_map[i].qc_code) return ruli_qclass_map[i].qc_name; return 0; } int ruli_rr_type_is_address(long options, int rr_type) { switch (rr_type) { case RULI_RR_TYPE_A: return !(options & RULI_RES_OPT_SRV_NOINET); case RULI_RR_TYPE_AAAA: return !(options & RULI_RES_OPT_SRV_NOINET6); } return 0; } const char *ruli_res_errstr(int result) { return "FIXME: ruli_res_errstr()"; } static void ruli_res_dispose_servers(ruli_res_t *res_ctx) { int err = errno; int size = ruli_list_size(&res_ctx->server_list); int i; ruli_server_t *server; for (i = 0; i < size; ++i) { server = (ruli_server_t *) ruli_list_get(&res_ctx->server_list, i); if (server->tcp_sd != -1) { int result = close(server->tcp_sd); assert(!result); } ruli_free(server); } ruli_list_delete(&res_ctx->server_list); errno = err; } static void conf_load(ruli_res_t *res_ctx) { assert(res_ctx); /* * Use custom conf handler? */ if (res_ctx->res_conf_handler) { res_ctx->search_list = res_ctx->res_conf_handler->search_loader(res_ctx->res_conf_handler); res_ctx->ns_list = res_ctx->res_conf_handler->ns_loader(res_ctx->res_conf_handler); return; } /* * Use default conf handler */ res_ctx->search_list = ruli_conf_load_search_list(0); res_ctx->ns_list = ruli_conf_load_ns_list(0); } static void conf_unload(ruli_res_t *res_ctx) { assert(res_ctx); /* * Use custom conf handler? */ if (res_ctx->res_conf_handler) { if (res_ctx->search_list) res_ctx->res_conf_handler->search_unloader(res_ctx->res_conf_handler, res_ctx->search_list); if (res_ctx->ns_list) res_ctx->res_conf_handler->ns_unloader(res_ctx->res_conf_handler, res_ctx->ns_list); return; } /* * Use default conf handler */ if (res_ctx->search_list) ruli_conf_unload_search_list(0, res_ctx->search_list); if (res_ctx->ns_list) ruli_conf_unload_ns_list(0, res_ctx->ns_list); } int ruli_res_new(ruli_res_t *res_ctx) { int i; int size; ruli_server_t *server; /* FIXME: We need a better method to check this */ assert(sizeof(ruli_uint8_t) == 1); assert(sizeof(ruli_uint16_t) == 2); assert(sizeof(ruli_uint32_t) == 4); /* * Load search and ns list */ res_ctx->search_list = 0; res_ctx->ns_list = 0; conf_load(res_ctx); if (!res_ctx->ns_list) return RULI_RES_NS_LIST; assert(res_ctx->ns_list); assert(ruli_list_size(res_ctx->ns_list)); /* * Allocate query list */ if (ruli_list_new_cap(&res_ctx->query_list, 2)) { conf_unload(res_ctx); return RULI_RES_LIST; } res_ctx->udp_sd = -1; res_ctx->udp_writers = 0; res_ctx->udp_readers = 0; res_ctx->udp6_sd = -1; res_ctx->udp6_writers = 0; res_ctx->udp6_readers = 0; res_ctx->next_server = 0; res_ctx->next_query_id = 0; /* * Allocate space for server information * Includes TCP socket descriptors */ size = ruli_list_size(res_ctx->ns_list); assert(size > 0); if (ruli_list_new_cap(&res_ctx->server_list, size)) { conf_unload(res_ctx); ruli_list_delete(&res_ctx->query_list); return RULI_RES_LIST; } for (i = 0; i < size; ++i) { server = (ruli_server_t *) ruli_malloc(sizeof(ruli_server_t)); if (!server) { conf_unload(res_ctx); ruli_list_delete(&res_ctx->query_list); ruli_res_dispose_servers(res_ctx); return RULI_RES_MALLOC; } if (ruli_list_push(&res_ctx->server_list, server)) { conf_unload(res_ctx); ruli_list_delete(&res_ctx->query_list); ruli_res_dispose_servers(res_ctx); return RULI_RES_MALLOC; } server->tcp_sd = -1; server->tcp_connecters = 0; server->tcp_writers = 0; server->tcp_readers = 0; server->port = 53; /* default DNS server port in host-order */ server->tcp_head_len = -1; } /* Be sure we considered all servers */ assert(ruli_list_size(&res_ctx->server_list) == size); ruli_rand_init(&res_ctx->rand_ctx); return RULI_RES_OK; } void ruli_res_delete(ruli_res_t *res_ctx) { #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: " "query_list_size=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, ruli_list_size(&res_ctx->query_list)); #endif /* RULI_RES_DEBUG */ /* * Clean UDP socket */ if (res_ctx->udp_sd != -1) { int result = close(res_ctx->udp_sd); assert(!result); res_ctx->udp_sd = -1; } /* * Clean UDP6 socket */ if (res_ctx->udp6_sd != -1) { int result = close(res_ctx->udp6_sd); assert(!result); res_ctx->udp6_sd = -1; } /* * Dispose servers information * Including TCP sockets */ ruli_res_dispose_servers(res_ctx); /* Please don't finish without releasing queries */ assert(!ruli_list_size(&res_ctx->query_list)); /* Release query list */ ruli_list_delete(&res_ctx->query_list); /* Release dynamic config */ conf_unload(res_ctx); } /* Many queries can use the same UDP socket, for a given address family. This function encapsulates this. */ static int get_udp_socket(ruli_res_query_t *res_qry) { ruli_addr_t *addr = ruli_res_get_curr_serv_addr(res_qry); ruli_res_t *res_ctx = res_qry->resolver; int sd = -1; /* picky compilers */ switch (addr->addr_family) { case PF_INET: sd = res_ctx->udp_sd; if (sd != -1) return sd; sd = ruli_sock_create_udp(PF_INET); if (sd == -1) return sd; res_ctx->udp_sd = sd; break; case PF_INET6: sd = res_ctx->udp6_sd; if (sd != -1) return sd; sd = ruli_sock_create_udp(PF_INET6); if (sd == -1) return sd; res_ctx->udp6_sd = sd; break; default: assert(0); } return sd; } static int start_query(ruli_res_query_t *res_qry) { int result; /* * Get UDP socket */ int udp_sd = get_udp_socket(res_qry); if (udp_sd == -1) return RULI_RES_SOCKET; /* * Build query */ result = ruli_msg_build(ruli_qry_udp_buf(res_qry), res_qry->query_buf_size, &res_qry->query_msg_len, res_qry->query_id, res_qry->full_dname, res_qry->full_dname_len, res_qry->q_class, res_qry->q_type); #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: start_query(): query_id=%d result=%d query_msg_len=%d\n", res_qry->query_id, result, res_qry->query_msg_len); #endif if (result) return RULI_RES_MSG_BUILD; assert(res_qry->query_msg_len <= res_qry->query_buf_size); /* * Encode TCP message length */ { ruli_uint8_t *i = ruli_unpack2(ruli_qry_tcp_buf(res_qry), res_qry->query_msg_len); assert(i == ruli_qry_tcp_buf(res_qry) + 2); } /* * Set handler for events on socket * * fsm will return in _ruli_fsm_query_done() */ _ruli_query_want_write_udp(res_qry); return RULI_RES_OK; } static int get_next_server(ruli_res_t *res_ctx) { int next; int servers; assert(res_ctx); assert(res_ctx->ns_list); servers = ruli_list_size(res_ctx->ns_list); assert(servers > 0); next = res_ctx->next_server++; res_ctx->next_server %= servers; assert(res_ctx->next_server >= 0); assert(res_ctx->next_server < servers); return next; } ruli_uint8_t *ruli_qry_tcp_buf(ruli_res_query_t *qry) { return qry->query_buf; } int ruli_qry_tcp_msg_len(ruli_res_query_t *qry) { return qry->query_msg_len + 2; } ruli_uint8_t *ruli_qry_udp_buf(ruli_res_query_t *qry) { return qry->query_buf + 2; } int ruli_qry_udp_msg_len(ruli_res_query_t *qry) { return qry->query_msg_len; } int ruli_res_query_submit(ruli_res_t *res_ctx, ruli_res_query_t *res_qry) { int result; /* Initially use the domain name without search list */ assert(res_qry->q_domain_len <= RULI_LIMIT_DNAME_ENCODED); memcpy(res_qry->full_dname, res_qry->q_domain, res_qry->q_domain_len); res_qry->full_dname_len = res_qry->q_domain_len; /* * Append query into resolver context */ res_qry->resolver_index = ruli_list_size(&res_ctx->query_list); result = ruli_list_push(&res_ctx->query_list, res_qry); assert(!result); assert(RULI_RES_QBUF_SIZE == RULI_LIMIT_MSG_HIGH + 2); /* * Attach to resolver */ res_qry->resolver = res_ctx; res_qry->query_id = res_ctx->next_query_id++; res_qry->status = RULI_QRY_STAT_VOID; res_qry->first_server = get_next_server(res_ctx); res_qry->curr_server = res_qry->first_server; res_qry->query_buf_size = RULI_LIMIT_MSG_HIGH; res_qry->query_msg_len = -1; res_qry->answer_buf = 0; res_qry->answer_buf_size = -1; res_qry->answer_msg_len = -1; res_qry->answer_code = RULI_CODE_VOID; res_qry->remaining_retries = res_ctx->res_retry; res_qry->search_index = -1; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: query_id=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, res_qry->query_id); #endif /* RULI_RES_DEBUG */ return start_query(res_qry); } void ruli_res_query_delete(ruli_res_query_t *res_qry) { ruli_res_t *res = res_qry->resolver; /* query resolver */ ruli_list_t *q_list; /* resolver query list */ int q_ind; /* query index in resolver */ #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: BEFORE delete: query_id=%d attached_res=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, res_qry->query_id, res != 0); #endif /* RULI_RES_DEBUG */ q_list = &res->query_list; q_ind = res_qry->resolver_index; /* * Perform state-specific clean-up */ _ruli_query_status_done(res_qry); /* * If we have an answer buffer allocated, release it. */ if (res_qry->answer_buf) { ruli_free(res_qry->answer_buf); res_qry->answer_buf = 0; res_qry->answer_buf_size = -1; res_qry->answer_msg_len = -1; res_qry->answer_code = RULI_CODE_VOID; } /* * If query is not attached to a resolver, it can't be deleted. */ if (!res) return; /* * Erase query from the resolver list. */ ruli_list_drop(q_list, q_ind); /* * Re-index the query which replaced this, if any. */ if (q_ind != ruli_list_size(q_list)) { ruli_res_query_t *qry = (ruli_res_query_t *) ruli_list_get(q_list, q_ind); qry->resolver_index = q_ind; } /* * Mark as detached from resolver. */ res_qry->resolver = 0; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: AFTER delete: query_list_size=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, ruli_list_size(q_list)); #endif /* RULI_RES_DEBUG */ } int ruli_res_get_curr_server_index(ruli_res_query_t *qry) { assert(qry->curr_server >= 0); assert(qry->curr_server < ruli_list_size(&qry->resolver->server_list)); return qry->curr_server; } ruli_server_t *ruli_res_get_curr_server(ruli_res_query_t *qry) { return (ruli_server_t *) ruli_list_get(&qry->resolver->server_list, ruli_res_get_curr_server_index(qry)); } ruli_addr_t *ruli_res_get_curr_serv_addr(ruli_res_query_t *res_qry) { ruli_res_t *res_ctx = res_qry->resolver; assert(res_ctx); assert(res_ctx->ns_list); assert(ruli_list_size(res_ctx->ns_list) > 0); assert(res_qry->curr_server >= 0); assert(res_qry->curr_server < ruli_list_size(res_ctx->ns_list)); return (ruli_addr_t *) ruli_list_get(res_ctx->ns_list, res_qry->curr_server); } int ruli_res_get_curr_serv_port(ruli_res_query_t *res_qry) { return ruli_res_get_curr_server(res_qry)->port; } int _ruli_get_curr_tcp_socket(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; int i = ruli_res_get_curr_server_index(qry); ruli_server_t *server = (ruli_server_t *) ruli_list_get(&res_ctx->server_list, i); int tcp_sd = server->tcp_sd; return tcp_sd; } int ruli_res_switch_server(ruli_res_query_t *res_qry) { int servers = ruli_list_size(res_qry->resolver->ns_list); assert(servers > 0); ++res_qry->curr_server; res_qry->curr_server %= servers; assert(res_qry->curr_server >= 0); assert(res_qry->curr_server < servers); if (res_qry->curr_server == res_qry->first_server) { if (res_qry->remaining_retries < 1) return -1; --res_qry->remaining_retries; } return 0; } ruli_res_query_t *ruli_res_find_query_by_id(ruli_list_t *query_list, ruli_uint16_t query_id) { ruli_res_query_t *qry; int query_list_size; int i; query_list_size = ruli_list_size(query_list); for (i = 0; i < query_list_size; ++i) { qry = (ruli_res_query_t *) ruli_list_get(query_list, i); if (qry->query_id == query_id) return qry; } return 0; } ruli_server_t *ruli_res_find_server_by_sd(ruli_list_t *server_list, int sd) { ruli_server_t *server; int list_size; int i; /* We should not look for an invalid fd */ assert(sd >= 0); list_size = ruli_list_size(server_list); for (i = 0; i < list_size; ++i) { server = (ruli_server_t *) ruli_list_get(server_list, i); if (server->tcp_sd == sd) return server; } return 0; } static const ruli_domain_t *next_search_suffix(ruli_res_query_t *qry) { ruli_res_t *res_ctx = qry->resolver; int search_list_size; ruli_domain_t *suffix; if (!res_ctx->search_list) return 0; assert(res_ctx->search_list); search_list_size = ruli_list_size(res_ctx->search_list); assert(qry->search_index >= -1); assert(qry->search_index < search_list_size); if (qry->search_index == (search_list_size - 1)) return 0; assert(qry->search_index < (search_list_size - 1)); ++qry->search_index; assert(qry->search_index >= 0); assert(qry->search_index < search_list_size); suffix = (ruli_domain_t *) ruli_list_get(res_ctx->search_list, qry->search_index); return suffix; } static void *do_user_callback(ruli_res_query_t *qry) { return qry->q_on_answer(qry, qry->q_on_answer_arg); } /* start_query() has passed control to fsm through query_want_write_udp() fsm returns here */ void *_ruli_fsm_query_done(ruli_res_query_t *qry) { #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: %s: %s()\n", __FILE__, __PRETTY_FUNCTION__); #endif /* * Use the search list? */ if (qry->q_options & RULI_RES_OPT_SEARCH) /* * If we received a server answer... */ if (!qry->answer_code) { ruli_uint8_t rcode = qry->answer_header.rcode; /* * And that answer misses the query name... */ if ((rcode == RULI_RCODE_SERVERFAILURE) || (rcode == RULI_RCODE_NAMEERROR)) { /* * ... Then yes, we try the search list */ const ruli_domain_t *suffix = next_search_suffix(qry); if (suffix) { #ifdef RULI_RES_DEBUG { char txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_len; int result; result = ruli_dname_decode(txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_len, (const char *) suffix->domain_name, suffix->domain_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): search list suffix name=%s len=%d\n", __FILE__, __PRETTY_FUNCTION__, txt, txt_len); } #endif /* RULI_RES_DEBUG */ /* * Build new query name with current search list item */ if (ruli_dname_concat(qry->full_dname, RULI_LIMIT_DNAME_ENCODED, &qry->full_dname_len, (ruli_uint8_t *) qry->q_domain, qry->q_domain_len, suffix->domain_name, suffix->domain_len)) { qry->answer_code = RULI_CODE_CONCAT_SEARCH_LIST; return do_user_callback(qry); } #ifdef RULI_RES_DEBUG { char txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_len; int result; result = ruli_dname_decode(txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_len, (char *) qry->full_dname, qry->full_dname_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): search list full domain name=%s len=%d\n", __FILE__, __PRETTY_FUNCTION__, txt, txt_len); } #endif /* RULI_RES_DEBUG */ /* * Tweak query state */ assert(qry->answer_buf); assert(qry->answer_buf_size > 0); assert(qry->answer_buf_size <= 65535); assert(qry->answer_msg_len > 0); assert(qry->answer_msg_len <= 65535); assert(qry->answer_msg_len == qry->answer_buf_size); assert(!qry->answer_code); ruli_free(qry->answer_buf); qry->answer_buf = 0; qry->answer_buf_size = -1; qry->answer_msg_len = -1; qry->answer_code = RULI_CODE_VOID; qry->remaining_retries = qry->resolver->res_retry; qry->first_server = qry->curr_server; /* * Re-start query */ if (!start_query(qry)) return OOP_CONTINUE; /* Oh well, tell the user we failed miserably */ qry->answer_code = RULI_CODE_LAUNCH_SEARCH_LIST; } } } /* * Finally invoke user callback */ return do_user_callback(qry); } ruli-0.33/src/ruli_res.h0000644000177100017710000002533510251152276015751 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_res.h,v 1.26 2005/06/06 22:57:02 evertonm Exp $ */ #ifndef RULI_RES_H #define RULI_RES_H #include #include #include #include #include enum { RULI_RES_QBUF_SIZE = RULI_LIMIT_MSG_HIGH + 2 /* largest query + TCP prefix */ }; enum { RULI_RES_OK = 0, RULI_RES_LIST, RULI_RES_SOCKET, RULI_RES_MSG_BUILD, RULI_RES_MALLOC, RULI_RES_NS_LIST }; enum { RULI_CODE_VOID = -1, /* no result yet */ RULI_CODE_OK = 0, /* successful, check rcode */ RULI_CODE_TIMEOUT, /* timed out */ RULI_CODE_MALLOC, /* malloc failed */ RULI_CODE_SEND, /* could not send */ RULI_CODE_CONNECT, /* could not connect */ RULI_CODE_LAUNCH_SEARCH_LIST, /* failure restarting query with search list */ RULI_CODE_CONCAT_SEARCH_LIST, /* failure concat'ng query with search list */ RULI_CODE_ANSWER_OPCODE, /* bad answer opcode */ RULI_CODE_ANSWER_FLAG_QR, /* bad answer flag */ RULI_CODE_ANSWER_FLAG_RD, /* bad answer flag */ RULI_CODE_ANSWER_FLAG_RA, /* bad answer flag */ RULI_CODE_ANSWER_FLAG_Z, /* bad answer flag */ RULI_CODE_ANSWER_TRUNC /* TC bit in TCP answer */ }; enum { RULI_RCODE_VOID = -1, /* RULI's internals only */ RULI_RCODE_NOERROR = 0, /* No error condition */ RULI_RCODE_FORMATERROR = 1, /* Format error */ RULI_RCODE_SERVERFAILURE = 2, /* Server failure */ RULI_RCODE_NAMEERROR = 3, /* Name error */ RULI_RCODE_NOTIMPLEMENTED = 4, /* Not implemented */ RULI_RCODE_REFUSED = 5 /* Refused */ }; enum { RULI_RR_TYPE_A = 1, /* 1 a host address */ RULI_RR_TYPE_NS = 2, /* 2 an authoritative name server */ RULI_RR_TYPE_MD = 3, /* 3 a mail destination (Obsolete - use MX) */ RULI_RR_TYPE_MF = 4, /* 4 a mail forwarder (Obsolete - use MX) */ RULI_RR_TYPE_CNAME = 5, /* 5 the canonical name for an alias */ RULI_RR_TYPE_SOA = 6, /* 6 marks the start of a zone of authority */ RULI_RR_TYPE_MB = 7, /* 7 a mailbox domain name (EXPERIMENTAL) */ RULI_RR_TYPE_MG = 8, /* 8 a mail group member (EXPERIMENTAL) */ RULI_RR_TYPE_MR = 9, /* 9 a mail rename domain name (EXPERIMENTAL) */ RULI_RR_TYPE_NULL = 10, /* 10 a null RR (EXPERIMENTAL) */ RULI_RR_TYPE_WKS = 11, /* 11 a well known service description */ RULI_RR_TYPE_PTR = 12, /* 12 a domain name pointer */ RULI_RR_TYPE_HINFO = 13, /* 13 host information */ RULI_RR_TYPE_MINFO = 14, /* 14 mailbox or mail list information */ RULI_RR_TYPE_MX = 15, /* 15 mail exchange */ RULI_RR_TYPE_TXT = 16, /* 16 text strings */ RULI_RR_TYPE_AAAA = 28, /* 28 IPv6 address (RFC 3596) */ RULI_RR_TYPE_SRV = 33, /* 33 location of service */ RULI_RR_TYPE_AXFR = 252, /* 252 a request for a transfer of an entire zone */ RULI_RR_TYPE_MAILB = 253, /* 253 a request for mailbox-related records (MB, MG or MR) */ RULI_RR_TYPE_MAILA = 254, /* 254 a request for mail agent RRs (Obsolete - see MX) */ RULI_RR_TYPE_ANY = 255 /* 255 a request for all records */ }; /* * From RFC 1035 */ enum { RULI_RR_CLASS_IN = 1, /* 1 the Internet */ RULI_RR_CLASS_CS = 2, /* 2 the CSNET class (Obsolete) */ RULI_RR_CLASS_CH = 3, /* 3 the CHAOS class */ RULI_RR_CLASS_HS = 4, /* 4 Hesiod (Dyer 87) */ RULI_RR_CLASS_ANY = 255 /* 255 any class */ }; /* * Query options */ enum { RULI_RES_OPT_VOID = 0, RULI_RES_OPT_SEARCH = 1 << 0, /* Use search list */ RULI_RES_OPT_NEED_RA = 1 << 1, /* Require RA bit in answer */ RULI_RES_OPT_SRV_NOINET = 1 << 2, /* Don't search IPv4 addresses */ RULI_RES_OPT_SRV_NOINET6 = 1 << 3, /* Don't search IPv6 addresses */ RULI_RES_OPT_SRV_URI_PORT = 1 << 4, /* Assume port was forced in URI */ RULI_RES_OPT_SRV_NOWALK = 1 << 5, /* Don't search missing addresses */ RULI_RES_OPT_SRV_NOFALL = 1 << 6, /* Don't launch fallback queries */ RULI_RES_OPT_SRV_NOSORT6 = 1 << 7, /* Don't sort favorably to v6 addrs */ RULI_RES_OPT_SRV_RFC3484 = 1 << 8 /* Apply RFC3484 destination address selection rules */ }; typedef struct { const char *qt_name; int qt_code; } ruli_qtype_pair_t; typedef struct { const char *qc_name; int qc_code; } ruli_qclass_pair_t ; typedef struct { int tcp_sd; /* TCP socket descriptor */ int tcp_connecters; /* # of TCP queries waiting for connection */ int tcp_writers; /* # of TCP queries waiting to send */ int tcp_readers; /* # of TCP queries waiting to receive */ int port; /* server DNS port */ /* 14-byte buffer for header */ ruli_uint8_t tcp_head_buf[RULI_LIMIT_TCP_HEADER]; int tcp_head_len; /* received length */ } ruli_server_t; /* * This type is used for the search list */ typedef struct { /* encoded, uncompressed */ ruli_uint8_t domain_name[RULI_LIMIT_DNAME_ENCODED]; size_t domain_len; } ruli_domain_t; struct ruli_conf_handler_t; typedef struct ruli_conf_handler_t ruli_conf_handler_t; struct ruli_conf_handler_t { void *opaque; /* * load/unload search list */ ruli_list_t *(*search_loader)(ruli_conf_handler_t *self); void (*search_unloader)(ruli_conf_handler_t *self, ruli_list_t *search_list); /* * load/unload ns list */ ruli_list_t *(*ns_loader)(ruli_conf_handler_t *self); void (*ns_unloader)(ruli_conf_handler_t *self, ruli_list_t *ns_list); }; /* Opaque resolver context */ typedef struct { /* * private members */ ruli_list_t server_list; /* list of ruli_server_t* */ ruli_list_t query_list; /* list of ruli_res_query_t* */ int udp_sd; /* descriptor for UDP socket */ int udp_writers; /* # of UDP queries waiting to send */ int udp_readers; /* # of UDP queries waiting to receive */ int udp6_sd; /* inet6: descriptor for UDP socket */ int udp6_writers; /* inet6: # of UDP queries waiting to send */ int udp6_readers; /* inet6: # of UDP queries waiting to receive */ int next_server; /* server given when a query asks for one */ ruli_uint16_t next_query_id; /* query id serial generator */ ruli_rand_t rand_ctx; /* random generator */ ruli_list_t *search_list; /* dynamic conf: list of ruli_domain_t* */ ruli_list_t *ns_list; /* dynamic conf: list of ruli_addr_t* */ /* * public members */ ruli_conf_handler_t *res_conf_handler; /* dynamic config handler */ oop_source *res_source; /* event source */ int res_retry; /* retry limit for each server */ int res_timeout; /* query timeout for each server */ } ruli_res_t; struct ruli_res_query_t; typedef struct ruli_res_query_t ruli_res_query_t; typedef void *(*ruli_res_query_call_t)(ruli_res_query_t *qry, void *arg); /* Opaque query context */ struct ruli_res_query_t { /* * private members */ ruli_res_t *resolver; /* the resolver */ int resolver_index; /* index of this query in the resolver list */ ruli_uint16_t query_id; /* the query unique id */ int status; /* query status */ int first_server; /* server suggested by resolver */ int curr_server; /* server the query is using */ ruli_uint8_t query_buf[RULI_RES_QBUF_SIZE]; /* buffer for query message */ int query_buf_size; /* size of buffer */ int query_msg_len; /* length of message */ int remaining_retries; /* # of remaining retries */ struct timeval tv; /* saved for timeout de-scheduling */ int search_index; /* index in the resolver search list */ ruli_uint8_t full_dname[RULI_LIMIT_DNAME_ENCODED]; /* encoded, uncomp. */ int full_dname_len; /* length of above */ /* * public members */ /* input */ ruli_res_query_call_t q_on_answer; /* query callback function */ void *q_on_answer_arg; /* query callback opaque argument */ char *q_domain; /* query domain */ int q_domain_len; /* domain length */ int q_class; /* query class */ int q_type; /* query type */ long q_options; /* query options */ /* output */ char *answer_buf; int answer_buf_size; int answer_msg_len; int answer_code; ruli_msg_header_t answer_header; }; int ruli_get_qtype_code(const char *qt_name); int ruli_get_qclass_code(const char *qc_name); const char *ruli_get_qtype_name(int qt_code); const char *ruli_get_qclass_name(int qc_code); int ruli_rr_type_is_address(long options, int rr_type); const char *ruli_res_errstr(int result); int ruli_res_new(ruli_res_t *res_ctx); void ruli_res_delete(ruli_res_t *res_ctx); int ruli_res_query_submit(ruli_res_t *res_ctx, ruli_res_query_t *res_qry); void ruli_res_query_delete(ruli_res_query_t *res_qry); int ruli_res_get_curr_server_index(ruli_res_query_t *res_qry); ruli_server_t *ruli_res_get_curr_server(ruli_res_query_t *res_qry); ruli_addr_t *ruli_res_get_curr_serv_addr(ruli_res_query_t *res_qry); int ruli_res_get_curr_serv_port(ruli_res_query_t *res_qry); int _ruli_get_curr_tcp_socket(ruli_res_query_t *qry); /* * Exported to ruli_fsm */ int ruli_res_switch_server(ruli_res_query_t *res_qry); ruli_res_query_t *ruli_res_find_query_by_id(ruli_list_t *query_list, ruli_uint16_t query_id); ruli_server_t *ruli_res_find_server_by_sd(ruli_list_t *server_list, int sd); ruli_uint8_t *ruli_qry_tcp_buf(ruli_res_query_t *qry); ruli_uint8_t *ruli_qry_udp_buf(ruli_res_query_t *qry); int ruli_qry_tcp_msg_len(ruli_res_query_t *qry); int ruli_qry_udp_msg_len(ruli_res_query_t *qry); void *_ruli_fsm_query_done(ruli_res_query_t *qry); #endif /* RULI_RES_H */ ruli-0.33/src/ruli_search.c0000644000177100017710000001473510131412767016423 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_search.c,v 1.9 2004/10/08 04:22:15 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #include #include #include static void *on_srv_answer(ruli_srv_t *srv_qry, void *srv_qry_arg) { ruli_search_srv_t *search = (ruli_search_srv_t *) srv_qry_arg; return search->search_call(search, search->search_call_arg); } /* If fallback call is 0, use implicit '_ruli_srv_answer_fallback_addr' as fallback call */ ruli_search_srv_t *_ruli_search_srv_submit(void *(*fallback_call) (ruli_srv_t *srv_query), ruli_res_t *resolver, void *(*call) (ruli_search_srv_t *search, void *arg), void *call_arg, long options, const char *txt_service, const char *txt_domain, int fallback_port) { ruli_search_srv_t *search; assert(memchr(txt_service, '\0', RULI_LIMIT_DNAME_TEXT_BUFSZ)); assert(memchr(txt_domain, '\0', RULI_LIMIT_DNAME_TEXT_BUFSZ)); search = (ruli_search_srv_t *) ruli_malloc(sizeof(ruli_search_srv_t)); if (!search) return 0; /* * Encode query arguments */ { int txt_service_len = strlen(txt_service); int txt_domain_len = strlen(txt_domain); char *i; assert(txt_service_len >= 0); assert(txt_domain_len >= 0); assert(txt_service_len <= RULI_LIMIT_DNAME_TEXT); assert(txt_domain_len <= RULI_LIMIT_DNAME_TEXT); /* Service: as in "_http._tcp" */ #ifdef RULI_SEARCH_DEBUG fprintf(stderr, "DEBUG: %s: %s: encoding service: (%d) %s\n", __FILE__, __PRETTY_FUNCTION__, txt_service_len, txt_service); #endif i = ruli_dname_encode(search->search_encoded_service, RULI_LIMIT_DNAME_ENCODED, txt_service, txt_service_len); if (!i) { ruli_free(search); return 0; } search->search_encoded_service_len = i - search->search_encoded_service; assert(search->search_encoded_service_len > 0); assert(search->search_encoded_service_len <= RULI_LIMIT_DNAME_ENCODED); /* Domain: example.com */ #ifdef RULI_SEARCH_DEBUG fprintf(stderr, "DEBUG: %s(): %s: encoding domain: (%d) %s\n", __FILE__, __PRETTY_FUNCTION__, txt_domain_len, txt_domain); #endif i = ruli_dname_encode(search->search_encoded_domain, RULI_LIMIT_DNAME_ENCODED, txt_domain, txt_domain_len); if (!i) { ruli_free(search); return 0; } search->search_encoded_domain_len = i - search->search_encoded_domain; assert(search->search_encoded_domain_len <= RULI_LIMIT_DNAME_ENCODED); } #ifdef RULI_SEARCH_DEBUG fprintf(stderr, "DEBUG: %s(): %s: encoding DONE\n", __FILE__, __PRETTY_FUNCTION__); #endif search->search_call = call; search->search_call_arg = call_arg; search->srv_query.srv_resolver = resolver; search->srv_query.srv_on_answer = on_srv_answer; search->srv_query.srv_on_answer_arg = search; search->srv_query.srv_service = search->search_encoded_service; search->srv_query.srv_service_len = search->search_encoded_service_len; search->srv_query.srv_domain = search->search_encoded_domain; search->srv_query.srv_domain_len = search->search_encoded_domain_len; search->srv_query.srv_fallback_port = fallback_port; search->srv_query.srv_options = options; /* Force explicit fallback call */ if (fallback_call) { assert(fallback_call); if (_ruli_srv_query_submit(&search->srv_query, fallback_call)) { ruli_free(search); return 0; } return search; } /* Use implicit '_ruli_srv_answer_fallback_addr' as fallback call' */ if (ruli_srv_query_submit(&search->srv_query)) { ruli_free(search); return 0; } return search; } /* This function just invokes _ruli_search_srv_submit with 0 as fallback call, what means to use the implicit '_ruli_srv_answer_fallback_addr' as fallback call */ ruli_search_srv_t *ruli_search_srv_submit(ruli_res_t *resolver, void *(*call) (ruli_search_srv_t *search, void *arg), void *call_arg, long options, const char *txt_service, const char *txt_domain, int fallback_port) { return _ruli_search_srv_submit(0, resolver, call, call_arg, options, txt_service, txt_domain, fallback_port); } void ruli_search_srv_delete(ruli_search_srv_t *search) { assert(search); ruli_srv_query_delete(&search->srv_query); ruli_free(search); } int ruli_search_srv_code(const ruli_search_srv_t *search) { assert(search); return search->srv_query.answer_code; } int ruli_search_srv_rcode(ruli_search_srv_t *search) { assert(search); return ruli_srv_rcode(&search->srv_query); } ruli_list_t *ruli_search_srv_answer_list(ruli_search_srv_t *search) { assert(search); return &(search->srv_query.answer_srv_list); } ruli_search_res_t *ruli_search_res_new(oop_source *source, int retry, int timeout) { ruli_search_res_t *search_res; search_res = (ruli_search_res_t *) ruli_malloc(sizeof(ruli_search_res_t)); if (!search_res) return 0; search_res->resolver.res_conf_handler = 0; /* default */ search_res->resolver.res_source = source; search_res->resolver.res_retry = retry; search_res->resolver.res_timeout = timeout; if (ruli_res_new(&search_res->resolver)) { ruli_free(search_res); return 0; } return search_res; } void ruli_search_res_delete(ruli_search_res_t *search_res) { assert(search_res); ruli_res_delete(&search_res->resolver); ruli_free(search_res); } ruli_res_t *ruli_search_resolver(ruli_search_res_t *search_res) { assert(search_res); return &search_res->resolver; } ruli-0.33/src/ruli_search.h0000644000177100017710000000513310130171425016410 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_search.h,v 1.7 2004/10/04 06:52:05 evertonm Exp $ */ #ifndef RULI_SEARCH_H #define RULI_SEARCH_H #include struct ruli_search_srv_t; typedef struct ruli_search_srv_t ruli_search_srv_t; /* * Query context */ struct ruli_search_srv_t { ruli_srv_t srv_query; void *(*search_call)(ruli_search_srv_t *search, void *arg); void *search_call_arg; char search_encoded_service[RULI_LIMIT_DNAME_ENCODED]; int search_encoded_service_len; char search_encoded_domain[RULI_LIMIT_DNAME_ENCODED]; int search_encoded_domain_len; }; /* * Resolver context */ typedef struct { ruli_res_t resolver; } ruli_search_res_t; /* * Query functions */ ruli_search_srv_t *_ruli_search_srv_submit(void *(*fallback_call) (ruli_srv_t *srv_query), ruli_res_t *resolver, void *(*call) (ruli_search_srv_t *search, void *arg), void *call_arg, long options, const char *txt_service, const char *txt_domain, int fallback_port); ruli_search_srv_t *ruli_search_srv_submit(ruli_res_t *resolver, void *(*call) (ruli_search_srv_t *search, void *arg), void *call_arg, long options, const char *txt_service, const char *txt_domain, int fallback_port); void ruli_search_srv_delete(ruli_search_srv_t *search); int ruli_search_srv_code(const ruli_search_srv_t *search); int ruli_search_srv_rcode(ruli_search_srv_t *search); ruli_list_t *ruli_search_srv_answer_list(ruli_search_srv_t *search); /* * Resolver functions */ ruli_search_res_t *ruli_search_res_new(oop_source *source, int retry, int timeout); void ruli_search_res_delete(ruli_search_res_t *res); ruli_res_t *ruli_search_resolver(ruli_search_res_t *search_res); #endif /* RULI_SEARCH_H */ ruli-0.33/src/ruli_smtp.c0000644000177100017710000002662310251152276016137 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_smtp.c,v 1.20 2005/06/06 22:57:02 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #include #include #include static int srv_cmp_priority(const void *srv1, const void *srv2) { const ruli_srv_entry_t *e1 = *(const ruli_srv_entry_t * const *) srv1; const ruli_srv_entry_t *e2 = *(const ruli_srv_entry_t * const *) srv2; if (e1->priority < e2->priority) return -1; if (e1->priority > e2->priority) return 1; return 0; } static void sort_srv_by_mx_priority(ruli_srv_t *srv_qry) { ruli_list_t *srv_list = &srv_qry->answer_srv_list; void **srv_head = srv_list->head; qsort(srv_head, ruli_list_size(srv_list), sizeof(void*), srv_cmp_priority); } static void _m_query_done(ruli_srv_t *srv_qry, ruli_res_query_t *mx_qry) { assert(mx_qry); /* sort srv records by mx priority ? */ if (mx_qry->answer_code == RULI_CODE_OK) sort_srv_by_mx_priority(srv_qry); ruli_res_query_delete(mx_qry); ruli_free(mx_qry); } static void *mx_query_done(ruli_srv_t *srv_qry, int srv_result_code, ruli_res_query_t *mx_qry) { #ifdef RULI_SMTP_DEBUG fprintf(stderr, "DEBUG: %s: %s(): query_result=%s [%d]\n", __FILE__, __PRETTY_FUNCTION__, srv_result_code ? "FAIL" : "SUCCESS", srv_result_code); #endif _m_query_done(srv_qry, mx_qry); return _ruli_srv_query_done(srv_qry, srv_result_code); } static void *on_mx_answer(ruli_res_query_t *mx_qry, void *qry_arg) { ruli_srv_t *srv_qry = (ruli_srv_t *) qry_arg; int prev_srv_list_size = ruli_list_size(&srv_qry->answer_srv_list); #ifdef RULI_SMTP_DEBUG { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; int result; result = ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, (const char *) mx_qry->full_dname, mx_qry->full_dname_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): domain=%s domain_len=%d\n", __FILE__, __PRETTY_FUNCTION__, txt_dname_buf, txt_dname_len); fprintf(stderr, "DEBUG: %s: %s(): id=%d answer_code=%d rcode=%d\n", __FILE__, __PRETTY_FUNCTION__, mx_qry->query_id, mx_qry->answer_code, mx_qry->answer_header.rcode); } #endif assert(mx_qry->answer_code != RULI_CODE_VOID); assert(!prev_srv_list_size); /* * Query failed? */ if (mx_qry->answer_code) { srv_qry->last_rcode = RULI_RCODE_VOID; if (mx_qry->answer_code == RULI_CODE_TIMEOUT) return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_ALARM, mx_qry); return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_QUERY, mx_qry); } /* * Bad RCODE ? */ { ruli_uint16_t rcode = mx_qry->answer_header.rcode; srv_qry->last_rcode = rcode; if (rcode != RULI_RCODE_NOERROR) return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_RCODE, mx_qry); } /* * Parse answer */ { ruli_uint8_t *wanted_owner; int wanted_owner_len; ruli_parse_t parse; if (ruli_parse_new(&parse)) return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER, mx_qry); { int result; assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_parse_message(&parse, &mx_qry->answer_header, (ruli_uint8_t *) mx_qry->answer_buf, mx_qry->answer_msg_len); if (result) { ruli_parse_delete(&parse); return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_PARSE, mx_qry); } } assert(sizeof(ruli_uint8_t) == sizeof(char)); wanted_owner = (ruli_uint8_t *) mx_qry->full_dname; wanted_owner_len = mx_qry->full_dname_len; /* * Search for MX records in answer section */ { ruli_list_t *an_list = &parse.answer_list; int an_list_size = ruli_list_size(an_list); int i; #ifdef RULI_SMTP_DEBUG { char wanted_txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int wanted_txt_len; int result; assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_dname_decode(wanted_txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &wanted_txt_len, (const char *) wanted_owner, wanted_owner_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): " "wanted owner=(%d)%s\n", __FILE__, __PRETTY_FUNCTION__, wanted_txt_len, wanted_txt); } #endif /* * Scan answer section for IN MX records */ for (i = 0; i < an_list_size; ++i) { ruli_rr_t *rr = (ruli_rr_t *) ruli_list_get(an_list, i); if (rr->qclass != RULI_RR_CLASS_IN) continue; if (rr->type != RULI_RR_TYPE_MX) continue; /* * Owner matches? */ if (ruli_dname_compare(rr->owner, (ruli_uint8_t *) mx_qry->answer_buf, mx_qry->answer_msg_len, wanted_owner, wanted_owner_len)) continue; /* * Find MX target */ { int j; ruli_mx_rdata_t mx_rdata; ruli_list_t *ad_list = &parse.additional_list; int ad_list_size = ruli_list_size(ad_list); ruli_srv_entry_t *srv_entry; if (ruli_parse_rr_mx(&mx_rdata, rr->rdata, rr->rdlength, (ruli_uint8_t *) mx_qry->answer_buf, mx_qry->answer_msg_len)) { ruli_parse_delete(&parse); return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_PARSE, mx_qry); } /* * Create SRV record and append it to list */ srv_entry =_ruli_srv_list_new_entry(&srv_qry->answer_srv_list, (const char *) \ mx_rdata.target, mx_rdata.target_len, mx_rdata.preference, -1, srv_qry->srv_fallback_port); if (!srv_entry) { ruli_parse_delete(&parse); return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER, mx_qry); } /* * Search MX target addresses in additional section */ for (j = 0; j < ad_list_size; ++j) { ruli_rr_t *ad_rr = (ruli_rr_t *) ruli_list_get(ad_list, j); ruli_addr_t *addr; if (ad_rr->qclass != RULI_RR_CLASS_IN) continue; if (!ruli_rr_type_is_address(srv_qry->srv_options, ad_rr->type)) continue; /* * MX owner matches? */ if (ruli_dname_compare(ad_rr->owner, (ruli_uint8_t *) mx_qry->answer_buf, mx_qry->answer_msg_len, mx_rdata.target, mx_rdata.target_len)) continue; /* * Save MX target address */ /* Allocate space */ addr = (ruli_addr_t *) ruli_malloc(sizeof(*addr)); if (!addr) { ruli_parse_delete(&parse); return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER, mx_qry); } /* Save space */ if (ruli_list_push(&srv_entry->addr_list, addr)) { ruli_free(addr); ruli_parse_delete(&parse); return mx_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER, mx_qry); } /* Write address into space */ ruli_parse_addr_rr(addr, ad_rr, srv_qry->srv_options); } /* Save MX target addresses */ } /* Search MX target in additional section */ } /* for: IN MX scan of answer section */ /* * Done if at least one SRV record has been built */ { int curr_srv_list_size = ruli_list_size(&srv_qry->answer_srv_list); assert(curr_srv_list_size >= prev_srv_list_size); if (curr_srv_list_size > prev_srv_list_size) { #ifdef RULI_SMTP_DEBUG { int ii; ruli_list_t *list = &srv_qry->answer_srv_list; fflush(stdout); for (ii = 0; ii < ruli_list_size(list); ++ii) { ruli_srv_entry_t *srv_entry = \ (ruli_srv_entry_t *) ruli_list_get(list, ii); fprintf(stderr, "DEBUG: %s: %s(): answer SRV RR: " "priority=%d weight=%d port=%d\n", __FILE__, __PRETTY_FUNCTION__, srv_entry->priority, srv_entry->weight, srv_entry->port); } fflush(stderr); } #endif ruli_parse_delete(&parse); /* Dispose current IN MX fallback query */ _m_query_done(srv_qry, mx_qry); /* * Launch queries to fill missing addresses, if any */ assert(srv_qry->under.walk_index == -1); srv_qry->under.walk_index = 0; return _ruli_srv_answer_walk(srv_qry); } } #ifdef RULI_SMTP_DEBUG fprintf(stderr, "DEBUG: %s: %s(): id=%d answer_code=%d, rcode=%d: " "BUT: no matching IN MX record\n", __FILE__, __PRETTY_FUNCTION__, mx_qry->query_id, mx_qry->answer_code, mx_qry->answer_header.rcode); #endif } /* MX scanning loop */ ruli_parse_delete(&parse); } /* parsed answer context */ /* Dispose failed, current IN MX fallback query, that is replaced by IN A fallback query below */ _m_query_done(srv_qry, mx_qry); /* Try default IN A fallback query */ return _ruli_srv_answer_fallback_addr(srv_qry); } /* Fallback to 'smtp' */ static void *srv_answer_fallback_smtp(ruli_srv_t *srv_qry) { ruli_res_query_t *mx_qry; #ifdef RULI_SMTP_DEBUG { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; int result; result = ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, srv_qry->srv_domain, srv_qry->srv_domain_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): domain=%s len=%d\n", __FILE__, __PRETTY_FUNCTION__, txt_dname_buf, txt_dname_len); } #endif assert(!ruli_list_size(&srv_qry->answer_srv_list)); /* * Allocate space for fallback query */ mx_qry = (ruli_res_query_t *) ruli_malloc(sizeof(*mx_qry)); if (!mx_qry) return _ruli_srv_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER); /* * Initialize fallback query arguments */ mx_qry->q_on_answer = on_mx_answer; mx_qry->q_on_answer_arg = srv_qry; mx_qry->q_domain = srv_qry->srv_domain; mx_qry->q_domain_len = srv_qry->srv_domain_len; mx_qry->q_class = RULI_RR_CLASS_IN; mx_qry->q_type = RULI_RR_TYPE_MX; mx_qry->q_options = srv_qry->srv_options; /* * Submit fallback query */ if (ruli_res_query_submit(srv_qry->srv_resolver, mx_qry)) { ruli_free(mx_qry); return _ruli_srv_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER); } /* Wait query answer */ return OOP_CONTINUE; } ruli_search_srv_t *ruli_search_smtp_submit(ruli_res_t *resolver, void *(*call)(ruli_search_srv_t *search, void *arg), void *call_arg, long options, const char *txt_domain) { return _ruli_search_srv_submit(srv_answer_fallback_smtp, resolver, call, call_arg, options, "_smtp._tcp", txt_domain, 25); } ruli-0.33/src/ruli_smtp.h0000644000177100017710000000225610065425130016133 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_smtp.h,v 1.2 2004/06/21 00:22:48 evertonm Exp $ */ #ifndef RULI_SMTP_H #define RULI_SMTP_H #include ruli_search_srv_t *ruli_search_smtp_submit(ruli_res_t *resolver, void *(*call) (ruli_search_srv_t *search, void *arg), void *call_arg, long options, const char *txt_domain); #endif /* RULI_SMTP_H */ ruli-0.33/src/ruli_sock.c0000644000177100017710000002106710251671544016114 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_sock.c,v 1.14 2005/06/08 22:38:28 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #include #include #include #include #include #include #include #ifdef RULI_SOCK_DUMP_DEBUG static void dump_buf(FILE *out, const ruli_uint8_t *buf, int len) { int i; fprintf(out, " dump=%d @%u", len, (unsigned int) buf); for(i = 0; i < len; ++i) fprintf(out, " %02x", (unsigned char) buf[i]); } #endif static int solve_protocol(const char *proto_name) { struct protoent *pe; pe = getprotobyname(proto_name); if (!pe) return -1; return pe->p_proto; } int ruli_sock_create(int family, int type, const char *proto_name) { union { struct sockaddr_in inet; struct sockaddr_in6 inet6; } sa; unsigned int sa_len = 0; /* picky compilers */ int proto; int sd; long flags; /* * Solve protocol */ proto = solve_protocol(proto_name); if (proto == -1) return -1; /* * Create socket descriptor */ sd = socket(family, type, proto); if (sd == -1) return -1; /* * Specify non-blocking behavior */ flags = fcntl(sd, F_GETFL, 0); if (flags == -1) { close(sd); return -1; } if (fcntl(sd, F_SETFL, flags | O_NONBLOCK)) { close(sd); return -1; } /* * Bind the socket to local addresses */ switch (family) { case PF_INET: sa_len = sizeof(sa.inet); sa.inet.sin_family = family; sa.inet.sin_port = htons(0); /* request a local port */ sa.inet.sin_addr.s_addr = INADDR_ANY; /* all local addresses */ memset((char *) sa.inet.sin_zero, 0, sizeof(sa.inet.sin_zero)); break; case PF_INET6: sa_len = sizeof(sa.inet6); memset(&sa.inet6, 0, sizeof(sa.inet6)); sa.inet6.sin6_family = family; sa.inet6.sin6_port = htons(0); /* request a local port */ /* all local addresses */ assert(sizeof(sa.inet6.sin6_addr.s6_addr) == sizeof(in6addr_any)); memcpy(sa.inet6.sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any)); break; default: assert(0); } if (bind(sd, (struct sockaddr *) &sa, sa_len)) { close(sd); return -1; } return sd; } int ruli_sock_create_udp(int family) { int sd = ruli_sock_create(family, SOCK_DGRAM, "udp"); #ifdef SO_BSDCOMPAT if (sd == -1) return -1; /* * We don't want Linux ECONNREFUSED on UDP sockets */ { int one = 1; if (setsockopt(sd, SOL_SOCKET, SO_BSDCOMPAT, &one, sizeof(one))) return -1; } #endif /* Linux SO_BSDCOMPAT */ return sd; } int ruli_sock_create_tcp(int family) { return ruli_sock_create(family, SOCK_STREAM, "tcp"); } /* Return true if socket has successfully connected */ int ruli_sock_has_connected(int tcp_sd) { int optval; socklen_t optlen = sizeof(optval); int result = getsockopt(tcp_sd, SOL_SOCKET, SO_ERROR, &optval, &optlen); assert(!result); assert(optlen == sizeof(optval)); return !optval; } /* BEWARE: - *sa must be large enough to hold either PF_INET or PF_INET6 - *sa_len is IN for *sa size and OUT for *addr size */ void ruli_sock_set_sockaddr(struct sockaddr *sa, int *sa_len, const _ruli_addr *inet, int family, int port) { assert(sa_len); switch (family) { case PF_INET: { struct sockaddr_in *ad = (struct sockaddr_in *) sa; assert(*sa_len >= sizeof(*ad)); ad->sin_family = family; ad->sin_port = htons(port); ad->sin_addr = inet->ipv4; memset((char *) ad->sin_zero, 0, sizeof(ad->sin_zero)); *sa_len = sizeof(*ad); } break; case PF_INET6: { struct sockaddr_in6 *ad = (struct sockaddr_in6 *) sa; assert(*sa_len >= sizeof(*ad)); *sa_len = sizeof(*ad); memset(ad, 0, *sa_len); ad->sin6_family = family; ad->sin6_port = htons(port); ad->sin6_addr = inet->ipv6; } break; default: assert(0); } } int ruli_sock_connect(int sd, const ruli_addr_t *remote_addr, int remote_port) { union { struct sockaddr_in inet; struct sockaddr_in6 inet6; } sa; int sa_len = sizeof(sa); int result; assert(sizeof(sa) > sizeof(struct sockaddr)); ruli_sock_set_sockaddr((struct sockaddr *) &sa, &sa_len, &remote_addr->addr, remote_addr->addr_family, remote_port); assert((size_t) sa_len >= sizeof(sa.inet)); assert((size_t) sa_len <= sizeof(sa.inet6)); result = connect(sd, (struct sockaddr *) &sa, sa_len); #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: connect(): result=%d errno=%d\n", result, errno); #endif if (!result) return RULI_SOCK_OK; if (errno == EINPROGRESS) return RULI_SOCK_WOULD_BLOCK; return RULI_SOCK_CONNECT_FAIL; } int ruli_sock_sendto(int sd, const ruli_addr_t *rem_addr, int rem_port, const ruli_uint8_t *buf, int msg_len) { union { struct sockaddr_in inet; struct sockaddr_in6 inet6; } sa; int sa_len = sizeof(sa); int wr; assert(sizeof(sa) > sizeof(struct sockaddr)); ruli_sock_set_sockaddr((struct sockaddr *) &sa, &sa_len, &rem_addr->addr, rem_addr->addr_family, rem_port); assert((size_t) sa_len >= sizeof(sa.inet)); assert((size_t) sa_len <= sizeof(sa.inet6)); #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: ruli_sock_sendto(): fd=%d len=%d dst=", sd, msg_len); ruli_addr_print(stderr, rem_addr); fprintf(stderr, ":%d", rem_port); #ifdef RULI_SOCK_DUMP_DEBUG dump_buf(stderr, buf, msg_len); #endif fprintf(stderr, "\n"); #endif wr = sendto(sd, buf, msg_len, 0, (struct sockaddr *) &sa, sa_len); if (wr != msg_len) { assert(wr == -1); if (errno == EWOULDBLOCK) return RULI_SOCK_WOULD_BLOCK; if (errno == EAGAIN) return RULI_SOCK_WOULD_BLOCK; return RULI_SOCK_SEND_FAIL; } return RULI_SOCK_OK; } int ruli_sock_send(int sd, const ruli_uint8_t *buf, int msg_len) { int wr; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: ruli_sock_send(): len=%d", msg_len); #ifdef RULI_SOCK_DUMP_DEBUG dump_buf(stderr, buf, msg_len); #endif fprintf(stderr, "\n"); #endif wr = send(sd, buf, msg_len, 0); if (wr != msg_len) { assert(wr == -1); if (errno == EWOULDBLOCK) return RULI_SOCK_WOULD_BLOCK; if (errno == EAGAIN) return RULI_SOCK_WOULD_BLOCK; return RULI_SOCK_SEND_FAIL; } return RULI_SOCK_OK; } int ruli_sock_recvfrom(int sd, ruli_uint8_t *buf, int buf_size, int *msg_len, struct sockaddr *sa, socklen_t *sa_len) { int rd; assert(buf_size > 0); rd = recvfrom(sd, buf, buf_size, 0, sa, sa_len); if (rd == -1) { if (errno == EWOULDBLOCK) return RULI_SOCK_WOULD_BLOCK; if (errno == EAGAIN) return RULI_SOCK_WOULD_BLOCK; return RULI_SOCK_RECV_FAIL; } assert(rd >= 0); assert(rd <= buf_size); if (msg_len) *msg_len = rd; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: ruli_sock_recvfrom(): recv_len=%d buf_size=%d", rd, buf_size); #ifdef RULI_SOCK_DUMP_DEBUG dump_buf(stderr, buf, rd); #endif fprintf(stderr, "\n"); #endif return RULI_SOCK_OK; } int ruli_sock_recv(int sd, ruli_uint8_t *buf, int buf_size, int *msg_len) { int rd; assert(buf_size > 0); rd = recv(sd, buf, buf_size, 0); if (rd == -1) { if (errno == EWOULDBLOCK) return RULI_SOCK_WOULD_BLOCK; if (errno == EAGAIN) return RULI_SOCK_WOULD_BLOCK; return RULI_SOCK_RECV_FAIL; } assert(rd >= 0); assert(rd <= buf_size); if (msg_len) *msg_len = rd; #ifdef RULI_RES_DEBUG fprintf(stderr, "DEBUG: ruli_sock_recv(): recv_len=%d buf_size=%d", rd, buf_size); #ifdef RULI_SOCK_DUMP_DEBUG dump_buf(stderr, buf, rd); #endif fprintf(stderr, "\n"); #endif if (!rd) return RULI_SOCK_CLOSED; return RULI_SOCK_OK; } ruli-0.33/src/ruli_sock.h0000644000177100017710000000365210251671544016121 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_sock.h,v 1.10 2005/06/08 22:38:28 evertonm Exp $ */ #ifndef RULI_SOCKET_H #define RULI_SOCKET_H #include #include #include #include enum { RULI_SOCK_OK = 0, RULI_SOCK_WOULD_BLOCK, RULI_SOCK_SEND_FAIL, RULI_SOCK_RECV_FAIL, RULI_SOCK_CONNECT_FAIL, RULI_SOCK_CLOSED }; int ruli_sock_create(int domain, int type, const char *proto_name); int ruli_sock_create_udp(int family); int ruli_sock_create_tcp(int family); int ruli_sock_has_connected(int tcp_sd); void ruli_sock_set_sockaddr(struct sockaddr *sa, int *sa_len, const _ruli_addr *inet, int family, int port); int ruli_sock_connect(int sd, const ruli_addr_t *remote_addr, int rem_port); int ruli_sock_sendto(int sd, const ruli_addr_t *rem_addr, int rem_port, const ruli_uint8_t *buf, int msg_len); int ruli_sock_send(int sd, const ruli_uint8_t *buf, int msg_len); int ruli_sock_recvfrom(int sd, ruli_uint8_t *buf, int buf_size, int *msg_len, struct sockaddr *sa, socklen_t *sa_len); int ruli_sock_recv(int sd, ruli_uint8_t *buf, int buf_size, int *msg_len); #endif ruli-0.33/src/ruli_srv.c0000644000177100017710000010411610254327412015757 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_srv.c,v 1.85 2005/06/16 16:55:38 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include /* FIXME: remove me [used for fprintf() debug] */ #include /* FIXME: remove me [used for fprintf() debug] */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #include #include #include #include #include const char *ruli_srv_errstr(int result) { return "FIXME: ruli_srv_errstr()"; } static void addr_selection(ruli_list_t *srv_list, long options) { int i; int srv_list_size = ruli_list_size(srv_list); /* scan srv entries */ for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, i); ruli_addr_rfc3484_sort(&entry->addr_list, options); } } /* This is an indirection to the srv user callback */ void *_ruli_srv_query_done(ruli_srv_t *srv_qry, int srv_result_code) { assert(srv_qry->answer_code == RULI_SRV_CODE_VOID); assert(srv_result_code != RULI_SRV_CODE_VOID); srv_qry->answer_code = srv_result_code; /* Sort addresses */ if (srv_result_code == RULI_SRV_CODE_OK) addr_selection(&srv_qry->answer_srv_list, srv_qry->srv_options); /* * Invoke srv user callback */ return srv_qry->srv_on_answer(srv_qry, srv_qry->srv_on_answer_arg); } static void *query_done(ruli_srv_t *srv_qry, int srv_result_code) { return _ruli_srv_query_done(srv_qry, srv_result_code); } /* dispose fallback query */ static void f_query_done(ruli_host_t *fall_qry) { assert(fall_qry); ruli_host_query_delete(fall_qry); ruli_free(fall_qry); } /* finish fallback query */ static void *fall_query_done(ruli_srv_t *srv_qry, int srv_result_code, ruli_host_t *fall_qry) { #ifdef RULI_SRV_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: id=%d query_result=%s [%d]\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, fall_qry->host_query.query_id, srv_result_code ? "FAIL" : "SUCCESS", srv_result_code); #endif f_query_done(fall_qry); return query_done(srv_qry, srv_result_code); } /* walk query context */ typedef struct { ruli_host_t walk_query; /* auxiliary query context for "walk" */ ruli_srv_t *srv_query; /* original srv query */ } walk_t; /* dispose walk query */ static void w_query_done(walk_t *walk) { assert(walk); ruli_host_query_delete(&walk->walk_query); ruli_free(walk); } /* finish walk query */ static void *walk_query_done(walk_t *walk, int srv_result_code) { ruli_srv_t *srv_qry = walk->srv_query; #ifdef RULI_SRV_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: id=%d query_result=%s [%d]\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, walk->walk_query.host_query.query_id, srv_result_code ? "FAIL" : "SUCCESS", srv_result_code); #endif w_query_done(walk); return query_done(srv_qry, srv_result_code); } static void *on_walk_answer(ruli_host_t *host_qry, void *qry_arg) { walk_t *walk_qry = (walk_t *) qry_arg; ruli_srv_t *srv_qry = walk_qry->srv_query; ruli_srv_entry_t *srv_entry; int prev_addr_list_size; assert(ruli_host_answer_code(host_qry) != RULI_SRV_CODE_VOID); srv_entry = (ruli_srv_entry_t *) ruli_list_get(&srv_qry->answer_srv_list, srv_qry->under.walk_index); prev_addr_list_size = ruli_list_size(&srv_entry->addr_list); #ifdef RULI_SRV_DEBUG { char target_txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int target_txt_len; int result; result = ruli_dname_decode(target_txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &target_txt_len, (const char *) walk_qry->walk_query.host_query.full_dname, walk_qry->walk_query.host_query.full_dname_len); assert(!result); fprintf(stderr, "DEBUG: on_walk_answer(): query target=%s target_len=%d\n", target_txt, target_txt_len); } #endif /* * Query failed? */ { int answer_code = ruli_host_answer_code(host_qry); if (answer_code) { srv_qry->last_rcode = RULI_RCODE_VOID; switch(answer_code) { case RULI_HOST_CODE_ALARM: return walk_query_done(walk_qry, RULI_SRV_CODE_WALK_ALARM); case RULI_HOST_CODE_EMPTY: return walk_query_done(walk_qry, RULI_SRV_CODE_WALK_EMPTY); case RULI_HOST_CODE_RCODE: assert(ruli_host_rcode(host_qry) != RULI_RCODE_VOID); assert(ruli_host_rcode(host_qry) != RULI_RCODE_NOERROR); srv_qry->last_rcode = ruli_host_rcode(host_qry); return walk_query_done(walk_qry, RULI_SRV_CODE_WALK_RCODE); default: return walk_query_done(walk_qry, RULI_SRV_CODE_WALK_QUERY); } assert(0); } } assert(ruli_host_rcode(host_qry) == RULI_RCODE_NOERROR); srv_qry->last_rcode = RULI_RCODE_NOERROR; /* * Move addresses into SRV record */ { ruli_list_t *addr_list = &host_qry->answer_addr_list; int addr_list_size = ruli_list_size(addr_list); int i; /* Move addresses from addr query to SRV entry */ for (i = 0; i < addr_list_size; ++i) { ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, i); if (ruli_list_push(&srv_entry->addr_list, addr)) { ruli_list_prune(&srv_entry->addr_list, 0); return walk_query_done(walk_qry, RULI_SRV_CODE_FALL_OTHER); } } } /* * Detaches addresses from addr-query ruli_list_t container * So that next ruli_host_query_delete does not dispose them */ ruli_host_query_detach(host_qry); /* Dispose auxiliary query as it will be re-created by next walk query */ w_query_done(walk_qry); /* In future walk query, consider next answer target */ ++srv_qry->under.walk_index; return _ruli_srv_answer_walk(srv_qry); } static int find_addr(const ruli_list_t *addr_list, long options) { int list_size = ruli_list_size(addr_list); int i; for (i = 0; i < list_size; ++i) { ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, i); switch (ruli_addr_family(addr)) { case PF_INET6: if (!(options & RULI_RES_OPT_SRV_NOINET6)) return -1; break; case PF_INET: if (!(options & RULI_RES_OPT_SRV_NOINET)) return -1; break; } } return 0; } /* Search missing addresses for targets. We make serialized queries so we don't need to keep more than one query reference (walk_query). */ void *_ruli_srv_answer_walk(ruli_srv_t *srv_qry) { ruli_list_t *srv_list = &srv_qry->answer_srv_list; int srv_list_size = ruli_list_size(srv_list); /* Have the user disabled walk query? */ if (srv_qry->srv_options & RULI_RES_OPT_SRV_NOWALK) return query_done(srv_qry, RULI_SRV_CODE_OK); /* * Scan SRV answer targets, considering address lists */ for (; srv_qry->under.walk_index < srv_list_size; ++srv_qry->under.walk_index) { ruli_srv_entry_t *entry = \ (ruli_srv_entry_t *) ruli_list_get(srv_list, srv_qry->under.walk_index); ruli_list_t *addr_list = &entry->addr_list; walk_t *walk_qry; /* If this target already has address(es), skip it */ if (find_addr(addr_list, srv_qry->srv_options)) continue; #ifdef RULI_SRV_DEBUG { char target_txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int target_txt_len; int result; result = ruli_dname_decode(target_txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &target_txt_len, entry->target, entry->target_len); assert(!result); fprintf(stderr, "DEBUG: _ruli_srv_answer_walk(): " "missing target=%s walk_index=%d\n", target_txt, srv_qry->under.walk_index); } #endif /* * Allocate space for auxiliary walk query */ walk_qry = \ (walk_t *) ruli_malloc(sizeof(*walk_qry)); if (!walk_qry) return query_done(srv_qry, RULI_SRV_CODE_WALK_OTHER); walk_qry->srv_query = srv_qry; /* * Initialize walk query arguments */ walk_qry->walk_query.host_resolver = srv_qry->srv_resolver; walk_qry->walk_query.host_on_answer = on_walk_answer; walk_qry->walk_query.host_on_answer_arg = walk_qry; walk_qry->walk_query.host_domain = entry->target; walk_qry->walk_query.host_domain_len = entry->target_len; walk_qry->walk_query.host_options = srv_qry->srv_options; /* RFC 2782 states CNAME aren't valid SRV targets */ walk_qry->walk_query.host_max_cname_depth = 0; /* * Submit walk query */ if (ruli_host_query_submit(&walk_qry->walk_query)) { ruli_free(walk_qry); return query_done(srv_qry, RULI_SRV_CODE_WALK_QUERY); } /* Wait answer */ return OOP_CONTINUE; } /* for */ /* * All targets scanned, we're done */ return query_done(srv_qry, RULI_SRV_CODE_OK); } static void *on_fallback_answer(ruli_host_t *qry, void *qry_arg) { ruli_srv_t *srv_qry = (ruli_srv_t *) qry_arg; int prev_srv_list_size = ruli_list_size(&srv_qry->answer_srv_list); int answer_code; assert(prev_srv_list_size == 0); assert(qry->answer_code != RULI_SRV_CODE_VOID); /* * Query failed? */ answer_code = ruli_host_answer_code(qry); if (answer_code) { srv_qry->last_rcode = RULI_RCODE_VOID; switch(answer_code) { case RULI_HOST_CODE_ALARM: return fall_query_done(srv_qry, RULI_SRV_CODE_FALL_ALARM, qry); case RULI_HOST_CODE_EMPTY: return fall_query_done(srv_qry, RULI_SRV_CODE_FALL_EMPTY, qry); case RULI_HOST_CODE_RCODE: assert(ruli_host_rcode(qry) != RULI_RCODE_VOID); assert(ruli_host_rcode(qry) != RULI_RCODE_NOERROR); srv_qry->last_rcode = ruli_host_rcode(qry); return fall_query_done(srv_qry, RULI_SRV_CODE_FALL_RCODE, qry); default: return fall_query_done(srv_qry, RULI_SRV_CODE_FALL_QUERY, qry); } assert(0); } assert(ruli_host_rcode(qry) == RULI_RCODE_NOERROR); srv_qry->last_rcode = RULI_RCODE_NOERROR; /* * Move addresses into SRV record */ { ruli_srv_entry_t *srv_entry; ruli_list_t *addr_list = &qry->answer_addr_list; int addr_list_size = ruli_list_size(addr_list); int i; /* Create SRV entry and append it to list */ srv_entry =_ruli_srv_list_new_entry(&srv_qry->answer_srv_list, srv_qry->srv_domain, srv_qry->srv_domain_len, -1, -1, srv_qry->srv_fallback_port); if (!srv_entry) return fall_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER, qry); /* Move addresses from addr query to SRV entry */ for (i = 0; i < addr_list_size; ++i) { ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, i); if (ruli_list_push(&srv_entry->addr_list, addr)) { ruli_list_prune(&srv_entry->addr_list, 0); return fall_query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER, qry); } } } /* * Detaches addresses from addr-query ruli_list_t container * So that next ruli_host_query_delete does not dispose them */ ruli_host_query_detach(qry); return fall_query_done(srv_qry, RULI_SRV_CODE_OK, qry); } /* Fallback to 'addr' */ void *_ruli_srv_answer_fallback_addr(ruli_srv_t *srv_qry) { ruli_host_t *fall_qry; #ifdef RULI_SRV_DEBUG { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; int result; result = ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, srv_qry->srv_domain, srv_qry->srv_domain_len); assert(!result); fprintf(stderr, "DEBUG: %s: %s(): %d: address query: " "domain=%s domain_len=%d fallback=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, txt_dname_buf, txt_dname_len, !!(srv_qry->srv_options & RULI_RES_OPT_SRV_NOFALL)); } #endif /* Has the user disabled fallback query? */ if (srv_qry->srv_options & RULI_RES_OPT_SRV_NOFALL) return query_done(srv_qry, RULI_SRV_CODE_OK); /* * Allocate space for fallback query */ fall_qry = (ruli_host_t *) \ ruli_malloc(sizeof(*fall_qry)); if (!fall_qry) return query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER); /* * Initialize fallback query arguments */ fall_qry->host_resolver = srv_qry->srv_resolver; fall_qry->host_on_answer = on_fallback_answer; fall_qry->host_on_answer_arg = srv_qry; fall_qry->host_domain = srv_qry->srv_domain; fall_qry->host_domain_len = srv_qry->srv_domain_len; fall_qry->host_options = srv_qry->srv_options; fall_qry->host_max_cname_depth = RULI_LIMIT_CNAME_DEPTH; /* * Submit fallback query */ if (ruli_host_query_submit(fall_qry)) { ruli_free(fall_qry); return query_done(srv_qry, RULI_SRV_CODE_FALL_OTHER); } /* Wait query answer */ return OOP_CONTINUE; } #ifdef RULI_SRV_DEBUG static void show_dname(const char *label, const char *dname, int dname_len) { char buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_len; int result; fprintf(stderr, "DEBUG: ruli_srv: show_dname(): dname=%u/%d", (unsigned int) dname, dname_len); result = ruli_dname_decode(buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_len, dname, dname_len); assert(!result); fprintf(stderr, ": %s=%s (encoded_len=%d txt_len=%d)\n", label, buf, dname_len, txt_len); } #endif static void *on_srv_answer(ruli_res_query_t *qry, void *arg) { ruli_srv_t *srv_qry = (ruli_srv_t *) arg; int result; assert(qry->answer_code != RULI_SRV_CODE_VOID); /* * Underlying query failed? */ if (qry->answer_code == RULI_CODE_TIMEOUT) return query_done(srv_qry, RULI_SRV_CODE_ALARM); if (qry->answer_code) return query_done(srv_qry, RULI_SRV_CODE_QUERY_FAILED); #ifdef RULI_SRV_DEBUG { ruli_msg_header_t msg_hdr; msg_hdr = qry->answer_header; fprintf(stderr, "DEBUG: on_srv_answer(): underlying query succeded: " "id=%d rcode=%d qd=%d an=%d ns=%d ar=%d " "answer_buf_size=%d answer_msg_len=%d\n", msg_hdr.id, msg_hdr.rcode, msg_hdr.qdcount, msg_hdr.ancount, msg_hdr.nscount, msg_hdr.arcount, qry->answer_buf_size, qry->answer_msg_len); } #endif /* * Parse answer for SRV records */ assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_parse_message(&srv_qry->parse, &qry->answer_header, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len); if (result) return query_done(srv_qry, RULI_SRV_CODE_PARSE_FAILED); /* * Check reply code and answer count */ if ((qry->answer_header.rcode != RULI_RCODE_NOERROR) || (qry->answer_header.ancount < 1)) { #ifdef RULI_SRV_DEBUG fprintf(stderr, "DEBUG: on_srv_answer(): SRV query failed\n"); #endif /* Fallback query */ return srv_qry->fallback(srv_qry); } /* * NOERROR && (ancount > 0) */ assert(qry->answer_header.rcode == RULI_RCODE_NOERROR); assert(qry->answer_header.ancount > 0); /* * Processing of SRV answer: * * Step 1/6: One SRV RR with target == '.' ? * Step 2/6: Parse rdata portion of all SRV RRs * Step 3/6: Sort SRV RRs by priority * Step 4/6: Select SRV RRs by random weighted order * Step 5/6: Build list of srv answers by inspecting additional section * Step 6/6: Launch queries to fill missing addresses, if any */ /* * Step 1/6: One SRV RR with target == '.' ? */ if (qry->answer_header.ancount == 1) { ruli_list_t *an_list = &srv_qry->parse.answer_list; if (ruli_list_size(an_list) == 1) { ruli_rr_t *rr = (ruli_rr_t *) ruli_list_top(an_list); if (rr->qclass == RULI_RR_CLASS_IN) { if (rr->type == RULI_RR_TYPE_SRV) { ruli_srv_rdata_t srv_rdata; if (ruli_parse_rr_srv(&srv_rdata, rr->rdata, rr->rdlength)) return query_done(srv_qry, RULI_SRV_CODE_PARSE_FAILED); /* target == '.' ? */ if (*srv_rdata.target == '\0') { /* Sanity test */ if (srv_rdata.target_len != 1) return query_done(srv_qry, RULI_SRV_CODE_PARSE_FAILED); /* * ruli_srv.c: target=='.': Owner match? */ assert(sizeof(ruli_uint8_t) == sizeof(char)); #ifdef RULI_SRV_DEBUG show_dname("on_srv_answer(): target=='.': qdomain", (const char *) qry->full_dname, qry->full_dname_len); #endif if (ruli_dname_compare(rr->owner, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len, (ruli_uint8_t *) qry->full_dname, qry->full_dname_len)) return query_done(srv_qry, RULI_SRV_CODE_PARSE_FAILED); return query_done(srv_qry, RULI_SRV_CODE_UNAVAILABLE); } } } } } /* One SRV RR with target == '.' ? */ /* * Step 2/6: Parse rdata portion of all SRV RRs */ { ruli_list_t *an_list = &srv_qry->parse.answer_list; int an_list_size = ruli_list_size(an_list); int i; for (i = 0; i < an_list_size; ++i) { ruli_rr_t *rr = (ruli_rr_t *) ruli_list_get(an_list, i); ruli_srv_rdata_t *srv_rdata; if (rr->qclass != RULI_RR_CLASS_IN) continue; if (rr->type != RULI_RR_TYPE_SRV) continue; #ifdef RULI_SRV_DEBUG fprintf(stderr, "DEBUG: on_srv_answer(): considering SRV-RR owner: %d of %d\n", (i + 1), an_list_size); #endif if (ruli_dname_compare(rr->owner, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len, (ruli_uint8_t *) qry->full_dname, qry->full_dname_len)) return query_done(srv_qry, RULI_SRV_CODE_PARSE_FAILED); #ifdef RULI_SRV_DEBUG fprintf(stderr, "DEBUG: on_srv_answer(): SRV-RR owner OK: %d of %d\n", (i + 1), an_list_size); #endif srv_rdata = (ruli_srv_rdata_t *) ruli_malloc(sizeof(ruli_srv_rdata_t)); if (!srv_rdata) return query_done(srv_qry, RULI_SRV_CODE_MALLOC); if (ruli_list_push(&srv_qry->rr_srv_list, srv_rdata)) { ruli_free(srv_rdata); return query_done(srv_qry, RULI_SRV_CODE_LIST); } if (ruli_parse_rr_srv(srv_rdata, rr->rdata, rr->rdlength)) return query_done(srv_qry, RULI_SRV_CODE_PARSE_FAILED); } } #ifdef RULI_SRV_DEBUG { int i; ruli_list_t *list = &srv_qry->rr_srv_list; fflush(stdout); for (i = 0; i < ruli_list_size(list); ++i) { ruli_srv_rdata_t *srv_rdata = \ (ruli_srv_rdata_t *) ruli_list_get(list, i); fflush(stderr); fprintf(stderr, "DEBUG: on_srv_answer(): SRV RR: " "priority=%d weight=%d port=%d\n", srv_rdata->priority, srv_rdata->weight, srv_rdata->port); fflush(stderr); } } #endif /* * Step 3/6: Sort SRV RRs by priority */ { ruli_list_t *src_list = &srv_qry->rr_srv_list; int src_list_size = ruli_list_size(src_list); int j; /* * Handle every RR based on priority (higher priority first) */ for (j = 0; j < src_list_size; ++j) { ruli_srv_rdata_t *srv_rdata = \ (ruli_srv_rdata_t *) ruli_list_get(src_list, j); ruli_list_t *dst_list = &srv_qry->pri_srv_list; int dst_list_size = ruli_list_size(dst_list); int i; assert(srv_rdata); /* * Find a lower-or-equal priority */ for (i = 0; i < dst_list_size; ++i) { ruli_srv_rdata_t *rd = (ruli_srv_rdata_t *) ruli_list_get(dst_list, i); if (srv_rdata->priority < rd->priority) continue; /* * For this priority, put 0-weight-elements at tail */ if (srv_rdata->weight == 0) { /* * Find begin of next priority and insert there */ for (; i < dst_list_size; ++i) { ruli_srv_rdata_t *s_rd = \ (ruli_srv_rdata_t *) ruli_list_get(dst_list, i); if (srv_rdata->priority != s_rd->priority) break; } /* for */ if (i == dst_list_size) break; /* Insert at tail (of this priority) */ } if (ruli_list_insert_at(dst_list, i, srv_rdata)) return query_done(srv_qry, RULI_SRV_CODE_LIST); srv_rdata = 0; /* mark as handled */ break; } /* for */ /* If not handled yet, insert at tail */ if (srv_rdata) if (ruli_list_push(dst_list, srv_rdata)) return query_done(srv_qry, RULI_SRV_CODE_LIST); } /* while */ } #ifdef RULI_SRV_DEBUG { int i; ruli_list_t *list = &srv_qry->pri_srv_list; fflush(stdout); for (i = 0; i < ruli_list_size(list); ++i) { ruli_srv_rdata_t *srv_rdata = \ (ruli_srv_rdata_t *) ruli_list_get(list, i); fflush(stderr); fprintf(stderr, "DEBUG: on_srv_answer(): priority SRV RR: " "priority=%d weight=%d port=%d\n", srv_rdata->priority, srv_rdata->weight, srv_rdata->port); fflush(stderr); } } #endif /* * Step 4/6: Select SRV RRs by random weighted order */ { ruli_list_t *src_list = &srv_qry->pri_srv_list; ruli_list_t *dst_list = &srv_qry->wei_srv_list; /* * Iterate over every priority */ for (;;) { int src_list_size = ruli_list_size(src_list); ruli_uint16_t curr_priority; int priority_weight_sum; int curr; int i; int rnd; int run_sum; ruli_srv_rdata_t *srv_rd; if (src_list_size < 1) break; /* * Get current priority */ curr = src_list_size - 1; srv_rd = (ruli_srv_rdata_t *) ruli_list_get(src_list, curr); curr_priority = srv_rd->priority; /* * Accumulate weight sum for priority */ priority_weight_sum = 0; for (i = curr; i >= 0; --i) { ruli_srv_rdata_t *rd = (ruli_srv_rdata_t *) ruli_list_get(src_list, i); if (curr_priority != rd->priority) break; priority_weight_sum += rd->weight; } /* for */ /* * Pick random number: 0..priority_weight_sum */ rnd = ruli_rand_next(&srv_qry->srv_resolver->rand_ctx, 0, priority_weight_sum); /* * Select least running sum */ run_sum = 0; for (i = curr; ; --i) { ruli_srv_rdata_t *rd; assert(i >= 0); rd = (ruli_srv_rdata_t *) ruli_list_get(src_list, i); run_sum += rd->weight; if (run_sum < rnd) continue; /* * Move from src_list to dst_list * (Both lists are only referential) */ ruli_list_shift_at(src_list, i); if (ruli_list_push(dst_list, rd)) return query_done(srv_qry, RULI_SRV_CODE_LIST); break; } /* for */ } /* for */ } #ifdef RULI_SRV_DEBUG { int i; ruli_list_t *list = &srv_qry->wei_srv_list; fflush(stdout); for (i = 0; i < ruli_list_size(list); ++i) { ruli_srv_rdata_t *srv_rdata = \ (ruli_srv_rdata_t *) ruli_list_get(list, i); fflush(stderr); fprintf(stderr, "DEBUG: on_srv_answer(): weight SRV RR: " "priority=%d weight=%d port=%d\n", srv_rdata->priority, srv_rdata->weight, srv_rdata->port); fflush(stderr); } } #endif /* * Step 5/6: Build list of srv answers by inspecting additional section */ { ruli_list_t *src_list = &srv_qry->wei_srv_list; ruli_list_t *dst_list = &srv_qry->answer_srv_list; int src_list_size = ruli_list_size(src_list); int i; assert(ruli_list_size(dst_list) == 0); #ifdef RULI_SRV_DEBUG { fflush(stdout); fprintf(stderr, "DEBUG: %s: %s(): %d: " "BEFORE addit inspection: " "srv_rr_list_size=%d srv_answer_list_size=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, src_list_size, ruli_list_size(&srv_qry->answer_srv_list)); fflush(stderr); } #endif /* * Build answer records inspecting additional section */ /* Scan all targets */ for (i = 0; i < src_list_size; ++i) { ruli_srv_rdata_t *rd = (ruli_srv_rdata_t *) ruli_list_get(src_list, i); ruli_srv_entry_t *srv_entry; /* Create SRV entry and append it to list */ srv_entry =_ruli_srv_list_new_entry(dst_list, (const char *) rd->target, rd->target_len, rd->priority, rd->weight, rd->port); if (!srv_entry) return query_done(srv_qry, RULI_SRV_CODE_MALLOC); /* * Look up target address(es) in additional section */ { ruli_list_t *ad_list = &srv_qry->parse.additional_list; int ad_list_size = ruli_list_size(ad_list); int j; /* Scan additional section */ for (j = 0; j < ad_list_size; ++j) { ruli_rr_t *rr = (ruli_rr_t *) ruli_list_get(ad_list, j); ruli_addr_t *addr; if (rr->qclass != RULI_RR_CLASS_IN) continue; if (!ruli_rr_type_is_address(srv_qry->srv_options, rr->type)) continue; /* Compare SRV target against additional record owner */ if (ruli_dname_compare(rr->owner, (ruli_uint8_t *) qry->answer_buf, qry->answer_msg_len, (ruli_uint8_t *) srv_entry->target, srv_entry->target_len)) continue; /* Allocate space for address */ addr = (ruli_addr_t *) ruli_malloc(sizeof(*addr)); if (!addr) return query_done(srv_qry, RULI_SRV_CODE_MALLOC); /* Save space */ if (ruli_list_push(&srv_entry->addr_list, addr)) { ruli_free(addr); return query_done(srv_qry, RULI_SRV_CODE_LIST); } /* Write address into space */ ruli_parse_addr_rr(addr, rr, srv_qry->srv_options); } /* for */ } } /* for */ #ifdef RULI_SRV_DEBUG { fflush(stdout); fprintf(stderr, "DEBUG: %s: %s(): %d: " "AFTER addit inspection: " "srv_rr_list_size=%d srv_answer_list_size=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, src_list_size, ruli_list_size(&srv_qry->answer_srv_list)); fflush(stderr); } #endif assert(ruli_list_size(dst_list) == src_list_size); } /* Build list of srv answers by inspecting additional section */ #ifdef RULI_SRV_DEBUG { int i; ruli_list_t *list = &srv_qry->answer_srv_list; fflush(stdout); for (i = 0; i < ruli_list_size(list); ++i) { ruli_srv_entry_t *srv_entry = \ (ruli_srv_entry_t *) ruli_list_get(list, i); fprintf(stderr, "DEBUG: on_srv_answer(): answer SRV RR: " "priority=%d weight=%d port=%d\n", srv_entry->priority, srv_entry->weight, srv_entry->port); } fflush(stderr); } #endif /* * Step 6/6: Launch queries to fill missing addresses, if any */ assert(srv_qry->under.walk_index == -1); srv_qry->under.walk_index = 0; return _ruli_srv_answer_walk(srv_qry); } int _ruli_srv_query_submit(ruli_srv_t *srv_qry, void *(*fallback_call)(ruli_srv_t *)) { ruli_res_query_t *qry = &srv_qry->query; int result; char *qdomain; int qdomain_len; assert(srv_qry); assert(fallback_call); /* can't disable all address families */ assert( !((srv_qry->srv_options & RULI_RES_OPT_SRV_NOINET) && (srv_qry->srv_options & RULI_RES_OPT_SRV_NOINET6)) ); srv_qry->fallback = fallback_call; /* * Concat srv_service + srv_domain into qdomain */ { int service_len = srv_qry->srv_service_len; int concat_len; --service_len; assert(srv_qry->srv_service[service_len] == '\0'); qdomain_len = service_len + srv_qry->srv_domain_len; qdomain = (char *) ruli_malloc(qdomain_len); if (!qdomain) return RULI_SRV_MALLOC; if (ruli_dname_concat((ruli_uint8_t *) qdomain, qdomain_len, &concat_len, (ruli_uint8_t *) srv_qry->srv_service, srv_qry->srv_service_len, (ruli_uint8_t *) srv_qry->srv_domain, srv_qry->srv_domain_len)) { ruli_free(qdomain); return RULI_SRV_CONCAT; } assert(qdomain_len == concat_len); srv_qry->qdomain = qdomain; srv_qry->qdomain_len = qdomain_len; #ifdef RULI_SRV_DEBUG { show_dname("ruli_srv_query_submit(): service", srv_qry->srv_service, srv_qry->srv_service_len); show_dname("ruli_srv_query_submit(): domain", srv_qry->srv_domain, srv_qry->srv_domain_len); show_dname("ruli_srv_query_submit(): qdomain", qdomain, qdomain_len); } #endif } /* * Initialize members */ /* stores data */ if (ruli_list_new(&srv_qry->rr_srv_list)) { ruli_free(srv_qry->qdomain); return RULI_SRV_CODE_LIST; } /* stores only references */ if (ruli_list_new(&srv_qry->pri_srv_list)) { ruli_free(srv_qry->qdomain); ruli_list_delete(&srv_qry->rr_srv_list); return RULI_SRV_CODE_LIST; } /* stores only references */ if (ruli_list_new(&srv_qry->wei_srv_list)) { ruli_free(srv_qry->qdomain); ruli_list_delete(&srv_qry->rr_srv_list); ruli_list_delete(&srv_qry->pri_srv_list); return RULI_SRV_CODE_LIST; } if (ruli_list_new(&srv_qry->answer_srv_list)) { ruli_free(srv_qry->qdomain); ruli_list_delete(&srv_qry->rr_srv_list); ruli_list_delete(&srv_qry->pri_srv_list); ruli_list_delete(&srv_qry->wei_srv_list); return RULI_SRV_CODE_LIST; } if (ruli_parse_new(&srv_qry->parse)) { ruli_free(srv_qry->qdomain); ruli_list_delete(&srv_qry->rr_srv_list); ruli_list_delete(&srv_qry->pri_srv_list); ruli_list_delete(&srv_qry->wei_srv_list); ruli_list_delete(&srv_qry->answer_srv_list); return RULI_SRV_CODE_LIST; } srv_qry->answer_code = RULI_SRV_CODE_VOID; srv_qry->last_rcode = RULI_RCODE_VOID; srv_qry->under.walk_index = -1; /* * Define callback parameters */ qry->q_on_answer = on_srv_answer; qry->q_on_answer_arg = srv_qry; /* * Pass on query parameters */ qry->q_domain = qdomain; qry->q_domain_len = qdomain_len; qry->q_class = RULI_RR_CLASS_IN; qry->q_type = RULI_RR_TYPE_SRV; qry->q_options = srv_qry->srv_options; /* * If the RULI port is explicitely defined in the URI, * the user wants only address records. * * Skip SRV query and fetch addresses instead. */ if (srv_qry->srv_options & RULI_RES_OPT_SRV_URI_PORT) { srv_qry->query.resolver = 0; { void *oop_result = _ruli_srv_answer_fallback_addr(srv_qry); if (oop_result != OOP_CONTINUE) return RULI_SRV_CODE_QUERY_FAILED; } return RULI_SRV_OK; } /* * Submit plain query to underlying resolver */ result = ruli_res_query_submit(srv_qry->srv_resolver, qry); if (result) { ruli_srv_query_delete(srv_qry); return RULI_SRV_QRY_SUBMIT; } return RULI_SRV_OK; } int ruli_srv_query_submit(ruli_srv_t *srv_qry) { assert(srv_qry); return _ruli_srv_query_submit(srv_qry, _ruli_srv_answer_fallback_addr); } void ruli_srv_query_delete(ruli_srv_t *srv_qry) { #ifdef RULI_SRV_DEBUG fprintf(stderr, "DEBUG: %s: %s(): %d: query_id=%d\n", __FILE__, __PRETTY_FUNCTION__, __LINE__, srv_qry->query.query_id); #endif /* RULI_SRV_DEBUG */ /* * Dispose list of srv answers */ { ruli_list_t *list = &srv_qry->answer_srv_list; int list_size = ruli_list_size(list); int i; /* * For each entry, release list of *ruli_addr_t */ for (i = 0; i < list_size; ++i) { ruli_srv_entry_t *srv_entry = (ruli_srv_entry_t *) \ ruli_list_get(list, i); ruli_list_dispose_trivial(&srv_entry->addr_list); } } ruli_list_dispose_trivial(&srv_qry->answer_srv_list); ruli_parse_delete(&srv_qry->parse); ruli_list_dispose_trivial(&srv_qry->rr_srv_list); ruli_list_delete(&srv_qry->pri_srv_list); ruli_list_delete(&srv_qry->wei_srv_list); ruli_free(srv_qry->qdomain); ruli_res_query_delete(&srv_qry->query); } ruli_srv_rcode_kind_t ruli_srv_rcode_kind(ruli_srv_t *srv_qry) { int code = srv_qry->answer_code; if ((code >= RULI_SRV_CODE_OK) && (code <= RULI_SRV_CODE_UNAVAILABLE)) return RULI_SRV_RCODE_SRV; if ((code >= RULI_SRV_CODE_WALK_EMPTY) && (code <= RULI_SRV_CODE_WALK_RCODE)) return RULI_SRV_RCODE_WALK; if ((code >= RULI_SRV_CODE_FALL_EMPTY) && (code <= RULI_SRV_CODE_FALL_RCODE)) return RULI_SRV_RCODE_FALL; return RULI_SRV_RCODE_NONE; } int ruli_srv_rcode(ruli_srv_t *srv_qry) { ruli_srv_rcode_kind_t kind = ruli_srv_rcode_kind(srv_qry); int rcode = -1; /* picky compilers */ switch (kind) { case RULI_SRV_RCODE_NONE: rcode = RULI_RCODE_VOID; break; case RULI_SRV_RCODE_SRV: rcode = srv_qry->query.answer_header.rcode; break; case RULI_SRV_RCODE_WALK: case RULI_SRV_RCODE_FALL: rcode = srv_qry->last_rcode; break; default: assert(0); } return rcode; } ruli_srv_entry_t *_ruli_srv_list_new_entry(ruli_list_t *srv_list, const char *target, int target_len, int priority, int weight, int port) { ruli_srv_entry_t *srv_entry; /* Create SRV record */ srv_entry = (ruli_srv_entry_t *) ruli_malloc(sizeof(*srv_entry)); if (!srv_entry) return 0; /* Create record addr list */ if (ruli_list_new(&srv_entry->addr_list)) { ruli_free(srv_entry); return 0; } /* Save record */ if (ruli_list_push(srv_list, srv_entry)) { ruli_list_delete(&srv_entry->addr_list); ruli_free(srv_entry); return 0; } /* * Init record */ srv_entry->priority = priority; srv_entry->weight = weight; srv_entry->port = port; assert(target_len <= RULI_LIMIT_DNAME_ENCODED); srv_entry->target_len = target_len; memcpy(srv_entry->target, target, target_len); return srv_entry; } ruli-0.33/src/ruli_srv.h0000644000177100017710000001272010067131357015766 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_srv.h,v 1.38 2004/06/25 23:19:11 evertonm Exp $ */ #ifndef RULI_SRV_H #define RULI_SRV_H #include #include #include #include /* Return codes for ruli_srv_query_submit() */ enum { RULI_SRV_OK = 0, RULI_SRV_QRY_SUBMIT, RULI_SRV_MALLOC, RULI_SRV_CONCAT }; /* Values for ruli_srv_t.answer_code */ enum { RULI_SRV_CODE_VOID = -1, /* no result yet */ RULI_SRV_CODE_OK = 0, /* successful */ RULI_SRV_CODE_UNAVAILABLE, /* service surely not avaible in domain */ RULI_SRV_CODE_ALARM, /* timeout */ RULI_SRV_CODE_QUERY_FAILED, /* query failed */ RULI_SRV_CODE_PARSE_FAILED, /* parse error */ RULI_SRV_CODE_MALLOC, /* resources */ RULI_SRV_CODE_LIST, /* resources */ RULI_SRV_CODE_WALK_QUERY, /* walk query failed */ RULI_SRV_CODE_WALK_PARSE, /* walk parse failed */ RULI_SRV_CODE_WALK_ALARM, /* walk timeout */ RULI_SRV_CODE_WALK_EMPTY, /* walk rcode == NOERROR, but no records */ RULI_SRV_CODE_WALK_RCODE, /* walk rcode != NOERROR, check rcode */ RULI_SRV_CODE_WALK_OTHER, /* other error, probably resources exhausted */ RULI_SRV_CODE_FALL_QUERY, /* fall query failed */ RULI_SRV_CODE_FALL_PARSE, /* fall parse failed */ RULI_SRV_CODE_FALL_ALARM, /* fall timeout */ RULI_SRV_CODE_FALL_EMPTY, /* fall rcode == NOERROR, but no records */ RULI_SRV_CODE_FALL_RCODE, /* fall rcode != NOERROR, check rcode */ RULI_SRV_CODE_FALL_CNAME, /* cname chain too deep */ RULI_SRV_CODE_FALL_OTHER /* other error, probably resources exhausted */ }; typedef enum { RULI_SRV_RCODE_NONE, /* no RCODE available */ RULI_SRV_RCODE_SRV, /* RCODE returned for SRV query */ RULI_SRV_RCODE_WALK, /* RCODE returned for SRV target query */ RULI_SRV_RCODE_FALL /* RCODE returned for IN A fallback query */ } ruli_srv_rcode_kind_t; typedef struct { char target[RULI_LIMIT_DNAME_ENCODED]; /* encoded, uncompressed */ int target_len; int priority; int weight; int port; ruli_list_t addr_list; /* list of *ruli_addr_t */ } ruli_srv_entry_t; struct ruli_srv_t; typedef struct ruli_srv_t ruli_srv_t; /* User callback function type */ typedef void *(*ruli_srv_call_t)(ruli_srv_t *srv_qry, void *srv_qry_arg); /* Query opaque context */ struct ruli_srv_t { /* * private members */ ruli_res_query_t query; /* underlying query context */ ruli_parse_t parse; /* store result of answer parsing */ char *qdomain; /* srv_service + srv_domain */ int qdomain_len; /* length of qdomain */ ruli_list_t rr_srv_list; /* list of *ruli_srv_rdata_t */ ruli_list_t pri_srv_list; /* priority ordered list of *ruli_srv_rdata_t (only references) */ ruli_list_t wei_srv_list; /* random weight ordered list of *ruli_srv_rdata_t (only references) */ /* auxiliary context for underlying queries */ union { int walk_index; /* index for answer_srv_list */ } under; int last_rcode; /* saved rcode for underlying query */ void *(*fallback)(ruli_srv_t *self); /* fallback function */ /* * public members */ /* input */ ruli_res_t *srv_resolver; /* resolver context */ ruli_srv_call_t srv_on_answer; /* user callback function */ void *srv_on_answer_arg; /* user callback argument */ char *srv_service; /* encoded _service._protocol part */ int srv_service_len; /* length of above */ char *srv_domain; /* encoded domain name */ int srv_domain_len; /* length of above */ int srv_fallback_port; /* fallback port */ long srv_options; /* query options */ /* output */ int answer_code; ruli_list_t answer_srv_list; /* list of *ruli_srv_entry_t */ }; const char *ruli_srv_errstr(int result); int ruli_srv_query_submit(ruli_srv_t *srv_qry); void ruli_srv_query_delete(ruli_srv_t *srv_qry); ruli_srv_rcode_kind_t ruli_srv_rcode_kind(ruli_srv_t *srv_qry); int ruli_srv_rcode(ruli_srv_t *srv_qry); void *_ruli_srv_query_done(ruli_srv_t *srv_qry, int srv_result_code); int _ruli_srv_query_submit(ruli_srv_t *srv_qry, void *(*fallback_call)(ruli_srv_t *)); void *_ruli_srv_answer_fallback_addr(ruli_srv_t *srv_qry); void *_ruli_srv_answer_walk(ruli_srv_t *srv_qry); ruli_srv_entry_t *_ruli_srv_list_new_entry(ruli_list_t *srv_list, const char *target, int target_len, int priority, int weight, int port); #endif /* RULI_SRV_H */ ruli-0.33/src/ruli_sync.c0000644000177100017710000001541010131412767016121 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_sync.c,v 1.27 2004/10/08 04:22:15 evertonm Exp $ */ #include /* FIXME: remove me [used for fprintf() debug] */ #include #include #include #include #include #include #include #include #include #include #include #include static void *on_search_answer(ruli_search_srv_t *search, void *search_arg) { /* ruli_sync_t *syn_qry = search_arg; */ return OOP_CONTINUE; } ruli_sync_t *ruli_sync_query(const char *txt_service, const char *txt_domain, int fallback_port, long options) { oop_source_sys *source_sys; oop_source *source; ruli_sync_t *syn_qry; /* * Create event source */ source_sys = oop_sys_new(); if (!source_sys) return 0; source = oop_sys_source(source_sys); if (!source) { oop_sys_delete(source_sys); return 0; } #ifdef RULI_SYNC_DEBUG fprintf(stderr, "ruli_sync_query(): DEBUG: event source DONE\n"); #endif /* * Create sync query context */ syn_qry = (ruli_sync_t *) ruli_malloc(sizeof(ruli_sync_t)); if (!syn_qry) { oop_sys_delete(source_sys); return 0; } #ifdef RULI_SYNC_DEBUG fprintf(stderr, "ruli_sync_query(): DEBUG: query context DONE\n"); #endif /* * Create search resolver context */ syn_qry->search_res = ruli_search_res_new(source, 2, 10); if (!syn_qry->search_res) { oop_sys_delete(source_sys); ruli_free(syn_qry); return 0; } /* * Submit query */ { ruli_res_t *res = ruli_search_resolver(syn_qry->search_res); assert(res); syn_qry->search = ruli_search_srv_submit(res, on_search_answer, syn_qry, options, txt_service, txt_domain, fallback_port); if (!syn_qry->search) { assert(syn_qry->search_res); ruli_search_res_delete(syn_qry->search_res); oop_sys_delete(source_sys); ruli_free(syn_qry); return 0; } } /* * Run event loop */ { void *oop_result = oop_sys_run(source_sys); assert(oop_result == OOP_CONTINUE); } oop_sys_delete(source_sys); /* destroy event source */ return syn_qry; } ruli_sync_t *ruli_sync_smtp_query(const char *txt_domain, long options) { oop_source_sys *source_sys; oop_source *source; ruli_sync_t *syn_qry; /* * Create event source */ source_sys = oop_sys_new(); if (!source_sys) return 0; source = oop_sys_source(source_sys); if (!source) { oop_sys_delete(source_sys); return 0; } /* * Create sync query context */ syn_qry = (ruli_sync_t *) ruli_malloc(sizeof(ruli_sync_t)); if (!syn_qry) { oop_sys_delete(source_sys); return 0; } /* * Create search resolver context */ syn_qry->search_res = ruli_search_res_new(source, 2, 10); if (!syn_qry->search_res) { oop_sys_delete(source_sys); ruli_free(syn_qry); return 0; } /* * Submit query */ { ruli_res_t *res = ruli_search_resolver(syn_qry->search_res); assert(res); syn_qry->search = ruli_search_smtp_submit(res, on_search_answer, syn_qry, options, txt_domain); if (!syn_qry->search) { assert(syn_qry->search_res); ruli_search_res_delete(syn_qry->search_res); oop_sys_delete(source_sys); ruli_free(syn_qry); return 0; } } /* * Run event loop */ { void *oop_result = oop_sys_run(source_sys); assert(oop_result == OOP_CONTINUE); } oop_sys_delete(source_sys); /* destroy event source */ return syn_qry; } /* * This query uses fallback to address * records as implicit fallback mechanism. */ ruli_sync_t *ruli_sync_http_query(const char *txt_domain, int port, long options) { oop_source_sys *source_sys; oop_source *source; ruli_sync_t *syn_qry; /* * Create event source */ source_sys = oop_sys_new(); if (!source_sys) return 0; source = oop_sys_source(source_sys); if (!source) { oop_sys_delete(source_sys); return 0; } /* * Create sync query context */ syn_qry = (ruli_sync_t *) ruli_malloc(sizeof(ruli_sync_t)); if (!syn_qry) { oop_sys_delete(source_sys); return 0; } /* * Create search resolver context */ syn_qry->search_res = ruli_search_res_new(source, 2, 10); if (!syn_qry->search_res) { oop_sys_delete(source_sys); ruli_free(syn_qry); return 0; } /* * Submit query */ { ruli_res_t *res = ruli_search_resolver(syn_qry->search_res); assert(res); /* * This query uses fallback to address * records as implicit fallback mechanism. */ syn_qry->search = ruli_search_http_submit(res, on_search_answer, syn_qry, port, options, txt_domain); if (!syn_qry->search) { assert(syn_qry->search_res); ruli_search_res_delete(syn_qry->search_res); oop_sys_delete(source_sys); ruli_free(syn_qry); return 0; } } /* * Run event loop */ { void *oop_result = oop_sys_run(source_sys); assert(oop_result == OOP_CONTINUE); } oop_sys_delete(source_sys); /* destroy event source */ return syn_qry; } void ruli_sync_delete(ruli_sync_t *syn_qry) { assert(syn_qry); assert(syn_qry->search); assert(syn_qry->search_res); ruli_search_srv_delete(syn_qry->search); ruli_search_res_delete(syn_qry->search_res); ruli_free(syn_qry); } int ruli_sync_srv_code(const ruli_sync_t *syn_qry) { assert(syn_qry); assert(syn_qry->search); return ruli_search_srv_code(syn_qry->search); } int ruli_sync_rcode(ruli_sync_t *syn_qry) { assert(syn_qry); assert(syn_qry->search); return ruli_search_srv_rcode(syn_qry->search); } ruli_list_t *ruli_sync_srv_list(ruli_sync_t *syn_qry) { assert(syn_qry); assert(syn_qry->search); return ruli_search_srv_answer_list(syn_qry->search); } ruli-0.33/src/ruli_sync.h0000644000177100017710000000327010131412767016127 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_sync.h,v 1.13 2004/10/08 04:22:15 evertonm Exp $ */ #ifndef RULI_SYNC_H #define RULI_SYNC_H #include #include /* Opaque query context */ typedef struct { /* * ruli_sync_t private members */ ruli_search_res_t *search_res; ruli_search_srv_t *search; ruli_conf_handler_t conf_handler; } ruli_sync_t; /* * ruli_sync_t public members */ ruli_sync_t *ruli_sync_query(const char *txt_service, const char *txt_domain, int fallback_port, long options); ruli_sync_t *ruli_sync_smtp_query(const char *txt_domain, long options); ruli_sync_t *ruli_sync_http_query(const char *txt_domain, int port, long options); void ruli_sync_delete(ruli_sync_t *syn_qry); int ruli_sync_srv_code(const ruli_sync_t *syn_qry); int ruli_sync_rcode(ruli_sync_t *syn_qry); ruli_list_t *ruli_sync_srv_list(ruli_sync_t *syn_qry); #endif /* RULI_SYNC_H */ ruli-0.33/src/ruli_txt.c0000644000177100017710000002750010113161267015763 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_txt.c,v 1.17 2004/08/25 19:04:23 evertonm Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE /* for GNU strncasecmp() */ #endif #include #include #include #include #include #include static int build_label(ruli_uint8_t *buf, int buf_len, const ruli_uint8_t *label, int label_len) { if (label_len < RULI_LIMIT_LABEL_LOW) return RULI_TXT_BAD; if (label_len > RULI_LIMIT_LABEL_HIGH) return RULI_TXT_BAD; if (label_len + 1 > buf_len) return RULI_TXT_BAD; *buf = label_len; ++buf; memcpy(buf, label, label_len); return RULI_TXT_OK; } int ruli_dname_encode_size(const char *dname, int dname_len) { return dname[dname_len - 1] == '.' ? dname_len + 1 : dname_len + 2; } char *ruli_dname_encode(char *buf, int buf_size, const char *dname, int dname_len) { const ruli_uint8_t *src; const ruli_uint8_t *src_pastend; ruli_uint8_t *dst; ruli_uint8_t *dst_pastend; /* * We ignore the trailing dot * because we always generate * the FQDN domain name. */ if (dname[dname_len - 1] == '.') --dname_len; /* * Ensure we have enough buffer space. */ if (buf_size < dname_len + 2) return 0; /* * Ensure given dname is not too long. * * ENCODED dname must fit into 255 * * When ignoring the trailing dot, * TEXTUAL dname must fit into 253 */ if (dname_len > RULI_LIMIT_DNAME_ENCODED) return 0; assert(sizeof(ruli_uint8_t) == sizeof(char)); src = (const ruli_uint8_t *) dname; src_pastend = (const ruli_uint8_t *) src + dname_len; dst = (ruli_uint8_t *) buf; dst_pastend = (ruli_uint8_t *) buf + buf_size; /* * Scan every label */ for (;;) { /* * Last label? */ if (src >= src_pastend) { assert(dst >= (ruli_uint8_t *) buf); assert(dst < dst_pastend); *dst = 0; /* mark as last, empty label */ ++dst; /* next position */ assert(dst > (ruli_uint8_t *) buf); assert(dst <= dst_pastend); return (char *) dst; } /* * Encode label */ { const ruli_uint8_t *i; int label_len; /* * Find label end */ for (i = src; i < src_pastend; ++i) if (*i == '.') break; label_len = i - src; /* * Build label */ if (build_label(dst, dst_pastend - dst, src, label_len)) return 0; /* * Skip label */ { int len = label_len + 1; src += len; dst += len; } } } } static int dname_decode(char *dst_buf, int dst_buf_size, int *dst_name_len, const char *src_dname, int src_dname_len) { char *dst = dst_buf; const char *dst_pastend = dst_buf + dst_buf_size; const char *src = src_dname; const char *src_pastend = src_dname + src_dname_len; int len, len_plus_1; assert(dst <= dst_pastend); assert(src <= src_pastend); /* * Iterate over labels */ for (;;) { /* Is the label still inside the source? */ if (src >= src_pastend) return RULI_TXT_BAD; len = *src; /* Last label? */ if (!len) { if (dst >= dst_pastend) return RULI_TXT_BAD; /* end of string */ *dst = '\0'; return RULI_TXT_OK; } /* Name compression disallowed */ if ((len & 0xC0) == 0xC0) return RULI_TXT_BAD; len_plus_1 = len + 1; /* Will name fit into buffer? */ if (dst + len_plus_1 >= dst_pastend) return RULI_TXT_BAD; *dst_name_len += len_plus_1; ++src; /* skip label length */ /* Copy label into buffer */ memcpy(dst, src, len); dst += len; *dst = '.'; ++dst; src += len; } /* NOT REACHED */ assert(0); } int ruli_dname_decode(char *dst_buf, int dst_buf_size, int *dst_name_len, const char *src_dname, int src_dname_len) { *dst_name_len = 0; return dname_decode(dst_buf, dst_buf_size, dst_name_len, src_dname, src_dname_len); } /* * '*total_len' must be zero before calling this function! * * Returns -1 on failure, 0 on success. */ static int dname_extract(const ruli_uint8_t *msg, const ruli_uint8_t *msg_pastend, ruli_uint8_t *buf, const ruli_uint8_t *buf_pastend, const ruli_uint8_t *label, int *total_len, int remaining_depth) { int len, len_plus_1; assert(msg <= msg_pastend); assert(msg <= label); assert(buf <= buf_pastend); assert(remaining_depth >= 0); if (label >= msg_pastend) return RULI_TXT_BAD; /* * Iterate over labels */ for (;;) { /* Is the label still inside the message? */ if (label >= msg_pastend) return RULI_TXT_BAD; len = *label; /* Last label? */ if (!len) { if (buf >= buf_pastend) return RULI_TXT_BAD; /* end of string */ *buf = '\0'; return RULI_TXT_OK; } /* Name compression? 0xC0 = 192 = 11000000 */ if ((len & 0xC0) == 0xC0) { if (!remaining_depth) return RULI_TXT_BAD; return dname_extract(msg, msg_pastend, buf, buf_pastend, msg + (ruli_pack2(label) & ~0xC000), total_len, --remaining_depth); } len_plus_1 = len + 1; /* Will name fit into buffer? */ if (buf + len_plus_1 >= buf_pastend) return RULI_TXT_BAD; *total_len += len_plus_1; ++label; /* skip label length */ /* Copy label into buffer */ memcpy(buf, label, len); buf += len; *buf = '.'; ++buf; label += len; } /* NOT REACHED */ assert(0); } int ruli_dname_extract(const ruli_uint8_t *msg, const ruli_uint8_t *msg_pastend, ruli_uint8_t *buf, const ruli_uint8_t *buf_pastend, const ruli_uint8_t *label, int *total_len) { *total_len = 0; return dname_extract(msg, msg_pastend, buf, buf_pastend, label, total_len, RULI_LIMIT_COMPRESSION_DEPTH); } /* Handle dname in text format */ int ruli_dname_match(const char *name1, int len1, const char *name2, int len2) { if (name1[len1 - 1] == '.') --len1; if (name2[len2 - 1] == '.') --len2; if (len1 != len2) return 0; return !strncasecmp(name1, name2, len1); } /* * '*expanded_len' must be zero before calling this function * * Returns -1 on failure, 0 on success */ static int dname_expand(const ruli_uint8_t *src_msg, const ruli_uint8_t *src_msg_pastend, ruli_uint8_t *dst_buf, const ruli_uint8_t *dst_buf_pastend, const ruli_uint8_t *src_label, size_t *expanded_len, int remaining_depth) { int len, len_plus_1; assert(src_msg <= src_msg_pastend); assert(src_msg <= src_label); assert(dst_buf <= dst_buf_pastend); assert(remaining_depth >= 0); if (src_label >= src_msg_pastend) return RULI_TXT_BAD; /* * Iterate over labels */ for (;;) { /* Is the label still inside the message? */ if (src_label >= src_msg_pastend) return RULI_TXT_BAD; len = *src_label; assert(0 <= len); assert(len <= 255); /* Last label? */ if (!len) { if (dst_buf >= dst_buf_pastend) return RULI_TXT_BAD; /* write empty label */ *dst_buf = '\0'; ++*expanded_len; return RULI_TXT_OK; } /* Name compression? 0xC0 = 192 = 11000000 */ if ((len & 0xC0) == 0xC0) { if (!remaining_depth) return RULI_TXT_BAD; return dname_expand(src_msg, src_msg_pastend, dst_buf, dst_buf_pastend, src_msg + (ruli_pack2(src_label) & ~0xC000), expanded_len, --remaining_depth); } len_plus_1 = len + 1; /* label_len + len_octet (1) */ assert(1 <= len_plus_1); assert(len_plus_1 <= 256); /* Will (len-octet + label) fit into buffer? */ if (dst_buf + len_plus_1 >= dst_buf_pastend) return RULI_TXT_BAD; /* Copy label into buffer */ memcpy(dst_buf, src_label, len_plus_1); dst_buf += len_plus_1; src_label += len_plus_1; assert((*expanded_len + len_plus_1) > *expanded_len); *expanded_len += len_plus_1; } /* NOT REACHED */ assert(0); } int ruli_dname_expand(const ruli_uint8_t *src_msg, const ruli_uint8_t *src_msg_pastend, ruli_uint8_t *dst_buf, const ruli_uint8_t *dst_buf_pastend, const ruli_uint8_t *src_label, size_t *expanded_len) { *expanded_len = 0; return dname_expand(src_msg, src_msg_pastend, dst_buf, dst_buf_pastend, src_label, expanded_len, RULI_LIMIT_COMPRESSION_DEPTH); } #ifdef RULI_TXT_COMPARE_DEBUG static void dump_dname(FILE *out, const ruli_uint8_t *dname, int dname_len) { char txt[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_len; int result; assert(sizeof(ruli_uint8_t) == sizeof(char)); result = ruli_dname_decode(txt, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_len, (const char *) dname, dname_len); assert(!result); fprintf(out, "(txt_len=%d)%s", txt_len, txt); } #endif /* Compares a compressed name against an uncompressed name */ int ruli_dname_compare(const ruli_uint8_t *comp_name, const ruli_uint8_t *comp_name_msg, size_t comp_name_msg_len, const ruli_uint8_t *uncomp_name, size_t uncomp_name_len) { ruli_uint8_t name_buf[RULI_LIMIT_DNAME_ENCODED]; size_t name_len; int result; result = ruli_dname_expand(comp_name_msg, comp_name_msg + comp_name_msg_len, name_buf, name_buf + RULI_LIMIT_DNAME_ENCODED, comp_name, &name_len); assert(!result); #ifdef RULI_TXT_COMPARE_DEBUG { fprintf (stderr, "DEBUG: ruli_dname_compare(): comp_name="); dump_dname(stderr, name_buf, name_len); fprintf (stderr, " uncomp_name="); dump_dname(stderr, uncomp_name, uncomp_name_len); fprintf (stderr, "\n"); } #endif if (name_len != uncomp_name_len) return RULI_TXT_BAD; if (memcmp(name_buf, uncomp_name, name_len)) return RULI_TXT_BAD; return RULI_TXT_OK; } /* Concatenate a pair of uncompressed, encoded domain names. */ int ruli_dname_concat(ruli_uint8_t *dst_buf, int dst_buf_len, int *len, const ruli_uint8_t *src1, int len1, const ruli_uint8_t *src2, int len2) { assert(len1 > 0); assert(len2 > 0); assert(len1 < RULI_LIMIT_DNAME_ENCODED); assert(len2 < RULI_LIMIT_DNAME_ENCODED); assert(src1[len1 - 1] == '\0'); assert(src2[len2 - 1] == '\0'); --len1; if ((len1 + len2) > RULI_LIMIT_DNAME_ENCODED) return RULI_TXT_BAD; if (len1 >= dst_buf_len) return RULI_TXT_BAD; if (len2 >= dst_buf_len) return RULI_TXT_BAD; if ((len1 + len2) > dst_buf_len) return RULI_TXT_BAD; assert((len1 + len2) <= RULI_LIMIT_DNAME_ENCODED); assert(len1 < dst_buf_len); assert(len2 < dst_buf_len); assert((len1 + len2) <= dst_buf_len); memcpy(dst_buf, src1, len1); memcpy(dst_buf + len1, src2, len2); *len = len1 + len2; return RULI_TXT_OK; } ruli-0.33/src/ruli_txt.h0000644000177100017710000000435510064101514015765 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_txt.h,v 1.9 2004/06/16 17:28:44 evertonm Exp $ */ #ifndef RULI_TXT_H #define RULI_TXT_H #include enum { RULI_TXT_OK = 0, RULI_TXT_BAD = -1 }; int ruli_dname_encode_size(const char *dname, int dname_len); char *ruli_dname_encode(char *buf, int buf_size, const char *dname, int dname_len); int ruli_dname_decode(char *dst_buf, int dst_buf_size, int *dst_name_len, const char *src_dname, int src_dname_len); int ruli_dname_extract(const ruli_uint8_t *msg, const ruli_uint8_t *msg_pastend, ruli_uint8_t *buf, const ruli_uint8_t *buf_pastend, const ruli_uint8_t *label, int *total_len); int ruli_dname_match(const char *name1, int len1, const char *name2, int len2); int ruli_dname_expand(const ruli_uint8_t *src_msg, const ruli_uint8_t *src_msg_pastend, ruli_uint8_t *dst_buf, const ruli_uint8_t *dst_buf_pastend, const ruli_uint8_t *src_label, size_t *expanded_len); int ruli_dname_compare(const ruli_uint8_t *comp_name, const ruli_uint8_t *comp_name_msg, size_t comp_name_msg_len, const ruli_uint8_t *uncomp_name, size_t uncomp_name_len); int ruli_dname_concat(ruli_uint8_t *dst_buf, int dst_buf_len, int *len, const ruli_uint8_t *src1, int len1, const ruli_uint8_t *src2, int len2); #endif /* RULI_TXT_H */ ruli-0.33/src/ruli_util.c0000644000177100017710000000310410064140532016110 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_util.c,v 1.4 2004/06/16 21:53:30 evertonm Exp $ */ #include ruli_uint8_t *ruli_unpack2(ruli_uint8_t *i, ruli_uint16_t val) { *i = val >> 8; *++i = val & 0xFF; return ++i; } ruli_uint16_t ruli_pack2(const ruli_uint8_t *i) { ruli_uint16_t a, b; a = (*i) << 8; b = *++i; return a | b; } ruli_uint32_t ruli_pack4(const ruli_uint8_t *i) { ruli_uint32_t a, b, c, d; a = (*i) << 24; b = (*++i) << 16; c = (*++i) << 8; d = *++i; return a | b | c | d; } void *ruli_memrchr(const void *buf, int c, size_t size) { unsigned char wanted = c; const unsigned char *begin = (const unsigned char *) buf; const unsigned char *i; for (i = begin + size - 1; i >= begin; --i) if (*i == wanted) return (void *) i; return 0; } ruli-0.33/src/ruli_util.h0000644000177100017710000000354310113161267016127 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli_util.h,v 1.5 2004/08/25 19:04:23 evertonm Exp $ */ #ifndef RULI_UTIL_H #define RULI_UTIL_H #include #ifndef RULI_MAX #define RULI_MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef RULI_MIN #define RULI_MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef LONG_MAX #define LONG_MAX ( (long) ((((unsigned long) -1L) - 1) >> 1) ) #endif #ifndef LONG_MIN #define LONG_MIN ( -(LONG_MAX + 1) ) #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #if defined(_RULI_SOLARIS_) && !defined(__cplusplus) extern int strcasecmp(const char *s1, const char *s2); extern int strncasecmp(const char *s1, const char *s2, size_t n); extern int snprintf(char *, size_t, const char *, ...); #endif typedef unsigned char ruli_uint8_t; typedef unsigned short ruli_uint16_t; typedef unsigned int ruli_uint32_t; ruli_uint8_t *ruli_unpack2(ruli_uint8_t *i, ruli_uint16_t val); ruli_uint16_t ruli_pack2(const ruli_uint8_t *i); ruli_uint32_t ruli_pack4(const ruli_uint8_t *i); void *ruli_memrchr(const void *buf, int c, size_t size); #endif /* RULI_UTIL_H */ ruli-0.33/tools/0000755000177100017710000000000010254521423014312 5ustar labratlabrat00000000000000ruli-0.33/tools/gpl-header/0000755000177100017710000000000010254521423016322 5ustar labratlabrat00000000000000ruli-0.33/tools/gpl-header/GNU-GPL-HEADER0000644000177100017710000000140207614250011020237 0ustar labratlabrat00000000000000RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ruli-0.33/tools/gpl-header/hdr.pl0000755000177100017710000000316507571434662017464 0ustar labratlabrat00000000000000#! /usr/bin/perl -w # # $Id: hdr.pl,v 1.1.1.1 2002/11/28 15:43:46 evertonm Exp $ my $gpl_begin = '-GNU-GPL-BEGIN-'; my $gpl_end = '-GNU-GPL-END-'; my @header; sub proc { my $source = shift; print "$source\n"; local *IN; if (!open(IN, "<$source")) { warn "can't read file: $source: $!\n"; return; } my @contents; SCAN: while () { # remove GNU GPL if (/$gpl_begin/) { END: while () { if (/$gpl_end/) { # remove brancos apos GNU GPL while () { if (/./) { push(@contents, $_); next SCAN; } } } } } else { push(@contents, $_); } } close(IN); local *OUT; if (!open(OUT, ">$source")) { warn "can't write file: $source: $!\n"; return; } print OUT "/*$gpl_begin*\n"; print OUT @header; print OUT "*$gpl_end*/\n"; print OUT "\n"; print OUT @contents; close(OUT); } sub process { my $f; foreach $f (@_) { &proc($f); } } sub explore { my $dir; foreach $dir (@_) { if (! -d $dir) { warn "skipping: '$dir' is not a directory\n"; return; } if (! -r $dir) { warn "skipping: can't read dir: $dir\n"; return; } local *DIR; if (!opendir(DIR, $dir)) { warn "can't open dir: $dir: $!\n"; return; } my @entries = readdir DIR; closedir DIR; my $i; for ($i = 0; $i <= $#entries; ++$i) { my $e = $entries[$i]; $entries[$i] = "$dir/$e"; } my @sources = grep { /\.[c|h]$/ && -f "$_" } @entries; my @dirs = grep { ($_ !~ /\/\./) && -d "$_" } @entries; &process(@sources); &explore(@dirs); } } @header = ; &explore(@ARGV); ruli-0.33/tools/Makefile0000644000177100017710000000446010253263133015756 0ustar labratlabrat00000000000000# # $Id: Makefile,v 1.24 2005/06/13 10:56:27 evertonm Exp $ # # # OOP_INCLUDE_DIR points the location of # Liboop headers in your system # # OOP_LIB_DIR points the location of # Liboop libraries in your system # OOP_BASE_DIR = /usr/local/oop OOP_INCLUDE_DIR = $(OOP_BASE_DIR)/include OOP_LIB_DIR = $(OOP_BASE_DIR)/lib # # INSTALL_BASE_DIR indicates where RULI # is to be installed in your system # INSTALL_BASE_DIR = ../install/ruli INSTALL_INCLUDE_DIR = $(INSTALL_BASE_DIR)/include INSTALL_LIB_DIR = $(INSTALL_BASE_DIR)/lib INSTALL_BIN_DIR = $(INSTALL_BASE_DIR)/bin WARN = -pedantic -ansi -Wshadow -Wpointer-arith -Wcast-qual \ -Wcast-align -Wwrite-strings -Wredundant-decls \ -Wall # gcc-specific options (not valid for g++) ifeq ($(CC),gcc) WARN += -Wnested-externs WARN += -Wmissing-prototypes WARN += -Wstrict-prototypes endif CC = gcc CFLAGS = $(WARN) -O2 -pipe -g -I../src -I$(OOP_INCLUDE_DIR) LDFLAGS = -L../src -L$(OOP_LIB_DIR) -lruli -loop TARGETS = list resolve hostsolver srvsolver syncsolver addrsolver \ srvsolver2 addrsolver2 addrsolver3 ruli-host rand cycle_res \ cycle_res2 ipv6 rfc3484 LINK = $(CC) $(ARCH) $(LDFLAGS) -o $@ $^ .PHONY: default default: $(TARGETS) .PHONY: clean clean: rm -f *~ .*~ *.o $(TARGETS) .PHONY: build build: clean default .PHONY: strip strip: $(TARGETS) strip $(TARGETS) .PHONY: install install: $(TARGETS) [ -d $(INSTALL_BIN_DIR) ] || mkdir -p $(INSTALL_BIN_DIR) || exit cp $(TARGETS) $(INSTALL_BIN_DIR) %.o: %.c $(CC) $(ARCH) $(CPPFLAGS) $(CFLAGS) -c $< list: list.o $(LINK) rand: rand.o $(LINK) resolve: resolve.o trivial_conf_handler.o $(LINK) hostsolver: hostsolver.o stdin_domains.o trivial_conf_handler.o $(LINK) srvsolver: srvsolver.o stdin_domains.o stdout_srv_list.o trivial_conf_handler.o $(LINK) srvsolver2: srvsolver2.o stdout_srv_list.o trivial_conf_handler.o $(LINK) syncsolver: syncsolver.o stdout_srv_list.o $(LINK) addrsolver: addrsolver.o trivial_conf_handler.o $(LINK) addrsolver2: addrsolver2.o trivial_conf_handler.o $(LINK) addrsolver3: addrsolver3.o trivial_conf_handler.o $(LINK) ruli-host: ruli-host.o trivial_conf_handler.o $(LINK) cycle_res: cycle_res.o trivial_conf_handler.o $(LINK) cycle_res2: cycle_res2.o trivial_conf_handler.o $(LINK) ipv6: ipv6.o $(LINK) rfc3484: rfc3484.o $(LINK) ruli-0.33/tools/README0000644000177100017710000000304210144432674015200 0ustar labratlabrat00000000000000# # $Id: README,v 1.6 2004/11/10 15:37:32 evertonm Exp $ # addrsolver3.c - one event source for each query - one resolver for each query - NOT prone to input overload - useful for memory leak testing addrsolver2.c - one event source across queries - one resolver for each query - NOT prone to input overload - useful for memory leak testing addrsolver.c - one event source across queries - one resolver across queries - NOT prone to input overload - useful for memory leak testing srvsolver2.c - query SRV records "almost" asynchronously - NOT prone to input overload - useful for memory leak testing ruli-host.c - query address records "almost" asynchronously - NOT prone to input overload - useful for ruli_host testing (asynchronous, address-family-agnostic layer) hostsolver.c - translates hostnames to addresses asynchronously - prone to input overload - uses output queue - useful for testing asynchronous resolver behavior srvsolver.c - query SRV records asynchronously - prone to input overload - useful for testing asynchronous SRV behavior resolve.c - perform an arbitrary query synchronously - can resubmit a query mutiple times - doesn't parse the answer - useful for very basic query submission testing syncsolver.c - query SRV records synchronously - useful for testing synchronous API list.c - test for ruli_list_t data structures stdin_domains.c - auxiliar functions to monitor stdin for input stdout_srv_list.c - auxiliar function to output SRV records ipv6.c - test for IPv6 helper functions ruli-0.33/tools/addrsolver.c0000644000177100017710000003052110251416417016627 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: addrsolver.c,v 1.23 2005/06/07 22:17:51 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "trivial_conf_handler.h" #undef ADDRSOLVER_DEBUG const char *prog_name; int qc; int qt; static void *clean_query(ruli_res_query_t *qry, char *domain) { /* Finish query */ ruli_res_query_delete(qry); /* Free buffers */ ruli_free(domain); ruli_free(qry->q_domain); ruli_free(qry); return OOP_CONTINUE; } static void *on_answer(ruli_res_query_t *qry, void *arg) { char *domain = (char *) arg; const int BUFSZ = 1024; char buf[BUFSZ]; int str_len; assert(qry->answer_code != RULI_CODE_VOID); if (qry->answer_code == RULI_CODE_TIMEOUT) { str_len = snprintf(buf, BUFSZ, "%s query-timeout\n", domain); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } if (qry->answer_code) { str_len = snprintf(buf, BUFSZ, "%s query-failure: %d\n", domain, qry->answer_code); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } if (qry->answer_header.rcode != RULI_RCODE_NOERROR) { printf("%s bad-server-rcode: %d\n", domain, qry->answer_header.rcode); return clean_query(qry, domain); } #ifdef ADDRSOLVER_DEBUG { ruli_msg_header_t msg_hdr; msg_hdr = qry->answer_header; str_len = snprintf(buf, BUFSZ, "%s: query succeded: domain=%s id=%d " "rcode=%d qd=%d an=%d ns=%d ar=%d " "answer_buf_size=%d answer_msg_len=%d\n", prog_name, domain, msg_hdr.id, msg_hdr.rcode, msg_hdr.qdcount, msg_hdr.ancount, msg_hdr.nscount, msg_hdr.arcount, qry->answer_buf_size, qry->answer_msg_len); assert(str_len < BUFSZ); printf(buf); } #endif { ruli_parse_t parse; int result; int i; int size; int addr_count = 0; ruli_parse_new(&parse); result = ruli_parse_message(&parse, &qry->answer_header, (ruli_uint8_t *) qry->answer_buf, qry->answer_buf_size); if (result) { str_len = snprintf(buf, BUFSZ, "%s answer-unparseable\n", domain); assert(str_len < BUFSZ); printf(buf); ruli_parse_delete(&parse); return clean_query(qry, domain); } size = ruli_list_size(&parse.answer_list); for (i = 0; i < size; ++i) { ruli_addr_t addr; ruli_rr_t *rr; rr = (ruli_rr_t *) ruli_list_get(&parse.answer_list, i); if (rr->qclass != RULI_RR_CLASS_IN) continue; switch (rr->type) { case RULI_RR_TYPE_A: result = ruli_parse_rr_a(&addr.addr.ipv4, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET); break; case RULI_RR_TYPE_AAAA: result = ruli_parse_rr_aaaa(&addr.addr.ipv6, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET6); break; default: continue; } { const int OWNER_BUFSZ = 256; char owner_buf[OWNER_BUFSZ]; int owner_len; result = ruli_dname_extract((ruli_uint8_t *) qry->answer_buf, (ruli_uint8_t *) qry->answer_buf + qry->answer_buf_size, (ruli_uint8_t *) owner_buf, (ruli_uint8_t *) owner_buf + OWNER_BUFSZ, rr->owner, &owner_len); assert(!result); #ifdef ADDRSOLVER_DEBUG fprintf(stderr, "DEBUG: on_answer(): domain=%s txt_owner=%s " "txt_owner_len=%d\n", domain, owner_buf, owner_len); #endif if (!ruli_dname_match(domain, strlen(domain), owner_buf, owner_len)) continue; } printf("%s ", domain); ruli_addr_print(stdout, &addr); printf("\n"); ++addr_count; } ruli_parse_delete(&parse); if (!addr_count) { str_len = snprintf(buf, BUFSZ, "%s answer-missing-address\n", domain); assert(str_len < BUFSZ); printf(buf); } } return clean_query(qry, domain); } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static ruli_res_query_t *submit_query(ruli_res_t *res_ctx, char *dname_buf, int dname_len, const char *domain, int domain_len) { int result; ruli_res_query_t *qry; char *dom_str; /* * Allocate space for query */ qry = (ruli_res_query_t *) ruli_malloc(sizeof(ruli_res_query_t)); if (!qry) return 0; /* * Save domain string */ dom_str = (char *) ruli_malloc(domain_len + 1); if (!dom_str) { ruli_free(qry); return 0; } memcpy(dom_str, domain, domain_len); dom_str[domain_len] = '\0'; /* * Send query */ #ifdef ADDRSOLVER_DEBUG fprintf(stderr, "%s: DEBUG: submit_query(): domain=%s resolver=%u " "dname_buf=%u qry=%u dname_len=%d class=%d type=%d\n", prog_name, dom_str, (unsigned int) res_ctx, (unsigned int) dname_buf, (unsigned int) qry, dname_len, qc, qt); #endif qry->q_on_answer = on_answer; qry->q_on_answer_arg = dom_str; qry->q_domain = dname_buf; qry->q_domain_len = dname_len; qry->q_class = qc; qry->q_type = qt; qry->q_options = RULI_RES_OPT_VOID; result = ruli_res_query_submit(res_ctx, qry); if (result) { fprintf(stderr, "%s: ruli_res_query_submit() failed: %s [%d]\n", prog_name, ruli_res_errstr(result), result); ruli_free(dom_str); ruli_free(qry); return 0; } return qry; } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef ADDRSOLVER_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static void do_query(ruli_res_t *res_ctx, const char *name) { int name_len = strlen(name); char *dname_buf; int dname_buf_len; int dname_len; char *i; dname_buf_len = ruli_dname_encode_size(name, name_len); /* Allocate buffer */ dname_buf = (char *) ruli_malloc(dname_buf_len); if (!dname_buf) { fprintf(stderr, "%s: do_query(): ruli_malloc(%d) failed: %s\n", prog_name, dname_buf_len, strerror(errno)); return; } i = ruli_dname_encode(dname_buf, dname_buf_len, name, name_len); if (!i) { const int DOM_BUFSZ = 256; char dom_buf[DOM_BUFSZ]; int dom_len = RULI_MIN(name_len, DOM_BUFSZ - 1); memcpy(dom_buf, name, dom_len); dom_buf[dom_len] = '\0'; fprintf(stderr, "%s: do_query(): can't encode domain: (total_len=%d displaying=%d) %s\n", prog_name, name_len, dom_len, dom_buf); return; } dname_len = i - dname_buf; /* * Send query */ { ruli_res_query_t *qry = submit_query(res_ctx, dname_buf, dname_len, name, name_len); if (!qry) { fprintf(stderr, "%s: do_query(): could not send query\n", prog_name); return; } } } static void go(int retry, int timeout, ruli_list_t *server_list) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(&res_ctx, tok); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ /* * Run event loop */ { void *oop_result = run_event_loop(source_sys); if (oop_result != OOP_CONTINUE) break; } } /* for */ /* * Destroy resolver */ ruli_res_delete(&res_ctx); /* * Destroy event source */ oop_sys_delete(source_sys); } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't save address: %s\n", prog_name, serverv[i]); exit(1); } #ifdef ADDRSOLVER_DEBUG fprintf(stderr, "%s: saving server: ", prog_name); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif { int result = ruli_list_push(server_list, addr); assert(!result); } } /* for */ } int main(int argc, const char **argv) { const char *qclass = "in"; const char *type = "a"; int retry; int timeout; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 4) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } retry = atoi(argv[1]); timeout = atoi(argv[2]); serverc = argc - 3; serverv = argv + 3; if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); qc = ruli_get_qclass_code(qclass); if (!qc) { fprintf(stderr, "%s: can't find query class: %s\n", prog_name, qclass); exit(1); } qt = ruli_get_qtype_code(type); if (!qt) { fprintf(stderr, "%s: can't find query type: %s\n", prog_name, type); exit(1); } go(retry, timeout, &server_list); ruli_list_dispose_trivial(&server_list); #ifdef ADDRSOLVER_DEBUG fprintf(stderr, "%s: done\n", prog_name); #endif exit(0); } ruli-0.33/tools/addrsolver2.c0000644000177100017710000003074610251416417016722 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: addrsolver2.c,v 1.18 2005/06/07 22:17:51 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "trivial_conf_handler.h" #undef ADDRSOLVER2_DEBUG const char *prog_name; int qc; int qt; static void *clean_query(ruli_res_query_t *qry, char *domain) { /* Finish query */ ruli_res_query_delete(qry); /* Free buffers */ ruli_free(domain); ruli_free(qry->q_domain); ruli_free(qry); return OOP_CONTINUE; } static void *on_answer(ruli_res_query_t *qry, void *arg) { char *domain = (char *) arg; const int BUFSZ = 1024; char buf[BUFSZ]; int str_len; assert(qry->answer_code != RULI_CODE_VOID); if (qry->answer_code == RULI_CODE_TIMEOUT) { str_len = snprintf(buf, BUFSZ, "%s query-timeout\n", domain); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } if (qry->answer_code) { str_len = snprintf(buf, BUFSZ, "%s query-failure: %d\n", domain, qry->answer_code); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } if (qry->answer_header.rcode != RULI_RCODE_NOERROR) { printf("%s bad-server-rcode: %d\n", domain, qry->answer_header.rcode); return clean_query(qry, domain); } #ifdef ADDRSOLVER2_DEBUG { ruli_msg_header_t msg_hdr; msg_hdr = qry->answer_header; str_len = snprintf(buf, BUFSZ, "%s: query succeded: domain=%s id=%d " "rcode=%d qd=%d an=%d ns=%d ar=%d " "answer_buf_size=%d answer_msg_len=%d\n", prog_name, domain, msg_hdr.id, msg_hdr.rcode, msg_hdr.qdcount, msg_hdr.ancount, msg_hdr.nscount, msg_hdr.arcount, qry->answer_buf_size, qry->answer_msg_len); assert(str_len < BUFSZ); printf(buf); } #endif { ruli_parse_t parse; int result; int i; int size; int addr_count = 0; ruli_parse_new(&parse); result = ruli_parse_message(&parse, &qry->answer_header, (ruli_uint8_t *) qry->answer_buf, qry->answer_buf_size); if (result) { str_len = snprintf(buf, BUFSZ, "%s answer-unparseable\n", domain); assert(str_len < BUFSZ); printf(buf); ruli_parse_delete(&parse); return clean_query(qry, domain); } size = ruli_list_size(&parse.answer_list); for (i = 0; i < size; ++i) { ruli_addr_t addr; ruli_rr_t *rr; rr = (ruli_rr_t *) ruli_list_get(&parse.answer_list, i); if (rr->qclass != RULI_RR_CLASS_IN) continue; switch (rr->type) { case RULI_RR_TYPE_A: result = ruli_parse_rr_a(&addr.addr.ipv4, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET); break; case RULI_RR_TYPE_AAAA: result = ruli_parse_rr_aaaa(&addr.addr.ipv6, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET6); break; default: continue; } { const int OWNER_BUFSZ = 256; char owner_buf[OWNER_BUFSZ]; int owner_len; result = ruli_dname_extract((ruli_uint8_t *) qry->answer_buf, (ruli_uint8_t *) qry->answer_buf + qry->answer_buf_size, (ruli_uint8_t *) owner_buf, (ruli_uint8_t *) owner_buf + OWNER_BUFSZ, rr->owner, &owner_len); assert(!result); #ifdef ADDRSOLVER2_DEBUG fprintf(stderr, "DEBUG: on_answer(): domain=%s txt_owner=%s " "txt_owner_len=%d\n", domain, owner_buf, owner_len); #endif if (!ruli_dname_match(domain, strlen(domain), owner_buf, owner_len)) continue; } printf("%s ", domain); ruli_addr_print(stdout, &addr); printf("\n"); ++addr_count; } ruli_parse_delete(&parse); if (!addr_count) { str_len = snprintf(buf, BUFSZ, "%s answer-missing-address\n", domain); assert(str_len < BUFSZ); printf(buf); } } return clean_query(qry, domain); } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static ruli_res_query_t *submit_query(ruli_res_t *res_ctx, char *dname_buf, int dname_len, const char *domain, int domain_len) { int result; ruli_res_query_t *qry; char *dom_str; /* * Allocate space for query */ qry = (ruli_res_query_t *) ruli_malloc(sizeof(ruli_res_query_t)); if (!qry) return 0; /* * Save domain string */ dom_str = (char *) ruli_malloc(domain_len + 1); if (!dom_str) { ruli_free(qry); return 0; } memcpy(dom_str, domain, domain_len); dom_str[domain_len] = '\0'; /* * Send query */ #ifdef ADDRSOLVER2_DEBUG fprintf(stderr, "%s: DEBUG: submit_query(): domain=%s resolver=%u " "dname_buf=%u qry=%u dname_len=%d class=%d type=%d\n", prog_name, dom_str, (unsigned int) res_ctx, (unsigned int) dname_buf, (unsigned int) qry, dname_len, qc, qt); #endif qry->q_on_answer = on_answer; qry->q_on_answer_arg = dom_str; qry->q_domain = dname_buf; qry->q_domain_len = dname_len; qry->q_class = qc; qry->q_type = qt; qry->q_options = RULI_RES_OPT_VOID; result = ruli_res_query_submit(res_ctx, qry); if (result) { fprintf(stderr, "%s: ruli_res_query_submit() failed: %s [%d]\n", prog_name, ruli_res_errstr(result), result); ruli_free(dom_str); ruli_free(qry); return 0; } return qry; } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef ADDRSOLVER2_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static void do_query(oop_source_sys *source_sys, oop_source *source, int retry, int timeout, ruli_list_t *server_list, const char *name) { ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; int name_len = strlen(name); char *dname_buf; int dname_buf_len; int dname_len; char *i; /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } dname_buf_len = ruli_dname_encode_size(name, name_len); /* Allocate buffer */ dname_buf = (char *) ruli_malloc(dname_buf_len); if (!dname_buf) { fprintf(stderr, "%s: do_query(): ruli_malloc(%d) failed: %s\n", prog_name, dname_buf_len, strerror(errno)); return; } i = ruli_dname_encode(dname_buf, dname_buf_len, name, name_len); if (!i) { const int DOM_BUFSZ = 256; char dom_buf[DOM_BUFSZ]; int dom_len = RULI_MIN(name_len, DOM_BUFSZ - 1); memcpy(dom_buf, name, dom_len); dom_buf[dom_len] = '\0'; fprintf(stderr, "%s: do_query(): can't encode domain: (total_len=%d displaying=%d) %s\n", prog_name, name_len, dom_len, dom_buf); return; } dname_len = i - dname_buf; /* * Send query */ { ruli_res_query_t *qry = submit_query(&res_ctx, dname_buf, dname_len, name, name_len); if (!qry) { fprintf(stderr, "%s: do_query(): could not send query\n", prog_name); return; } } /* * Run event loop */ { void *oop_result = run_event_loop(source_sys); assert(oop_result == OOP_CONTINUE); } /* * Destroy resolver */ ruli_res_delete(&res_ctx); } static void go(int retry, int timeout, ruli_list_t *server_list) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ /* * Create event source */ create_oop_source(&source_sys, &source); /* * Scan stdin */ for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(source_sys, source, retry, timeout, server_list, tok); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ } /* for */ /* * Destroy event source */ oop_sys_delete(source_sys); } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't save address: %s\n", prog_name, serverv[i]); exit(1); } #ifdef ADDRSOLVER2_DEBUG fprintf(stderr, "%s: saving server: ", prog_name); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif { int result = ruli_list_push(server_list, addr); assert(!result); } } /* for */ } int main(int argc, const char **argv) { const char *qclass = "in"; const char *type = "a"; int retry; int timeout; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 4) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } retry = atoi(argv[1]); timeout = atoi(argv[2]); serverc = argc - 3; serverv = argv + 3; if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); qc = ruli_get_qclass_code(qclass); if (!qc) { fprintf(stderr, "%s: can't find query class: %s\n", prog_name, qclass); exit(1); } qt = ruli_get_qtype_code(type); if (!qt) { fprintf(stderr, "%s: can't find query type: %s\n", prog_name, type); exit(1); } go(retry, timeout, &server_list); ruli_list_dispose_trivial(&server_list); #ifdef ADDRSOLVER2_DEBUG fprintf(stderr, "%s: done\n", prog_name); #endif exit(0); } ruli-0.33/tools/addrsolver3.c0000644000177100017710000003063610251416417016721 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: addrsolver3.c,v 1.18 2005/06/07 22:17:51 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "trivial_conf_handler.h" #undef ADDRSOLVER3_DEBUG const char *prog_name; int qc; int qt; static void *clean_query(ruli_res_query_t *qry, char *domain) { /* Finish query */ ruli_res_query_delete(qry); /* Free buffers */ ruli_free(domain); ruli_free(qry->q_domain); ruli_free(qry); return OOP_CONTINUE; } static void *on_answer(ruli_res_query_t *qry, void *arg) { char *domain = (char *) arg; const int BUFSZ = 1024; char buf[BUFSZ]; int str_len; assert(qry->answer_code != RULI_CODE_VOID); if (qry->answer_code == RULI_CODE_TIMEOUT) { str_len = snprintf(buf, BUFSZ, "%s query-timeout\n", domain); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } if (qry->answer_code) { str_len = snprintf(buf, BUFSZ, "%s query-failure: %d\n", domain, qry->answer_code); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } if (qry->answer_header.rcode != RULI_RCODE_NOERROR) { printf("%s bad-server-rcode: %d\n", domain, qry->answer_header.rcode); return clean_query(qry, domain); } #ifdef ADDRSOLVER3_DEBUG { ruli_msg_header_t msg_hdr; msg_hdr = qry->answer_header; str_len = snprintf(buf, BUFSZ, "%s: query succeded: domain=%s id=%d " "rcode=%d qd=%d an=%d ns=%d ar=%d " "answer_buf_size=%d answer_msg_len=%d\n", prog_name, domain, msg_hdr.id, msg_hdr.rcode, msg_hdr.qdcount, msg_hdr.ancount, msg_hdr.nscount, msg_hdr.arcount, qry->answer_buf_size, qry->answer_msg_len); assert(str_len < BUFSZ); printf(buf); } #endif { ruli_parse_t parse; int result; int i; int size; int addr_count = 0; ruli_parse_new(&parse); result = ruli_parse_message(&parse, &qry->answer_header, (ruli_uint8_t *) qry->answer_buf, qry->answer_buf_size); if (result) { str_len = snprintf(buf, BUFSZ, "%s answer-unparseable\n", domain); assert(str_len < BUFSZ); printf(buf); ruli_parse_delete(&parse); return clean_query(qry, domain); } size = ruli_list_size(&parse.answer_list); for (i = 0; i < size; ++i) { ruli_addr_t addr; ruli_rr_t *rr; rr = (ruli_rr_t *) ruli_list_get(&parse.answer_list, i); if (rr->qclass != RULI_RR_CLASS_IN) continue; switch (rr->type) { case RULI_RR_TYPE_A: result = ruli_parse_rr_a(&addr.addr.ipv4, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET); break; case RULI_RR_TYPE_AAAA: result = ruli_parse_rr_aaaa(&addr.addr.ipv6, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET6); break; default: continue; } { const int OWNER_BUFSZ = 256; char owner_buf[OWNER_BUFSZ]; int owner_len; result = ruli_dname_extract((ruli_uint8_t *) qry->answer_buf, (ruli_uint8_t *) qry->answer_buf + qry->answer_buf_size, (ruli_uint8_t *) owner_buf, (ruli_uint8_t *) owner_buf + OWNER_BUFSZ, rr->owner, &owner_len); assert(!result); #ifdef ADDRSOLVER3_DEBUG fprintf(stderr, "DEBUG: on_answer(): domain=%s txt_owner=%s " "txt_owner_len=%d\n", domain, owner_buf, owner_len); #endif if (!ruli_dname_match(domain, strlen(domain), owner_buf, owner_len)) continue; } printf("%s ", domain); ruli_addr_print(stdout, &addr); printf("\n"); ++addr_count; } ruli_parse_delete(&parse); if (!addr_count) { str_len = snprintf(buf, BUFSZ, "%s answer-missing-address\n", domain); assert(str_len < BUFSZ); printf(buf); } } return clean_query(qry, domain); } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static ruli_res_query_t *submit_query(ruli_res_t *res_ctx, char *dname_buf, int dname_len, const char *domain, int domain_len) { int result; ruli_res_query_t *qry; char *dom_str; /* * Allocate space for query */ qry = (ruli_res_query_t *) ruli_malloc(sizeof(ruli_res_query_t)); if (!qry) return 0; /* * Save domain string */ dom_str = (char *) ruli_malloc(domain_len + 1); if (!dom_str) { ruli_free(qry); return 0; } memcpy(dom_str, domain, domain_len); dom_str[domain_len] = '\0'; /* * Send query */ #ifdef ADDRSOLVER3_DEBUG fprintf(stderr, "%s: DEBUG: submit_query(): domain=%s resolver=%u " "dname_buf=%u qry=%u dname_len=%d class=%d type=%d\n", prog_name, dom_str, (unsigned int) res_ctx, (unsigned int) dname_buf, (unsigned int) qry, dname_len, qc, qt); #endif qry->q_on_answer = on_answer; qry->q_on_answer_arg = dom_str; qry->q_domain = dname_buf; qry->q_domain_len = dname_len; qry->q_class = qc; qry->q_type = qt; qry->q_options = RULI_RES_OPT_VOID; result = ruli_res_query_submit(res_ctx, qry); if (result) { fprintf(stderr, "%s: ruli_res_query_submit() failed: %s [%d]\n", prog_name, ruli_res_errstr(result), result); ruli_free(dom_str); ruli_free(qry); return 0; } return qry; } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef ADDRSOLVER3_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static void do_query(int retry, int timeout, ruli_list_t *server_list, const char *name) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; int name_len = strlen(name); char *dname_buf; int dname_buf_len; int dname_len; char *i; /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } dname_buf_len = ruli_dname_encode_size(name, name_len); /* Allocate buffer */ dname_buf = (char *) ruli_malloc(dname_buf_len); if (!dname_buf) { fprintf(stderr, "%s: do_query(): ruli_malloc(%d) failed: %s\n", prog_name, dname_buf_len, strerror(errno)); return; } i = ruli_dname_encode(dname_buf, dname_buf_len, name, name_len); if (!i) { const int DOM_BUFSZ = 256; char dom_buf[DOM_BUFSZ]; int dom_len = RULI_MIN(name_len, DOM_BUFSZ - 1); memcpy(dom_buf, name, dom_len); dom_buf[dom_len] = '\0'; fprintf(stderr, "%s: do_query(): can't encode domain: (total_len=%d displaying=%d) %s\n", prog_name, name_len, dom_len, dom_buf); return; } dname_len = i - dname_buf; /* * Send query */ { ruli_res_query_t *qry = submit_query(&res_ctx, dname_buf, dname_len, name, name_len); if (!qry) { fprintf(stderr, "%s: do_query(): could not send query\n", prog_name); return; } } /* * Run event loop */ { void *oop_result = run_event_loop(source_sys); assert(oop_result == OOP_CONTINUE); } /* * Destroy resolver */ ruli_res_delete(&res_ctx); /* * Destroy event source */ oop_sys_delete(source_sys); } static void go(int retry, int timeout, ruli_list_t *server_list) { /* * Scan stdin */ for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(retry, timeout, server_list, tok); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ } /* for */ } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't save address: %s\n", prog_name, serverv[i]); exit(1); } #ifdef ADDRSOLVER3_DEBUG fprintf(stderr, "%s: saving server: ", prog_name); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif { int result = ruli_list_push(server_list, addr); assert(!result); } } /* for */ } int main(int argc, const char **argv) { const char *qclass = "in"; const char *type = "a"; int retry; int timeout; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 4) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } retry = atoi(argv[1]); timeout = atoi(argv[2]); serverc = argc - 3; serverv = argv + 3; if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); qc = ruli_get_qclass_code(qclass); if (!qc) { fprintf(stderr, "%s: can't find query class: %s\n", prog_name, qclass); exit(1); } qt = ruli_get_qtype_code(type); if (!qt) { fprintf(stderr, "%s: can't find query type: %s\n", prog_name, type); exit(1); } go(retry, timeout, &server_list); ruli_list_dispose_trivial(&server_list); #ifdef ADDRSOLVER3_DEBUG fprintf(stderr, "%s: done\n", prog_name); #endif exit(0); } ruli-0.33/tools/as.sh0000755000177100017710000000117407607224637015276 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_res_t # # $Id: as.sh,v 1.1 2003/01/09 07:49:51 evertonm Exp $ show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains | while read d; do echo $d | ./addrsolver 0 10 127.0.0.1 127.0.0.1 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done doneruli-0.33/tools/as2.sh0000755000177100017710000000115007607225761015351 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_res_t # # $Id: as2.sh,v 1.1 2003/01/09 07:59:45 evertonm Exp $ show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains | while read d do echo $d done | ./addrsolver 0 10 127.0.0.1 127.0.0.1 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done ruli-0.33/tools/as3.sh0000755000177100017710000000115107607461567015361 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_res_t # # $Id: as3.sh,v 1.1 2003/01/10 06:08:55 evertonm Exp $ show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains | while read d do echo $d done | ./addrsolver2 0 10 127.0.0.1 127.0.0.1 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done ruli-0.33/tools/as4.sh0000755000177100017710000000115107607461567015362 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_res_t # # $Id: as4.sh,v 1.1 2003/01/10 06:08:55 evertonm Exp $ show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains | while read d do echo $d done | ./addrsolver3 0 10 127.0.0.1 127.0.0.1 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done ruli-0.33/tools/cycle_res.c0000644000177100017710000000353510144431743016437 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: cycle_res.c,v 1.3 2004/11/10 15:29:39 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "trivial_conf_handler.h" static void go() { ruli_conf_handler_t handler; ruli_list_t bogus_list; int result; result = ruli_list_new(&bogus_list); assert(!result); result = ruli_list_push(&bogus_list, 0); assert(!result); handler.opaque = &bogus_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; for (;;) { ruli_res_t res_ctx; res_ctx.res_conf_handler = &handler; result = ruli_res_new(&res_ctx); assert(!result); ruli_res_delete(&res_ctx); } ruli_list_delete(&bogus_list); } int main(int argc, const char **argv) { go(); exit(0); } ruli-0.33/tools/cycle_res2.c0000644000177100017710000000567010144432674016527 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: cycle_res2.c,v 1.6 2004/11/10 15:37:32 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "trivial_conf_handler.h" static void *on_answer(ruli_res_query_t *qry, void *arg) { assert(0); return OOP_CONTINUE; } static void go() { char *dname_buf = ""; int dname_len = 1; ruli_addr_t server_addr; oop_source_sys *source_sys; oop_source *source; ruli_res_query_t qry; ruli_list_t server_list; ruli_res_t res_ctx; int result; int i; ruli_conf_handler_t handler; result = ruli_addr_parse("127.0.0.1", &server_addr); assert(!result); source_sys = oop_sys_new(); assert(source_sys); source = oop_sys_source(source_sys); assert(source); qry.q_on_answer = on_answer; qry.q_on_answer_arg = 0; qry.q_domain = dname_buf; qry.q_domain_len = dname_len; qry.q_class = RULI_RR_CLASS_IN; qry.q_type = RULI_RR_TYPE_A; qry.q_options = RULI_RES_OPT_VOID; ruli_list_new(&server_list); ruli_list_push(&server_list, &server_addr); handler.opaque = &server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; for (i = 0; /*i <*/ 1000; ++i) { res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = 1; res_ctx.res_timeout = 1; result = ruli_res_new(&res_ctx); assert(!result); assert(!ruli_list_size(&res_ctx.query_list)); result = ruli_res_query_submit(&res_ctx, &qry); assert(!result); assert(ruli_list_size(&res_ctx.query_list) == 1); ruli_res_query_delete(&qry); assert(!ruli_list_size(&res_ctx.query_list)); ruli_res_delete(&res_ctx); } ruli_list_delete(&server_list); } int main(int argc, const char **argv) { go(); exit(0); } ruli-0.33/tools/hostsolver.c0000644000177100017710000003671610251416417016706 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: hostsolver.c,v 1.20 2005/06/07 22:17:51 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include "stdin_domains.h" #include "trivial_conf_handler.h" const char *prog_name; int qc; int qt; ruli_list_t output_list; /* list of null-terminated strings (char*) */ static void *on_stdout_write(oop_source *oop_src, int std_out, oop_event event, void *bogus) { char *str; int wr; int len; assert(event == OOP_WRITE); str = (char *) ruli_list_pop(&output_list); len = strlen(str); wr = write(std_out, str, len); if (wr != len) fprintf(stderr, "%s: on_stdout_write(): write(): partial write: %d/%d\n", prog_name, wr, len); if (!ruli_list_size(&output_list)) oop_src->cancel_fd(oop_src, std_out, OOP_WRITE); ruli_free(str); return OOP_CONTINUE; } static void enqueue_output(oop_source *oop_src, const char *str, int len, int std_out) { int output_queue_len; char *buf; ++len; buf = (char *) ruli_malloc(len); if (!buf) { fprintf(stderr, "%s: enqueue_output(): ruli_malloc() failed\n", prog_name); return; } memcpy(buf, str, len); output_queue_len = ruli_list_size(&output_list); assert(output_queue_len >= 0); if (!output_queue_len) oop_src->on_fd(oop_src, std_out, OOP_WRITE, on_stdout_write, 0); { int result = ruli_list_push(&output_list, buf); assert(!result); } } static void *clean_query(ruli_res_query_t *qry, char *domain) { /* Finish query */ ruli_res_query_delete(qry); /* Free buffers */ ruli_free(domain); ruli_free(qry->q_domain); ruli_free(qry); return OOP_CONTINUE; } static void *on_answer(ruli_res_query_t *qry, void *arg) { oop_source *oop_src = qry->resolver->res_source; int std_out = 1; char *domain = (char *) arg; const int BUFSZ = 1024; char buf[BUFSZ]; int str_len; assert(qry->answer_code != RULI_CODE_VOID); if (qry->answer_code == RULI_CODE_TIMEOUT) { str_len = snprintf(buf, BUFSZ, "%s query-timeout\n", domain); assert(str_len < BUFSZ); enqueue_output(oop_src, buf, str_len, std_out); return clean_query(qry, domain); } if (qry->answer_code) { str_len = snprintf(buf, BUFSZ, "%s query-failure\n", domain); assert(str_len < BUFSZ); enqueue_output(oop_src, buf, str_len, std_out); return clean_query(qry, domain); } #ifdef HOSTSOLVER_DEBUG { ruli_msg_header_t msg_hdr; msg_hdr = qry->answer_header; str_len = snprintf(buf, BUFSZ, "%s: query succeded: domain=%s id=%d " "rcode=%d qd=%d an=%d ns=%d ar=%d " "answer_buf_size=%d answer_msg_len=%d\n", prog_name, domain, msg_hdr.id, msg_hdr.rcode, msg_hdr.qdcount, msg_hdr.ancount, msg_hdr.nscount, msg_hdr.arcount, qry->answer_buf_size, qry->answer_msg_len); assert(str_len < BUFSZ); enqueue_output(oop_src, buf, str_len, std_out); } #endif { ruli_parse_t parse; int result; int i; int size; int addr_count = 0; ruli_parse_new(&parse); result = ruli_parse_message(&parse, &qry->answer_header, (ruli_uint8_t *) qry->answer_buf, qry->answer_buf_size); if (result) { str_len = snprintf(buf, BUFSZ, "%s answer-unparseable\n", domain); assert(str_len < BUFSZ); enqueue_output(oop_src, buf, str_len, std_out); } size = ruli_list_size(&parse.answer_list); for (i = 0; i < size; ++i) { ruli_addr_t addr; ruli_rr_t *rr; rr = (ruli_rr_t *) ruli_list_get(&parse.answer_list, i); if (rr->qclass != RULI_RR_CLASS_IN) continue; switch (rr->type) { case RULI_RR_TYPE_A: result = ruli_parse_rr_a(&addr.addr.ipv4, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET); break; case RULI_RR_TYPE_AAAA: result = ruli_parse_rr_aaaa(&addr.addr.ipv6, rr->rdata, rr->rdlength); if (result) continue; ruli_addr_init(&addr, PF_INET6); break; default: continue; } { const int OWNER_BUFSZ = 256; char owner_buf[OWNER_BUFSZ]; int owner_len; result = ruli_dname_extract((ruli_uint8_t *) qry->answer_buf, (ruli_uint8_t *) qry->answer_buf + qry->answer_buf_size, (ruli_uint8_t *) owner_buf, (ruli_uint8_t *) owner_buf + OWNER_BUFSZ, rr->owner, &owner_len); assert(!result); #ifdef HOSTSOLVER_DEBUG fprintf(stderr, "DEBUG: on_answer(): domain=%s txt_owner=%s " "txt_owner_len=%d\n", domain, owner_buf, owner_len); #endif if (!ruli_dname_match(domain, strlen(domain), owner_buf, owner_len)) continue; } str_len = snprintf(buf, BUFSZ, "%s ", domain); assert(str_len > 0); assert(str_len < BUFSZ); { int len = ruli_addr_snprint(buf + str_len , BUFSZ - str_len, &addr); assert(len > 0); assert(len < (BUFSZ - str_len)); str_len += len; } { char *dst = strncat(buf, "\n", BUFSZ); assert(dst); } enqueue_output(oop_src, buf, str_len, std_out); ++addr_count; } ruli_parse_delete(&parse); if (!addr_count) { str_len = snprintf(buf, BUFSZ, "%s answer-missing-address\n", domain); assert(str_len < BUFSZ); enqueue_output(oop_src, buf, str_len, std_out); } } return clean_query(qry, domain); } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static ruli_res_query_t *submit_query(ruli_res_t *res_ctx, char *dname_buf, int dname_len, const char *domain, int domain_len) { int result; ruli_res_query_t *qry; char *dom_str; /* * Allocate space for query */ qry = (ruli_res_query_t *) ruli_malloc(sizeof(ruli_res_query_t)); if (!qry) return 0; /* * Save domain string */ dom_str = (char *) ruli_malloc(domain_len + 1); if (!dom_str) { ruli_free(qry); return 0; } memcpy(dom_str, domain, domain_len); dom_str[domain_len] = '\0'; /* * Send query */ #ifdef HOSTSOLVER_DEBUG fprintf(stderr, "%s: DEBUG: submit_query(): domain=%s resolver=%u " "dname_buf=%u qry=%u dname_len=%d class=%d type=%d\n", prog_name, dom_str, (unsigned int) res_ctx, (unsigned int) dname_buf, (unsigned int) qry, dname_len, qc, qt); #endif qry->q_on_answer = on_answer; qry->q_on_answer_arg = dom_str; qry->q_domain = dname_buf; qry->q_domain_len = dname_len; qry->q_class = qc; qry->q_type = qt; qry->q_options = RULI_RES_OPT_VOID; result = ruli_res_query_submit(res_ctx, qry); if (result) { fprintf(stderr, "%s: ruli_res_query_submit() failed: %s [%d]\n", prog_name, ruli_res_errstr(result), result); ruli_free(dom_str); ruli_free(qry); return 0; } return qry; } static void *on_stdin_read(oop_source *oop_src, int std_in, oop_event event, void *ctx) { ruli_res_t *res_ctx = (ruli_res_t *) ctx; int result; assert(std_in == 0); assert(event == OOP_READ); /* * Read stdin */ result = read_stdin(std_in); switch (result) { case STDIN_READ_OK: break; case STDIN_READ_BLOCK: return OOP_CONTINUE; case STDIN_READ_EOF: /* Stop monitoring stdin */ oop_src->cancel_fd(oop_src, std_in, OOP_READ); return OOP_CONTINUE; case STDIN_READ_ERROR: return OOP_HALT; case STDIN_READ_OVERFLOW: fprintf(stderr, "%s: on_stdin_read(): stdin read buffer overflow\n", prog_name); reset_stdin_buf(); return OOP_CONTINUE; default: assert(0); } /* Scan possible hostnames from stdin */ for (;;) { char *i; /* plain domain */ const int domain_buf_size = IN_BUF_SIZE; char domain[domain_buf_size]; int domain_len; /* encoded domain */ char *dname_buf; int dname_buf_len; int dname_len; /* * Parse hostname */ result = get_next_domain(domain, domain_buf_size, &domain_len); /* If no domain found yet, keep waiting for one */ if (result == PARSE_DOMAIN_NONE) return OOP_CONTINUE; /* Do not expect other errors, not even overflow */ assert(!result); /* * Now we have a hostname, submit a query for it */ /* * Allocate space for encoded domain in dname_buf; */ /* Find required size */ dname_buf_len = ruli_dname_encode_size(domain, domain_len); /* Allocate buffer */ dname_buf = (char *) ruli_malloc(dname_buf_len); if (!dname_buf) { fprintf(stderr, "%s: on_stdin_read(): ruli_malloc(%d) failed: %s\n", prog_name, dname_buf_len, strerror(errno)); return OOP_CONTINUE; } #ifdef HOSTSOLVER_DEBUG { /* Debug */ const int DEBUG_BUFSZ = 256; char debug_buf[DEBUG_BUFSZ]; assert(domain_len < DEBUG_BUFSZ); memcpy(debug_buf, domain, domain_len); debug_buf[domain_len] = '\0'; fprintf(stderr, "%s: DEBUG: on_stdin_read(): dname_buf=%u domain=%s domain_len=%d\n", prog_name, (unsigned int) dname_buf, debug_buf, domain_len); } #endif /* * Encode domain */ i = ruli_dname_encode(dname_buf, dname_buf_len, domain, domain_len); if (!i) { const int DOM_BUFSZ = 256; char dom_buf[DOM_BUFSZ]; int dom_len = RULI_MIN(domain_len, DOM_BUFSZ - 1); memcpy(dom_buf, domain, dom_len); dom_buf[dom_len] = '\0'; fprintf(stderr, "%s: on_stdin_read(): can't encode domain: (total_len=%d displaying=%d) %s\n", prog_name, domain_len, dom_len, dom_buf); continue; } dname_len = i - dname_buf; /* * Send query */ { ruli_res_query_t *qry = submit_query(res_ctx, dname_buf, dname_len, domain, domain_len); if (!qry) { fprintf(stderr, "%s: on_stdin_read(): could not send query\n", prog_name); return OOP_CONTINUE; } } } /* for loop */ assert(0); /* NOT REACHED */ return OOP_CONTINUE; } static void go(int retry, int timeout, ruli_list_t *server_list) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } /* * Monitor stdin for read */ { int std_in = 0; set_non_blocking(std_in); source->on_fd(source, std_in, OOP_READ, on_stdin_read, &res_ctx); } /* * Run event loop */ { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef HOSTSOLVER_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); } /* * Destroy resolver */ ruli_res_delete(&res_ctx); /* * Destroy event source */ oop_sys_delete(source_sys); } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't save address: %s\n", prog_name, serverv[i]); ruli_free(addr); exit(1); } #ifdef HOSTSOLVER_DEBUG fprintf(stderr, "%s: saving server: ", prog_name); ruli_addr_printf(stderr, addr); fprintf(stderr, "\n"); #endif { int result = ruli_list_push(server_list, addr); assert(!result); } } /* server for() loop */ } int main(int argc, const char **argv) { const char *qclass = "in"; const char *type = "a"; int retry; int timeout; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 4) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } retry = atoi(argv[1]); timeout = atoi(argv[2]); serverc = argc - 3; serverv = argv + 3; if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); qc = ruli_get_qclass_code(qclass); if (!qc) { fprintf(stderr, "%s: can't find query class: %s\n", prog_name, qclass); exit(1); } qt = ruli_get_qtype_code(type); if (!qt) { fprintf(stderr, "%s: can't find query type: %s\n", prog_name, type); exit(1); } { int result = ruli_list_new(&output_list); assert(!result); } { int std_out = 1; set_non_blocking(std_out); } go(retry, timeout, &server_list); assert(!ruli_list_size(&output_list)); ruli_list_delete(&output_list); ruli_list_dispose_trivial(&server_list); #ifdef HOSTSOLVER_DEBUG fprintf(stderr, "%s: done\n", prog_name); #endif exit(0); } ruli-0.33/tools/ipv6.c0000644000177100017710000000540310064151126015342 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ipv6.c,v 1.5 2004/06/16 23:05:58 evertonm Exp $ */ #include #include #include #include static void perform(int expected_good, const char *str) { struct in6_addr in; int good; printf("%4s %-39s = ", expected_good ? "good" : "bad", str); good = ruli_inet6_aton(str, &in); if (good) { char buf[40]; int r = ruli_inet6_snprintf(buf, 40, "%04X", &in); assert(r > 0); assert(r < 40); printf(buf); } if (!good == !expected_good) printf(" ok\n"); else printf(" ugh\n"); } static void go() { perform(0, "0"); perform(0, ":"); perform(0, "0:"); perform(0, ":0"); perform(0, "0:0"); perform(0, "0:0:"); perform(0, ":0:0"); perform(0, "1:1:"); perform(0, ":1:1"); perform(0, "1:1:1:"); perform(0, ":1:1:1"); perform(0, "1:2:3:4:5:6:7"); perform(0, "1:2:3:4:5:6:7:"); perform(0, ":1:2:3:4:5:6:7"); perform(0, "1:2:3:4:5:6:7-8"); perform(0, "1:2:3:4:5:6:7 8"); perform(1, "0:1:2:3:4:5:6:7"); perform(1, "F:E:D:C:B:A:9:8"); perform(1, "00:10:20:30:40:50:60:70"); perform(1, "01:11:21:31:41:51:61:71"); perform(1, "00FF:10EE:20DD:30CC:40BB:50AA:6099:7088"); perform(1, "01FF:11EE:21DD:31CC:41BB:51AA:6199:7188"); perform(1, "00FF:11EE:22DD:33CC:44BB:55AA:6699:7788"); perform(1, "0FFF:1EEE:2DDD:3CCC:4BBB:5AAA:6999:7888"); perform(1, "::"); perform(1, "0::"); perform(1, "::0"); perform(1, "0::0"); perform(1, "1::"); perform(1, "::1"); perform(1, "1::1"); perform(1, "1:0::0:2"); perform(1, "0:1::2:0"); perform(1, "2:0:1::2:0:1"); perform(1, "1:0::"); perform(1, "1:2::"); perform(1, "::1:0"); perform(1, "::1:2"); perform(0, "1::1:"); perform(0, ":1::1"); perform(0, "1:1::1:"); perform(0, ":1::1:1"); perform(0, "::1:"); perform(0, ":1:"); perform(0, ":::"); perform(0, "1::1::1"); perform(0, "1::1::"); perform(0, "::1::1"); perform(0, "::1::"); } int main(int argc, const char **argv) { go(); exit(0); } ruli-0.33/tools/list.c0000644000177100017710000000564010053444466015446 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: list.c,v 1.3 2004/05/21 18:23:50 evertonm Exp $ */ #include #include #include #include #include #include "ruli.h" static void static_push(ruli_list_t *list, int i) { int result = ruli_list_push(list, (void *) i); assert(!result); printf("static pushed=%d size=%d capacity=%d\n", i, ruli_list_size(list), ruli_list_capacity(list)); } static void static_pop(ruli_list_t *list) { int i = (int) ruli_list_pop(list); printf("static popped=%d size=%d capacity=%d\n", i, ruli_list_size(list), ruli_list_capacity(list)); } static void static_show_item(ruli_list_t *list, int i) { printf("static item=%d value=%d\n", i, (int) ruli_list_get(list, i)); } static void dynamic_push(ruli_list_t *list, int i) { int *j = (int *) malloc(sizeof(int)); if (!j) { fprintf(stderr, "dynamic_push(): malloc() failed: %s", strerror(errno)); exit(1); } *j = i; { int result = ruli_list_push(list, j); assert(!result); } printf("dynamic pushed=%d size=%d capacity=%d\n", i, ruli_list_size(list), ruli_list_capacity(list)); } static void dynamic_show_item(ruli_list_t *list, int i) { int *j = (int *) ruli_list_get(list, i); printf("dynamic item=%d value=%d\n", i, *j); } static void static_test() { const int MAX = 10; int i; ruli_list_t list; { int result = ruli_list_new_cap(&list, 2); assert(!result); } for (i = 0; i < MAX; ++i) static_push(&list, i); for (i = 0; i < ruli_list_size(&list); ++i) static_show_item(&list, i); while (ruli_list_size(&list) > 0) static_pop(&list); ruli_list_delete(&list); } static void int_disposer(void *ptr) { int *i = (int *) ptr; printf("int_disposer: %d\n", *i); free(i); } static void dynamic_test() { const int MAX = 10; int i; ruli_list_t list; { int result = ruli_list_new_cap(&list, 2); assert(!result); } for (i = 0; i < MAX; ++i) dynamic_push(&list, i); for (i = 0; i < ruli_list_size(&list); ++i) dynamic_show_item(&list, i); ruli_list_dispose(&list, int_disposer); } int main() { static_test(); dynamic_test(); exit(0); } ruli-0.33/tools/rand.c0000644000177100017710000000255210016733076015413 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: rand.c,v 1.2 2004/02/24 20:38:22 evertonm Exp $ */ #include #include #include #include "ruli_rand.h" static void go() { const int N = 100000; const int M = 10; int x[M]; ruli_rand_t rand_ctx; int i; for (i = 0; i < M; ++i) x[i] = 0; ruli_rand_init(&rand_ctx); for (i = 0; i < N; ++i) { int j = ruli_rand_next(&rand_ctx, 0, M - 1); assert(j >= 0); assert(j < M); ++x[j]; } for (i = 0; i < M; ++i) printf("%2d: %d\n", i, x[i]); } int main() { go(); exit(0); } ruli-0.33/tools/repeat-hostsolver.sh0000755000177100017710000000037107571434662020360 0ustar labratlabrat00000000000000#! /bin/sh int_handler () { echo INTERRUPTED repeat=0 } #trap int_handler SIGINT repeat=1 while [ $repeat -eq 1 ] do i=0 while [ $i -lt 100 ]; do echo br. i=$(($i + 1)) done sleep 3 done | ./hostsolver 0 2 127.0.0.1 2>/dev/null ruli-0.33/tools/resolve.c0000644000177100017710000001772010064101515016137 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* This test program can redo one query N times. One query is resent only after the previous instance is finished. $Id: resolve.c,v 1.10 2004/06/16 17:28:45 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include "trivial_conf_handler.h" const char *prog_name; int redo; static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static void *perform_redo(ruli_res_t *res_ctx, ruli_res_query_t *qry) { assert(redo >= 0); ruli_res_query_delete(qry); if (--redo >= 0) ruli_res_query_submit(res_ctx, qry); return OOP_CONTINUE; } static void *on_answer(ruli_res_query_t *res_qry, void *arg) { ruli_res_t *res_ctx = res_qry->resolver; ruli_msg_header_t msg_hdr; /* Just to check we received the same arg we passed */ assert(res_qry == arg); if (res_qry->answer_code == RULI_CODE_TIMEOUT) { printf("%s: query timed out\n", prog_name); return perform_redo(res_ctx, res_qry); } if (res_qry->answer_code) { printf("%s: query failed with code=%d\n", prog_name, res_qry->answer_code); return perform_redo(res_ctx, res_qry); } msg_hdr = res_qry->answer_header; printf("%s: query succeded: id=%d rcode=%d qd=%d an=%d ns=%d ar=%d " "answer_buf_size=%d answer_msg_len=%d\n", prog_name, msg_hdr.id, msg_hdr.rcode, msg_hdr.qdcount, msg_hdr.ancount, msg_hdr.nscount, msg_hdr.arcount, res_qry->answer_buf_size, res_qry->answer_msg_len); return perform_redo(res_ctx, res_qry); } static void submit_query(ruli_res_t *res_ctx, ruli_res_query_t *res_qry, const char *domain, int domain_len, char *dname_buf, int dname_buf_len, const char *qclass, const char *type) { int qc, qt; int result; char *i; qc = ruli_get_qclass_code(qclass); if (!qc) { fprintf(stderr, "%s: can't find query class: %s\n", prog_name, qclass); exit(1); } qt = ruli_get_qtype_code(type); if (!qt) { fprintf(stderr, "%s: can't find query type: %s\n", prog_name, type); exit(1); } i = ruli_dname_encode(dname_buf, dname_buf_len, domain, domain_len); if (!i) { fprintf(stderr, "%s: can't encode domain: %s\n", prog_name, domain); exit(1); } res_qry->q_on_answer = on_answer; res_qry->q_on_answer_arg = res_qry; /* bogus arg */ res_qry->q_domain = dname_buf; res_qry->q_domain_len = i - dname_buf; res_qry->q_class = qc; res_qry->q_type = qt; res_qry->q_options = RULI_RES_OPT_VOID; result = ruli_res_query_submit(res_ctx, res_qry); if (result) { fprintf(stderr, "%s: ruli_res_query_submit() failed: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } } static void perform_query(const char *domain, const char *qclass, const char *type, int retry, int timeout, ruli_list_t *server_list) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; int domain_len = strlen(domain); int dname_buf_len = ruli_dname_encode_size(domain, domain_len); char dname_buf[dname_buf_len]; ruli_res_query_t res_qry; /* ruli_res_query_t res_qry2; */ /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } /* * Submit query */ submit_query(&res_ctx, &res_qry, domain, domain_len, dname_buf, dname_buf_len, qclass, type); /* * Replay */ /* submit_query(&res_ctx, &res_qry2, domain, domain_len, dname_buf, dname_buf_len, qclass, type); */ /* * Run event loop */ { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) printf("%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) printf("%s: oop system source had no event registered\n", prog_name); else if (oop_result == OOP_HALT) printf("%s: some sink requested oop system halt\n", prog_name); else printf("%s: unexpected oop system source result (!)\n", prog_name); } /* * Destroy resolver */ ruli_res_delete(&res_ctx); /* * Destroy event source */ oop_sys_delete(source_sys); } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr; addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't create address: %s\n", prog_name, serverv[i]); exit(1); } printf("%s: saving server: ", prog_name); ruli_addr_print(stdout, addr); printf("\n"); { int result = ruli_list_push(server_list, addr); assert(!result); } } } int main(int argc, const char **argv) { const char *domain; const char *qclass; const char *type; int retry; int timeout; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 8) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } redo = atoi(argv[1]); domain = argv[2]; qclass = argv[3]; type = argv[4]; retry = atoi(argv[5]); timeout = atoi(argv[6]); serverc = argc - 7; serverv = argv + 7; if (redo < 0) { fprintf(stderr, "%s: bad REDO: %d\n", prog_name, redo); exit(1); } if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); perform_query(domain, qclass, type, retry, timeout, &server_list); ruli_list_dispose_trivial(&server_list); fprintf(stderr, "%s: done\n", prog_name); exit(0); } ruli-0.33/tools/rfc3484.c0000644000177100017710000001531310254425551015563 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2005 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: rfc3484.c,v 1.7 2005/06/17 01:46:17 evertonm Exp $ */ #include #include #include #include typedef struct addr_entry addr_entry; /* RFC 3484 Prefix Precedence Label ::1/128 50 0 ::/0 40 1 2002::/16 30 2 ::/96 20 3 ::ffff:0:0/96 10 4 */ struct addr_entry { const char *addr; int scope; int label; int precedence; } addr_table[] = { /* IPv4 */ { "255.255.255.255", RULI_ADDR_SCOPE_GLOBAL, 4, 10 }, { "0.0.0.0", RULI_ADDR_SCOPE_UNSPEC, 3, 20 }, { "127.0.0.1", RULI_ADDR_SCOPE_LINK_LOCAL, 0, 50 }, { "127.0.0.0", RULI_ADDR_SCOPE_LINK_LOCAL, 0, 50 }, { "127.0.0.2", RULI_ADDR_SCOPE_LINK_LOCAL, 0, 50 }, { "10.0.0.0", RULI_ADDR_SCOPE_SITE_LOCAL, 4, 10 }, { "11.0.0.0", RULI_ADDR_SCOPE_GLOBAL, 4, 10 }, { "172.16.0.0", RULI_ADDR_SCOPE_SITE_LOCAL, 4, 10 }, { "172.31.0.0", RULI_ADDR_SCOPE_SITE_LOCAL, 4, 10 }, { "172.15.0.0", RULI_ADDR_SCOPE_GLOBAL, 4, 10 }, { "172.32.0.0", RULI_ADDR_SCOPE_GLOBAL, 4, 10 }, { "192.168.0.0", RULI_ADDR_SCOPE_SITE_LOCAL, 4, 10 }, { "192.169.0.0", RULI_ADDR_SCOPE_GLOBAL, 4, 10 }, /* IPv6 */ /* vv----< multicast, hence */ /* v--< this is the scope */ { "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", 0xF, 1, 40 }, { "FF00:0000:0000:0000:0000:0000:0000:0000", 0, 1, 40 }, { "::", RULI_ADDR_SCOPE_UNSPEC, 3, 20 }, { "::1", RULI_ADDR_SCOPE_LINK_LOCAL, 0, 50 }, { "::2", RULI_ADDR_SCOPE_GLOBAL, 3, 20 }, { "::3", RULI_ADDR_SCOPE_GLOBAL, 3, 20 }, /* 0xFE8/10 is link local */ /* 0x8 = 1000 (only first two bits are meaningful) */ { "FE80::", RULI_ADDR_SCOPE_LINK_LOCAL, 1, 40 }, /* 0xB = 1011 (only first two bits are meaningful) */ { "FEB0::1", RULI_ADDR_SCOPE_LINK_LOCAL, 1, 40 }, /* 0xFEC/10 is site local */ /* 0xC = 1100 (only first two bits are meaningful) */ { "FEC0::", RULI_ADDR_SCOPE_SITE_LOCAL, 1, 40 }, /* 0xF = 1111 (only first two bits are meaningful) */ { "FEF0::1", RULI_ADDR_SCOPE_SITE_LOCAL, 1, 40 }, { "2000::", RULI_ADDR_SCOPE_GLOBAL, 1, 40 }, /* 0x2002/16 is label=2, precedence=30 */ { "2002::", RULI_ADDR_SCOPE_GLOBAL, 2, 30 }, { "2002:8000::", RULI_ADDR_SCOPE_GLOBAL, 2, 30 }, { "2003::", RULI_ADDR_SCOPE_GLOBAL, 1, 40 }, #if 0 { "0.0.0.0", RULI_ADDR_SCOPE_UNSPEC, 3, 20 }, { "::", RULI_ADDR_SCOPE_UNSPEC, 3, 20 }, #endif /* end of table */ { 0, 0, 0, 0 } }; static void eval_addresses(ruli_list_t *addr_list) { char buf[40]; int result; addr_entry *entry; result = ruli_list_new(addr_list); assert(!result); for (entry = &addr_table[0]; entry->addr; ++entry) { ruli_addr_t *addr; int scope_must, label_must, prec_must; int scope_found, label_found, prec_found; addr = ruli_addr_parse_new(entry->addr); if (!addr) { fprintf(stderr, "parsing failed: %s\n", entry->addr); continue; } if (ruli_list_push(addr_list, addr)) { fprintf(stderr, "storing failed: %s\n", entry->addr); continue; } scope_must = entry->scope; scope_found = ruli_addr_get_scope(&addr->addr, ruli_addr_family(addr)); label_must = entry->label; label_found = ruli_addr_get_label(&addr->addr, ruli_addr_family(addr)); prec_must = entry->precedence; prec_found = ruli_addr_get_precedence(&addr->addr, ruli_addr_family(addr)); ruli_addr_snprint(buf, sizeof(buf), addr); fprintf(stderr, "%39s s_m=%2d s=%2d %4s", buf, scope_must, scope_found, (scope_must == scope_found) ? "sOK" : "sBAD"); fprintf(stderr, " l_m=%d l=%d %4s", label_must, label_found, (label_must == label_found) ? "lOK" : "lBAD"); fprintf(stderr, " p_m=%2d p=%2d %4s", prec_must, prec_found, (prec_must == prec_found) ? "pOK" : "pBAD"); fprintf(stderr, "\n"); } } static void show_addresses(ruli_list_t *addr_list) { int addr_list_size = ruli_list_size(addr_list); char buf[40]; int i; for (i = 0; i < addr_list_size; ++i) { ruli_addr_t *addr = ruli_list_get(addr_list, i); int scope; int label; int prec; scope = ruli_addr_get_scope(&addr->addr, ruli_addr_family(addr)); label = ruli_addr_get_label(&addr->addr, ruli_addr_family(addr)); prec = ruli_addr_get_precedence(&addr->addr, ruli_addr_family(addr)); ruli_addr_snprint(buf, sizeof(buf), addr); fprintf(stderr, "%39s S%2d L%d P%2d", buf, scope, label, prec); if (ruli_addr_has_source(addr)) { char src[40]; int src_scope; int src_label; int src_prec; int bitlen; const _ruli_addr *src_ad = ruli_addr_src_get_addr(addr); int src_family = ruli_addr_src_get_family(addr); src_scope = ruli_addr_get_scope(src_ad, src_family); src_label = ruli_addr_get_label(src_ad, src_family); src_prec = ruli_addr_get_precedence(src_ad, src_family); if (ruli_addr_family(addr) == src_family) bitlen = ruli_addr_get_common_prefix_bitlen((const ruli_uint8_t *) &addr->addr, (const ruli_uint8_t *) src_ad, ruli_addr_size(addr)); else bitlen = -1; ruli_in_snprint(src, sizeof(src), src_ad, src_family); fprintf(stderr, " %s S%2d L%d P%2d C%3d", src, src_scope, src_label, src_prec, bitlen); } else { fprintf(stderr, " UNREACHABLE"); } fprintf(stderr, "\n"); } } static void go() { ruli_list_t addr_list; eval_addresses(&addr_list); ruli_addr_rfc3484_sort(&addr_list, RULI_RES_OPT_SRV_RFC3484); fprintf(stderr, "-- after RFC3484 --\n"); show_addresses(&addr_list); ruli_list_dispose_trivial(&addr_list); } int main() { go(); exit(0); } ruli-0.33/tools/ruli-host.c0000644000177100017710000002526210144431743016416 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2004 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: ruli-host.c,v 1.4 2004/11/10 15:29:39 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "trivial_conf_handler.h" #undef RULI_HOST_DEBUG const char *prog_name; static void *clean_query(ruli_host_t *qry, char *domain) { ruli_free(domain); ruli_host_query_delete(qry); ruli_free(qry); return OOP_CONTINUE; } static void *on_answer(ruli_host_t *qry, void *arg) { char *domain = (char *) arg; const int BUFSZ = 1024; char buf[BUFSZ]; int str_len; int answer_code = ruli_host_answer_code(qry); assert(answer_code != RULI_HOST_CODE_VOID); if (answer_code == RULI_HOST_CODE_ALARM) { str_len = snprintf(buf, BUFSZ, "%s query-timeout\n", domain); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } if (answer_code) { int rcode = ruli_host_rcode(qry); if (rcode != RULI_RCODE_NOERROR) { printf("%s bad-server-rcode: %d\n", domain, rcode); return clean_query(qry, domain); } str_len = snprintf(buf, BUFSZ, "%s query-failure: %d\n", domain, answer_code); assert(str_len < BUFSZ); printf(buf); return clean_query(qry, domain); } #ifdef RULI_HOST_DEBUG { ruli_msg_header_t msg_hdr; /* debug only, DON'T do this in real programs >:] */ msg_hdr = qry->host_query.answer_header; str_len = snprintf(buf, BUFSZ, "%s: query succeded: domain=%s id=%d " "rcode=%d qd=%d an=%d ns=%d ar=%d " "answer_buf_size=%d answer_msg_len=%d\n", prog_name, domain, msg_hdr.id, msg_hdr.rcode, msg_hdr.qdcount, msg_hdr.ancount, msg_hdr.nscount, msg_hdr.arcount, qry->host_query.answer_buf_size, qry->host_query.answer_msg_len); assert(str_len < BUFSZ); printf(buf); } #endif { ruli_list_t *addr_list = &qry->answer_addr_list; int addr_list_size = ruli_list_size(addr_list); int i; printf("%s", domain); for (i = 0; i < addr_list_size; ++i) { ruli_addr_t *addr = ruli_list_get(addr_list, i); printf(" "); ruli_addr_print(stdout, addr); } printf("\n"); } return clean_query(qry, domain); } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static ruli_host_t *submit_query(ruli_res_t *res_ctx, char *dname_buf, int dname_len, const char *domain, int domain_len, int cname) { int result; ruli_host_t *qry; char *dom_str; /* * Allocate space for query */ qry = (ruli_host_t *) ruli_malloc(sizeof(*qry)); if (!qry) return 0; /* * Save domain string */ dom_str = (char *) ruli_malloc(domain_len + 1); if (!dom_str) { ruli_free(qry); return 0; } memcpy(dom_str, domain, domain_len); dom_str[domain_len] = '\0'; /* * Send query */ #ifdef RULI_HOST_DEBUG fprintf(stderr, "%s: DEBUG: submit_query(): domain=%s resolver=%u " "dname_buf=%u qry=%u dname_len=%d\n", prog_name, dom_str, (unsigned int) res_ctx, (unsigned int) dname_buf, (unsigned int) qry, dname_len); #endif qry->host_resolver = res_ctx; qry->host_on_answer = on_answer; qry->host_on_answer_arg = dom_str; qry->host_domain = dname_buf; qry->host_domain_len = dname_len; qry->host_options = RULI_RES_OPT_VOID; qry->host_max_cname_depth = cname; result = ruli_host_query_submit(qry); if (result) { fprintf(stderr, "%s: ruli_host_query_submit() failed: %s [%d]\n", prog_name, ruli_host_errstr(result), result); ruli_free(dom_str); ruli_free(qry); return 0; } return qry; } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef RULI_HOST_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static void do_query(ruli_res_t *res_ctx, const char *name, int cname) { int name_len = strlen(name); char *dname_buf; int dname_buf_len; int dname_len; char *i; dname_buf_len = ruli_dname_encode_size(name, name_len); /* Allocate buffer */ dname_buf = (char *) ruli_malloc(dname_buf_len); if (!dname_buf) { fprintf(stderr, "%s: do_query(): ruli_malloc(%d) failed: %s\n", prog_name, dname_buf_len, strerror(errno)); return; } i = ruli_dname_encode(dname_buf, dname_buf_len, name, name_len); if (!i) { const int DOM_BUFSZ = 256; char dom_buf[DOM_BUFSZ]; int dom_len = RULI_MIN(name_len, DOM_BUFSZ - 1); memcpy(dom_buf, name, dom_len); dom_buf[dom_len] = '\0'; fprintf(stderr, "%s: do_query(): can't encode domain: (total_len=%d displaying=%d) %s\n", prog_name, name_len, dom_len, dom_buf); return; } dname_len = i - dname_buf; /* * Send query */ { ruli_host_t *qry = submit_query(res_ctx, dname_buf, dname_len, name, name_len, cname); if (!qry) { fprintf(stderr, "%s: do_query(): could not send query\n", prog_name); return; } } } static void solve(int retry, int timeout, int cname, const ruli_list_t *server_list) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } /* * main solve loop */ for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(&res_ctx, tok, cname); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ /* * Run event loop (send queries, receive answers) */ { void *oop_result = run_event_loop(source_sys); if (oop_result != OOP_CONTINUE) break; } } /* main solve loop */ /* * Destroy resolver */ ruli_res_delete(&res_ctx); /* * Destroy event source */ oop_sys_delete(source_sys); } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't save address: %s\n", prog_name, serverv[i]); exit(1); } #ifdef RULI_HOST_DEBUG fprintf(stderr, "%s: saving server: ", prog_name); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif { int result = ruli_list_push(server_list, addr); assert(!result); } } /* for */ } int main(int argc, const char **argv) { int retry; int timeout; int cname; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 4) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } retry = atoi(argv[1]); timeout = atoi(argv[2]); cname = atoi(argv[3]); serverc = argc - 4; serverv = argv + 4; if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } if (cname < 0) { fprintf(stderr, "%s: bad cname: %d\n", prog_name, cname); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); solve(retry, timeout, cname, &server_list); ruli_list_dispose_trivial(&server_list); #ifdef RULI_HOST_DEBUG fprintf(stderr, "%s: done\n", prog_name); #endif exit(0); } ruli-0.33/tools/ruli_res_leaking.sh0000755000177100017710000000074607607175714020216 0ustar labratlabrat00000000000000#! /bin/sh # # $Id: ruli_res_leaking.sh,v 1.2 2003/01/09 04:34:20 evertonm Exp $ me=`basename $0` if [ $# -lt 1 ]; then cat >&2 <<__EOF__ usage: $me name-server-list example: $me 127.0.0.1 192.168.0.1 __EOF__ exit fi ns_list=$* show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost xxx bogus __EOF__ } while :; do show_domains; done | ./addrsolver 0 10 $ns_list ruli-0.33/tools/ruli_res_leaking2.sh0000755000177100017710000000075007607461567020277 0ustar labratlabrat00000000000000#! /bin/sh # # $Id: ruli_res_leaking2.sh,v 1.1 2003/01/10 06:08:55 evertonm Exp $ me=`basename $0` if [ $# -lt 1 ]; then cat >&2 <<__EOF__ usage: $me name-server-list example: $me 127.0.0.1 192.168.0.1 __EOF__ exit fi ns_list=$* show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost xxx bogus __EOF__ } while :; do show_domains; done | ./addrsolver2 0 10 $ns_list ruli-0.33/tools/ruli_res_leaking3.sh0000755000177100017710000000075007607461567020300 0ustar labratlabrat00000000000000#! /bin/sh # # $Id: ruli_res_leaking3.sh,v 1.1 2003/01/10 06:08:55 evertonm Exp $ me=`basename $0` if [ $# -lt 1 ]; then cat >&2 <<__EOF__ usage: $me name-server-list example: $me 127.0.0.1 192.168.0.1 __EOF__ exit fi ns_list=$* show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost xxx bogus __EOF__ } while :; do show_domains; done | ./addrsolver3 0 10 $ns_list ruli-0.33/tools/ruli_srv_leaking.sh0000755000177100017710000000106707607732723020233 0ustar labratlabrat00000000000000#! /bin/sh # # $Id: ruli_srv_leaking.sh,v 1.3 2003/01/11 06:12:35 evertonm Exp $ me=`basename $0` if [ $# -lt 1 ]; then cat >&2 <<__EOF__ usage: $me name-server-list example: $me 127.0.0.1 192.168.0.1 __EOF__ exit fi ns_list=$* show_domains () { cat <<__EOF__ savannah.gnu.org sf.net google.com microsoft.com uol.com.br msn.com cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } while :; do show_domains | while read d do echo _http._tcp.$d _smtp._tcp.$d done done | ./srvsolver2 0 10 $ns_list ruli-0.33/tools/ruli_srv_target_leaking.sh0000755000177100017710000000071107610117477021571 0ustar labratlabrat00000000000000#! /bin/sh # # $Id: ruli_srv_target_leaking.sh,v 1.1 2003/01/11 22:48:31 evertonm Exp $ me=`basename $0` if [ $# -lt 1 ]; then cat >&2 <<__EOF__ usage: $me name-server-list example: $me 127.0.0.1 192.168.0.1 __EOF__ exit fi ns_list=$* show_domains () { cat <<__EOF__ bad-target.ruli cname-target.ruli foreign-target.ruli __EOF__ } while :; do show_domains | while read d do echo _http._tcp.$d done done | ./srvsolver2 0 1 $ns_list ruli-0.33/tools/ruli_sync_leaking.sh0000755000177100017710000000107107613677505020373 0ustar labratlabrat00000000000000#! /bin/sh # # $Id: ruli_sync_leaking.sh,v 1.3 2003/01/23 05:36:05 evertonm Exp $ me=`basename $0` if [ $# -ne 0 ]; then cat >&2 <<__EOF__ usage: $me __EOF__ exit fi ns=$1 show_domains () { cat <<__EOF__ cname-target.ruli foreign-target.ruli locaweb.com.br savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } while :; do show_domains | while read d do echo _http._tcp.$d _smtp._tcp.$d done done | ./syncsolver ruli-0.33/tools/srvsolver.c0000644000177100017710000003153410064101515016524 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: srvsolver.c,v 1.26 2004/06/16 17:28:45 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include "stdin_domains.h" #include "stdout_srv_list.h" #include "trivial_conf_handler.h" const char *prog_name; #define QBUFSZ 256 /* * Store query buffers */ typedef struct { /* plain text domain names */ char txt_service[QBUFSZ]; int txt_service_len; char txt_domain[QBUFSZ]; int txt_domain_len; /* label-encoded domain names */ char raw_service[QBUFSZ]; int raw_service_len; char raw_domain[QBUFSZ]; int raw_domain_len; } srv_qbuf_t; #ifdef SRVSOLVER_DEBUG static void debug_dump_buf(FILE *out, const char *fmt, const char *buf, int buf_len) { const int MSG_BUFSZ = 512; char msg[MSG_BUFSZ]; assert(buf_len + 1 < MSG_BUFSZ); memcpy(msg, buf, buf_len); msg[buf_len] = '\0'; fprintf(out, "%s: debug_dump_buf(): ", prog_name); fprintf(out, fmt, msg, buf_len); fprintf(out, "\n"); } #endif static void release_query(ruli_srv_t *srv_qry, srv_qbuf_t *qbuf) { free(qbuf); ruli_srv_query_delete(srv_qry); free(srv_qry); } static void *on_srv_answer(ruli_srv_t *srv_qry, void *srv_qry_arg) { srv_qbuf_t *qbuf = (srv_qbuf_t *) srv_qry_arg; assert(srv_qry->answer_code != RULI_SRV_CODE_VOID); /* * Timeout? */ if (srv_qry->answer_code == RULI_SRV_CODE_ALARM) { printf("%s.%s timeout\n", qbuf->txt_service, qbuf->txt_domain); release_query(srv_qry, qbuf); return OOP_CONTINUE; } /* * Service is not provided by that domain? */ if (srv_qry->answer_code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s.%s service-not-provided\n", qbuf->txt_service, qbuf->txt_domain); release_query(srv_qry, qbuf); return OOP_CONTINUE; } /* * RCODE error? */ if (srv_qry->answer_code) { printf("%s.%s srv-query-failed=%d ", qbuf->txt_service, qbuf->txt_domain, srv_qry->answer_code); switch (ruli_srv_rcode_kind(srv_qry)) { case RULI_SRV_RCODE_NONE: printf("non-rcode-failure\n"); break; case RULI_SRV_RCODE_WALK: printf("target-walk-query-rcode=%d\n", ruli_srv_rcode(srv_qry)); break; case RULI_SRV_RCODE_FALL: printf("fallback-query-rcode=%d\n", ruli_srv_rcode(srv_qry)); break; case RULI_SRV_RCODE_SRV: printf("underlying-query-rcode=%d\n", ruli_srv_rcode(srv_qry)); break; default: assert(0); } release_query(srv_qry, qbuf); return OOP_CONTINUE; } /* * Query successful */ { char fullname[RULI_LIMIT_DNAME_TEXT_BUFSZ]; snprintf(fullname, RULI_LIMIT_DNAME_TEXT_BUFSZ, "%s.%s", qbuf->txt_service, qbuf->txt_domain); show_srv_list(fullname, &srv_qry->answer_srv_list); } release_query(srv_qry, qbuf); return OOP_CONTINUE; } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static int encode_srv_qbuf(srv_qbuf_t *qbuf) { char *i; int len; /* * Encode service */ len = ruli_dname_encode_size(qbuf->txt_service, qbuf->txt_service_len); if (len > QBUFSZ) return -1; i = ruli_dname_encode(qbuf->raw_service, QBUFSZ, qbuf->txt_service, qbuf->txt_service_len); if (!i) return -1; qbuf->raw_service_len = i - qbuf->raw_service; assert(len == qbuf->raw_service_len); /* * Encode domain */ len = ruli_dname_encode_size(qbuf->txt_domain, qbuf->txt_domain_len); if (len > QBUFSZ) return -1; i = ruli_dname_encode(qbuf->raw_domain, QBUFSZ, qbuf->txt_domain, qbuf->txt_domain_len); if (!i) return -1; qbuf->raw_domain_len = i - qbuf->raw_domain; assert(len == qbuf->raw_domain_len); return 0; } static ruli_srv_t *submit_query(ruli_res_t *res_ctx, srv_qbuf_t *qbuf) { int result; ruli_srv_t *srv_qry; /* * Allocate space for query */ srv_qry = (ruli_srv_t *) malloc(sizeof(ruli_srv_t)); if (!srv_qry) return 0; /* * Send query */ #ifdef SRVSOLVER_DEBUG fprintf(stderr, "%s: DEBUG: submit_query(): resolver=%u srv_qry=%u\n", prog_name, (unsigned int) res_ctx, (unsigned int) srv_qry); #endif srv_qry->srv_resolver = res_ctx; srv_qry->srv_on_answer = on_srv_answer; srv_qry->srv_on_answer_arg = qbuf; srv_qry->srv_service = qbuf->raw_service; srv_qry->srv_service_len = qbuf->raw_service_len; srv_qry->srv_domain = qbuf->raw_domain; srv_qry->srv_domain_len = qbuf->raw_domain_len; srv_qry->srv_fallback_port = -1; srv_qry->srv_options = RULI_RES_OPT_VOID; result = ruli_srv_query_submit(srv_qry); if (result) { fprintf(stderr, "%s: ruli_srv_query_submit() failed: %s [%d]\n", prog_name, ruli_srv_errstr(result), result); free(srv_qry); return 0; } return srv_qry; } static void *on_stdin_read(oop_source *oop_src, int std_in, oop_event event, void *ctx) { ruli_res_t *res_ctx = (ruli_res_t *) ctx; int result; const int QBUF_SIZE = sizeof(srv_qbuf_t); assert(std_in == 0); assert(event == OOP_READ); /* * Read stdin */ result = read_stdin(std_in); switch (result) { case STDIN_READ_OK: break; case STDIN_READ_BLOCK: return OOP_CONTINUE; case STDIN_READ_EOF: /* Stop monitoring stdin */ oop_src->cancel_fd(oop_src, std_in, OOP_READ); return OOP_CONTINUE; case STDIN_READ_ERROR: return OOP_HALT; case STDIN_READ_OVERFLOW: fprintf(stderr, "%s: on_stdin_read(): stdin read buffer overflow\n", prog_name); reset_stdin_buf(); return OOP_CONTINUE; default: assert(0); /* NOT REACHED */ } /* * Scan possible hostnames from stdin */ for (;;) { srv_qbuf_t *qbuf; /* plain domain */ const int domain_buf_size = IN_BUF_SIZE; char domain[domain_buf_size]; int domain_len; /* * Parse hostname */ result = get_next_domain(domain, domain_buf_size, &domain_len); /* If no domain found yet, keep waiting for one */ if (result == PARSE_DOMAIN_NONE) return OOP_CONTINUE; /* Do not expect other errors, not even overflow */ assert(!result); /* * Now we have the full domain name, submit a query for it */ /* * Break full domain name in service + domain into qbuf */ { char *past_end = domain + domain_len; char *i = domain; for (; i < past_end; ++i) { if (*i == '.') { ++i; if (i < past_end) { if (*i != '_') break; } } } if (i >= past_end) { fprintf(stderr, "%s: on_stdin_read(): could not split service/domain\n", prog_name); return OOP_CONTINUE; } /* Allocate qbuf */ qbuf = (srv_qbuf_t *) malloc(QBUF_SIZE); if (!qbuf) { fprintf(stderr, "%s: on_stdin_read(): could not allocate srv_qbuf_t: malloc(%d) failed\n", prog_name, QBUF_SIZE); return OOP_CONTINUE; } qbuf->txt_service_len = i - domain - 1; assert(qbuf->txt_service_len < QBUFSZ); memcpy(qbuf->txt_service, domain, qbuf->txt_service_len); qbuf->txt_service[qbuf->txt_service_len] = '\0'; #ifdef SRVSOLVER_DEBUG debug_dump_buf(stderr, "on_stdin_read(): txt_service=%s txt_service_len=%d", qbuf->txt_service, qbuf->txt_service_len); #endif qbuf->txt_domain_len = past_end - i; assert(qbuf->txt_domain_len < QBUFSZ); memcpy(qbuf->txt_domain, i, qbuf->txt_domain_len); qbuf->txt_domain[qbuf->txt_domain_len] = '\0'; #ifdef SRVSOLVER_DEBUG debug_dump_buf(stderr, "on_stdin_read(): txt_domain=%s txt_domain_len=%d", qbuf->txt_domain, qbuf->txt_domain_len); #endif } /* * Encode buffers in qbuf (txt => raw) */ if (encode_srv_qbuf(qbuf)) { fprintf(stderr, "%s: on_stdin_read(): could not encode domain in srv_qbuf_t\n", prog_name); free(qbuf); return OOP_CONTINUE; } /* * Send query */ { ruli_srv_t *srv_qry = submit_query(res_ctx, qbuf); if (!srv_qry) { fprintf(stderr, "%s: on_stdin_read(): could not send SRV query\n", prog_name); free(qbuf); return OOP_CONTINUE; } } } /* for loop */ assert(0); /* NOT REACHED */ return OOP_CONTINUE; } static void go(int retry, int timeout, ruli_list_t *server_list) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } /* * Monitor stdin for read */ { int std_in = 0; set_non_blocking(std_in); source->on_fd(source, std_in, OOP_READ, on_stdin_read, &res_ctx); } /* * Run event loop */ { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef SRVSOLVER_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); } /* * Destroy resolver */ ruli_res_delete(&res_ctx); /* * Destroy event source */ oop_sys_delete(source_sys); } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't save address: %s\n", prog_name, serverv[i]); free(addr); exit(1); } #ifdef SRVSOLVER_DEBUG fprintf(stderr, "%s: saving server: ", prog_name); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif { int result = ruli_list_push(server_list, addr); assert(!result); } } } int main(int argc, const char **argv) { int retry; int timeout; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 4) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } retry = atoi(argv[1]); timeout = atoi(argv[2]); serverc = argc - 3; serverv = argv + 3; if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); go(retry, timeout, &server_list); ruli_list_dispose_trivial(&server_list); exit(0); } ruli-0.33/tools/srvsolver2.c0000644000177100017710000003132110064101515016600 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: srvsolver2.c,v 1.17 2004/06/16 17:28:45 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include "stdout_srv_list.h" #include "trivial_conf_handler.h" #undef SRVSOLVER2_DEBUG const char *prog_name; int qc; int qt; #define QBUFSZ 256 /* * Store query buffers */ typedef struct { /* plain text domain names */ char txt_service[QBUFSZ]; int txt_service_len; char txt_domain[QBUFSZ]; int txt_domain_len; /* label-encoded domain names */ char raw_service[QBUFSZ]; int raw_service_len; char raw_domain[QBUFSZ]; int raw_domain_len; } srv_qbuf_t; #ifdef SRVSOLVER2_DEBUG static void debug_dump_buf(FILE *out, const char *fmt, const char *buf, int buf_len) { const int MSG_BUFSZ = 512; char msg[MSG_BUFSZ]; assert(buf_len + 1 < MSG_BUFSZ); memcpy(msg, buf, buf_len); msg[buf_len] = '\0'; fprintf(out, "%s: debug_dump_buf(): ", prog_name); fprintf(out, fmt, msg, buf_len); fprintf(out, "\n"); } #endif static void release_query(ruli_srv_t *srv_qry, srv_qbuf_t *qbuf) { ruli_free(qbuf); ruli_srv_query_delete(srv_qry); ruli_free(srv_qry); } static void *on_srv_answer(ruli_srv_t *srv_qry, void *srv_qry_arg) { srv_qbuf_t *qbuf = (srv_qbuf_t *) srv_qry_arg; assert(srv_qry->answer_code != RULI_SRV_CODE_VOID); /* * Timeout? */ if (srv_qry->answer_code == RULI_SRV_CODE_ALARM) { printf("%s.%s timeout\n", qbuf->txt_service, qbuf->txt_domain); release_query(srv_qry, qbuf); return OOP_CONTINUE; } /* * Service is not provided by that domain? */ if (srv_qry->answer_code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s.%s service-not-provided\n", qbuf->txt_service, qbuf->txt_domain); release_query(srv_qry, qbuf); return OOP_CONTINUE; } /* * RCODE error? */ if (srv_qry->answer_code) { printf("%s.%s srv-query-failed=%d ", qbuf->txt_service, qbuf->txt_domain, srv_qry->answer_code); switch (ruli_srv_rcode_kind(srv_qry)) { case RULI_SRV_RCODE_NONE: printf("non-rcode-failure\n"); break; case RULI_SRV_RCODE_WALK: printf("target-walk-query-rcode=%d\n", ruli_srv_rcode(srv_qry)); break; case RULI_SRV_RCODE_FALL: printf("fallback-query-rcode=%d\n", ruli_srv_rcode(srv_qry)); break; case RULI_SRV_RCODE_SRV: printf("underlying-query-rcode=%d\n", ruli_srv_rcode(srv_qry)); break; default: assert(0); } release_query(srv_qry, qbuf); return OOP_CONTINUE; } /* * Query successful */ { char fullname[RULI_LIMIT_DNAME_TEXT_BUFSZ]; snprintf(fullname, RULI_LIMIT_DNAME_TEXT_BUFSZ, "%s.%s", qbuf->txt_service, qbuf->txt_domain); show_srv_list(fullname, &srv_qry->answer_srv_list); } release_query(srv_qry, qbuf); return OOP_CONTINUE; } static void create_oop_source(oop_source_sys **source_sys, oop_source **source) { /* Create the system event source */ *source_sys = oop_sys_new(); if (!*source_sys) { fprintf(stderr, "%s: can't create system event source: oop_sys_new() failed\n", prog_name); exit(1); } /* Get the system event registration interface */ *source = oop_sys_source(*source_sys); if (!*source) { fprintf(stderr, "%s: can't get registration interface: oop_sys_source() failed\n", prog_name); exit(1); } } static ruli_srv_t *submit_query(ruli_res_t *res_ctx, srv_qbuf_t *qbuf) { int result; ruli_srv_t *srv_qry; /* * Allocate space for query */ srv_qry = (ruli_srv_t *) ruli_malloc(sizeof(ruli_srv_t)); if (!srv_qry) return 0; /* * Send query */ #ifdef SRVSOLVER2_DEBUG fprintf(stderr, "%s: DEBUG: submit_query(): resolver=%u srv_qry=%u\n", prog_name, (unsigned int) res_ctx, (unsigned int) srv_qry); #endif srv_qry->srv_resolver = res_ctx; srv_qry->srv_on_answer = on_srv_answer; srv_qry->srv_on_answer_arg = qbuf; srv_qry->srv_service = qbuf->raw_service; srv_qry->srv_service_len = qbuf->raw_service_len; srv_qry->srv_domain = qbuf->raw_domain; srv_qry->srv_domain_len = qbuf->raw_domain_len; srv_qry->srv_fallback_port = -1; srv_qry->srv_options = RULI_RES_OPT_VOID; result = ruli_srv_query_submit(srv_qry); if (result) { fprintf(stderr, "%s: ruli_srv_query_submit() failed: %s [%d]\n", prog_name, ruli_srv_errstr(result), result); ruli_free(srv_qry); return 0; } return srv_qry; } static void *run_event_loop(oop_source_sys *source_sys) { void *oop_result = oop_sys_run(source_sys); if (oop_result == OOP_ERROR) fprintf(stderr, "%s: oop system source returned error\n", prog_name); else if (oop_result == OOP_CONTINUE) { /* * Normal termination */ #ifdef SRVSOLVER2_DEBUG fprintf(stderr, "%s: oop system source had no event registered\n", prog_name); #endif } else if (oop_result == OOP_HALT) fprintf(stderr, "%s: some sink requested oop system halt\n", prog_name); else fprintf(stderr, "%s: unexpected oop system source result (!)\n", prog_name); return oop_result; } static int encode_srv_qbuf(srv_qbuf_t *qbuf) { char *i; int len; /* * Encode service */ len = ruli_dname_encode_size(qbuf->txt_service, qbuf->txt_service_len); if (len > QBUFSZ) return -1; i = ruli_dname_encode(qbuf->raw_service, QBUFSZ, qbuf->txt_service, qbuf->txt_service_len); if (!i) return -1; qbuf->raw_service_len = i - qbuf->raw_service; assert(len == qbuf->raw_service_len); /* * Encode domain */ len = ruli_dname_encode_size(qbuf->txt_domain, qbuf->txt_domain_len); if (len > QBUFSZ) return -1; i = ruli_dname_encode(qbuf->raw_domain, QBUFSZ, qbuf->txt_domain, qbuf->txt_domain_len); if (!i) return -1; qbuf->raw_domain_len = i - qbuf->raw_domain; assert(len == qbuf->raw_domain_len); return 0; } static void do_query(ruli_res_t *res_ctx, const char *domain) { const int QBUF_SIZE = sizeof(srv_qbuf_t); srv_qbuf_t *qbuf; /* * Break full domain name in service + domain into qbuf */ { int domain_len = strlen(domain); const char *past_end = domain + domain_len; const char *i = domain; for (; i < past_end; ++i) { if (*i == '.') { ++i; if (i < past_end) { if (*i != '_') break; } } } if (i >= past_end) { fprintf(stderr, "%s: do_query(): could not split service/domain\n", prog_name); return; } /* Allocate qbuf */ qbuf = (srv_qbuf_t *) ruli_malloc(QBUF_SIZE); if (!qbuf) { fprintf(stderr, "%s: do_query(): could not allocate srv_qbuf_t: ruli_malloc(%d) failed\n", prog_name, QBUF_SIZE); return; } qbuf->txt_service_len = i - domain - 1; assert(qbuf->txt_service_len < QBUFSZ); memcpy(qbuf->txt_service, domain, qbuf->txt_service_len); qbuf->txt_service[qbuf->txt_service_len] = '\0'; #ifdef SRVSOLVER2_DEBUG debug_dump_buf(stderr, "do_query(): txt_service=%s txt_service_len=%d", qbuf->txt_service, qbuf->txt_service_len); #endif qbuf->txt_domain_len = past_end - i; assert(qbuf->txt_domain_len < QBUFSZ); memcpy(qbuf->txt_domain, i, qbuf->txt_domain_len); qbuf->txt_domain[qbuf->txt_domain_len] = '\0'; #ifdef SRVSOLVER2_DEBUG debug_dump_buf(stderr, "do_query(): txt_domain=%s txt_domain_len=%d", qbuf->txt_domain, qbuf->txt_domain_len); #endif } /* Break full domain name in service + domain into qbuf */ /* * Encode buffers in qbuf (txt => raw) */ if (encode_srv_qbuf(qbuf)) { fprintf(stderr, "%s: do_query(): could not encode domain in srv_qbuf_t\n", prog_name); ruli_free(qbuf); return; } /* * Send query */ { ruli_srv_t *srv_qry = submit_query(res_ctx, qbuf); if (!srv_qry) { fprintf(stderr, "%s: do_query(): could not send SRV query\n", prog_name); ruli_free(qbuf); return; } } } static void go(int retry, int timeout, ruli_list_t *server_list) { oop_source_sys *source_sys; /* System event source */ oop_source *source; /* Event registration interface */ ruli_res_t res_ctx; int result; ruli_conf_handler_t handler; /* * Create event source */ create_oop_source(&source_sys, &source); /* * Initialize resolver */ handler.opaque = server_list; handler.search_loader = load_search_list; handler.search_unloader = unload_search_list; handler.ns_loader = load_ns_list; handler.ns_unloader = unload_ns_list; res_ctx.res_conf_handler = &handler; res_ctx.res_source = source; res_ctx.res_retry = retry; res_ctx.res_timeout = timeout; result = ruli_res_new(&res_ctx); if (result) { fprintf(stderr, "%s: can't create ruli resolver: %s [%d]\n", prog_name, ruli_res_errstr(result), result); exit(1); } for (;;) { const int INBUFSZ = 1024; char inbuf[INBUFSZ]; /* * Read stdin */ if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Submit query for token */ do_query(&res_ctx, tok); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ /* * Run event loop */ { void *oop_result = run_event_loop(source_sys); if (oop_result != OOP_CONTINUE) break; } } /* for */ /* * Destroy resolver */ ruli_res_delete(&res_ctx); /* * Destroy event source */ oop_sys_delete(source_sys); } static void parse_servers(ruli_list_t *server_list, int serverc, const char **serverv) { int i; assert(serverc >= 1); for (i = 0; i < serverc; ++i) { ruli_addr_t *addr; addr = ruli_addr_parse_new(serverv[i]); if (!addr) { fprintf(stderr, "%s: can't create address: %s\n", prog_name, serverv[i]); exit(1); } #ifdef SRVSOLVER2_DEBUG fprintf(stderr, "%s: saving server: ", prog_name); ruli_addr_print(stderr, addr); fprintf(stderr, "\n"); #endif { int result = ruli_list_push(server_list, addr); assert(!result); } } } int main(int argc, const char **argv) { const char *qclass = "in"; const char *type = "a"; int retry; int timeout; int serverc; const char **serverv; ruli_list_t server_list; /* list of ruli_addr_t* */ prog_name = argv[0]; if (argc < 4) { fprintf(stderr, "usage: %s [ ... ]\n", prog_name); exit(1); } retry = atoi(argv[1]); timeout = atoi(argv[2]); serverc = argc - 3; serverv = argv + 3; if (retry < 0) { fprintf(stderr, "%s: bad retry: %d\n", prog_name, retry); exit(1); } if (timeout < 0) { fprintf(stderr, "%s: bad timeout: %d\n", prog_name, timeout); exit(1); } { int result = ruli_list_new(&server_list); assert(!result); } parse_servers(&server_list, serverc, serverv); qc = ruli_get_qclass_code(qclass); if (!qc) { fprintf(stderr, "%s: can't find query class: %s\n", prog_name, qclass); exit(1); } qt = ruli_get_qtype_code(type); if (!qt) { fprintf(stderr, "%s: can't find query type: %s\n", prog_name, type); exit(1); } go(retry, timeout, &server_list); ruli_list_dispose_trivial(&server_list); #ifdef SRVSOLVER2_DEBUG fprintf(stderr, "%s: done\n", prog_name); #endif exit(0); } ruli-0.33/tools/ss.sh0000755000177100017710000000121207607224637015311 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_srv_t # # $Id: ss.sh,v 1.1 2003/01/09 07:49:51 evertonm Exp $ show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains | while read d; do echo _http._tcp.$d | ./srvsolver2 0 10 127.0.0.1 127.0.0.1 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done done ruli-0.33/tools/ss2.sh0000755000177100017710000000116607607225761015402 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_srv_t # # $Id: ss2.sh,v 1.1 2003/01/09 07:59:45 evertonm Exp $ show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains | while read d do echo _http._tcp.$d done | ./srvsolver2 0 10 127.0.0.1 127.0.0.1 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done ruli-0.33/tools/stdin_domains.c0000644000177100017710000000642610144431743017324 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: stdin_domains.c,v 1.6 2004/11/10 15:29:39 evertonm Exp $ */ #include #include #include #include #include #include #include #include #include "stdin_domains.h" char in_buf[IN_BUF_SIZE]; int in_buf_len = 0; static int is_blank(int c) { return isspace(c); } static void shift_in_buffer_from(char *i) { int len = in_buf + in_buf_len - i; memcpy(in_buf, i, len); in_buf_len = len; } void reset_stdin_buf() { in_buf_len = 0; } int read_stdin(int std_in) { int rd; if (in_buf_len >= IN_BUF_SIZE) { fprintf(stderr, "read_stdin(): buffer overflow reading from stdin\n"); return STDIN_READ_OVERFLOW; } rd = read(std_in, in_buf + in_buf_len, IN_BUF_SIZE - in_buf_len); /* EOF ? */ if (!rd) return STDIN_READ_EOF; /* Error ? */ if (rd < 0) { if (errno == EAGAIN) return STDIN_READ_BLOCK; fprintf(stderr, "read_stdin(): can't read stdin: %s\n", strerror(errno)); return STDIN_READ_ERROR; } assert(rd <= (IN_BUF_SIZE - in_buf_len)); in_buf_len += rd; return STDIN_READ_OK; } int get_next_domain(char *domain_buf, int domain_buf_size, int *domain_len) { char *i; char *j; char *past_end; /* * Find domain-name begin */ i = in_buf; past_end = in_buf + in_buf_len; for (; i < past_end; ++i) if (!is_blank(*i)) break; if (i >= past_end) { /* optimized shift_in_buffer_from(past_end) */ in_buf_len = 0; return PARSE_DOMAIN_NONE; } /* * Find domain-name end */ j = i + 1; for (; j < past_end; ++j) if (is_blank(*j)) break; if (j >= past_end) { fprintf(stderr, "get_next_domain(): can't find end of hostname\n"); assert(j == past_end); /* strip off leading blank spaces */ shift_in_buffer_from(i); return PARSE_DOMAIN_NONE; } /* * So we have at least one domain name */ { int len = j - i; *domain_len = len; if (domain_buf_size < len) { fprintf(stderr, "get_next_domain(): won't fit: domain_buf_size=%d < domain_len=%d\n", domain_buf_size, len); return PARSE_DOMAIN_OVERFLOW; } memcpy(domain_buf, i, len); } shift_in_buffer_from(j); return PARSE_DOMAIN_OK; } void set_non_blocking(int fd) { int result; long flags; flags = fcntl(fd, F_GETFL, 0); assert(flags != -1); result = fcntl(fd, F_SETFL, flags | O_NONBLOCK); assert(result != -1); } ruli-0.33/tools/stdin_domains.h0000644000177100017710000000345107614250011017317 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: stdin_domains.h,v 1.5 2003/01/24 14:39:05 evertonm Exp $ */ #ifndef STDIN_DOMAINS_H #define STDIN_DOMAINS_H #define IN_BUF_SIZE 512 extern char in_buf[]; extern int in_buf_len; #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif /* 0: ok, proceed -1: stdin would block, force continue -2: stdin eof, please finish reading from stdin -3: stdin error, please halt reading from stdin -4: internal buffer overflow */ #define STDIN_READ_OK 0 #define STDIN_READ_BLOCK -1 #define STDIN_READ_EOF -2 #define STDIN_READ_ERROR -3 #define STDIN_READ_OVERFLOW -4 /* 0: ok, domain found -1: no domain found yet -2: overflow: domain won't fit on buffer provided */ #define PARSE_DOMAIN_OK 0 #define PARSE_DOMAIN_NONE -1 #define PARSE_DOMAIN_OVERFLOW -2 void reset_stdin_buf(); int read_stdin(int std_in); int get_next_domain(char *domain_buf, int domain_buf_size, int *domain_len); void set_non_blocking(int fd); #endif /* STDIN_DOMAINS_H */ ruli-0.33/tools/stdout_srv_list.c0000644000177100017710000000460310064101515017723 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: stdout_srv_list.c,v 1.11 2004/06/16 17:28:45 evertonm Exp $ */ #include #include #include #include #include #include "stdout_srv_list.h" void show_srv_list(const char *fullname, const ruli_list_t *srv_list) { int srv_list_size = ruli_list_size(srv_list); int i; assert(srv_list_size >= 0); if (srv_list_size < 1) { printf("%s empty\n", fullname); return; } /* * Scan list of SRV records */ for (i = 0; i < srv_list_size; ++i) { ruli_srv_entry_t *entry = (ruli_srv_entry_t *) ruli_list_get(srv_list, i); ruli_list_t *addr_list = &entry->addr_list; int addr_list_size = ruli_list_size(addr_list); int j; /* * Show original full query name */ printf("%s ", fullname); /* * Show target */ { char txt_dname_buf[RULI_LIMIT_DNAME_TEXT_BUFSZ]; int txt_dname_len; if (ruli_dname_decode(txt_dname_buf, RULI_LIMIT_DNAME_TEXT_BUFSZ, &txt_dname_len, entry->target, entry->target_len)) { printf("target-decoding-failed\n"); continue; } printf("target=%s ", txt_dname_buf); } /* * Show port number and addresses */ printf("priority=%d weight=%d port=%d addresses=", entry->priority, entry->weight, entry->port); /* * Scan addresses */ for (j = 0; j < addr_list_size; ++j) { ruli_addr_t *addr = (ruli_addr_t *) ruli_list_get(addr_list, j); ruli_addr_print(stdout, addr); printf(" "); } printf("\n"); } } ruli-0.33/tools/stdout_srv_list.h0000644000177100017710000000204507614250011017731 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: stdout_srv_list.h,v 1.2 2003/01/24 14:39:05 evertonm Exp $ */ #ifndef STDOUT_SRV_LIST_H #define STDOUT_SRV_LIST_H #include void show_srv_list(const char *fullname, const ruli_list_t *srv_list); #endif /* STDOUT_SRV_LIST_H */ ruli-0.33/tools/sync.sh0000755000177100017710000000116207607224637015644 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_sync_t # # $Id: sync.sh,v 1.1 2003/01/09 07:49:51 evertonm Exp $ show_domains () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains | while read d; do echo _http._tcp.$d | ./syncsolver 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done doneruli-0.33/tools/sync2.sh0000755000177100017710000000121707607225761015726 0ustar labratlabrat00000000000000#! /bin/sh # # debug memory leak for ruli_sync_t # # $Id: sync2.sh,v 1.1 2003/01/09 07:59:45 evertonm Exp $ do_cat () { cat <<__EOF__ savannah.gnu.org sf.net www.google.com www.microsoft.com www.uol.com.br www.msn.com www.cisco.com freshmeat.net slashdot.org localhost kensingtonlabs.com vanrein.org xxx bogus __EOF__ } show_domains () { do_cat do_cat do_cat } show_domains | while read d do echo _http._tcp.$d done | ./syncsolver 2> x grep malloc x | awk '{ print $4 }' | sort > x.1 grep free x | awk '{ print $4 }' | sort > x.2 diff x.1 x.2 > y cat y grep addr y | awk '{ print $2 }' | while read i; do grep $i x done ruli-0.33/tools/syncsolver.c0000644000177100017710000001005510144431743016671 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: syncsolver.c,v 1.10 2004/11/10 15:29:39 evertonm Exp $ */ #include #include #include #include #include #include #include #include "stdout_srv_list.h" const int INBUFSZ = 1024; const char *prog_name; static void solve(const char *fullname) { int name_len = strlen(fullname); char name[name_len + 1]; char *txt_service; int txt_service_len; char *txt_domain; int txt_domain_len; memcpy(name, fullname, name_len + 1); /* * Split full domain name in service + domain * Example: _http._tcp.domain => _http._tcp + domain */ { int len = strlen(name); char *past_end = name + len; char *i = name; assert(len > 0); assert(len < INBUFSZ); if (*i != '_') { fprintf(stderr, "%s: solve(): could not split service/domain\n", prog_name); return; } /* * Find domain */ for (; i < past_end; ++i) { if (*i == '.') { ++i; if (i < past_end) { if (*i != '_') break; } } } if (i >= past_end) { fprintf(stderr, "%s: solve(): could not split service/domain\n", prog_name); return; } txt_service = name; txt_service_len = i - name - 1; txt_domain = i; txt_domain_len = past_end - i; txt_service[txt_service_len] = '\0'; } /* * Submit synchronous query */ { ruli_sync_t *sync_query = ruli_sync_query(txt_service, txt_domain, -1, RULI_RES_OPT_SEARCH); int srv_code; /* * Sync query failure? */ if (!sync_query) { printf("%s could-not-submit-query\n", fullname); return; } /* * Underlying SRV query failure? */ srv_code = ruli_sync_srv_code(sync_query); assert(srv_code != RULI_SRV_CODE_VOID); /* Timeout ? */ if (srv_code == RULI_SRV_CODE_ALARM) { printf("%s timeout\n", fullname); ruli_sync_delete(sync_query); return; } /* Service provided ? */ if (srv_code == RULI_SRV_CODE_UNAVAILABLE) { printf("%s srv-service-not-provided\n", fullname); ruli_sync_delete(sync_query); return; } if (srv_code) { int rcode = ruli_sync_rcode(sync_query); printf("%s srv-query-failed: srv_code=%d rcode=%d\n", fullname, srv_code, rcode); ruli_sync_delete(sync_query); return; } /* * Show the result */ show_srv_list(fullname, ruli_sync_srv_list(sync_query)); ruli_sync_delete(sync_query); } } static void go() { char inbuf[INBUFSZ]; /* * Scan stdin */ for (;;) { if (!fgets(inbuf, INBUFSZ, stdin)) { if (feof(stdin)) break; fprintf(stderr, "%s: reading from stdin: %s\n", prog_name, strerror(errno)); continue; } /* * Scan tokens */ { const char *SEP = "\r\n\t "; char *ptr; char *tok; tok = strtok_r(inbuf, SEP, &ptr); if (!tok) continue; for (;;) { /* * Make SRV query for token */ solve(tok); tok = strtok_r(0, SEP, &ptr); if (!tok) break; } /* for */ } /* Scan tokens */ } } int main(int argc, char *argv[]) { prog_name = argv[0]; go(); exit(0); } ruli-0.33/tools/trivial_conf_handler.c0000644000177100017710000000242710064101515020632 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: trivial_conf_handler.c,v 1.2 2004/06/16 17:28:45 evertonm Exp $ */ #include "trivial_conf_handler.h" ruli_list_t *load_search_list(ruli_conf_handler_t *handler) { return 0; } void unload_search_list(ruli_conf_handler_t *handler, ruli_list_t *search_list) { /* do nothing */ } ruli_list_t *load_ns_list(ruli_conf_handler_t *handler) { return (ruli_list_t *) handler->opaque; } void unload_ns_list(ruli_conf_handler_t *handler, ruli_list_t *ns_list) { /* do nothing */ } ruli-0.33/tools/trivial_conf_handler.h0000644000177100017710000000240207622605427020651 0ustar labratlabrat00000000000000/*-GNU-GPL-BEGIN-* RULI - Resolver User Layer Interface - Querying DNS SRV records Copyright (C) 2003 Everton da Silva Marques RULI 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. RULI 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 RULI; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *-GNU-GPL-END-*/ /* $Id: trivial_conf_handler.h,v 1.1 2003/02/13 03:03:51 evertonm Exp $ */ #ifndef TRIVIAL_CONF_HANDLER_H #define TRIVIAL_CONF_HANDLER_H #include ruli_list_t *load_search_list(ruli_conf_handler_t *handler); void unload_search_list(ruli_conf_handler_t *handler, ruli_list_t *search_list); ruli_list_t *load_ns_list(ruli_conf_handler_t *handler); void unload_ns_list(ruli_conf_handler_t *handler, ruli_list_t *ns_list); #endif /* TRIVIAL_CONF_HANDLER_H */