pax_global_header00006660000000000000000000000064122005552770014517gustar00rootroot0000000000000052 comment=9203f6fce4f57908e81701c6473836d4454b5150 inadyn-1.99.4/000077500000000000000000000000001220055527700131055ustar00rootroot00000000000000inadyn-1.99.4/.gitignore000066400000000000000000000007241220055527700151000ustar00rootroot00000000000000bin/* src/inadyn src/inadyn.exe depcomp inadyn.anjuta install-sh missing .anjuta .tm_project* .anjuta_sym_db.db .libs .deps .*swp .nautilus-metafile.xml *.autosave *.pws *.bak *~ #*# *.gladep *.la *.lo *.o *.class *.pyc aclocal.m4 autom4te.cache config.h config.h.in config.log config.status configure intltool-extract* intltool-merge* intltool-modules* intltool-update* libtool prepare.sh stamp-h* ltmain.sh mkinstalldirs config.guess config.sub Makefile Makefile.in inadyn-1.99.4/COPYING000066400000000000000000000013201220055527700141340ustar00rootroot00000000000000Copyright (C) 2003-2004 Narcis Ilisei, This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. inadyn-1.99.4/LICENSE000066400000000000000000000431031220055527700141130ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. inadyn-1.99.4/Makefile000066400000000000000000000045001220055527700145440ustar00rootroot00000000000000# Makefile for INADYN, a simple and small ddns client. -*-Makefile-*- # Use "make V=1" to see full GCC output #VERSION ?= $(shell git tag -l | tail -1) VERSION ?= 1.99.4 NAME = inadyn EXEC = src/$(NAME) PKG = $(NAME)-$(VERSION) ARCHIVE = $(PKG).tar.bz2 MAN5 = inadyn.conf.5 MAN8 = inadyn.8 ROOTDIR ?= $(dir $(shell pwd)) RM ?= rm -f CC ?= $(CROSS)gcc prefix ?= /usr/local sysconfdir ?= /etc datadir = $(prefix)/share/doc/inadyn mandir = $(prefix)/share/man # This magic trick looks like a comment, but works on BSD PMake #include include config.mk BASE_OBJS = src/base64.o src/md5.o src/dyndns.o src/errorcode.o src/get_cmd.o \ src/http_client.o src/ip.o src/main.o src/os_unix.o src/os_windows.o \ src/os.o src/os_psos.o src/tcp.o src/inadyn_cmd.o src/sha1.o OBJS = $(BASE_OBJS) $(CFG_OBJ) $(EXTRA_OBJS) CFLAGS ?= -O2 -W -Wall -Werror CFLAGS += $(CFG_INC) $(EXTRA_CFLAGS) CPPFLAGS ?= CPPFLAGS += -Iinclude -DVERSION_STRING=\"$(VERSION)\" LDFLAGS ?= LDLIBS += $(EXTRA_LIBS) DISTFILES = README COPYING LICENSE # Pattern rules .c.o: $(PRINTF) " CC $@\n" $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< # Build rules all: $(EXEC) $(EXEC): $(OBJS) $(PRINTF) " LINK $@\n" $(Q)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) install: $(EXEC) @install -d $(DESTDIR)$(prefix)/sbin @install -d $(DESTDIR)$(sysconfdir) @install -d $(DESTDIR)$(datadir) @install -d $(DESTDIR)$(mandir)/man8 @install -d $(DESTDIR)$(mandir)/man5 @install -m 0755 $(EXEC) $(DESTDIR)$(prefix)/sbin/ @install -m 0644 man/$(MAN5) $(DESTDIR)$(mandir)/man5/$(MAN5) @install -m 0644 man/$(MAN8) $(DESTDIR)$(mandir)/man8/$(MAN8) @for file in $(DISTFILES); do \ install -m 0644 $$file $(DESTDIR)$(datadir)/$$file; \ done uninstall: -@$(RM) $(DESTDIR)$(prefix)/sbin/$(EXEC) -@$(RM) -r $(DESTDIR)$(datadir) -@$(RM) $(DESTDIR)$(mandir)/man5/$(MAN5) -@$(RM) $(DESTDIR)$(mandir)/man8/$(MAN8) clean: -@$(RM) $(OBJS) $(EXEC) distclean: -@$(RM) $(OBJS) core $(EXEC) *.o *.map .*.d *.out tags TAGS dist: @echo "Building bzip2 tarball of $(PKG) in parent dir..." git archive --format=tar --prefix=$(PKG)/ $(VERSION) | bzip2 >../$(ARCHIVE) @(cd ..; md5sum $(ARCHIVE) | tee $(ARCHIVE).md5) inadyn-1.99.4/NEWS000066400000000000000000000242101220055527700136030ustar00rootroot00000000000000Ver. current - Add ability to specify cache file. - Add ability to check IP of interface (unix only). If interface is specified, no external IP check permormed. Old --iface option renamed to --bind. - Specify IP address in freedns.afraid.org update request (only autodetect was used). - Add changeip.com support. - Minor bugfixes and code optimization Ver. 1.99.2 - Sep 7 2012 - Fix inability to change update period (broken in 1.99.0). - Get http status description. - Fix debug output description. Ver. 1.99.1 - Sep 1 2012 - Make HTTP status code check server-specific. - Change e-mail address. Ver. 1.99.0 - Aug 17 2012 - Merge wl500g patches from http://code.google.com/p/wl500g: - 120-heipv6tb.patch adds support for tunnelbroker. - 121-hedyndns.patch adds support for HE dyndns. - 210-wildcard.patch makes wildcard option account specific. - For ddns services that have their own checkip service, use it instead of dyndns.org checkip service. - Add ability to handle non-fatal temporary errors ("update too often", system error etc.). - Fix malformed HTTP request. - Warn if initial DNS request failed. - Add dnsexit.com support. - Modify http client to parse response for http status code and response body. - Remove DynDNS ignored and deprecated parameters (wildcard, mx, backmx, system). Wildcard kept for easydns.com. - Report detected IP to sitelutions and dynsip servers (only autodetect was used). - Update TZO support. - Check HTTP status code before validating response. - Remake zoneedit response validation. - Little code cleanup. Ver. 1.98.1 - Jul 18 2011 - Preserve time since last update (forced update counter) and num interations from being reset by SIGHUP restart command. - Bug fix --drop-privs uid/gid was swapped and a possible buffer overflow. - Extend --drop-privs to support hyphens. - Bug fix segfault at initial DNS lookup. - Cleanup of inadyn log messages, reformat & clarification. - Typo fixes and polish to man pages inadyn(8) and inadyn.conf(5) Ver. 1.98.0 - Feb 28 2011 - New config file, command line, syntax (still backwards compatible!). - New option --drop-privs USER[:GROUP] to support privilege separation. - Drop privileges before creating any files. - Documentation updates. Ver. 1.97.4 - Nov 2 2010 - Support for dynsip.org by milkfish, from DD-WRT. - Add support for sitelutions.com, from inadyn-mt (untested). - Clear DNS cache before calling getaddrinfo(), should fix GitHub issue #3. Ver. 1.97.3 - Nov 2 2010 - Merge wl500g patches from http://code.google.com/p/wl500g: - 101-http-request.patch. This cleans up the DDNS server defintions and callbacks, evidently originating from ideas implemented by DD-WRT. - 102-zoneedit.patch. This fixes issues in what appears to be both request and response formats in ZoneEdit DDNS. Originating from DD-WRT. - 103-tzo.patch. This patch adds support for tzo.com DDNS serivices. - 110-dnsomatic.patch. This patch adds support for DNS-O-Matic , an OpenDNS service which can act as a "meta" update to several other DDNS service providers. - 120-heipv6tb.patch. This patch adds support for Hurricane Electric's http://tunnelbroker.net/ DDNS services . - When starting: always use cache file, if it exists, or seed with DNS lookup. - Fix Debian bug #575549: freedns.afraid.org example in inadyn(8) is incorrect. Ver. 1.97.2 - Oct 30 2010 - Fix missing man pages from install/uninstall targets. - Fix GitHub issue #2: setsocktopt() takes pointer to struct timeval, not int as argument. - Replace gethostbyname() with getaddrinfo() and improve logging at connect(). Ver. 1.97.1 - Oct 19 2010 - Add support for properly restarting inadyn on SIGHUP. - Remove INADYN: prefix in MODULE_TAG entirely - messes up syslog output. Ver. 1.97.0 - Oct 18 2010 - Apply patches by Neufbox4 from http://dev.efixo.net: - 100-inadyn-1.96.2.patch, cache file support. - 100-inadyn-1.96.2.patch, bind interface support. - 200-inadyn-1.96.2-64bits-fix.patch. - 300-inadyn-1.96.2-pidfile-and-improve.patch. - New README, COPYING and LICENSE file, remove readme.html. - Refactor and cleanup Makefile (renamed from makefile). - Add support for SIGTERM signal. - Relocate include files to include directory. - Apply patch for multiple accounts from Christian Eyrich. - Remove unused uint typedef causing trouble on ARM GCC 4.4.x. - Fix missing strdup() of input config file and free any preexisting. - Make sure TYPE_TCP enum relly is 0 on all compilers. - Improve error messages using strerror() and use -1 as stale socket, not 0. - Fix nasty socket leak. - Merge with inadyn-advanced (http://sf.net/projects/inadyn-advanced): - Add support for 3322.org and easydns.org - Add support for domain wildcarding, --wildcard option. NOTE: Domain wildcarding is now *disabled* by default. - Add support for running an external command hook on IP update, new --exec option. - Add support for datetime in debug messages. - Refactor DBG_PRINTF((..)) --> logit(..). - Update man page inadyn(8) with info on --bind_interface, --wildcard, --exec options and support for easydns.org and 3322.org services. - Misc fixes and cleanups. Ver. 1.96.2 - 12 March 2007 - Fixes: - If the Dynamic DNS server responds with an error Inadyn will abort. This will prevent further retries with wrong dyndns credentials. - Default port number included in the request, to support the requests via Proxy, to ports different than 80. - Simplified main inadyn update loop function. (there was no bug there) Ver. 1.96 - 9 September 2005 - New features: - zoneedit.com supported. - no-ip.com supported. - support for generic DNS services that support HTTP updates - Fixes: - immediate exit in case of --iterations=1 (not after a sleep period) - added missing option for specifying the path in the DNS server Ver. 1.95 - 20 July 2005 - New features: - UNIX signals supported - inadyn will stop gracefully in case of ALRM, HUP, INT, ... - new dynamic dns service supported - www.zoneedit.com - Not tested! - makefile adjusted for Solaris - compilable under Solaris. - support for generic DYNDNS service that supports update via HTTP with basic authentication not yet fully complete. Not known where might be applicable. Ver. 1.90 - 24 February 2005 - New features/enhancements: - new option '--change_persona uid:gid' - inadyn can switch the user after launch. Typical feature for daemons. - addition to '--ip_server_name' feature, now it has another parameter: the URL to read from the given server name. - reduced some error messages - manual pages updated. (thanks to Shaul Karl) - Bugfixes: - typo fixed (--ip_server_name option) Ver. 1.86 - 30 January 2005 - Updated UNIX man pages for inadyn. Even a page for inadyn.conf! (thanks to Shaul Karl) - Enhancement: - Inadyn doesn't print anything (e.g. ver. number) anymore when goes to background. - new config file parser. Accepts ESCAPE character: '\'. - Bugfix: - Corrected check of the return code from socket() call. Ver. 1.85 - 10 January 2005 - Config file related enhancements: - a default location for the config file in case of no arguments for inadyn - a more **NIX like format for the config file. Thanks to Jerome Benoit. - Small bugfix: - in case when 'iterations' option is specified as being '1', inadyn exits immediately after first update, not after the sleep period as before. Ver. 1.81 - 23 November 2004 No new features. Just a better integration with Linux OS: Reviewed usage of syslog and fork to background in 'daemon mode', thanks to Shaul Karl. Ver. 1.80 - 16 October 2004 - New feature: - syslog: output to syslog for Linux (should work for all **nix systems) - run in background for Linux (should work for all **nix systems) - Minor compile warnings removed. Ver. 1.70 - 5 July 2004 - Bugfix: - custom dns from dyndns option was not accepted by the cmd line parser. "Copy-paste" error :-( ! - New option: - --iterations. Now one can run inadyn with only one iteration. (not tested. It was a debug option now made accessible via cmd line. It should work) Ver. 1.60 - 5 June 2004 On users' request the inadyn can read the options from file. Ver. 1.51 - 3 May 2004 - support for more aliases for DNS service offered by freedns.afraid.org Ver. 1.5 - 1 May 2004 - Support for dynamic DNS service offered by freedns.afraid.org - support for http proxy - GPL Copyright notice added. Ver. 1.4 - 1 March 2004 - Support for custom DNS and static DNS services offered by dyndns.org. - support for forced IP update (so the account will not expire even though the IP never changes) Ver. 1.35 - February 2004 - Bugfixes: - multiple aliases are AGAIN supported - in case of error in IP update the OS signal handler is not installed again. Ver. 1.34 - Various bugfixes. Ver. 1.3 - 6 November 2003 - first port to *NIX - (Linux) - Linux version running OK as console app Future plans: - run as a background daemon in Unix - better interface Ver 1.2 - June 2003 - port to pSOS Note: - no DNS support under pSOS -> hard coded IP addresses of the server Ver. 1.0 - 20 May 2003, first stable version. main features ready: - DYNDNS client - free - works fine behind a NAT router - runs fine as a service - has a nice log file - it is MINE ;) Future plans: - port to *NIX - port to pSOS inadyn-1.99.4/README000077700000000000000000000000001220055527700152372README.mdustar00rootroot00000000000000inadyn-1.99.4/README.md000066400000000000000000000034451220055527700143720ustar00rootroot00000000000000README ====== Inadyn is a simple and small dynamic DNS (DDNS) client written in C. DDNS is a popular service for Internet users with dynamically allocated IP addresses. If your ISP provides you with a DHCP or PPPoE/PPPoA connection you risk losing your IP address every time you reconnect, or in DHCP even when the lease is renegotiated. By using a DDNS client such as inadyn you can register an Internet name at certain providers that the DDNS client updates, periodically and/or on demand when your IP changes. Inadyn can maintain multiple host names with the same IP address, and has a web based IP detection which runs well behind a NAT router. Common DDNS service providers supported by inadyn: * http://www.dyndns.org * http://freedns.afraid.org * http://www.zoneedit.com * http://www.no-ip.com * http://www.easydns.com * http://www.tzo.com * http://www.3322.org * http://www.dnsomatic.com * http://www.tunnelbroker.net * http://dns.he.net/ * http://www.dynsip.org * http://www.sitelutions.com * http://www.dnsexit.com * http://www.changeip.com Some of these services are free of charge for non-commercial use, others take a small fee, but also provide more domains to choose from. Multiple Accounts Support ========================= Inadyn supports updating several DDNS servers, several accounts even on different DDNS providers. The following example config file illustrates how it can be used. Feature is courtesy of [Christian Eyrich](http://eyrich-net.org/programmiertes.html) background verbose 1 logfile /var/log/inadyn.log pidfile /var/run/inadyn.pid system default@dyndns.org username yxxx password xyxx period 300 alias yyyy alias yyyy system default@no-ip.com username xxyx password xxxy period 300 alias yyyy inadyn-1.99.4/bin/000077500000000000000000000000001220055527700136555ustar00rootroot00000000000000inadyn-1.99.4/bin/win32/000077500000000000000000000000001220055527700146175ustar00rootroot00000000000000inadyn-1.99.4/bin/win32/configure_inadyn_service_dyndns.reg000066400000000000000000000004241220055527700237400ustar00rootroot00000000000000REGEDIT4 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\inadyn\Parameters] "Application"="E:\\programs\\dyndns\\inadyn\\inadyn.exe" "AppParameters"="--background -u test -p test --update_period 60000 --alias test.homeip.net --log_file inadyn_srv.log" inadyn-1.99.4/bin/win32/configure_inadyn_service_freedns.reg000066400000000000000000000005021220055527700240640ustar00rootroot00000000000000REGEDIT4 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\inadyn\Parameters] "Application"="E:\\FULL_PATH_TO_INADYN\\inadyn\\inadyn.exe" "AppParameters"="--dyndns_system default@freedns.afraid.org --background --update_period 60000 --alias test.homeip.net,PASTE_HASH_HERE --log_file inadyn_srv.log" inadyn-1.99.4/bin/win32/install_inadyn_service.bat000066400000000000000000000006561220055527700220460ustar00rootroot00000000000000 @echo This batch file installs inadyn as a service. @echo The 'instsrv.exe' and 'srvany.exe' are needed. These are free programs, part of Windows Res Kit CD , but cannot be re-distributed. So one has to download them from Microsoft or other sites: Example: http://www.electrasoft.com/srvany/srvany.htm. See documentation for more details. copy srvany.exe %SystemRoot%\srvany.exe INSTSRV inadyn %SystemRoot%\srvany.exe inadyn-1.99.4/bin/win32/remove_inadyn_service.bat000066400000000000000000000000261220055527700216640ustar00rootroot00000000000000INSTSRV inadyn removeinadyn-1.99.4/config.mk000066400000000000000000000011201220055527700146750ustar00rootroot00000000000000# Oversimplified arch setup, no smart detection. # Possible values: linux, mac, solaris, yourown ifndef TARGET_ARCH TARGET_ARCH = linux endif # Some targets, or older systems, may need -lresolv in EXTRA_LIBS ifeq ($(TARGET_ARCH),solaris) EXTRA_CFLAGS = EXTRA_OBJS = EXTRA_LIBS = -lsocket -lnsl endif ifeq ($(TARGET_ARCH),linux) EXTRA_CFLAGS = EXTRA_OBJS = EXTRA_LIBS = endif ifdef DEBUG EXTRA_CFLAGS += -g endif ifdef V Q = MAKEFLAGS = PRINTF = @true else Q = @ MAKEFLAGS = --silent --no-print-directory PRINTF = @printf endif inadyn-1.99.4/doc/000077500000000000000000000000001220055527700136525ustar00rootroot00000000000000inadyn-1.99.4/doc/Doxyfile000066400000000000000000000135531220055527700153670ustar00rootroot00000000000000PROJECT_NAME = INADYN PROJECT_NUMBER = OUTPUT_DIRECTORY = OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = YES INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = NO TAB_SIZE = 4 ALIASES = obsolete=@deprecated OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES EXTRACT_ALL = NO EXTRACT_PRIVATE = YES EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = YES HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = YES CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = NO GENERATE_TESTLIST = NO GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES QUIET = NO WARNINGS = NO WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES WARN_FORMAT = WARN_LOGFILE = INPUT = ../src FILE_PATTERNS = *.h \ *.cpp \ *.cc \ *.c \ *.hpp \ *.dox \ *.c++ \ *.cxx \ *.h++ \ *.hh RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = *.moc.* \ moc* \ *.all_cpp.* \ *unload.* \ */test/* \ */tests/* \ *_p.h EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_SOURCE_FILES = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = NO REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES VERBATIM_HEADERS = YES ALPHABETICAL_INDEX = YES COLS_IN_ALPHA_INDEX = 3 IGNORE_PREFIX = K GENERATE_HTML = YES HTML_OUTPUT = HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = YES TREEVIEW_WIDTH = 250 GENERATE_LATEX = NO LATEX_OUTPUT = LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO GENERATE_RTF = NO RTF_OUTPUT = COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = GENERATE_MAN = NO MAN_OUTPUT = MAN_EXTENSION = .kde3 MAN_LINKS = YES GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = NO GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = QT_VERSION=320 \ __cplusplus \ Q_WS_X11 EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = NO PERL_PATH = CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = NO HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES UML_LOOK = NO TEMPLATE_RELATIONS = YES INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO GRAPHICAL_HIERARCHY = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 800 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 0 GENERATE_LEGEND = YES DOT_CLEANUP = YES SEARCHENGINE = NO ### KDE Settings ALIASES = \ "intern=\parInternal use only." \ "reimp=\parReimplemented from superclass." \ "obsolete=@deprecated" \ "feature=\xrefitem features \"Feature(s)\" \"Features\"" \ "maintainer=\xrefitem maintainers \"Maintainer(s)\" \"Maintainers\"" \ "unmaintained=\xrefitem unmaintained \"Unmaintained\" \"Unmaintained\"" \ "requirement=\xrefitem requirements \"Requirement(s)\" \"Requirements\"" \ "faq=\xrefitem FAQ \"F.A.Q.\" \"F.A.Q.\"" \ "authors=\xrefitem authors \"Author(s)\" \"Authors\"" \ "FIXME=\xrefitem fixme \"Fixme\" \"Fixme\"" HTML_ALIGN_MEMBERS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO VERBATIM_HEADERS = NO GENERATE_LATEX = NO GENERATE_RTF = NO GENERATE_MAN = NO GENERATE_XML = NO GENERATE_HTML = YES SOURCE_BROWSER = NO GENERATE_AUTOGEN_DEF = NO ENABLE_PREPROCESSING = NO CLASS_DIAGRAMS = NO HAVE_DOT = NO IGNORE_PREFIX = K EXTRACT_ALL = YES inadyn-1.99.4/include/000077500000000000000000000000001220055527700145305ustar00rootroot00000000000000inadyn-1.99.4/include/base64.h000066400000000000000000000052101220055527700157630ustar00rootroot00000000000000/** * \file base64.h * * \brief RFC 1521 base64 encoding/decoding * * Copyright (C) 2006-2010, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef BASE64_H #define BASE64_H #include #define ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ #define ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ /** * \brief Encode a buffer into base64 format * * \param dst destination buffer * \param dlen size of the buffer * \param src source buffer * \param slen amount of data to be encoded * * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. * *dlen is always updated to reflect the amount * of data that has (or would have) been written. * * \note Call this function with *dlen = 0 to obtain the * required buffer size in *dlen */ int base64_encode( unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen ); /** * \brief Decode a base64-formatted buffer * * \param dst destination buffer * \param dlen size of the buffer * \param src source buffer * \param slen amount of data to be decoded * * \return 0 if successful, POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL, or * POLARSSL_ERR_BASE64_INVALID_DATA if the input data is not * correct. *dlen is always updated to reflect the amount * of data that has (or would have) been written. * * \note Call this function with *dlen = 0 to obtain the * required buffer size in *dlen */ int base64_decode( unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen ); #endif /* base64.h */ inadyn-1.99.4/include/debug_if.h000066400000000000000000000031741220055527700164520ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ /* Copyright (C) 2003-2006 INAtech Author: Narcis Ilisei */ /* custom error logging system */ #ifndef _DEBUG_IF_INCLUDED #define _DEBUG_IF_INCLUDED #include #include "os.h" typedef struct { int level; int verbose; char p_logfilename[1024]; FILE *p_file; } DBG_TYPE; /** Returns the dbg destination. DBG_SYS_LOG for SysLog DBG_STD_LOG for standard console */ DBG_DEST get_dbg_dest(void); void set_dbg_dest(DBG_DEST dest); /** A printf function that may print to syslog if that is activated. */ void os_printf(int prio, char *fmt, ... ); #ifndef DBG_PRINT_DISABLED # ifndef logit # ifndef PSOS_OS # define logit(prio, fmt, args...) os_printf(prio, fmt, ##args) # else # define _BMC_MOD_DEBUG 1 # include # endif # endif #else # define logit(fmt, args...) #endif #endif /* _DEBUG_IF_INCLUDED */ inadyn-1.99.4/include/dyndns.h000066400000000000000000000273641220055527700162140ustar00rootroot00000000000000/* Interface for main ddns functions * * Copyright (C) 2003-2004 Narcis Ilisei * Copyright (C) 2006 Steve Horbachuk * * 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. */ #ifndef _DYNDNS_INCLUDED #define _DYNDNS_INCLUDED #include "os.h" #include "errorcode.h" #include "http_client.h" #include "debug_if.h" #define DYNDNS_VERSION_STRING "Inadyn version " VERSION_STRING " -- Dynamic DNS update client." #define DYNDNS_AGENT_NAME "inadyn/" VERSION_STRING #define DYNDNS_EMAIL_ADDR "troglobit@gmail.com" typedef enum { DYNDNS_DEFAULT, FREEDNS_AFRAID_ORG_DEFAULT, ZONE_EDIT_DEFAULT, CUSTOM_HTTP_BASIC_AUTH, NOIP_DEFAULT, EASYDNS_DEFAULT, TZO_DEFAULT, DYNDNS_3322_DYNAMIC, SITELUTIONS_DOMAIN, DNSOMATIC_DEFAULT, DNSEXIT_DEFAULT, HE_IPV6TB, HE_DYNDNS, CHANGEIP_DEFAULT, DYNSIP_DEFAULT, LAST_DNS_SYSTEM = -1 } DYNDNS_SYSTEM_ID; /*test values*/ #define DYNDNS_DEFAULT_DEBUG_LEVEL 1 #define DYNDNS_DEFAULT_CONFIG_FILE "/etc/inadyn.conf" #define DYNDNS_RUNTIME_DATA_DIR "/var/run/inadyn" #define DYNDNS_DEFAULT_CACHE_FILE DYNDNS_RUNTIME_DATA_DIR"/inadyn.cache" #define DYNDNS_CACHE_FILE DYNDNS_RUNTIME_DATA_DIR"/%s.cache" #define DYNDNS_DEFAULT_PIDFILE DYNDNS_RUNTIME_DATA_DIR"/inadyn.pid" #define DYNDNS_MY_IP_SERVER "checkip.dyndns.org" #define DYNDNS_MY_IP_SERVER_URL "/" /*REQ/RSP definitions*/ #define DYNDNS_DEFAULT_DNS_SYSTEM DYNDNS_DEFAULT /* Conversation with the IP server */ #define DYNDNS_GET_IP_HTTP_REQUEST \ "GET %s HTTP/1.0\r\n" \ "Host: %s\r\n" \ "User-Agent: " DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR "\r\n\r\n" #define GENERIC_HTTP_REQUEST \ "GET %s HTTP/1.0\r\n" \ "Host: %s\r\n" \ "User-Agent: " DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR "\r\n\r\n" #define GENERIC_AUTH_HTTP_REQUEST \ "GET %s HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Authorization: Basic %s\r\n" \ "User-Agent: " DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR "\r\n\r\n" /* dyndns.org specific update address format * 3322.org has the same parameters ... */ #define DYNDNS_UPDATE_IP_HTTP_REQUEST \ "GET %s?" \ "hostname=%s&" \ "myip=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Authorization: Basic %s\r\n" \ "User-Agent: " DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR "\r\n\r\n" /* freedns.afraid.org specific update request format */ #define FREEDNS_UPDATE_IP_REQUEST \ "GET %s?" \ "%s&" \ "address=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" /** generic update format for sites that perform the update with: http://some.address.domain/somesubdir ?some_param_name=MY_ALIAS and then the normal http stuff and basic base64 encoded auth. The parameter here is the entire request but NOT including the alias. */ #define GENERIC_BASIC_AUTH_UPDATE_IP_REQUEST \ "GET %s" \ "%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Authorization: Basic %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" #define ZONEEDIT_UPDATE_IP_REQUEST \ "GET %s?" \ "host=%s&" \ "dnsto=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Authorization: Basic %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" /* dont ask me why easydns is so picky * http://support.easydns.com/tutorials/dynamicUpdateSpecs.php */ #define EASYDNS_UPDATE_IP_REQUEST \ "GET %s?" \ "hostname=%s&" \ "myip=%s&" \ "wildcard=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Authorization: Basic %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" /* tzo doesnt encode password */ #define TZO_UPDATE_IP_REQUEST \ "GET %s?" \ "tzoname=%s&" \ "email=%s&" \ "tzokey=%s&" \ "ipaddress=%s&" \ "system=tzodns&" \ "info=1 " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" /* sitelutions.com specific update address format */ #define SITELUTIONS_UPDATE_IP_HTTP_REQUEST \ "GET %s?" \ "user=%s&" \ "pass=%s&" \ "id=%s&" \ "ip=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" #define DNSEXIT_UPDATE_IP_HTTP_REQUEST \ "GET %s?" \ "login=%s&" \ "password=%s&" \ "host=%s&" \ "myip=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" /* HE tunnelbroker.com specific update request format */ #define HE_IPV6TB_UPDATE_IP_REQUEST \ "GET %s?" \ "ip=%s&" \ "apikey=%s&" \ "pass=%s&" \ "tid=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "User-Agent: "DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR"\r\n\r\n" #define CHANGEIP_UPDATE_IP_HTTP_REQUEST \ "GET %s?" \ "system=dyndns&" \ "hostname=%s&" \ "myip=%s " \ "HTTP/1.0\r\n" \ "Host: %s\r\n" \ "Authorization: Basic %s\r\n" \ "User-Agent: " DYNDNS_AGENT_NAME " " DYNDNS_EMAIL_ADDR "\r\n\r\n" /* Some default configurations */ #define DYNDNS_DEFAULT_SLEEP (120) /* sec */ #define DYNDNS_MIN_SLEEP (30) /* sec */ #define DYNDNS_MAX_SLEEP (10 * 24 * 3600) /* 10 days in sec */ #define DYNDNS_ERROR_UPDATE_PERIOD (600) /* 10 min */ #define DYNDNS_FORCED_UPDATE_PERIOD (30 * 24 * 3600) /* 30 days in sec */ #define DYNDNS_DEFAULT_CMD_CHECK_PERIOD (1) /* sec */ #define DYNDNS_DEFAULT_ITERATIONS 0 /* Forever */ #define DYNDNS_HTTP_RESPONSE_BUFFER_SIZE (2500) /* Bytes */ #define DYNDNS_HTTP_REQUEST_BUFFER_SIZE (2500) /* Bytes */ #define DYNDNS_MAX_ALIAS_NUMBER 10 /* maximum number of aliases per server that can be maintained */ #define DYNDNS_MAX_SERVER_NUMBER 5 /* maximum number of servers that can be maintained */ /* local configs */ #define DYNDNS_MY_IP_ADDRESS_LENGTH 20 /* chars */ #define DYNDNS_MY_USERNAME_LENGTH 50 /* chars */ #define DYNDNS_MY_PASSWORD_LENGTH 50 /* chars */ #define DYNDNS_SERVER_NAME_LENGTH 256 /* chars */ #define DYNDNS_SERVER_URL_LENGTH 256 /* chars */ #define IP_V4_MAX_LENGTH 16 /* chars: nnn.nnn.nnn.nnn\0 */ /* typedefs */ struct _DYN_DNS_CLIENT; struct DYNDNS_SYSTEM; /* Types used for DNS system specific configuration */ /* Function to prepare DNS system specific server requests */ typedef int (*DNS_SYSTEM_REQUEST_FUNC)(struct _DYN_DNS_CLIENT *this, int infnr, int alnr); typedef RC_TYPE (*DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)(struct _DYN_DNS_CLIENT *this, HTTP_TRANSACTION *p_tr, int infnr); typedef struct { const char* p_key; DNS_SYSTEM_SRV_RESPONSE_OK_FUNC p_rsp_ok_func; DNS_SYSTEM_REQUEST_FUNC p_dns_update_req_func; const char *p_ip_server_name; const char *p_ip_server_url; const char *p_dyndns_server_name; const char *p_dyndns_server_url; } DYNDNS_SYSTEM; typedef struct { DYNDNS_SYSTEM_ID id; DYNDNS_SYSTEM system; } DYNDNS_SYSTEM_INFO; typedef enum { NO_CMD = 0, CMD_STOP = 1, CMD_RESTART = 2, } DYN_DNS_CMD; typedef struct { char my_username[DYNDNS_MY_USERNAME_LENGTH]; char my_password[DYNDNS_MY_PASSWORD_LENGTH]; char *p_enc_usr_passwd_buffer; int size; BOOL encoded; } DYNDNS_CREDENTIALS; typedef struct { char name[DYNDNS_SERVER_NAME_LENGTH]; int port; } DYNDNS_SERVER_NAME; typedef struct { DYNDNS_SERVER_NAME names; int update_required; } DYNDNS_ALIAS_INFO; typedef struct { BOOL my_ip_has_changed; DYNDNS_SERVER_NAME my_ip_address; DYNDNS_CREDENTIALS credentials; DYNDNS_SYSTEM *p_dns_system; DYNDNS_SERVER_NAME dyndns_server_name; /* Address of DDNS update service */ char dyndns_server_url[DYNDNS_SERVER_URL_LENGTH]; DYNDNS_SERVER_NAME ip_server_name; /* Address of "What's my IP" checker */ char ip_server_url[DYNDNS_SERVER_URL_LENGTH]; DYNDNS_SERVER_NAME proxy_server_name; DYNDNS_ALIAS_INFO alias_info[DYNDNS_MAX_ALIAS_NUMBER]; int alias_count; BOOL wildcard; } DYNDNS_INFO_TYPE; typedef struct { uid_t uid; gid_t gid; } USER_INFO; typedef struct DYN_DNS_CLIENT { char *cfgfile; char *pidfile; char *external_command; DYN_DNS_CMD cmd; int sleep_sec; /* time between 2 updates*/ int normal_update_period_sec; int error_update_period_sec; int forced_update_period_sec; int time_since_last_update; int cmd_check_period; /*time to wait for a command*/ int total_iterations; int num_iterations; char *cache_file; char *bind_interface; char *check_interface; BOOL initialized; BOOL run_in_background; BOOL debug_to_syslog; BOOL change_persona; BOOL test_update; HTTP_CLIENT http_to_ip_server[DYNDNS_MAX_SERVER_NUMBER]; HTTP_CLIENT http_to_dyndns[DYNDNS_MAX_SERVER_NUMBER]; HTTP_TRANSACTION http_tr; char *p_work_buffer; /* for HTTP responses*/ int work_buffer_size; char *p_req_buffer; /* for HTTP requests*/ int req_buffer_size; USER_INFO sys_usr_info; /* info about the current account running inadyn */ DYNDNS_INFO_TYPE info[DYNDNS_MAX_SERVER_NUMBER]; /* servers, names, passwd */ int info_count; BOOL abort_on_network_errors; BOOL force_addr_update; BOOL use_proxy; BOOL abort; DBG_TYPE dbg; } DYN_DNS_CLIENT; /*public functions*/ /** Returns the table of supported dyndns systems */ DYNDNS_SYSTEM_INFO* get_dyndns_system_table(void); /** * Returns the default DYNDNS client config data. */ RC_TYPE get_default_config_data(DYN_DNS_CLIENT *p_self); /* Set up all details: - ip server name - dns server name - username, passwd - ... Implementation: - load defaults - parse cmd line - assign settings that may change due to cmd line options - check data */ RC_TYPE get_config_data(DYN_DNS_CLIENT *p_self, int argc, char** argv); /* printout of version */ void dyn_dns_print_hello(void); /* basic resource allocations for the dyn_dns object */ RC_TYPE dyn_dns_construct(DYN_DNS_CLIENT **pp_self); /* Resource free. */ RC_TYPE dyn_dns_destruct(DYN_DNS_CLIENT *p_self); /* Sets up the object. - sets the IPs of the DYN DNS server - ... */ RC_TYPE dyn_dns_init(DYN_DNS_CLIENT *p_self); /* Disconnect and some other clean up. */ RC_TYPE dyn_dns_shutdown(DYN_DNS_CLIENT *p_self); /* the real action: - detect current IP - connect to an HTTP server - parse the response for IP addr - for all the names that have to be maintained - get the current DYN DNS address from DYN DNS server - compare and update if neccessary */ RC_TYPE dyn_dns_update_ip(DYN_DNS_CLIENT *p_self); /* MAIN - Dyn DNS update entry point.*/ /* Actions: - read the configuration options - create and init dyn_dns object. - launch the IP update action */ int dyn_dns_main(DYN_DNS_CLIENT *p_self, int argc, char* argv[]); /* help. */ void print_help_page(void); /* main entry point */ int inadyn_main(int argc, char* argv[]); #endif /*_DYNDNS_INCLUDED*/ /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/include/errorcode.h000066400000000000000000000045731220055527700166760ustar00rootroot00000000000000/* Error code definitions * * Copyright (C) 2003-2004 Narcis Ilisei * * 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. */ #ifndef _ERRORCODE_INCLUDED #define _ERRORCODE_INCLUDED typedef enum { RC_OK = 0, RC_ERROR = 1, RC_INVALID_POINTER = 2, RC_OUT_OF_MEMORY = 3, RC_OUT_BUFFER_OVERFLOW = 4, RC_IP_SOCKET_CREATE_ERROR = 0x10, RC_IP_BAD_PARAMETER = 0x11, RC_IP_INVALID_REMOTE_ADDR = 0x12, RC_IP_CONNECT_FAILED = 0x13, RC_IP_SEND_ERROR = 0x14, RC_IP_RECV_ERROR = 0x15, RC_IP_OBJECT_NOT_INITIALIZED = 0x16, RC_IP_OS_SOCKET_INIT_FAILED = 0x17, RC_IP_SOCKET_BIND_ERROR = 0x18, RC_TCP_OBJECT_NOT_INITIALIZED = 0x20, RC_HTTP_OBJECT_NOT_INITIALIZED = 0x30, RC_HTTP_BAD_PARAMETER = 0x31, RC_DYNDNS_BUFFER_TOO_SMALL = 0x40, RC_DYNDNS_INVALID_IP_ADDR_IN_HTTP_RESPONSE = 0x41, RC_DYNDNS_INVALID_RSP_FROM_IP_SERVER = 0x42, RC_DYNDNS_TOO_MANY_ALIASES = 0x43, RC_DYNDNS_INVALID_OPTION = 0x44, RC_DYNDNS_INVALID_OR_MISSING_PARAMETERS = 0x45, RC_DYNDNS_UNRESOLVED_ALIAS = 0x46, RC_DYNDNS_INVALID_DNS_SYSTEM_DEFAULT = 0x47, RC_DYNDNS_RSP_NOTOK = 0x48, RC_DYNDNS_RSP_RETRY_LATER = 0x49, RC_CMD_PARSER_INVALID_OPTION = 0x50, RC_CMD_PARSER_INVALID_OPTION_ARGUMENT = 0x51, RC_OS_ERROR_INSTALLING_SIGNAL_HANDLER = 0x60, RC_OS_INVALID_IP_ADDRESS = 0x61, RC_OS_FORK_FAILURE = 0x62, RC_OS_CHANGE_PERSONA_FAILURE = 0x63, RC_OS_INVALID_UID = 0x64, RC_OS_INVALID_GID = 0x65, RC_FILE_IO_OPEN_ERROR = 0x70, RC_FILE_IO_READ_ERROR = 0x71, RC_FILE_IO_OUT_OF_BUFFER = 0x72, RC_RESTART = 0xff, } RC_TYPE; const char* errorcode_get_name(RC_TYPE rc); #endif /* ERRORCODE_INCLUDED */ /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/include/get_cmd.h000066400000000000000000000036411220055527700163070ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ /* Interface functions for CMD options parsing system Author: Narcis Ilisei Date: May 2003 History: - may 15 2003 : first version. Basic, table driven option line parsing. */ #ifndef _GET_CMD_IF_INCLUDED #define _GET_CMD_IF_INCLUDED #include "errorcode.h" typedef struct { int argc; char **argv; } CMD_DATA; typedef RC_TYPE (*CMD_OPTION_HANDLER_FUNC)(CMD_DATA *p_cmd, int current_nr, void *p_context); typedef struct { CMD_OPTION_HANDLER_FUNC p_func; void *p_context; } CMD_OPTION_HANDLER_TYPE; typedef struct { char *p_option; int arg_nr; CMD_OPTION_HANDLER_TYPE p_handler; char *p_description; } CMD_DESCRIPTION_TYPE; /* Parses the incoming argv list data. Arguments: argv, argc, cmd description Action: performs a match for every p_option string in the CMD description. checks the number of arguments left calls the user handler with the pointer to the correct arguments */ RC_TYPE get_cmd_parse_data(char **argv, int argc, CMD_DESCRIPTION_TYPE *p_cmd_descr); /** Adds a new option (string) to the command line */ RC_TYPE cmd_add_val(CMD_DATA *p_cmd, char *p_val); #endif /*_GET_CMD_IF_INCLUDED*/ inadyn-1.99.4/include/http_client.h000066400000000000000000000045601220055527700172230ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ /*interface for http_client */ #ifndef _HTTP_CLIENT_H_INCLUDED #define _HTTP_CLIENT_H_INCLUDED #include "os.h" #include "errorcode.h" #include "tcp.h" /* SOME DEFAULT CONFIGURATIONS */ #define HTTP_DEFAULT_TIMEOUT 10000 /*ms*/ #define HTTP_DEFAULT_PORT 80 typedef struct { TCP_SOCKET super; BOOL initialized; } HTTP_CLIENT; typedef struct { char *p_req; int req_len; char *p_rsp; int max_rsp_len; int rsp_len; char *p_rsp_body; int status; char status_desc[256]; } HTTP_TRANSACTION; /*public functions*/ /* basic resource allocations for the tcp object */ RC_TYPE http_client_construct(HTTP_CLIENT *p_self); /* Resource free. */ RC_TYPE http_client_destruct(HTTP_CLIENT *p_self, int num); /* Sets up the object. - ... */ RC_TYPE http_client_init(HTTP_CLIENT *p_self, char *msg); /* Disconnect and some other clean up. */ RC_TYPE http_client_shutdown(HTTP_CLIENT *p_self); /* Send req and get response */ RC_TYPE http_client_transaction(HTTP_CLIENT *p_self, HTTP_TRANSACTION *p_tr ); /* Accessors */ RC_TYPE http_client_set_port(HTTP_CLIENT *p_self, int p); RC_TYPE http_client_set_remote_name(HTTP_CLIENT *p_self, const char* p); RC_TYPE http_client_set_remote_addr(HTTP_CLIENT *p_self, const char* p); RC_TYPE http_client_set_remote_timeout(HTTP_CLIENT *p_self, int t); RC_TYPE http_client_set_bind_iface(HTTP_CLIENT *p_self, char *ifname); RC_TYPE http_client_get_port(HTTP_CLIENT *p_self, int *p_port); RC_TYPE http_client_get_remote_name(HTTP_CLIENT *p_self, const char* *p); RC_TYPE http_client_get_remote_timeout(HTTP_CLIENT *p_self, int *p); RC_TYPE http_client_get_bind_iface(HTTP_CLIENT *p_self, char **ifname); #endif /*_HTTP_CLIENT_H_INCLUDED*/ inadyn-1.99.4/include/ip.h000066400000000000000000000051261220055527700153150ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ /* interface for tcp functions */ #ifndef _IP_H_INCLUDED #define _IP_H_INCLUDED #include "os.h" #include "errorcode.h" /* SOME DEFAULT CONFIGURATIONS */ #define IP_DEFAULT_TIMEOUT 20000 /* ms */ #define IP_SOCKET_MAX_PORT 65535 #define IP_DEFAULT_READ_CHUNK_SIZE 100 /* typedefs */ typedef enum { TYPE_TCP = 0, TYPE_UDP } IP_TYPES; typedef struct { BOOL initialized; char *ifname; BOOL bound; /* When bound to an interface */ int type; SOCKET socket; struct sockaddr_in local_addr; struct sockaddr remote_addr; socklen_t remote_len; const char *p_remote_host_name; unsigned short port; int timeout; } IP_SOCKET; /*public functions*/ /* basic resource allocations for the object */ RC_TYPE ip_construct(IP_SOCKET *p_self); /* Resource free . */ RC_TYPE ip_destruct(IP_SOCKET *p_self); /* Sets up the object. - ... */ RC_TYPE ip_initialize(IP_SOCKET *p_self); /* Disconnect and some other clean up. */ RC_TYPE ip_shutdown(IP_SOCKET *p_self); /* send data*/ RC_TYPE ip_send(IP_SOCKET *p_self, const char *p_buf, int len); /* receive data*/ RC_TYPE ip_recv(IP_SOCKET *p_self, char *p_buf, int max_recv_len, int *p_recv_len); /*Accessors */ RC_TYPE ip_set_port(IP_SOCKET *p_self, int p); RC_TYPE ip_set_remote_name(IP_SOCKET *p_self, const char *p); RC_TYPE ip_set_remote_timeout(IP_SOCKET *p_self, int t); RC_TYPE ip_set_bind_iface(IP_SOCKET *p_self, char *ifname); RC_TYPE ip_get_port(IP_SOCKET *p_self, int *p_port); RC_TYPE ip_get_remote_name(IP_SOCKET *p_self, const char **p); RC_TYPE ip_get_remote_timeout(IP_SOCKET *p_self, int *p); RC_TYPE ip_get_bind_iface(IP_SOCKET *p_self, char **ifname); #endif /*_IP_H_INCLUDED*/ /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/include/md5.h000066400000000000000000000042271220055527700153730ustar00rootroot00000000000000/** * \file md5.h * * \brief MD5 message digest algorithm (hash function) * * Copyright (C) 2006-2010, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef MD5_H #define MD5_H #include /** * \brief MD5 context structure */ typedef struct { unsigned long total[2]; /*!< number of bytes processed */ unsigned long state[4]; /*!< intermediate digest state */ unsigned char buffer[64]; /*!< data block being processed */ } md5_context; /** * \brief MD5 context setup * * \param ctx context to be initialized */ void md5_starts( md5_context *ctx ); /** * \brief MD5 process buffer * * \param ctx MD5 context * \param input buffer holding the data * \param ilen length of the input data */ void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ); /** * \brief MD5 final digest * * \param ctx MD5 context * \param output MD5 checksum result */ void md5_finish( md5_context *ctx, unsigned char output[16] ); /** * \brief Output = MD5( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output MD5 checksum result */ void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); #endif /* md5.h */ inadyn-1.99.4/include/os.h000066400000000000000000000132601220055527700153240ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * Copyright (C) 2006 Steve Horbachuk * * 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. */ #ifndef _OS_H_INCLUDED #define _OS_H_INCLUDED /* Include the correct headers for each OS. TODO Note: This is a very thin and hacked way of supporting multiple OSes. Must be another way of doing it. */ #define OS_DEF_OK 0 #ifdef _WIN32 #include #undef OS_DEF_OK #define OS_DEF_OK 1 #ifndef BOOL #define BOOL WINBOOL #define HAVE_OS_BOOL 1 #endif #endif #ifdef RMC_DEBUG_VERSION #undef OS_DEF_OK #define OS_DEF_OK 1 #define PSOS_OS 1 #include #include #define HAVE_OS_BOOL 1 #include #include "psos_net.h" #endif #if OS_DEF_OK == 0 /*default to Unix*/ #define UNIX_OS 1 #define HAVE_OS_SYSLOG 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef int SOCKET; #define closesocket close #define FAR #endif #ifndef IN_PRIVATE #define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) || \ ((addr & 0xfff00000) == 0xac100000) || \ ((addr & IN_CLASSB_NET) == 0xc0a80000)) #endif #ifndef IN_LINKLOCAL #define IN_LINKLOCALNETNUM 0xa9fe0000 #define IN_LINKLOCAL(addr) ((addr & IN_CLASSB_NET) == IN_LINKLOCALNETNUM) #endif #ifndef IN_LOOPBACK #define IN_LOOPBACK(addr) ((addr & IN_CLASSA_NET) == 0x7f000000) #endif #ifndef IN_ZERONET #define IN_ZERONET(addr) ((addr & IN_CLASSA_NET) == 0) #endif #ifndef __TIMESTAMP__ #define __TIMESTAMP__ "0" #endif #ifdef __cplusplus extern "C" { #endif /*real begin */ #include "errorcode.h" #ifndef FALSE #define FALSE (1 == 0) #define TRUE !FALSE #endif #ifndef HAVE_OS_BOOL typedef int BOOL; #endif #ifndef UNIX_OS typedef unsigned int uid_t; typedef unsigned int gid_t; #endif /* general defines */ #ifndef SOCKET_ERROR #define SOCKET_ERROR (-1) #endif #define IP_V4_IP_ADDR_FORMAT "%u.%u.%u.%u" /** Syslog support */ #ifndef HAVE_OS_SYSLOG #define LOG_EMERG 0 /* system is unusable */ #define LOG_ALERT 1 /* action must be taken immediately */ #define LOG_CRIT 2 /* critical conditions */ #define LOG_ERR 3 /* error conditions */ #define LOG_WARNING 4 /* warning conditions */ #define LOG_NOTICE 5 /* normal but significant condition */ #define LOG_INFO 6 /* informational */ #define LOG_DEBUG 7 /* debug-level messages */ #endif typedef enum { OS_CTRL_C_SIGNAL = 0, OS_CTRL_CLOSE_SIGNAL = 1, OS_CTRL_BREAK_SIGNAL = 2, OS_CTRL_LOGOFF_SIGNAL = 3, OS_CTRL_SHUTDOWN_SIGNAL = 4, LAST_SIGNAL = -1 } OS_SIGNALS; typedef struct { OS_SIGNALS signal; void *p_in_data; void *p_out_data; } OS_SIGNAL_TYPE; typedef int (*OS_SIGNAL_HANDLER_FUNC) (OS_SIGNAL_TYPE, void*); typedef struct { OS_SIGNAL_HANDLER_FUNC p_func; void *p_in_data; } OS_SIGNAL_HANDLER_TYPE; typedef struct { uid_t uid; gid_t gid; } OS_USER_INFO; RC_TYPE os_change_persona(OS_USER_INFO *p_usr_info); /* Blocks a thread the specified number of milliseconds*/ void os_sleep_ms(int ms); /* returns the last error that happend in the os ip_support */ int os_get_socket_error (void); /* NETWORK SUPPORT*/ /* Socket system start */ RC_TYPE os_ip_support_startup(void); /* Socket system stop*/ RC_TYPE os_ip_support_cleanup(void); /* OS SIGNALS */ RC_TYPE os_install_signal_handler(void*); /* MAIN - Dyn DNS update entry point.*/ int inadyn_main(int argc, char* argv[]); /* Threads */ typedef struct { void (*p_func) (void*); void *p_params; int priority; unsigned int nStackSize; unsigned int dwCreateFlags; } OS_THREAD_TYPE; int thread_start(OS_THREAD_TYPE *p_thread); /* console */ RC_TYPE close_console_window(void); typedef enum { DBG_STD_LOG, /*stdout*/ DBG_SYS_LOG, /*syslog, for Unix only*/ DBG_FILE_LOG /*file output*/ } DBG_DEST; /** * Opens the dbg output for the required destination. * */ RC_TYPE os_open_dbg_output(DBG_DEST dest, const char *p_prg_name, const char *p_logfile_name); /** * Closes the dbg output device. */ RC_TYPE os_close_dbg_output(void); /** * Opens the system's syslog. The prg name is what will be printed before every message. */ RC_TYPE os_syslog_open(const char *p_prg_name); RC_TYPE os_syslog_close(void); /** * Execute command on successful update. */ RC_TYPE os_shell_execute(char *p_cmd, char *ip, char *hostname, char *iface); #ifdef __cplusplus } #endif #endif /* _OS_H_INCLUDED */ inadyn-1.99.4/include/psos_net.h000066400000000000000000000026251220055527700165400ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ #ifndef _PSOS_OS_H_INCLUDED #define _PSOS_OS_H_INCLUDED #include "os.h" #ifdef PSOS_OS #include typedef int SOCKET; #define closesocket close #define connect(in_socket, in_sock_addr, in_addrlen) \ connect(in_socket, (struct sockaddr_in*) (in_sock_addr), in_addrlen) #define FAR typedef struct hostent { char FAR * h_name; char FAR * FAR * h_aliases; short h_addrtype; short h_length; char FAR * FAR * h_addr_list; } HOSTENT; /* dummy */ struct hostent FAR *gethostbyname(const char FAR *name ); #endif #endif /*_PSOS_OS_H_INCLUDED*/inadyn-1.99.4/include/sha1.h000066400000000000000000000042521220055527700155400ustar00rootroot00000000000000/** * \file sha1.h * * \brief SHA-1 cryptographic hash function * * Copyright (C) 2006-2010, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef SHA1_H #define SHA1_H #include /** * \brief SHA-1 context structure */ typedef struct { unsigned long total[2]; /*!< number of bytes processed */ unsigned long state[5]; /*!< intermediate digest state */ unsigned char buffer[64]; /*!< data block being processed */ } sha1_context; /** * \brief SHA-1 context setup * * \param ctx context to be initialized */ void sha1_starts( sha1_context *ctx ); /** * \brief SHA-1 process buffer * * \param ctx SHA-1 context * \param input buffer holding the data * \param ilen length of the input data */ void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); /** * \brief SHA-1 final digest * * \param ctx SHA-1 context * \param output SHA-1 checksum result */ void sha1_finish( sha1_context *ctx, unsigned char output[20] ); /** * \brief Output = SHA-1( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output SHA-1 checksum result */ void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); #endif /* sha1.h */ inadyn-1.99.4/include/tcp.h000066400000000000000000000042751220055527700154770ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ /* interface for tcp functions */ #ifndef _TCP_H_INCLUDED #define _TCP_H_INCLUDED #include "os.h" #include "errorcode.h" #include "ip.h" /* SOME DEFAULT CONFIGURATIONS */ #define TCP_DEFAULT_TIMEOUT 20000 /*ms*/ typedef struct { IP_SOCKET super; BOOL initialized; } TCP_SOCKET; typedef struct { TCP_SOCKET super; } TCP_CLIENT_SOCKET; /*public functions*/ /* basic resource allocations for the tcp object */ RC_TYPE tcp_construct(TCP_SOCKET *p_self); /* Resource free. */ RC_TYPE tcp_destruct(TCP_SOCKET *p_self); /* Sets up the object. - ... */ RC_TYPE tcp_initialize(TCP_SOCKET *p_self, char *msg); /* Disconnect and some other clean up. */ RC_TYPE tcp_shutdown(TCP_SOCKET *p_self); /* send data*/ RC_TYPE tcp_send(TCP_SOCKET *p_self, const char *p_buf, int len); /* receive data*/ RC_TYPE tcp_recv(TCP_SOCKET *p_self, char *p_buf, int max_recv_len, int *p_recv_len); /* Accessors */ RC_TYPE tcp_set_port(TCP_SOCKET *p_self, int p); RC_TYPE tcp_set_remote_name(TCP_SOCKET *p_self, const char* p); RC_TYPE tcp_set_remote_timeout(TCP_SOCKET *p_self, int t); RC_TYPE tcp_set_bind_iface(TCP_SOCKET *p_self, char *ifname); RC_TYPE tcp_get_port(TCP_SOCKET *p_self, int *p_port); RC_TYPE tcp_get_remote_name(TCP_SOCKET *p_self, const char* *p); RC_TYPE tcp_get_remote_timeout(TCP_SOCKET *p_self, int *p); RC_TYPE tcp_get_bind_iface(TCP_SOCKET *p_self, char **ifname); #endif /*_TCP_H_INCLUDED*/ inadyn-1.99.4/man/000077500000000000000000000000001220055527700136605ustar00rootroot00000000000000inadyn-1.99.4/man/inadyn.8000066400000000000000000000211401220055527700152310ustar00rootroot00000000000000.\" -*- nroff -*- .\" .\" Process this file with .\" groff -man -Tascii foo.1 .\" .\" Copyright 2004, by Shaul Karl. .\" Copyright 2010, by Joachim Nilsson. .\" .\" You may modify and distribute this document for any purpose, as .\" long as this copyright notice remains intact. .\" .Dd October 31, 2010 .Dt INADYN 8 SMM .Os .Sh NAME .Nm inadyn .Nd a small DDNS client to maintain your presence on the Internet .Sh SYNOPSIS .Nm inadyn .Bk .Op Fl a, -alias Ar ALIAS Ns Op , Ns Ar HASH .Op Fl b, -background .Op Fl B, -bind Ar IFNAME .Op Fl d, -drop-privs Ar USER Ns Op : Ns Ar GROUP .Op Fl e, -exec Ar SCRIPT .Op Fl f, -forced-update Ar SEC .Op Fl F, -config Ar FILE .Op Fl L, -logfile Ar FILE .Op Fl P, -pidfile Ar FILE .Op Fl c, -cachefile Ar FILE .Op Fl s, -syslog .Op Fl h, -help .Op Fl i, -iface Ar IFNAME .Op Fl n, -iterations Ar NUM .Op Fl H, -checkip-url Ar SERVER Ns Oo : Ns Ar PORT Oc Ar URL .Op Fl N, -server-name Ar SERVER Ns Op : Ns Ar PORT .Op Fl U, -server-url Ar PATH .Op Fl S, -system Ar PROVIDER .Op Fl t, -test .Op Fl T, -period Ar SEC .Op Fl u, -username Ar USERNAME .Op Fl p, -password Ar PASSWORD .Op Fl v, -version .Op Fl V, -verbose Ar LEVEL .Op Fl w, -wildcard .Op Fl x, -proxy-server Ar SERVER Ns Op : Ns Ar PORT .Ek .Sh DESCRIPTION .Nm inadyn is a client for .Dq open name servers, also known as DDNS service providers. That is, it lets you have a public Internet name for your DHCP/PPPoE assigned system. Some of these services are free of charge for non-commercial use, others take a small fee, but also provide more domains to choose from. .Pp Common DDNS service providers supported by .Nm inadyn : .Bl -bullet -compact .It http://www.dyndns.org .It http://freedns.afraid.org .It http://zoneedit.com .It http://www.no-ip.com .It http://www.easydns.com .It http://www.tzo.com .It http://www.3322.org .It http://www.dnsomatic.com .It http://www.tunnelbroker.net .It http://dns.he.net/ .It http://www.dynsip.org .It http://www.sitelutions.com .It http://www.dnsexit.com .It http://www.changeip.com .El .Pp The basic operation of .Nm inadyn is to periodically check whether the actual Internet accessible IP of your system is the same one that is recorded in the name server, and update the name server records when there is a mismatch. .Sh OPTIONS .Bl -tag -width Ds .It Fl h, -help Print a summary of the options and exit. .It Fl u, -username Ar USERNAME The username, if applicable. This might be referred to as hash. .It Fl p, -password Ar PASSWORD The password, if applicable. .It Fl a, -alias Ar ALIAS A host name alias. This option can appear multiple times, for each domain that has the same IP. .It Fl F, -config Ar FILE The file name that contains .Nm inadyn command options exactly as specified in the command line syntax (adds to those already present on the cmd line). The default configuration file name, .Pa /etc/inadyn.conf , is looked at automatically if .Nm inadyn is called without any command line options. The format is as expected for a UNIX config file; the hash character is used to comment entire lines. Spaces are ingored. The long options may be specified without \-\- if placed at the beginning of the line. .It Fl H, -checkip-url Ar SERVER Ns Oo : Ns Ar PORT Oc Ar URL The client IP is detected by calling .Ar URL from this .Ar SERVER Ns Oo : Ns Ar PORT Oc . Defaults to http://checkip.dyndns.org. .It Fl N, -server-name Ar SERVER Ns Op : Ns Ar PORT The server that receives the update DNS requests. When no proxy is specified it is sufficient to set the .Fl -system option so that the default servers will be taken. The option is useful for generic DynDNS services that support HTTP update. .It Fl U, -server-url Ar PATH The update path on the DynDNS server. .It Fl S, -system Ar email@ddns-service.tld DNS service to connect to. Defaults to .Ar default@dyndns.org . .Bl -tag -width TERM -compact -offset indent .It Cm default@dyndns.org http://www.dyndns.org .It Cm default@freedns.afraid.org http://freedns.afraid.org .It Cm default@zoneedit.com http://zoneedit.com .It Cm default@no-ip.com http://www.no-ip.com .It Cm default@easydns.com http://www.easydns.com .It Cm default@tzo.com http://www.tzo.com .It Cm dyndns@3322.org http://www.3322.org .It Cm default@dnsomatic.com http://www.dnsomatic.com .It Cm ipv6tb@he.net http://www.tunnelbroker.net .It Cm dyndns@he.net http://dns.he.net/ .It Cm default@dynsip.org http://www.dynsip.org .It Cm default@sitelutions.com http://www.sitelutions.com .It Cm default@dnsexit.com http://www.dnsexit.com .It Cm default@changeip.com http://www.changeip.com .It Cm custom@http_svr_basic_auth .El .It Fl x, -proxy-server Ar SERVER Ns Op : Ns Ar PORT HTTP proxy server name and port. Default: N/A. .It Fl T, -period Ar SEC How often the IP is checked, in seconds. Default: apx 1 minute. Max: 10 days. .It Fl f, -forced-update Ar SEC How often the IP should be updated even if it is not changed. The time should be given in seconds. .It Fl -L, -logfile Ar FILE The name, including the full path, of a log file. See also the .Fl --syslog option, below. .It Fl b, -background Run in background. Output is sent to the UNIX syslog facilities or to a log file, if one was specified. .It Fl V, -verbose Ar LEVEL Set the debug level, which is an integer between .Ar 0 to .Ar 5 . .It Fl n, -iterations Ar NUM Set the number of DNS updates. The default is .Ar 0 , which means infinity. .It Fl s, -syslog Use the system .Xr syslog 3 mechanism for log messages, warnings and error conditions. .It Fl d, -drop-privs Ar USER Ns Op : Ns Ar GROUP Drop privileges after initial setup to the given user and group. .It Fl B, -bind Ar IFNAME Set interface to bind to. Only on UNIX systems. .It Fl i, -iface Ar IFNAME Set interface to check for IP. Only on UNIX systems. External IP check is not performed. .It Fl P, -pidfile Ar FILE Set pidfile, defaults to .Pa /var/run/inadyn/inadyn.pid . .It Fl c, -cachefile Ar FILE Set cachefile, defaults to .Pa /var/run/inadyn/inadyn.cache . .It Fl e, -exec Ar SCRIPT Full path to external command, or script, to run after a successful DDNS update. .Ar SCRIPT can use following environment variables: INADYN_IP, INADYN_HOSTNAME. First environment variable contains new IP address, second one - host name alias. INADYN_IFACE is available, if .Fl -iface option used. .It Fl w, -wildcard Enable domain name wildcarding for easydns.com. Default disabled. For .Nm inadyn < 1.96.3 wildcarding was enabled by default. .It Fl t, -test Force one update and quit. .El .Sh "TYPICAL USAGE" .Ss http://www.dyndns.org .Nm inadyn .No -u username -p password -a my.registered.name .Pp .Nm inadyn .No --username username --password password --period 60 .No --alias test.homeip.net --alias my.second.domain .Pp .Nm inadyn .No --background -u test -p test --period 60 .No --alias test.homeip.net --alias my.second.domain .No --logfile inadyn_srv.log .Ss http://freedns.afraid.org .Nm inadyn .No --system default@freedns.afraid.org .No -u username -p password -a my.registrated.name .Pp .Nm inadyn .No -u username -p password .No --period 60 --alias test.homeip.net .No -a my.second.domain --system default@freedns.afraid.org .Pp The .Dq hash is automatically retrieved by .Nm inadyn using freedns API. .Sh OUTPUT .Nm inadyn prints a message when the IP is updated. If no update is needed then by default it prints a single .Dq .\& character, unless .Fl -verbose is set to .Ar 0 . Therefore, unless .Fl -verbose is set to .Ar 0 , the log file will contains lot of dots. When the connection goes down it could be that .Nm inadyn will print some error messages. Those are harmless and should be followed by .Dq OK messages after the connection is back up. .Sh SIGNALS .Nm responds to the following signals: .Pp .Bl -tag -width TERM -compact .It HUP Restarts .Nm . The configuration file is reread every time this signal is evoked. It is also useful when a new DHCP/PPPoE lease or new gateway is received. Please note that .Nm does not track such events by itself. You need an external monitor for that. .It TERM Terminates .Nm gracefully. .It INT The same as TERM. .It QUIT The same as TERM. .El .Pp For convenience in sending signals, .Nm writes its process ID to .Pa /var/run/inadyn/inadyn.pid upon startup. .Sh FILES .Bl -tag -width /var/tmp/pimd.cache -compact .It Pa /etc/inadyn.conf .It Pa /var/run/inadyn/inadyn.cache .It Pa /var/run/inadyn/inadyn.pid .El .Sh SEE ALSO .Xr inadyn.conf 5 .br The .Nm inadyn home page is http://github.com/troglobit/inadyn .Sh AUTHORS .Nm inadyn was written by .An -nosplit .An Narcis Ilisei Aq inarcis2002@hotpop.com , .An Steve Horbachuk and later .An Joachim Nilsson Aq troglobit@gmail.com . .Pp This manual page was initially written for the .Em Debian GNU/Linux system by .An Shaul Karl Aq shaul@debian.org . Later Joachim Nilsson picked up maintenance. inadyn-1.99.4/man/inadyn.conf.5000066400000000000000000000033211220055527700161530ustar00rootroot00000000000000.\" -*- nroff -*- .\" .\" Process this file with .\" groff -man -Tascii foo.1 .\" .\" Copyright 2005, by Shaul Karl. .\" Copyright 2010, by Joachim Nilsson. .\" .\" You may modify and distribute this document for any purpose, as .\" long as this copyright notice remains intact. .\" .Dd October 31, 2010 .Dt INADYN 5 SMM .Os .Sh NAME .Nm inadyn.conf .Nd inadyn DDNS client configuration file .Sh SYNOPSIS .Nm /etc/inadyn.conf .Sh DESCRIPTION .Nm inadyn can read the very same command line options from a configuration file. This feature allows the user to write the options only once, and avoids frequent retyping. .Pp The format of the file follows the UN*X tradition: .Bl -bullet -offset abcd .It The .Dq #\& character denotes a comment. .It Long options (those with .Dq \-\- in front) can also be placed at the beginning of the line without .Dq \-\- signs. .It The \\ character can be used as an escape character. .El .Sh EXAMPLES .Ss 1. Config file with long options # Some comments about the inadyn conf file .br \-\-username test .br \-\-password test .br \-\-period 60 .br \-\-alias test.homeip.net .br \-\-alias my.second.domain .Ss 2. Config file without Dq \-\- username test # user .br password test .br period 60 # some other param without '\-\-' .br alias test.homeip.net .Sh "SEE ALSO" .Xr inadyn 8 .Ss "Internet resources" The .Nm inadyn home page is http://github.com/troglobit/inadyn .Sh AUTHORS .Nm inadyn was written by .An -nosplit .An Narcis Ilisei Aq inarcis2002@hotpop.com , .An Steve Horbachuk and later .An Joachim Nilsson Aq troglobit@gmail.com . .Pp This manual page was initially written for the .Em Debian GNU/Linux system by .An Shaul Karl Aq shaul@debian.org . Later Joachim Nilsson picked up maintenance. inadyn-1.99.4/src/000077500000000000000000000000001220055527700136745ustar00rootroot00000000000000inadyn-1.99.4/src/base64.c000066400000000000000000000114521220055527700151270ustar00rootroot00000000000000/* * RFC 1521 base64 encoding/decoding * * Copyright (C) 2006-2010, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "base64.h" static const unsigned char base64_enc_map[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; static const unsigned char base64_dec_map[128] = { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 127, 127, 127, 127, 127 }; /* * Encode a buffer into base64 format */ int base64_encode( unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen ) { size_t i, n; int C1, C2, C3; unsigned char *p; if( slen == 0 ) return( 0 ); n = (slen << 3) / 6; switch( (slen << 3) - (n * 6) ) { case 2: n += 3; break; case 4: n += 2; break; default: break; } if( *dlen < n + 1 ) { *dlen = n + 1; return( ERR_BASE64_BUFFER_TOO_SMALL ); } n = (slen / 3) * 3; for( i = 0, p = dst; i < n; i += 3 ) { C1 = *src++; C2 = *src++; C3 = *src++; *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; *p++ = base64_enc_map[C3 & 0x3F]; } if( i < slen ) { C1 = *src++; C2 = ((i + 1) < slen) ? *src++ : 0; *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; if( (i + 1) < slen ) *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; else *p++ = '='; *p++ = '='; } *dlen = p - dst; *p = 0; return( 0 ); } /* * Decode a base64-formatted buffer */ int base64_decode( unsigned char *dst, size_t *dlen, const unsigned char *src, size_t slen ) { size_t i, j, n; unsigned long x; unsigned char *p; for( i = j = n = 0; i < slen; i++ ) { if( ( slen - i ) >= 2 && src[i] == '\r' && src[i + 1] == '\n' ) continue; if( src[i] == '\n' ) continue; if( src[i] == '=' && ++j > 2 ) return( ERR_BASE64_INVALID_CHARACTER ); if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) return( ERR_BASE64_INVALID_CHARACTER ); if( base64_dec_map[src[i]] < 64 && j != 0 ) return( ERR_BASE64_INVALID_CHARACTER ); n++; } if( n == 0 ) return( 0 ); n = ((n * 6) + 7) >> 3; if( *dlen < n ) { *dlen = n; return( ERR_BASE64_BUFFER_TOO_SMALL ); } for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) { if( *src == '\r' || *src == '\n' ) continue; j -= ( base64_dec_map[*src] == 64 ); x = (x << 6) | ( base64_dec_map[*src] & 0x3F ); if( ++n == 4 ) { n = 0; if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); if( j > 2 ) *p++ = (unsigned char)( x ); } } *dlen = p - dst; return( 0 ); } inadyn-1.99.4/src/dyndns.c000066400000000000000000001312751220055527700153500ustar00rootroot00000000000000/* DDNS client updater main implementation file * * Copyright (C) 2003-2004 Narcis Ilisei * Copyright (C) 2006 Steve Horbachuk * * 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. */ #define MODULE_TAG "" #include #include #include #include #include #include #include #include #include #include "dyndns.h" #include "debug_if.h" #include "base64.h" #include "md5.h" #include "sha1.h" #include "get_cmd.h" #define MD5_DIGEST_BYTES (16) #define SHA1_DIGEST_BYTES (20) /* To preserve from being reset at SIGHUP */ static int cached_time_since_last_update = 0; static int cached_num_iterations = 0; static int get_req_for_dyndns_server(DYN_DNS_CLIENT *this, int infcnt, int alcnt); static int get_req_for_freedns_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_generic_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_zoneedit_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_easydns_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_tzo_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_sitelutions_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_dnsexit_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_he_ipv6tb_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt); static int get_req_for_changeip_server(DYN_DNS_CLIENT *this, int infcnt, int alcnt); static RC_TYPE is_dyndns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_freedns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_generic_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_zoneedit_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_easydns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_tzo_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_sitelutions_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_dnsexit_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); static RC_TYPE is_he_ipv6_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infcnt); DYNDNS_SYSTEM_INFO dns_system_table[] = { {DYNDNS_DEFAULT, {"default@dyndns.org", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_dyndns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC)get_req_for_dyndns_server, DYNDNS_MY_IP_SERVER, DYNDNS_MY_IP_SERVER_URL, "members.dyndns.org", "/nic/update"}}, {FREEDNS_AFRAID_ORG_DEFAULT, {"default@freedns.afraid.org", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_freedns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_freedns_server, DYNDNS_MY_IP_SERVER, DYNDNS_MY_IP_SERVER_URL, "freedns.afraid.org", "/dynamic/update.php"}}, {ZONE_EDIT_DEFAULT, {"default@zoneedit.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_zoneedit_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_zoneedit_server, "dynamic.zoneedit.com", "/checkip.html", "dynamic.zoneedit.com", "/auth/dynamic.html"}}, {NOIP_DEFAULT, {"default@no-ip.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_dyndns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_dyndns_server, "ip1.dynupdate.no-ip.com", "/", "dynupdate.no-ip.com", "/nic/update"}}, {EASYDNS_DEFAULT, {"default@easydns.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_easydns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_easydns_server, DYNDNS_MY_IP_SERVER, DYNDNS_MY_IP_SERVER_URL, "members.easydns.com", "/dyn/dyndns.php"}}, {TZO_DEFAULT, {"default@tzo.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_tzo_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_tzo_server, "echo.tzo.com", "/", "rh.tzo.com", "/webclient/tzoperl.html"}}, {DYNDNS_3322_DYNAMIC, {"dyndns@3322.org", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_dyndns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_dyndns_server, "bliao.com", "/ip.phtml", "members.3322.org", "/dyndns/update"}}, {SITELUTIONS_DOMAIN, {"default@sitelutions.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_sitelutions_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC)get_req_for_sitelutions_server, DYNDNS_MY_IP_SERVER, DYNDNS_MY_IP_SERVER_URL, "www.sitelutions.com", "/dnsup"}}, {DNSOMATIC_DEFAULT, {"default@dnsomatic.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_dyndns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_dyndns_server, "myip.dnsomatic.com", "/", "updates.dnsomatic.com", "/nic/update"}}, {DNSEXIT_DEFAULT, {"default@dnsexit.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_dnsexit_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_dnsexit_server, "ip.dnsexit.com", "/", "update.dnsexit.com", "/RemoteUpdate.sv"}}, {HE_IPV6TB, {"ipv6tb@he.net", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_he_ipv6_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_he_ipv6tb_server, "checkip.dns.he.net", "/", "ipv4.tunnelbroker.net", "/ipv4_end.php"}}, {HE_DYNDNS, {"dyndns@he.net", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC) is_dyndns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_dyndns_server, "checkip.dns.he.net", "/", "dyn.dns.he.net", "/nic/update"}}, {CHANGEIP_DEFAULT, {"default@changeip.com", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC) is_dyndns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_changeip_server, "ip.changeip.com", "/", "nic.changeip.com", "/nic/update"}}, /* Support for dynsip.org by milkfish, from DD-WRT */ {DYNSIP_DEFAULT, {"default@dynsip.org", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_dyndns_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC)get_req_for_dyndns_server, DYNDNS_MY_IP_SERVER, DYNDNS_MY_IP_SERVER_URL, "dynsip.org", "/nic/update"}}, {CUSTOM_HTTP_BASIC_AUTH, {"custom@http_srv_basic_auth", (DNS_SYSTEM_SRV_RESPONSE_OK_FUNC)is_generic_server_rsp_ok, (DNS_SYSTEM_REQUEST_FUNC) get_req_for_generic_server, DYNDNS_MY_IP_SERVER, DYNDNS_MY_IP_SERVER_URL, "", ""}}, {LAST_DNS_SYSTEM, {NULL, NULL, NULL, NULL, NULL, NULL, NULL}} }; static DYNDNS_SYSTEM* get_dns_system_by_id(DYNDNS_SYSTEM_ID id) { DYNDNS_SYSTEM_INFO *it; for (it = dns_system_table; it->id != LAST_DNS_SYSTEM; ++it) { if (it->id == id) { return &it->system; } } return NULL; } DYNDNS_SYSTEM_INFO* get_dyndns_system_table(void) { return dns_system_table; } /*************PRIVATE FUNCTIONS ******************/ static RC_TYPE dyn_dns_wait_for_cmd(DYN_DNS_CLIENT *p_self) { int counter; DYN_DNS_CMD old_cmd; if (p_self == NULL) { return RC_INVALID_POINTER; } old_cmd = p_self->cmd; if (old_cmd != NO_CMD) { return RC_OK; } counter = p_self->sleep_sec / p_self->cmd_check_period; while (counter --) { if (p_self->cmd != old_cmd) { break; } os_sleep_ms(p_self->cmd_check_period * 1000); } return RC_OK; } static RC_TYPE is_http_status_code_ok(int status) { if (status == 200) return RC_OK; else if (status >= 500 && status < 600) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; } static int get_req_for_dyndns_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, DYNDNS_UPDATE_IP_HTTP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name, p_self->info[infcnt].credentials.p_enc_usr_passwd_buffer); } static int get_req_for_freedns_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { RC_TYPE rc = RC_OK, rc2; HTTP_CLIENT http_to_dyndns; HTTP_TRANSACTION http_tr; char buffer[256]; unsigned char digestbuf[SHA1_DIGEST_BYTES]; char digeststr[SHA1_DIGEST_BYTES*2+1]; int i; char *buf, *tmp, *line; char host[256], updateurl[256]; char *hash = NULL; if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } // I know it's ugly, http client needs redesign. do { if ((rc = http_client_construct(&http_to_dyndns)) != RC_OK) break; http_client_set_port(&http_to_dyndns, p_self->info[infcnt].dyndns_server_name.port); http_client_set_remote_name(&http_to_dyndns, p_self->info[infcnt].dyndns_server_name.name); http_client_set_bind_iface(&http_to_dyndns, p_self->bind_interface); if ((rc = http_client_init(&http_to_dyndns, "Sending update URL query")) != RC_OK) break; snprintf(buffer, sizeof(buffer), "%s|%s", p_self->info[infcnt].credentials.my_username, p_self->info[infcnt].credentials.my_password); sha1((unsigned char *)buffer, strlen(buffer), digestbuf); for (i = 0; i < SHA1_DIGEST_BYTES; i++) sprintf(&digeststr[i*2], "%02x", digestbuf[i]); snprintf(buffer, sizeof(buffer), "/api/?action=getdyndns&sha=%s", digeststr); http_tr.req_len = sprintf(p_self->p_req_buffer, GENERIC_HTTP_REQUEST, buffer, p_self->info[infcnt].dyndns_server_name.name); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1; /* Save place for a \0 at the end */ http_tr.rsp_len = 0; rc = http_client_transaction(&http_to_dyndns, &http_tr); http_tr.p_rsp[http_tr.rsp_len] = 0; rc2 = http_client_shutdown(&http_to_dyndns); http_client_destruct(&http_to_dyndns, 1); if (rc != RC_OK || rc2 != RC_OK) break; if ((rc = is_http_status_code_ok(http_tr.status)) != RC_OK) break; tmp = buf = strdup(http_tr.p_rsp_body); for (line = strsep(&tmp, "\n"); line; line = strsep(&tmp, "\n")) { if (*line && sscanf(line, "%255[^|\r\n]|%*[^|\r\n]|%255[^|\r\n]", host, updateurl) == 2 && !strcmp(host, p_self->info[infcnt].alias_info[alcnt].names.name)) { hash = strstr(updateurl, "?"); break; } } free(buf); if (!hash) rc = RC_DYNDNS_RSP_NOTOK; } while (0); if (rc != RC_OK) { logit(LOG_INFO, MODULE_TAG "Update URL query failed"); return 0; } return sprintf(p_self->p_req_buffer, FREEDNS_UPDATE_IP_REQUEST, p_self->info[infcnt].dyndns_server_url, hash, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name); } static int get_req_for_generic_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, GENERIC_BASIC_AUTH_UPDATE_IP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].dyndns_server_name.name, p_self->info[infcnt].credentials.p_enc_usr_passwd_buffer); } static int get_req_for_zoneedit_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, ZONEEDIT_UPDATE_IP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name, p_self->info[infcnt].credentials.p_enc_usr_passwd_buffer); } static int get_req_for_easydns_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, EASYDNS_UPDATE_IP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].wildcard ? "ON" : "OFF", p_self->info[infcnt].dyndns_server_name.name, p_self->info[infcnt].credentials.p_enc_usr_passwd_buffer); } static int get_req_for_tzo_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, TZO_UPDATE_IP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].credentials.my_username, p_self->info[infcnt].credentials.my_password, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name); } static int get_req_for_sitelutions_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, SITELUTIONS_UPDATE_IP_HTTP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].credentials.my_username, p_self->info[infcnt].credentials.my_password, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name); } static int get_req_for_dnsexit_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, DNSEXIT_UPDATE_IP_HTTP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].credentials.my_username, p_self->info[infcnt].credentials.my_password, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name); } static int get_req_for_he_ipv6tb_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { unsigned char digestbuf[MD5_DIGEST_BYTES]; char digeststr[MD5_DIGEST_BYTES*2+1]; int i; if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } md5((unsigned char *)p_self->info[infcnt].credentials.my_password, strlen(p_self->info[infcnt].credentials.my_password), digestbuf); for (i = 0; i < MD5_DIGEST_BYTES; i++) sprintf(&digeststr[i*2], "%02x", digestbuf[i]); return sprintf(p_self->p_req_buffer, HE_IPV6TB_UPDATE_IP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].credentials.my_username, digeststr, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].dyndns_server_name.name); } static int get_req_for_changeip_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, CHANGEIP_UPDATE_IP_HTTP_REQUEST, p_self->info[infcnt].dyndns_server_url, p_self->info[infcnt].alias_info[alcnt].names.name, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name, p_self->info[infcnt].credentials.p_enc_usr_passwd_buffer); } /* Get the IP address from interface */ static RC_TYPE do_ip_check_interface(DYN_DNS_CLIENT *p_self) { struct ifreq ifr; in_addr_t new_ip; char *new_ip_str; int i; if (p_self == NULL) { return RC_INVALID_POINTER; } if (p_self->check_interface) { logit(LOG_INFO, MODULE_TAG "Checking for IP# change, querying interface %s", p_self->check_interface); int sd = socket(PF_INET, SOCK_DGRAM, 0); if (sd < 0) { int code = os_get_socket_error(); logit(LOG_WARNING, MODULE_TAG "Failed opening network socket: %s", strerror(code)); return RC_IP_OS_SOCKET_INIT_FAILED; } memset(&ifr, 0, sizeof(struct ifreq)); ifr.ifr_addr.sa_family = AF_INET; snprintf(ifr.ifr_name, IFNAMSIZ, "%s", p_self->check_interface); if (ioctl(sd, SIOCGIFADDR, &ifr) != -1) { new_ip = ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr); new_ip_str = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr); } else { int code = os_get_socket_error(); logit(LOG_ERR, MODULE_TAG "Failed reading IP address of interface %s: %s", p_self->check_interface, strerror(code)); return RC_ERROR; } close(sd); } else { return RC_ERROR; } if (IN_ZERONET(new_ip) || IN_LOOPBACK(new_ip) || IN_LINKLOCAL(new_ip) || IN_MULTICAST(new_ip) || IN_EXPERIMENTAL(new_ip)) { logit(LOG_WARNING, MODULE_TAG "Interface %s has invalid IP# %s", p_self->check_interface, new_ip_str); return RC_ERROR; } int anychange = 0; for (i = 0; i < p_self->info_count; i++) { DYNDNS_INFO_TYPE *info = &p_self->info[i]; info->my_ip_has_changed = strcmp(info->my_ip_address.name, new_ip_str) != 0; if (info->my_ip_has_changed) { anychange++; strcpy(info->my_ip_address.name, new_ip_str); } } if (!anychange) { logit(LOG_INFO, MODULE_TAG "No IP# change detected, still at %s", new_ip_str); } return RC_OK; } static int get_req_for_ip_server(DYN_DNS_CLIENT *p_self, int infcnt) { if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } return sprintf(p_self->p_req_buffer, DYNDNS_GET_IP_HTTP_REQUEST, p_self->info[infcnt].ip_server_url, p_self->info[infcnt].ip_server_name.name); } /* Send req to IP server and get the response */ static RC_TYPE do_ip_server_transaction(DYN_DNS_CLIENT *p_self, int servernum) { RC_TYPE rc = RC_OK; HTTP_CLIENT *p_http; HTTP_TRANSACTION *p_tr; if (p_self == NULL) { return RC_INVALID_POINTER; } p_http = &p_self->http_to_ip_server[servernum]; rc = http_client_init(p_http, "Checking for IP# change"); if (rc != RC_OK) { return rc; } /* Prepare request for IP server */ p_tr = &p_self->http_tr; p_tr->req_len = get_req_for_ip_server(p_self, servernum); if (p_self->dbg.level > 2) { logit(LOG_DEBUG, MODULE_TAG "Querying DDNS server for my public IP#:"); logit(LOG_DEBUG, MODULE_TAG "%s", p_self->p_req_buffer); } p_tr->p_req = (char*) p_self->p_req_buffer; p_tr->p_rsp = (char*) p_self->p_work_buffer; p_tr->max_rsp_len = p_self->work_buffer_size - 1; /* Save place for terminating \0 in string. */ p_tr->rsp_len = 0; rc = http_client_transaction(p_http, &p_self->http_tr); p_tr->p_rsp[p_tr->rsp_len] = 0; if (p_tr->status != 200) rc = RC_DYNDNS_INVALID_RSP_FROM_IP_SERVER; http_client_shutdown(p_http); return rc; } /* Read in 4 integers the ip addr numbers. construct then the IP address from those numbers. Note: it updates the flag: info->'my_ip_has_changed' if the old address was different */ static RC_TYPE do_parse_my_ip_address(DYN_DNS_CLIENT *p_self, int servernum) { int ip1 = 0, ip2 = 0, ip3 = 0, ip4 = 0; int count, i; char *p_ip, *p_current_str; BOOL found; char new_ip_str[IP_V4_MAX_LENGTH]; (void)servernum; if (p_self == NULL || p_self->http_tr.rsp_len <= 0 || p_self->http_tr.p_rsp == NULL) { return RC_INVALID_POINTER; } p_current_str = p_self->http_tr.p_rsp_body; found = FALSE; do { /* Try to find first decimal number (begin of IP) */ p_ip = strpbrk(p_current_str, "0123456789"); if (p_ip != NULL) { /* Maybe I found it? */ count = sscanf(p_ip, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4); if (count != 4 || ip1 <= 0 || ip1 > 255 || ip2 < 0 || ip2 > 255 || ip3 < 0 || ip3 > 255 || ip4 < 0 || ip4 > 255) { p_current_str = p_ip + 1; } else { /* FIRST occurence of a valid IP found */ found = TRUE; break; } } } while (p_ip != NULL); if (found) { int anychange = 0; for (i = 0; i < p_self->info_count; i++) { DYNDNS_INFO_TYPE *info = &p_self->info[i]; sprintf(new_ip_str, "%d.%d.%d.%d", ip1, ip2, ip3, ip4); info->my_ip_has_changed = strcmp(info->my_ip_address.name, new_ip_str) != 0; if (info->my_ip_has_changed) { anychange++; strcpy(info->my_ip_address.name, new_ip_str); } } if (!anychange) { logit(LOG_INFO, MODULE_TAG "No IP# change detected, still at %s", new_ip_str); } return RC_OK; } return RC_DYNDNS_INVALID_RSP_FROM_IP_SERVER; } /* Updates for every maintained name the property: 'update_required'. The property will be checked in another function and updates performed. Action: Check if my IP address has changed. -> ALL names have to be updated. Nothing else. Note: In the update function the property will set to false if update was successful. */ static RC_TYPE do_check_alias_update_table(DYN_DNS_CLIENT *p_self) { int i, j; /* Uses fix test if ip of server 0 has changed. * That should be OK even if changes dyn_dns_update_ip to * iterate over servernum, but not if it's fix set to =! 0 */ if (p_self->info[0].my_ip_has_changed || p_self->force_addr_update || (p_self->time_since_last_update > p_self->forced_update_period_sec)) { for (i = 0; i < p_self->info_count; i++) { DYNDNS_INFO_TYPE *info = &p_self->info[i]; for (j = 0; j < info->alias_count; j++) { info->alias_info[j].update_required = TRUE; logit(LOG_WARNING, MODULE_TAG "Update needed for alias %s, new IP# %s", info->alias_info[j].names.name, info->my_ip_address.name); } } } return RC_OK; } /* DynDNS org.specific response validator. 'good' or 'nochg' are the good answers, */ static RC_TYPE is_dyndns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; char *p_rsp = p_tr->p_rsp_body; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, "good") != NULL || strstr(p_rsp, "nochg") != NULL) return RC_OK; else if (strstr(p_rsp, "dnserr") != NULL || strstr(p_rsp, "911") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; } /* Freedns afraid.org.specific response validator. ok blabla and n.n.n.n fail blabla and n.n.n.n are the good answers. We search our own IP address in response and that's enough. */ static RC_TYPE is_freedns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { char *p_rsp = p_tr->p_rsp_body; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, p_self->info[infnr].my_ip_address.name) != NULL) return RC_OK; else return RC_DYNDNS_RSP_NOTOK; } /** generic http dns server ok parser parses a given string. If found is ok, Example : 'SUCCESS CODE=' */ static RC_TYPE is_generic_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; char *p_rsp = p_tr->p_rsp_body; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, "OK") != NULL) return RC_OK; else return RC_DYNDNS_RSP_NOTOK; } /** the OK codes are: CODE=200, 201 CODE=707, for duplicated updates */ static RC_TYPE is_zoneedit_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; int code = -1; sscanf(p_tr->p_rsp_body, "%*s CODE=\"%d\" ", &code); switch (code) { case 200: case 201: case 707: // is 707 really ok?? return RC_OK; default: return RC_DYNDNS_RSP_NOTOK; } } /** NOERROR is the OK code here */ static RC_TYPE is_easydns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; char *p_rsp = p_tr->p_rsp_body; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, "NOERROR") != NULL) return RC_OK; else if (strstr(p_rsp, "TOOSOON") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; } /* TZO specific response validator. */ static RC_TYPE is_tzo_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; int code = -1; sscanf(p_tr->p_rsp_body, "%d ", &code); switch (code) { case 200: case 304: return RC_OK; case 414: case 500: return RC_DYNDNS_RSP_RETRY_LATER; default: return RC_DYNDNS_RSP_NOTOK; } } static RC_TYPE is_sitelutions_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; char *p_rsp = p_tr->p_rsp_body; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, "success") != NULL) return RC_OK; else if (strstr(p_rsp, "dberror") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; } static RC_TYPE is_dnsexit_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; int code = -1; char *tmp; if ((tmp = strstr(p_tr->p_rsp_body, "\n")) != NULL) sscanf(++tmp, "%d=", &code); switch (code) { case 0: case 1: return RC_OK; case 4: case 11: return RC_DYNDNS_RSP_RETRY_LATER; default: return RC_DYNDNS_RSP_NOTOK; } } /* HE ipv6 tunnelbroker specific response validator. own IP address and 'already in use' are the good answers. */ static RC_TYPE is_he_ipv6_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { char *p_rsp = p_tr->p_rsp_body; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, p_self->info[infnr].my_ip_address.name) != NULL || strstr(p_rsp, "-ERROR: This tunnel is already associated with this IP address.") != NULL) return RC_OK; else return RC_DYNDNS_RSP_NOTOK; } static RC_TYPE do_update_alias_table(DYN_DNS_CLIENT *p_self) { int i, j; RC_TYPE rc = RC_OK, rc2; HTTP_TRANSACTION http_tr; int anychange = 0; for (i = 0; i < p_self->info_count; i++) { DYNDNS_INFO_TYPE *info = &p_self->info[i]; for (j = 0; j < info->alias_count; j++) { if (info->alias_info[j].update_required != TRUE) { continue; } rc = http_client_init(&p_self->http_to_dyndns[i], "Sending IP# update to DDNS server"); if (rc != RC_OK) { break; } /* Build dyndns transaction */ http_tr.req_len = info->p_dns_system->p_dns_update_req_func( (struct _DYN_DNS_CLIENT*) p_self, i, j); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1; /* Save place for a \0 at the end */ http_tr.rsp_len = 0; rc = http_client_transaction(&p_self->http_to_dyndns[i], &http_tr); http_tr.p_rsp[http_tr.rsp_len] = 0; if (p_self->dbg.level > 2) { p_self->p_req_buffer[http_tr.req_len] = 0; logit(LOG_DEBUG, MODULE_TAG "Sending alias table update to DDNS server:"); logit(LOG_DEBUG, MODULE_TAG "%s", p_self->p_req_buffer); } if (rc == RC_OK) { rc = info->p_dns_system->p_rsp_ok_func((struct _DYN_DNS_CLIENT*)p_self, &http_tr, i); if (rc == RC_OK) { info->alias_info[j].update_required = FALSE; logit(LOG_INFO, MODULE_TAG "Successful alias table update for %s => new IP# %s", info->alias_info[j].names.name, info->my_ip_address.name); p_self->time_since_last_update = 0; anychange++; /* Adjust forced update period on success */ } else { logit(LOG_WARNING, MODULE_TAG "%s error in DDNS server response:", rc == RC_DYNDNS_RSP_RETRY_LATER ? "Temporary" : "Fatal"); logit(LOG_WARNING, MODULE_TAG "[%d %s] %s", http_tr.status, http_tr.status_desc, http_tr.p_rsp_body != http_tr.p_rsp ? http_tr.p_rsp_body : ""); } if (p_self->dbg.level > 2) { logit(LOG_DEBUG, MODULE_TAG "DDNS server response:"); logit(LOG_DEBUG, MODULE_TAG "%s", http_tr.p_rsp); } } rc2 = http_client_shutdown(&p_self->http_to_dyndns[i]); if (rc == RC_OK) { /* Only overwrite rc with of http_client_shutdown() rc if previous call, in * e.g., http_client_transaction() or the p_rsp_ok_func() callback was OK. */ rc = rc2; } if (rc != RC_OK) { break; } os_sleep_ms(1000); } } /* Successful change or when cache file does not yet exist! */ if (anychange || access(p_self->cache_file, F_OK)) { FILE *fp; /* Update cache with new IP */ fp = fopen(p_self->cache_file, "w"); if (fp) { fprintf(fp, "%s", p_self->info[0].my_ip_address.name); fclose(fp); } /* Run external command hook on update. */ if (anychange && p_self->external_command) { os_shell_execute(p_self->external_command, p_self->info[0].my_ip_address.name, p_self->info[0].alias_info[0].names.name, p_self->bind_interface); } } return rc; } RC_TYPE get_default_config_data(DYN_DNS_CLIENT *p_self) { RC_TYPE rc = RC_OK; int i; do { p_self->info[0].p_dns_system = get_dns_system_by_id(DYNDNS_DEFAULT_DNS_SYSTEM); if (p_self->info[0].p_dns_system == NULL) { rc = RC_DYNDNS_INVALID_DNS_SYSTEM_DEFAULT; break; } /* forced update period */ p_self->forced_update_period_sec = DYNDNS_FORCED_UPDATE_PERIOD; /* non-fatal error update period */ p_self->error_update_period_sec = DYNDNS_ERROR_UPDATE_PERIOD; /* normal update period */ p_self->normal_update_period_sec = DYNDNS_DEFAULT_SLEEP; p_self->sleep_sec = DYNDNS_DEFAULT_SLEEP; /* Domain wildcarding disabled by default */ for (i = 0; i < DYNDNS_MAX_SERVER_NUMBER; i++) p_self->info[i].wildcard = FALSE; /* pidfile */ p_self->pidfile = strdup(DYNDNS_DEFAULT_PIDFILE); /* Default cache_file is setup in get_config_data() */ } while (0); return rc; } static RC_TYPE get_encoded_user_passwd(DYN_DNS_CLIENT *p_self) { RC_TYPE rc = RC_OK; const char* format = "%s:%s"; char *p_tmp_buff = NULL; int size, actual_len; int i = 0; char *p_b64_buff = NULL; int rc2; do { size_t dlen = 0; DYNDNS_INFO_TYPE *info = &p_self->info[i]; size = strlen(info->credentials.my_password) + strlen(info->credentials.my_username) + strlen(format) + 1; p_tmp_buff = (char *)malloc(size); if (p_tmp_buff == NULL) { info->credentials.encoded = 0; rc = RC_OUT_OF_MEMORY; break; } actual_len = sprintf(p_tmp_buff, format, info->credentials.my_username, info->credentials.my_password); if (actual_len >= size) { info->credentials.encoded = 0; rc = RC_OUT_BUFFER_OVERFLOW; break; } /* query required buffer size for base64 encoded data */ base64_encode(NULL, &dlen, (unsigned char *)p_tmp_buff, strlen(p_tmp_buff)); p_b64_buff = (char *)malloc(dlen); if (p_b64_buff == NULL) { info->credentials.encoded = 0; rc = RC_OUT_OF_MEMORY; break; } /* encode */ rc2 = base64_encode((unsigned char *)p_b64_buff, &dlen, (unsigned char *)p_tmp_buff, strlen(p_tmp_buff)); if (rc2 != 0) { info->credentials.encoded = 0; rc = RC_OUT_BUFFER_OVERFLOW; break; } info->credentials.p_enc_usr_passwd_buffer = p_b64_buff; info->credentials.encoded = 1; info->credentials.size = strlen(info->credentials.p_enc_usr_passwd_buffer); free(p_tmp_buff); p_tmp_buff = NULL; } while (++i < p_self->info_count); if (p_tmp_buff) free(p_tmp_buff); p_tmp_buff = NULL; return rc; } void dyn_dns_print_hello(void) { logit(LOG_INFO, "%s", DYNDNS_VERSION_STRING); } /** basic resource allocations for the dyn_dns object */ RC_TYPE dyn_dns_construct(DYN_DNS_CLIENT **pp_self) { RC_TYPE rc; DYN_DNS_CLIENT *p_self; BOOL http_to_dyndns_constructed = FALSE; BOOL http_to_ip_constructed = FALSE; int i; if (pp_self == NULL) { return RC_INVALID_POINTER; } *pp_self = (DYN_DNS_CLIENT *) malloc(sizeof(DYN_DNS_CLIENT)); if (*pp_self == NULL) { return RC_OUT_OF_MEMORY; } do { p_self = *pp_self; memset(p_self, 0, sizeof(DYN_DNS_CLIENT)); /*alloc space for http_to_ip_server data*/ p_self->work_buffer_size = DYNDNS_HTTP_RESPONSE_BUFFER_SIZE; p_self->p_work_buffer = (char*) malloc(p_self->work_buffer_size); if (p_self->p_work_buffer == NULL) { rc = RC_OUT_OF_MEMORY; break; } /*alloc space for request data*/ p_self->req_buffer_size = DYNDNS_HTTP_REQUEST_BUFFER_SIZE; p_self->p_req_buffer = (char*) malloc(p_self->req_buffer_size); if (p_self->p_req_buffer == NULL) { rc = RC_OUT_OF_MEMORY; break; } i = 0; while (i < DYNDNS_MAX_SERVER_NUMBER) { rc = http_client_construct(&p_self->http_to_ip_server[i++]); if (rc != RC_OK) { rc = RC_OUT_OF_MEMORY; break; } } http_to_ip_constructed = TRUE; i = 0; while (i < DYNDNS_MAX_SERVER_NUMBER) { rc = http_client_construct(&p_self->http_to_dyndns[i++]); if (rc != RC_OK) { rc = RC_OUT_OF_MEMORY; break; } } http_to_dyndns_constructed = TRUE; (p_self)->cmd = NO_CMD; (p_self)->normal_update_period_sec = DYNDNS_DEFAULT_SLEEP; (p_self)->sleep_sec = DYNDNS_DEFAULT_SLEEP; (p_self)->total_iterations = DYNDNS_DEFAULT_ITERATIONS; (p_self)->initialized = FALSE; i = 0; while (i < DYNDNS_MAX_SERVER_NUMBER) { p_self->info[i++].credentials.p_enc_usr_passwd_buffer = NULL; } } while (0); if (rc != RC_OK) { free(*pp_self); free(p_self->p_work_buffer); free (p_self->p_work_buffer); if (http_to_dyndns_constructed) { http_client_destruct(p_self->http_to_dyndns, DYNDNS_MAX_SERVER_NUMBER); } if (http_to_ip_constructed) { http_client_destruct(p_self->http_to_ip_server, DYNDNS_MAX_SERVER_NUMBER); } } return RC_OK; } /** Resource free. */ RC_TYPE dyn_dns_destruct(DYN_DNS_CLIENT *p_self) { int i; RC_TYPE rc; if (p_self == NULL) { return RC_OK; } if (p_self->initialized == TRUE) { dyn_dns_shutdown(p_self); } rc = http_client_destruct(p_self->http_to_ip_server, DYNDNS_MAX_SERVER_NUMBER); if (rc != RC_OK) { /* XXX */ } rc = http_client_destruct(p_self->http_to_dyndns, DYNDNS_MAX_SERVER_NUMBER); if (rc != RC_OK) { /* XXX */ } free(p_self->p_work_buffer); p_self->p_work_buffer = NULL; free(p_self->p_req_buffer); p_self->p_req_buffer = NULL; i = 0; while (i < DYNDNS_MAX_SERVER_NUMBER) { DYNDNS_INFO_TYPE *info = &p_self->info[i]; free(info->credentials.p_enc_usr_passwd_buffer); info->credentials.p_enc_usr_passwd_buffer = NULL; i++; } free(p_self->cfgfile); p_self->cfgfile = NULL; free(p_self->pidfile); p_self->pidfile = NULL; free(p_self->external_command); p_self->external_command = NULL; free(p_self->bind_interface); p_self->bind_interface = NULL; free(p_self->check_interface); p_self->check_interface = NULL; free(p_self->cache_file); p_self->cache_file = NULL; /* Save old value, if restarted by SIGHUP */ cached_time_since_last_update = p_self->time_since_last_update; cached_num_iterations = p_self->num_iterations; free(p_self); p_self = NULL; return RC_OK; } /** Sets up the object. - sets the IPs of the DYN DNS server - if proxy server is set use it! - ... */ RC_TYPE dyn_dns_init(DYN_DNS_CLIENT *p_self) { int i = 0; if (p_self == NULL) { return RC_INVALID_POINTER; } if (p_self->initialized == TRUE) { return RC_OK; } p_self->abort_on_network_errors = FALSE; p_self->force_addr_update = FALSE; do { DYNDNS_INFO_TYPE *info = &p_self->info[i]; if (strlen(info->proxy_server_name.name) > 0) { http_client_set_port(&p_self->http_to_ip_server[i], info->proxy_server_name.port); http_client_set_remote_name(&p_self->http_to_ip_server[i], info->proxy_server_name.name); http_client_set_port(&p_self->http_to_dyndns[i], info->proxy_server_name.port); http_client_set_remote_name(&p_self->http_to_dyndns[i], info->proxy_server_name.name); } else { http_client_set_port(&p_self->http_to_ip_server[i], info->ip_server_name.port); http_client_set_remote_name(&p_self->http_to_ip_server[i], info->ip_server_name.name); http_client_set_port(&p_self->http_to_dyndns[i], info->dyndns_server_name.port); http_client_set_remote_name(&p_self->http_to_dyndns[i], info->dyndns_server_name.name); } http_client_set_bind_iface(&p_self->http_to_dyndns[i], p_self->bind_interface); http_client_set_bind_iface(&p_self->http_to_ip_server[i], p_self->bind_interface); } while (++i < p_self->info_count); p_self->cmd = NO_CMD; if (p_self->cmd_check_period == 0) { p_self->cmd_check_period = DYNDNS_DEFAULT_CMD_CHECK_PERIOD; } /* Reset to old value, if restarted by SIGHUP */ p_self->time_since_last_update = cached_time_since_last_update; p_self->num_iterations = cached_num_iterations; p_self->initialized = TRUE; return RC_OK; } /** Disconnect and some other clean up. */ RC_TYPE dyn_dns_shutdown(DYN_DNS_CLIENT *p_self) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (p_self->initialized == FALSE) { return RC_OK; } return RC_OK; } /** the real action: - increment the forced update times counter - detect current IP - connect to an HTTP server - parse the response for IP addr - for all the names that have to be maintained - get the current DYN DNS address from DYN DNS server - compare and update if neccessary */ RC_TYPE dyn_dns_update_ip(DYN_DNS_CLIENT *p_self) { int servernum = 0; /* server to use for requesting IP */ /*use server 0 by default, should be always exist */ RC_TYPE rc; if (p_self == NULL) { return RC_INVALID_POINTER; } do { if (p_self->check_interface) { rc = do_ip_check_interface(p_self); if (rc != RC_OK) { break; } } else { /* Ask IP server something so he will respond and give me my IP */ rc = do_ip_server_transaction(p_self, servernum); if (rc != RC_OK) { break; } if (p_self->dbg.level > 1) { logit(LOG_DEBUG, MODULE_TAG "IP server response:"); logit(LOG_DEBUG, MODULE_TAG "%s", p_self->p_work_buffer); } /* Extract our IP, check if different than previous one */ rc = do_parse_my_ip_address(p_self, servernum); if (rc != RC_OK) { break; } if (p_self->dbg.level > 1) { logit(LOG_INFO, MODULE_TAG "Current public IP# %s", p_self->info[servernum].my_ip_address.name); } } /* Step through aliases list, resolve them and check if they point to my IP */ rc = do_check_alias_update_table(p_self); if (rc != RC_OK) { break; } /* Update IPs marked as not identical with my IP */ rc = do_update_alias_table(p_self); if (rc != RC_OK) { break; } } while (0); return rc; } /** MAIN - Dyn DNS update entry point Actions: - read the configuration options - perform various init actions as specified in the options - create and init dyn_dns object. - launch the IP update action loop */ int dyn_dns_main(DYN_DNS_CLIENT *p_dyndns, int argc, char* argv[]) { FILE *fp; RC_TYPE rc = RC_OK; int i, s; char name[DYNDNS_SERVER_NAME_LENGTH]; if (p_dyndns == NULL) { return RC_INVALID_POINTER; } /* Create pid and cache file repository. */ mkdir(DYNDNS_RUNTIME_DATA_DIR, 0755); /* read cmd line options and set object properties */ rc = get_config_data(p_dyndns, argc, argv); if (rc != RC_OK || p_dyndns->abort) { return rc; } if (p_dyndns->change_persona) { OS_USER_INFO os_usr_info; memset(&os_usr_info, 0, sizeof(os_usr_info)); os_usr_info.gid = p_dyndns->sys_usr_info.gid; os_usr_info.uid = p_dyndns->sys_usr_info.uid; rc = os_change_persona(&os_usr_info); if (rc != RC_OK) { return rc; } } /* if logfile provided, redirect output to log file */ if (strlen(p_dyndns->dbg.p_logfilename) != 0) { rc = os_open_dbg_output(DBG_FILE_LOG, "", p_dyndns->dbg.p_logfilename); if (rc != RC_OK) { return rc; } } if (p_dyndns->debug_to_syslog == TRUE || (p_dyndns->run_in_background == TRUE)) { if (get_dbg_dest() == DBG_STD_LOG) /* avoid file and syslog output */ { rc = os_open_dbg_output(DBG_SYS_LOG, "inadyn", NULL); if (rc != RC_OK) { return rc; } } } /* if silent required, close console window */ if (p_dyndns->run_in_background == TRUE) { rc = close_console_window(); if (rc != RC_OK) { return rc; } if (get_dbg_dest() == DBG_SYS_LOG) { fclose(stdout); } } /* Create files with permissions 0644 */ umask(S_IWGRP | S_IWOTH); /* write pid file */ fp = fopen(p_dyndns->pidfile, "w"); if (!fp) { logit(LOG_ERR, MODULE_TAG "Failed opening pidfile %s for writing: %s", p_dyndns->pidfile, strerror(errno)); return RC_ERROR; } fprintf(fp, "%u", getpid()); fclose(fp); dyn_dns_print_hello(); /* At boot, or when restarting inadyn at runtime, the memory struct holding * our current IP# is empty. We want to avoid unnecessary updates of our * DDNS server record, since we might get locked out for abuse, so we "seed" * each of the DDNS records of our struct with the cached IP# from our cache * file, or from a regular DNS query. */ fp = fopen(p_dyndns->cache_file, "r"); if (!fp) { struct addrinfo hints; struct addrinfo *result; /* Clear DNS cache before querying for the IP below. */ res_init(); /* Try a DNS lookup of our last known IP#. */ for (i = 0; i < p_dyndns->info_count; i++) { if (p_dyndns->info[i].alias_count && /* exception for tunnelbroker.net - no name to lookup */ strcmp(p_dyndns->info[i].p_dns_system->p_key, "ipv6tb@he.net")) { /* DNS Lookup */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* IPv4 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = 0; hints.ai_protocol = 0; /* Any protocol */ if (!(s = getaddrinfo(p_dyndns->info[i].alias_info[0].names.name, NULL, &hints, &result))) { /* DNS reply for alias found, convert to IP# */ if (!getnameinfo(result->ai_addr, result->ai_addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST)) { /* Update local record for next checkip call. */ strncpy(p_dyndns->info[i].my_ip_address.name, name, sizeof(p_dyndns->info[i].my_ip_address.name)); logit(LOG_INFO, MODULE_TAG "Resolving hostname %s => IP# %s", p_dyndns->info[i].alias_info[0].names.name, name); } freeaddrinfo(result); } else logit(LOG_WARNING, MODULE_TAG "Failed resolving hostname %s: %s", p_dyndns->info[i].alias_info[0].names.name, gai_strerror(s)); } } } else { /* Read cached IP# from inadyn cache file. */ if (fgets(name, sizeof(name), fp)) { logit(LOG_INFO, MODULE_TAG "Cached IP# %s from previous invocation.", name); /* Update local record for next checkip call. */ for (i = 0; i < p_dyndns->info_count; i++) { strncpy(p_dyndns->info[i].my_ip_address.name, name, sizeof(p_dyndns->info[i].my_ip_address.name)); } } fclose(fp); } do { rc = dyn_dns_init(p_dyndns); if (rc != RC_OK) break; rc = get_encoded_user_passwd(p_dyndns); if (rc != RC_OK) break; if (p_dyndns->test_update == TRUE) p_dyndns->force_addr_update = TRUE; /* DDNS client main loop */ while (1) { rc = dyn_dns_update_ip(p_dyndns); if (rc != RC_OK) { if (p_dyndns->cmd == CMD_RESTART) { logit(LOG_DEBUG, "RESTART command received. Restarting."); rc = RC_RESTART; break; } if (rc == RC_DYNDNS_RSP_NOTOK) { logit(LOG_ERR, MODULE_TAG "Error response from DDNS server, exiting!"); break; } } else { /* count only the successful iterations */ p_dyndns->num_iterations ++; } /* check if the user wants us to stop */ if (p_dyndns->total_iterations != 0 && p_dyndns->num_iterations >= p_dyndns->total_iterations) break; p_dyndns->sleep_sec = rc == RC_DYNDNS_RSP_RETRY_LATER ? p_dyndns->error_update_period_sec : p_dyndns->normal_update_period_sec; if (rc != RC_OK) { /* dyn_dns_update_ip() failed above, and we've not reached MAX iterations. * Time to inform the user the (network) error is not fatal and that we * will try again in a short while. */ logit(LOG_WARNING, MODULE_TAG "Will retry again in %d sec...", p_dyndns->sleep_sec); } /* Now sleep a while. Using the time set in sleep_sec data member */ dyn_dns_wait_for_cmd(p_dyndns); if (p_dyndns->cmd == CMD_STOP) { logit(LOG_DEBUG, MODULE_TAG "STOP command received, exiting."); rc = RC_OK; break; } else if (p_dyndns->cmd == CMD_RESTART) { logit(LOG_DEBUG, "RESTART command received, restarting."); rc = RC_RESTART; break; } if (p_dyndns->dbg.level > 0) { logit(LOG_DEBUG, "."); // logit(LOG_DEBUG, "Time since last update: %d", p_dyndns->time_since_last_update); } p_dyndns->time_since_last_update += p_dyndns->sleep_sec; } } while (0); /* if everything ok here we should exit. End of program */ if (rc == RC_OK) { rc = dyn_dns_shutdown(p_dyndns); } return rc; } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/errorcode.c000066400000000000000000000065371220055527700160370ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * * 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. */ #include "errorcode.h" #include typedef struct { RC_TYPE rc; const char *p_name; } ERROR_NAME; static const ERROR_NAME global_error_table[] = { {RC_OK, "RC_OK"}, {RC_ERROR, "RC_ERROR"}, {RC_INVALID_POINTER, "RC_INVALID_POINTER"}, {RC_OUT_OF_MEMORY, "RC_OUT_OF_MEMORY"}, {RC_OUT_BUFFER_OVERFLOW, "RC_OUT_BUFFER_OVERFLOW"}, {RC_IP_SOCKET_CREATE_ERROR, "RC_IP_SOCKET_CREATE_ERROR"}, {RC_IP_BAD_PARAMETER, "RC_IP_BAD_PARAMETER"}, {RC_IP_INVALID_REMOTE_ADDR, "RC_IP_INVALID_REMOTE_ADDR"}, {RC_IP_CONNECT_FAILED, "RC_IP_CONNECT_FAILED"}, {RC_IP_SEND_ERROR, "RC_IP_SEND_ERROR"}, {RC_IP_RECV_ERROR, "RC_IP_RECV_ERROR"}, {RC_IP_OBJECT_NOT_INITIALIZED, "RC_IP_OBJECT_NOT_INITIALIZED"}, {RC_IP_OS_SOCKET_INIT_FAILED, "RC_IP_OS_SOCKET_INIT_FAILED"}, {RC_TCP_OBJECT_NOT_INITIALIZED, "RC_TCP_OBJECT_NOT_INITIALIZED"}, {RC_HTTP_OBJECT_NOT_INITIALIZED, "RC_HTTP_OBJECT_NOT_INITIALIZED"}, {RC_HTTP_BAD_PARAMETER, "RC_HTTP_BAD_PARAMETER"}, {RC_DYNDNS_BUFFER_TOO_SMALL, "RC_DYNDNS_BUFFER_TOO_SMALL"}, {RC_DYNDNS_INVALID_IP_ADDR_IN_HTTP_RESPONSE, "RC_DYNDNS_INVALID_IP_ADDR_IN_HTTP_RESPONSE"}, {RC_DYNDNS_INVALID_RSP_FROM_IP_SERVER, "RC_DYNDNS_INVALID_RSP_FROM_IP_SERVER"}, {RC_DYNDNS_TOO_MANY_ALIASES, "RC_DYNDNS_TOO_MANY_ALIASES"}, {RC_DYNDNS_INVALID_OPTION, "RC_DYNDNS_INVALID_OPTION"}, {RC_DYNDNS_INVALID_OR_MISSING_PARAMETERS, "RC_DYNDNS_INVALID_OR_MISSING_PARAMETERS"}, {RC_DYNDNS_UNRESOLVED_ALIAS, "RC_DYNDNS_UNRESOLVED_ALIAS"}, {RC_DYNDNS_RSP_NOTOK, "RC_DYNDNS_RSP_NOTOK"}, {RC_DYNDNS_RSP_RETRY_LATER, "RC_DYNDNS_RSP_RETRY_LATER"}, {RC_CMD_PARSER_INVALID_OPTION, "RC_CMD_PARSER_INVALID_OPTION"}, {RC_CMD_PARSER_INVALID_OPTION_ARGUMENT, "RC_CMD_PARSER_INVALID_OPTION_ARGUMENT"}, {RC_OS_ERROR_INSTALLING_SIGNAL_HANDLER, "RC_OS_ERROR_INSTALLING_SIGNAL_HANDLER"}, {RC_OS_FORK_FAILURE, "RC_FORK_FAILURE"}, {RC_OS_CHANGE_PERSONA_FAILURE, "RC_OS_CHANGE_PERSONA_FAILURE"}, {RC_OS_INVALID_UID, "RC_OS_INVALID_UID"}, {RC_OS_INVALID_GID, "RC_OS_INVALID_GID"}, {RC_FILE_IO_OPEN_ERROR, "RC_FILE_IO_OPEN_ERROR"}, {RC_FILE_IO_READ_ERROR, "RC_FILE_IO_READ_ERROR"}, {RC_FILE_IO_OUT_OF_BUFFER, "RC_FILE_IO_OUT_OF_BUFFER"}, {RC_OK, NULL} }; static const char *unknown_error = "Unknown error"; const char *errorcode_get_name(RC_TYPE rc) { const ERROR_NAME *it = global_error_table; while (it->p_name != NULL) { if (it->rc == rc) { return it->p_name; } ++it; } return unknown_error; } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/get_cmd.c000066400000000000000000000113001220055527700154350ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ /* Inplementation functions for CMD options parsing system Author: Narcis Ilisei Date: May 2003 History: - may 15 2003 : first version. Basic, table driven option line parsing. */ #define MODULE_TAG "" #include #include #include "get_cmd.h" #include "debug_if.h" static CMD_DESCRIPTION_TYPE * opt_search(CMD_DESCRIPTION_TYPE *p_table, char *p_opt) { CMD_DESCRIPTION_TYPE *it = p_table; while( it->p_option != NULL) { if (strcmp(p_opt, it->p_option) == 0) { return it; } ++it; } return NULL; } /** Init the CMD_DATA */ RC_TYPE cmd_init(CMD_DATA *p_cmd) { if (!p_cmd) { return RC_INVALID_POINTER; } memset(p_cmd, 0, sizeof(*p_cmd)); return RC_OK; } RC_TYPE cmd_destruct(CMD_DATA *p_cmd) { if (!p_cmd) { return RC_INVALID_POINTER; } if (p_cmd->argv) { int i; for (i = 0; i < p_cmd->argc; ++i) { if (p_cmd->argv[i]) { free(p_cmd->argv[i]); } } free(p_cmd->argv); } return RC_OK; } /** Adds a new option (string) to the command line */ RC_TYPE cmd_add_val(CMD_DATA *p_cmd, char *p_val) { RC_TYPE rc = RC_OK; if (!p_cmd || !p_val) { return RC_INVALID_POINTER; } do { char *p; char **pp = (char **)realloc(p_cmd->argv, (p_cmd->argc + 1) * sizeof(char *)); if (!pp) { rc = RC_OUT_OF_MEMORY; break; } p_cmd->argv = pp; p = (char *)malloc(strlen(p_val) + 1); if (!p) { rc = RC_OUT_OF_MEMORY; break; } strcpy(p, p_val); p_cmd->argv[p_cmd->argc] = p; p_cmd->argc ++; } while (0); return rc; } /** Creates a struct of argvals from the given command line. Action: copy the argv from the command line to the given CMD_DATA struct set the data val of the list element to the current argv */ RC_TYPE cmd_add_vals_from_argv(CMD_DATA *p_cmd, char **argv, int argc) { int i; RC_TYPE rc = RC_OK; if (!p_cmd || !argv || !argc) { return RC_INVALID_POINTER; } for (i = 0; i < argc; ++i) { rc = cmd_add_val(p_cmd, argv[i]); if (rc != RC_OK) break; } return rc; } /* Parses the incoming argv list. Arguments: argv, argc, cmd description Action: performs a match for every p_option string in the CMD description. checks the number of arguments left calls the user handler with the pointer to the correct arguments Implementation: - for each option in the table - find it in the argv list - check the required number of arguments - call the handler */ RC_TYPE get_cmd_parse_data(char **argv, int argc, CMD_DESCRIPTION_TYPE *p_cmd_descr) { RC_TYPE rc = RC_OK; CMD_DATA cmd; int curr_arg_nr = 1; /* without the prg name*/ if (argv == NULL || p_cmd_descr == NULL) { return RC_INVALID_POINTER; } do { rc = cmd_init(&cmd); if (rc != RC_OK) { break; } rc = cmd_add_vals_from_argv(&cmd, argv, argc); if (rc != RC_OK) { break; } while (curr_arg_nr < cmd.argc) { CMD_DESCRIPTION_TYPE *p_curr_opt = opt_search(p_cmd_descr, cmd.argv[curr_arg_nr]); if (p_curr_opt == NULL) { rc = RC_CMD_PARSER_INVALID_OPTION; logit(LOG_WARNING, MODULE_TAG "Invalid option name at position %d: %s", curr_arg_nr + 1, cmd.argv[curr_arg_nr]); break; } // logit(LOG_NOTICE, MODULE_TAG "Found opt %d: %s", curr_arg_nr, cmd.argv[curr_arg_nr]); ++curr_arg_nr; /*check arg nr required by the current option*/ if (curr_arg_nr + p_curr_opt->arg_nr > cmd.argc) { rc = RC_CMD_PARSER_INVALID_OPTION_ARGUMENT; logit(LOG_WARNING, MODULE_TAG "Missing option value at position %d: %s", curr_arg_nr + 1, p_curr_opt->p_option); break; } rc = p_curr_opt->p_handler.p_func(&cmd, curr_arg_nr, p_curr_opt->p_handler.p_context); if (rc != RC_OK) { logit(LOG_WARNING, MODULE_TAG "Error parsing option %s", cmd.argv[curr_arg_nr - 1]); break; } curr_arg_nr += p_curr_opt->arg_nr; } } while (0); cmd_destruct(&cmd); return rc; } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/http_client.c000066400000000000000000000122441220055527700163600ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * * 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. */ #include #include "http_client.h" #include "errorcode.h" #define super_construct(p) tcp_construct(p) #define super_destruct(p) tcp_destruct(p) #define super_init(p,msg) tcp_initialize(p, msg) #define super_shutdown(p) tcp_shutdown(p) /* basic resource allocations for the http object */ RC_TYPE http_client_construct(HTTP_CLIENT *p_self) { RC_TYPE rc; if (p_self == NULL) { return RC_INVALID_POINTER; } rc = super_construct(&p_self->super); if (rc != RC_OK) { return rc; } /*init*/ memset( (char*)p_self + sizeof(p_self->super), 0 , sizeof(*p_self) - sizeof(p_self->super)); p_self->initialized = FALSE; return RC_OK; } /* Resource free. */ RC_TYPE http_client_destruct(HTTP_CLIENT *p_self, int num) { int i = 0, rv = RC_OK; while (i < num) { rv = super_destruct(&p_self[i++].super); } return rv; } /* Set default TCP specififc params */ static RC_TYPE local_set_params(HTTP_CLIENT *p_self) { int timeout = 0; int port; http_client_get_remote_timeout(p_self, &timeout); if (timeout == 0) { http_client_set_remote_timeout(p_self, HTTP_DEFAULT_TIMEOUT); } http_client_get_port(p_self, &port); if (port == 0) { http_client_set_port(p_self, HTTP_DEFAULT_PORT); } return RC_OK; } /* Sets up the object. - ... */ RC_TYPE http_client_init(HTTP_CLIENT *p_self, char *msg) { RC_TYPE rc; do { rc = local_set_params(p_self); if (rc != RC_OK) { break; } rc = super_init(&p_self->super, msg); if (rc != RC_OK) { break; } } while (0); if (rc != RC_OK) { http_client_shutdown(p_self); return rc; } p_self->initialized = TRUE; return RC_OK; } /* Disconnect and some other clean up. */ RC_TYPE http_client_shutdown(HTTP_CLIENT *p_self) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_OK; } p_self->initialized = FALSE; return super_shutdown(&p_self->super); } static void http_response_parse (HTTP_TRANSACTION *p_tr) { char *body; char *rsp = p_tr->p_rsp_body = p_tr->p_rsp; int status = p_tr->status = 0; memset(p_tr->status_desc, 0, sizeof(p_tr->status_desc)); const char sep[] = "\r\n\r\n"; if (rsp != NULL && (body = strstr(rsp, sep)) != NULL) { body += strlen(sep); p_tr->p_rsp_body = body; } if (sscanf(p_tr->p_rsp, "HTTP/1.%*c %d %255[^\r\n]", &status, p_tr->status_desc) == 2) p_tr->status = status; } /* Send req and get response */ RC_TYPE http_client_transaction(HTTP_CLIENT *p_self, HTTP_TRANSACTION *p_tr) { RC_TYPE rc; if (p_self == NULL || p_tr == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_HTTP_OBJECT_NOT_INITIALIZED; } do { rc = tcp_send(&p_self->super, p_tr->p_req, p_tr->req_len); if (rc != RC_OK) { break; } rc = tcp_recv(&p_self->super, p_tr->p_rsp, p_tr->max_rsp_len, &p_tr->rsp_len); } while (0); http_response_parse(p_tr); return rc; } /* Accessors */ RC_TYPE http_client_set_port(HTTP_CLIENT *p_self, int p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return tcp_set_port(&p_self->super, p); } RC_TYPE http_client_set_remote_name(HTTP_CLIENT *p_self, const char* p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return tcp_set_remote_name(&p_self->super, p); } RC_TYPE http_client_set_remote_timeout(HTTP_CLIENT *p_self, int p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return tcp_set_remote_timeout(&p_self->super, p); } RC_TYPE http_client_set_bind_iface(HTTP_CLIENT *p_self, char *ifname) { if (p_self == NULL) { return RC_INVALID_POINTER; } return tcp_set_bind_iface(&p_self->super, ifname); } RC_TYPE http_client_get_port(HTTP_CLIENT *p_self, int *p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return tcp_get_port(&p_self->super, p); } RC_TYPE http_client_get_remote_name(HTTP_CLIENT *p_self, const char* *p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return tcp_get_remote_name(&p_self->super, p); } RC_TYPE http_client_get_remote_timeout(HTTP_CLIENT *p_self, int *p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return tcp_get_remote_timeout(&p_self->super, p); } RC_TYPE http_client_get_bind_iface(HTTP_CLIENT *p_self, char **ifname) { if (p_self == NULL || ifname == NULL) { return RC_INVALID_POINTER; } return tcp_get_bind_iface(&p_self->super, ifname); } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/inadyn_cmd.c000066400000000000000000001052521220055527700161520ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * Copyright (C) 2006 Steve Horbachuk * * 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. */ #define MODULE_TAG "" #include #include #include #include #include /* sysconf() */ #include /* getpwnam_r() */ #include /* getgrnam_r() */ #include "dyndns.h" #include "debug_if.h" #include "base64.h" #include "get_cmd.h" static int curr_info; /* command line options */ #define DYNDNS_INPUT_FILE_OPT_STRING "--input_file" static RC_TYPE help_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE test_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_wildcard_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_username_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_password_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_alias_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_dns_server_name_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_dns_server_url_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_ip_server_name_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_dyndns_system_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_update_period_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_update_period_sec_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_forced_update_period_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_logfile_name(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_silent_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_verbose_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_proxy_server_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_options_from_file_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_iterations_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_syslog_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_change_persona_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_bind_interface(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_check_interface(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_pidfile(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE set_cachefile(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE print_version_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static RC_TYPE get_exec_handler(CMD_DATA *p_cmd, int current_nr, void *p_context); static CMD_DESCRIPTION_TYPE cmd_options_table[] = { {"-a", 1, {get_alias_handler, NULL}, "" }, {"--alias", 1, {get_alias_handler, NULL}, "\n" "\t\t\tAlias hostname. This option can appear multiple times." }, {"-b", 0, {set_silent_handler, NULL}, ""}, {"--background", 0, {set_silent_handler, NULL}, "Run in background."}, {"-B", 1, {set_bind_interface, NULL}, ""}, {"--bind", 1, {set_bind_interface, NULL}, "\n" "\t\t\tSet interface to bind to, only on UNIX systems."}, {"-c", 1, {set_cachefile, NULL}, ""}, {"--cachefile", 1, {set_cachefile, NULL}, "\n" "\t\t\tSet cachefile, default " DYNDNS_DEFAULT_CACHE_FILE}, {"-d", 1, {set_change_persona_handler, NULL}, ""}, {"--drop-privs", 1, {set_change_persona_handler, NULL}, "\n" "\t\t\tAfter init switch to a new user/group.\n" "\t\t\tOnly on UNIX systems."}, {"--change_persona", 1, {set_change_persona_handler, NULL}, NULL}, /* COMPAT */ {"-e", 1, {get_exec_handler, NULL}, ""}, {"--exec", 1, {get_exec_handler, NULL}, "Full path to external command to run after an IP update."}, {"-f", 1, {get_forced_update_period_handler, NULL}, ""}, {"--forced-update", 1, {get_forced_update_period_handler, NULL}, "\n" "\t\t\tForced DDNS server update interval. Default: 1 week"}, {"--forced_update_period", 1, {get_forced_update_period_handler, NULL}, NULL}, /* COMPAT */ {"-F", 1, {get_options_from_file_handler, NULL}, ""}, {"--config", 1, {get_options_from_file_handler, NULL}, "\n" "\t\t\tConfiguration file, containing further options. Default\n" "\t\t\tconfig file: " DYNDNS_DEFAULT_CONFIG_FILE ", is used if inadyn is\n" "\t\t\tcalled without any command line options." }, {DYNDNS_INPUT_FILE_OPT_STRING, 1, {get_options_from_file_handler, NULL}, NULL}, {"-H", 2, {get_ip_server_name_handler, NULL}, ""}, {"--checkip-url", 2, {get_ip_server_name_handler, NULL}, "\n" "\t\t\tLocal IP is detected by parsing the response after\n" "\t\t\treturned by this server and URL. The first IP found\n" "\t\t\tin the HTTP response is considered 'my IP'.\n" "\t\t\tDefault value: 'checkip.dyndns.org /'"}, {"--ip_server_name", 2, {get_ip_server_name_handler, NULL}, NULL}, {"-n", 1, {set_iterations_handler, NULL}, ""}, {"--iterations", 1, {set_iterations_handler, NULL}, "\n" "\t\t\tSet the number of DNS updates. Default: 0 (forever)"}, {"-i", 1, {set_check_interface, NULL}, ""}, {"--iface", 1, {set_check_interface, NULL}, "\n" "\t\t\tSet interface to check for IP, only on UNIX systems.\n" "\t\t\tExternal IP check is not performed."}, {"-L", 1, {get_logfile_name, NULL}, ""}, {"--logfile", 1, {get_logfile_name, NULL}, "\n" "\t\t\tFull path to log file"}, {"--log_file", 1, {get_logfile_name, NULL}, NULL}, {"-N", 1, {get_dns_server_name_handler, NULL}, ""}, {"--server-name", 1, {get_dns_server_name_handler, NULL}, "[[:port]]\n" "\t\t\tThe server that receives the update DNS request.\n" "\t\t\tAllows the use of unknown DNS services that accept HTTP\n" "\t\t\tupdates. If no proxy is wanted, then it is enough to\n" "\t\t\tset the dyndns system. Default servers will be taken."}, {"--dyndns_server_name", 1, {get_dns_server_name_handler, NULL}, NULL}, {"-U", 1, {get_dns_server_url_handler, NULL}, ""}, {"--server-url", 1, {get_dns_server_url_handler, NULL}, "\n" "\t\t\tFull URL relative to DynDNS server root.\n" "\t\t\tEx: /some_script.php?hostname=\n"}, {"--dyndns_server_url", 1, {get_dns_server_url_handler, NULL}, NULL}, {"-S", 1, {get_dyndns_system_handler, NULL}, ""}, {"--system", 1, {get_dyndns_system_handler, NULL}, "\n" "\t\t\tSelect DDNS service provider, one of the following.\n" "\t\t\to For dyndns.org: default@dyndns.org\n" "\t\t\to For freedns.afraid.org: default@freedns.afraid.org\n" "\t\t\to For zoneedit.com: default@zoneedit.com\n" "\t\t\to For no-ip.com: default@no-ip.com\n" "\t\t\to For easydns.com: default@easydns.com\n" "\t\t\to For tzo.com: default@tzo.com\n" "\t\t\to For 3322.org: dyndns@3322.org\n" "\t\t\to For dnsomatic.com: default@dnsomatic.com\n" "\t\t\to For tunnelbroker.net: ipv6tb@he.net\n" "\t\t\to For dns.he.net: dyndns@he.net\n" "\t\t\to For dynsip.org: default@dynsip.org\n" "\t\t\to For sitelutions.com: default@sitelutions.com\n" "\t\t\to For dnsexit.com: default@dnsexit.com\n" "\t\t\to For generic: custom@http_svr_basic_auth\n\n" "\t\t\tDefault value: default@dyndns.org"}, {"--dyndns_system", 1, {get_dyndns_system_handler, NULL}, NULL}, {"-x", 1, {get_proxy_server_handler, NULL}, ""}, {"--proxy-server", 1, {get_proxy_server_handler, NULL}, "[NAME[:port]]\n" "\t\t\tHTTP proxy server name, and optional port. Default: N/A"}, {"--proxy_server", 1, {get_proxy_server_handler, NULL}, NULL}, /* COMPAT */ {"-T", 1, {get_update_period_sec_handler, NULL}, ""}, {"--period", 1, {get_update_period_sec_handler, NULL}, "\n" "\t\t\tIP change check interval. Default: 2 min. Max: 10 days"}, {"--update_period_sec", 1, {get_update_period_sec_handler, NULL}, NULL}, {"--update_period", 1, {get_update_period_handler, NULL}, NULL}, {"-P", 1, {set_pidfile, NULL}, ""}, {"--pidfile", 1, {set_pidfile, NULL}, "\n" "\t\t\tSet pidfile, default " DYNDNS_DEFAULT_PIDFILE}, {"-s", 0, {set_syslog_handler, NULL}, ""}, {"--syslog", 0, {set_syslog_handler, NULL}, "Force logging to syslog, e.g., /var/log/messages, only on UNIX systems"}, {"-t", 0, {test_handler, NULL}, ""}, {"--test", 0, {test_handler, NULL}, "Force one update and quit."}, {"-u", 1, {get_username_handler, NULL}, ""}, {"--username", 1, {get_username_handler, NULL}, "\n" "\t\t\tYour DDNS user name, or hash"}, {"-p", 1, {get_password_handler, NULL}, ""}, {"--password", 1, {get_password_handler, NULL}, "\n" "\t\t\tYour DDNS user password."}, {"-w", 0, {get_wildcard_handler, NULL}, ""}, {"--wildcard", 0, {get_wildcard_handler, NULL}, "Enable domain wildcarding for easydns.com."}, {"-h", 0, {help_handler, NULL}, "" }, {"--help", 0, {help_handler, NULL}, "This online help." }, {"-V", 1, {set_verbose_handler, NULL}, ""}, {"--verbose", 1, {set_verbose_handler, NULL}, "Debug level: 0 - 5"}, {"-v", 0, {print_version_handler, NULL}, ""}, {"--version", 0, {print_version_handler, NULL}, "Show inadyn version"}, {NULL, 0, {0, NULL}, NULL } }; void print_help_page(void) { CMD_DESCRIPTION_TYPE *it; puts("Inadyn is a dynamic DNS (DDNS) client. It does periodic and/or on-demand checks\n" "of your externally visible IP address and updates the hostname to IP mapping at\n" "your DDNS service provider when necessary.\n"); puts("dyndns.org:\n" "\tinadyn -u username -p password -a my.registrated.name\n"); it = cmd_options_table; while (it->p_option != NULL) { if (it->p_description) { if (strlen(it->p_option) == 2) printf(" %s, ", it->p_option); else printf("%-16s %s\n", it->p_option, it->p_description); } ++it; } } static RC_TYPE help_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; (void)p_cmd; (void)current_nr; if (p_self == NULL) return RC_INVALID_POINTER; p_self->abort = TRUE; print_help_page(); return RC_OK; } static RC_TYPE test_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; (void)p_cmd; (void)current_nr; if (p_self == NULL) return RC_INVALID_POINTER; p_self->test_update = TRUE; p_self->total_iterations = 1; p_self->dbg.level = 5; return RC_OK; } static RC_TYPE get_wildcard_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; (void)p_cmd; (void)current_nr; if (p_self == NULL) return RC_INVALID_POINTER; p_self->info[curr_info].wildcard = TRUE; return RC_OK; } static RC_TYPE set_verbose_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sscanf(p_cmd->argv[current_nr], "%d", &p_self->dbg.level) != 1) return RC_DYNDNS_INVALID_OPTION; return RC_OK; } static RC_TYPE set_iterations_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sscanf(p_cmd->argv[current_nr], "%d", &p_self->total_iterations) != 1) return RC_DYNDNS_INVALID_OPTION; p_self->total_iterations = (p_self->sleep_sec < 0) ? DYNDNS_DEFAULT_ITERATIONS : p_self->total_iterations; return RC_OK; } static RC_TYPE set_silent_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; (void)p_cmd; (void)current_nr; if (p_self == NULL) return RC_INVALID_POINTER; p_self->run_in_background = TRUE; return RC_OK; } static RC_TYPE get_logfile_name(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sizeof(p_self->dbg.p_logfilename) < strlen(p_cmd->argv[current_nr])) return RC_DYNDNS_BUFFER_TOO_SMALL; strcpy(p_self->dbg.p_logfilename, p_cmd->argv[current_nr]); return RC_OK; } static RC_TYPE get_username_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sizeof(p_self->info[curr_info].credentials.my_username) < strlen(p_cmd->argv[current_nr])) return RC_DYNDNS_BUFFER_TOO_SMALL; strcpy(p_self->info[curr_info].credentials.my_username, p_cmd->argv[current_nr]); return RC_OK; } static RC_TYPE get_password_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sizeof(p_self->info[curr_info].credentials.my_password) < strlen(p_cmd->argv[current_nr])) return RC_DYNDNS_BUFFER_TOO_SMALL; strcpy(p_self->info[curr_info].credentials.my_password, (p_cmd->argv[current_nr])); return RC_OK; } static RC_TYPE get_alias_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (p_self->info[curr_info].alias_count >= DYNDNS_MAX_ALIAS_NUMBER) return RC_DYNDNS_TOO_MANY_ALIASES; if (sizeof(p_self->info[curr_info].alias_info[p_self->info[curr_info].alias_count].names) < strlen(p_cmd->argv[current_nr])) return RC_DYNDNS_BUFFER_TOO_SMALL; strcpy(p_self->info[curr_info].alias_info[p_self->info[curr_info].alias_count].names.name, (p_cmd->argv[current_nr])); p_self->info[curr_info].alias_count++; return RC_OK; } static RC_TYPE get_name_and_port(char *p_src, char *p_dest_name, int *p_dest_port) { const char *p_port = strstr(p_src,":"); if (p_port) { int port_nr, len; int port_ok = sscanf(p_port + 1, "%d",&port_nr); if (port_ok != 1) return RC_DYNDNS_INVALID_OPTION; *p_dest_port = port_nr; len = p_port - p_src; memcpy(p_dest_name, p_src, len); p_dest_name[len] = 0; } else { strcpy(p_dest_name, p_src); } return RC_OK; } /** Returns the svr name and port if the format is : * name[:port] url. */ static RC_TYPE get_ip_server_name_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; RC_TYPE rc; int port = -1; if (p_self == NULL) return RC_INVALID_POINTER; /*ip_server_name*/ if (sizeof(p_self->info[curr_info].ip_server_name) < strlen(p_cmd->argv[current_nr]) + 1) return RC_DYNDNS_BUFFER_TOO_SMALL; p_self->info[curr_info].ip_server_name.port = HTTP_DEFAULT_PORT; rc = get_name_and_port(p_cmd->argv[current_nr], p_self->info[curr_info].ip_server_name.name, &port); if (rc == RC_OK && port != -1) p_self->info[curr_info].ip_server_name.port = port; if (sizeof(p_self->info[curr_info].ip_server_url) < strlen(p_cmd->argv[current_nr + 1]) + 1) return RC_DYNDNS_BUFFER_TOO_SMALL; strcpy(p_self->info[curr_info].ip_server_url, p_cmd->argv[current_nr + 1]); return rc; } static RC_TYPE get_dns_server_name_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; RC_TYPE rc; int port = -1; if (p_self == NULL) return RC_INVALID_POINTER; if (sizeof(p_self->info[curr_info].dyndns_server_name) < strlen(p_cmd->argv[current_nr])) return RC_DYNDNS_BUFFER_TOO_SMALL; p_self->info[curr_info].dyndns_server_name.port = HTTP_DEFAULT_PORT; rc = get_name_and_port(p_cmd->argv[current_nr], p_self->info[curr_info].dyndns_server_name.name, &port); if (rc == RC_OK && port != -1) p_self->info[curr_info].dyndns_server_name.port = port; return rc; } RC_TYPE get_dns_server_url_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sizeof(p_self->info[curr_info].dyndns_server_url) < strlen(p_cmd->argv[current_nr])) return RC_DYNDNS_BUFFER_TOO_SMALL; strcpy(p_self->info[curr_info].dyndns_server_url, p_cmd->argv[current_nr]); return RC_OK; } /* returns the proxy server nme and port */ static RC_TYPE get_proxy_server_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; RC_TYPE rc; int port = -1; if (p_self == NULL) return RC_INVALID_POINTER; if (sizeof(p_self->info[curr_info].proxy_server_name) < strlen(p_cmd->argv[current_nr])) return RC_DYNDNS_BUFFER_TOO_SMALL; p_self->info[curr_info].proxy_server_name.port = HTTP_DEFAULT_PORT; rc = get_name_and_port(p_cmd->argv[current_nr], p_self->info[curr_info].proxy_server_name.name, &port); if (rc == RC_OK && port != -1) p_self->info[curr_info].proxy_server_name.port = port; return rc; } /* Read the dyndnds name update period. and impose the max and min limits */ static RC_TYPE get_update_period_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sscanf(p_cmd->argv[current_nr], "%d", &p_self->sleep_sec) != 1) return RC_DYNDNS_INVALID_OPTION; p_self->sleep_sec /= 1000; p_self->sleep_sec = (p_self->sleep_sec < DYNDNS_MIN_SLEEP) ? DYNDNS_MIN_SLEEP: p_self->sleep_sec; (p_self->sleep_sec > DYNDNS_MAX_SLEEP) ? p_self->sleep_sec = DYNDNS_MAX_SLEEP: 1; return RC_OK; } static RC_TYPE get_update_period_sec_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sscanf(p_cmd->argv[current_nr], "%d", &p_self->normal_update_period_sec) != 1) return RC_DYNDNS_INVALID_OPTION; p_self->normal_update_period_sec = (p_self->normal_update_period_sec < DYNDNS_MIN_SLEEP) ? DYNDNS_MIN_SLEEP: p_self->normal_update_period_sec; (p_self->normal_update_period_sec > DYNDNS_MAX_SLEEP) ? p_self->normal_update_period_sec = DYNDNS_MAX_SLEEP: 1; return RC_OK; } static RC_TYPE get_forced_update_period_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; if (sscanf(p_cmd->argv[current_nr], "%d", &p_self->forced_update_period_sec) != 1) return RC_DYNDNS_INVALID_OPTION; return RC_OK; } static RC_TYPE set_syslog_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; (void)p_cmd; (void)current_nr; if (p_self == NULL) return RC_INVALID_POINTER; p_self->debug_to_syslog = TRUE; return RC_OK; } /** * Reads the params for change persona. Format: * */ static RC_TYPE set_change_persona_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { int s, result = RC_OK; char *arg, *buf, *p_gid; ssize_t bufsize; gid_t gid; uid_t uid; struct passwd pwd, *pwd_res; long login_len_max; DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; if (p_self == NULL) return RC_INVALID_POINTER; /* Determine max length of a username */ login_len_max = sysconf(_SC_LOGIN_NAME_MAX); if (login_len_max <= 0) login_len_max = 32; arg = p_cmd->argv[current_nr]; { char groupname[33] = ""; /* MAX 32 chars + '\0', groupadd(8) */ char username[login_len_max+1]; char fmt[65]; /* Conversion string for username */ uid = getuid(); gid = getgid(); p_gid = strstr(arg, ":"); if (p_gid) { if ((strlen(p_gid + 1) > 0) && /* if something is present after : */ sscanf(p_gid + 1, "%32[a-zA-Z-]", groupname) != 1) return RC_DYNDNS_INVALID_OPTION; } snprintf(fmt, sizeof(fmt), "%%%ld[a-zA-Z-]", login_len_max); if (sscanf(arg, fmt, username) != 1) return RC_DYNDNS_INVALID_OPTION; /* Get uid and gid by their names */ if (strlen(groupname) > 0) { struct group grp; struct group *grp_res; bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); if (bufsize == -1) bufsize = 16384; /* Should be more than enough */ buf = malloc(bufsize); if (buf == NULL) return RC_OUT_OF_MEMORY; s = getgrnam_r(groupname, &grp, buf, bufsize, &grp_res); if (grp_res != NULL) { gid = grp.gr_gid; } else { if (s == 0) { logit(LOG_ERR, MODULE_TAG "Cannot find GROUP %s", groupname); result = RC_OS_INVALID_GID; } else { result = RC_ERROR; } } free(buf); if (RC_OK != result) return result; } bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize == -1) /* Value was indeterminate */ bufsize = 16384; /* Should be more than enough */ buf = malloc(bufsize); if (buf == NULL) return RC_OUT_OF_MEMORY; s = getpwnam_r(username, &pwd, buf, bufsize, &pwd_res); if (pwd_res != NULL) { uid = pwd.pw_uid; if (gid == getgid()) gid = pwd.pw_gid; } else { if (s == 0) { logit(LOG_ERR, MODULE_TAG "Cannot find USER %s", username); result = RC_OS_INVALID_UID; } else { result = RC_ERROR; } } free(buf); if (RC_OK != result) return result; p_self->change_persona = TRUE; p_self->sys_usr_info.gid = gid; p_self->sys_usr_info.uid = uid; } return RC_OK; } static RC_TYPE set_bind_interface(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; if (p_self == NULL) return RC_INVALID_POINTER; p_self->bind_interface = strdup(p_cmd->argv[current_nr]); return RC_OK; } static RC_TYPE set_check_interface(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; if (p_self == NULL) return RC_INVALID_POINTER; p_self->check_interface = strdup(p_cmd->argv[current_nr]); return RC_OK; } static RC_TYPE set_pidfile(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; if (p_self == NULL) return RC_INVALID_POINTER; p_self->pidfile = strdup(p_cmd->argv[current_nr]); return RC_OK; } static RC_TYPE set_cachefile(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; if (p_self == NULL) return RC_INVALID_POINTER; p_self->cache_file = strdup(p_cmd->argv[current_nr]); return RC_OK; } RC_TYPE print_version_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; (void)p_cmd; (void)current_nr; if (p_self == NULL) return RC_INVALID_POINTER; printf("%s\n", DYNDNS_VERSION_STRING); p_self->abort = TRUE; return RC_OK; } static RC_TYPE get_exec_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; (void)p_cmd; (void)current_nr; if (p_self == NULL) return RC_INVALID_POINTER; p_self->external_command = strdup(p_cmd->argv[current_nr]); return RC_OK; } /** Searches the DYNDNS system by the argument. Input is like: system@server.name system=statdns|custom|dyndns|default server name = dyndns.org | freedns.afraid.org The result is a pointer in the table of DNS systems. */ static RC_TYPE get_dyndns_system_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { DYNDNS_SYSTEM *p_dns_system = NULL; DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)p_context; DYNDNS_SYSTEM_INFO *it; if (p_self == NULL) return RC_INVALID_POINTER; it = get_dyndns_system_table(); for (; it != NULL && it->id != LAST_DNS_SYSTEM; ++it) { if (strcmp(it->system.p_key, p_cmd->argv[current_nr]) == 0) { p_dns_system = &it->system; break; } } if (p_dns_system == NULL) { logit(LOG_ERR, MODULE_TAG "Cannot find DDNS provider %s, check your spelling.", p_cmd->argv[current_nr]); return RC_CMD_PARSER_INVALID_OPTION_ARGUMENT; } for (curr_info = 0; curr_info < p_self->info_count && curr_info < DYNDNS_MAX_SERVER_NUMBER && p_self->info[curr_info].p_dns_system != p_dns_system; curr_info++) ; if (curr_info >= p_self->info_count) { if (curr_info < DYNDNS_MAX_SERVER_NUMBER) { p_self->info_count++; p_self->info[curr_info].p_dns_system = p_dns_system; } else { return RC_DYNDNS_BUFFER_TOO_SMALL; } } return RC_OK; } static RC_TYPE push_in_buffer(char* p_src, int src_len, char *p_buffer, int* p_act_len, int max_len) { if (*p_act_len + src_len > max_len) return RC_FILE_IO_OUT_OF_BUFFER; memcpy(p_buffer + *p_act_len,p_src, src_len); *p_act_len += src_len; return RC_OK; } typedef enum { NEW_LINE, COMMENT, DATA, SPACE, ESCAPE } PARSER_STATE; typedef struct { FILE *p_file; PARSER_STATE state; } OPTION_FILE_PARSER; static RC_TYPE parser_init(OPTION_FILE_PARSER *p_cfg, FILE *p_file) { memset(p_cfg, 0, sizeof(*p_cfg)); p_cfg->state = NEW_LINE; p_cfg->p_file = p_file; return RC_OK; } /** Read one single option from file into the given buffer. When the first separator is encountered it returns. Actions: - read chars while not eof - skip comments (parts beginning with '#' and ending with '\n') - switch to DATA STATE if non space char is encountered - assume first name in lines to be a long option name by adding '--' if necesssary - add data to buffer - do not forget a 0 at the end * States: * NEW_LINE - wait here until some option. Add '--' if not already there * SPACE - between options. Like NEW_LINE but no additions * DATA - real data. Stop on space. * COMMENT - everything beginning with # until EOLine * ESCAPE - everything that is otherwise (incl. spaces). Next char is raw copied. */ static RC_TYPE parser_read_option(OPTION_FILE_PARSER *p_cfg, char *p_buffer, int maxlen) { RC_TYPE rc = RC_OK; BOOL parse_end = FALSE; int count = 0; *p_buffer = 0; while (!parse_end) { char ch; { int n; if ((n = fscanf(p_cfg->p_file, "%c", &ch)) < 0) { if (feof(p_cfg->p_file)) break; rc = RC_FILE_IO_READ_ERROR; break; } } switch (p_cfg->state) { case NEW_LINE: if (ch == '\\') { p_cfg->state = ESCAPE; break; } if (ch == '#') /*comment*/ { p_cfg->state = COMMENT; break; } if (!isspace(ch)) { if (ch != '-')/*add '--' to first word in line*/ { if ((rc = push_in_buffer("--", 2, p_buffer, &count, maxlen)) != RC_OK) break; } if ((rc = push_in_buffer(&ch, 1, p_buffer, &count, maxlen)) != RC_OK) break; p_cfg->state = DATA; break; } /*skip actual leading spaces*/ break; case SPACE: if (ch == '\\') { p_cfg->state = ESCAPE; break; } if (ch == '#') /*comment*/ { p_cfg->state = COMMENT; break; } if (ch == '\n' || ch == '\r') { p_cfg->state = NEW_LINE; break; } if (!isspace(ch)) { if ((rc = push_in_buffer(&ch, 1, p_buffer, &count, maxlen)) != RC_OK) break; p_cfg->state = DATA; break; } break; case COMMENT: /*skip comments*/ if (ch == '\n' || ch == '\r') p_cfg->state = NEW_LINE; break; case DATA: if (ch == '\\') { p_cfg->state = ESCAPE; break; } if (ch == '#') { p_cfg->state = COMMENT; break; } if (ch == '\n' || ch == '\r') { p_cfg->state = NEW_LINE; parse_end = TRUE; break; } if (isspace(ch)) { p_cfg->state = SPACE; parse_end = TRUE; break; } /*actual data*/ if ((rc = push_in_buffer(&ch, 1, p_buffer, &count, maxlen)) != RC_OK) break; break; case ESCAPE: if ((rc = push_in_buffer(&ch, 1, p_buffer, &count, maxlen)) != RC_OK) break; p_cfg->state = DATA; break; default: rc = RC_CMD_PARSER_INVALID_OPTION; break; } if (rc != RC_OK) break; } if (rc == RC_OK) { char ch = 0; rc = push_in_buffer(&ch, 1, p_buffer, &count, maxlen); } return rc; } /** This handler reads the data in the passed file name. Then appends the words in the table (cutting all spaces) to the existing cmd line options. It adds to the CMD_DATA struct. Actions: - open file - read characters and cut spaces away - add values one by one to the existing p_cmd data */ static RC_TYPE get_options_from_file_handler(CMD_DATA *p_cmd, int current_nr, void *p_context) { RC_TYPE rc = RC_OK; DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_context; FILE *p_file = NULL; char *p_tmp_buffer = NULL; const int buffer_size = DYNDNS_SERVER_NAME_LENGTH; OPTION_FILE_PARSER parser; if (!p_self || !p_cmd) return RC_INVALID_POINTER; do { p_tmp_buffer = malloc(buffer_size); if (!p_tmp_buffer) { rc = RC_OUT_OF_MEMORY; break; } p_file = fopen(p_cmd->argv[current_nr], "r"); if (!p_file) { logit(LOG_ERR, MODULE_TAG "Cannot open config file %s: %s", p_cmd->argv[current_nr], strerror(errno)); rc = RC_FILE_IO_OPEN_ERROR; break; } /* Save for later... */ if (p_self->cfgfile) free(p_self->cfgfile); p_self->cfgfile = strdup(p_cmd->argv[current_nr]); if ((rc = parser_init(&parser, p_file)) != RC_OK) break; while (!feof(p_file)) { rc = parser_read_option(&parser,p_tmp_buffer, buffer_size); if (rc != RC_OK) break; if (!strlen(p_tmp_buffer)) break; rc = cmd_add_val(p_cmd, p_tmp_buffer); if (rc != RC_OK) break; } } while (0); if (p_file) fclose(p_file); if (p_tmp_buffer) free(p_tmp_buffer); return rc; } static void check_setting(int cond, int no, char *msg, int *ok) { if (!cond) { logit(LOG_WARNING, MODULE_TAG "%s in account %d", msg, no + 1); *ok = 0; } } /* Returns POSIX OK(0) on success, non-zero on validation failure. */ static int validate_configuration(DYN_DNS_CLIENT *p_self) { int i, num = 0; if (!p_self->info_count) { logit(LOG_ERR, MODULE_TAG "No DDNS provider setup in configuration."); return 1; } for (i = 0; i < p_self->info_count; i++) { int ok = 1; DYNDNS_INFO_TYPE *account = &p_self->info[i]; check_setting(strlen(account->credentials.my_username), i, "Missing username", &ok); check_setting(strlen(account->credentials.my_password), i, "Missing password", &ok); check_setting(account->alias_count, i, "Missing your alias/hostname", &ok); check_setting(strlen(account->dyndns_server_name.name), i, "Missing DDNS server address, check DDNS provider", &ok); check_setting(strlen(account->ip_server_name.name), i, "Missing check IP address, check DDNS provider", &ok); if (ok) num++; } if (!num) { logit(LOG_ERR, MODULE_TAG "No valid DDNS setup exists."); return 1; } if (num != p_self->info_count) logit(LOG_WARNING, MODULE_TAG "Not all account setups are valid, please check configuration."); return 0; } /* Set up all details: - ip server name - dns server name - username, passwd - ... Implementation: - load defaults - parse cmd line - assign settings that may change due to cmd line options - check data Note: - if no argument is specified tries to call the cmd line parser with the default cfg file path. */ RC_TYPE get_config_data(DYN_DNS_CLIENT *p_self, int argc, char** argv) { int i; RC_TYPE rc = RC_OK; int cache_file_len; CMD_DESCRIPTION_TYPE *it; do { /*load default data */ rc = get_default_config_data(p_self); if (rc != RC_OK) break; /*set up the context pointers */ it = cmd_options_table; while (it->p_option != NULL) { it->p_handler.p_context = (void*) p_self; ++it; } /* in case of no options, assume the default cfg file may be present */ if (argc == 1) { char *custom_argv[] = {"", DYNDNS_INPUT_FILE_OPT_STRING, DYNDNS_DEFAULT_CONFIG_FILE}; int custom_argc = sizeof(custom_argv) / sizeof(char*); if (p_self->dbg.level) logit(LOG_NOTICE, MODULE_TAG "Using default config file %s", DYNDNS_DEFAULT_CONFIG_FILE); if (p_self->cfgfile) free(p_self->cfgfile); p_self->cfgfile = strdup(DYNDNS_DEFAULT_CONFIG_FILE); rc = get_cmd_parse_data(custom_argv, custom_argc, cmd_options_table); } else { rc = get_cmd_parse_data(argv, argc, cmd_options_table); } if (rc != RC_OK || p_self->abort) break; /* settings that may change due to cmd line options */ i = 0; do { /*ip server*/ if (strlen(p_self->info[i].ip_server_name.name) == 0) { if (sizeof(p_self->info[i].ip_server_name.name) < strlen(p_self->info[i].p_dns_system->p_ip_server_name)) { rc = RC_DYNDNS_BUFFER_TOO_SMALL; break; } strcpy(p_self->info[i].ip_server_name.name, p_self->info[i].p_dns_system->p_ip_server_name); if (sizeof(p_self->info[i].ip_server_url) < strlen(p_self->info[i].p_dns_system->p_ip_server_url)) { rc = RC_DYNDNS_BUFFER_TOO_SMALL; break; } strcpy(p_self->info[i].ip_server_url, p_self->info[i].p_dns_system->p_ip_server_url); } /*dyndns server*/ if (strlen(p_self->info[i].dyndns_server_name.name) == 0) { if (sizeof(p_self->info[i].dyndns_server_name.name) < strlen(p_self->info[i].p_dns_system->p_dyndns_server_name)) { rc = RC_DYNDNS_BUFFER_TOO_SMALL; break; } strcpy(p_self->info[i].dyndns_server_name.name, p_self->info[i].p_dns_system->p_dyndns_server_name); if (sizeof(p_self->info[i].dyndns_server_url) < strlen(p_self->info[i].p_dns_system->p_dyndns_server_url)) { rc = RC_DYNDNS_BUFFER_TOO_SMALL; break; } strcpy(p_self->info[i].dyndns_server_url, p_self->info[i].p_dns_system->p_dyndns_server_url); } } while(++i < p_self->info_count); /* Check if the neccessary params have been provided */ if (validate_configuration(p_self)) { rc = RC_DYNDNS_INVALID_OR_MISSING_PARAMETERS; break; } /* Setup a default cache file, unless the user provided one for us. */ if (p_self->bind_interface && !p_self->cache_file) { cache_file_len = (strlen(DYNDNS_CACHE_FILE) - 2) + strlen(p_self->bind_interface); if ((p_self->cache_file = malloc(cache_file_len + 1)) == NULL) { rc = RC_OUT_OF_MEMORY; break; } if (snprintf(p_self->cache_file, cache_file_len + 1, DYNDNS_CACHE_FILE, p_self->bind_interface) != cache_file_len) { rc = RC_ERROR; break; } } else { p_self->cache_file = strdup(DYNDNS_DEFAULT_CACHE_FILE); } } while (0); return rc; } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/ip.c000066400000000000000000000173071220055527700144600ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * * 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. */ #define MODULE_TAG "" #include #include #include #include #include #include #include #include "debug_if.h" #include "ip.h" /* basic resource allocations for the ip object */ RC_TYPE ip_construct(IP_SOCKET *p_self) { if (p_self == NULL) { return RC_INVALID_POINTER; } memset(p_self, 0, sizeof(IP_SOCKET)); p_self->initialized = FALSE; p_self->bound = FALSE; p_self->socket = -1; /* Initialize to 'error', not a possible socket id. */ memset(&p_self->local_addr, 0, sizeof(p_self->local_addr)); memset(&p_self->remote_addr, 0, sizeof(p_self->remote_addr)); p_self->timeout = IP_DEFAULT_TIMEOUT; return RC_OK; } /* Resource free. */ RC_TYPE ip_destruct(IP_SOCKET *p_self) { if (p_self == NULL) { return RC_OK; } if (p_self->initialized == TRUE) { ip_shutdown(p_self); } return RC_OK; } /* Sets up the object. - ... */ RC_TYPE ip_initialize(IP_SOCKET *p_self) { RC_TYPE rc = RC_OK; struct ifreq ifr; struct sockaddr_in *addrp = NULL; if (p_self->initialized == TRUE) { return RC_OK; } do { rc = os_ip_support_startup(); if (rc != RC_OK) { break; } /* local bind, to interface */ if (p_self->ifname) { int sd = socket(PF_INET, SOCK_DGRAM, 0); if (sd < 0) { int code = os_get_socket_error(); logit(LOG_WARNING, MODULE_TAG "Failed opening network socket: %s", strerror(code)); rc = RC_IP_OS_SOCKET_INIT_FAILED; break; } memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, p_self->ifname, IFNAMSIZ); if (ioctl(sd, SIOCGIFADDR, &ifr) != -1) { p_self->local_addr.sin_family = AF_INET; p_self->local_addr.sin_port = htons(0); addrp = (struct sockaddr_in *)&(ifr.ifr_addr); p_self->local_addr.sin_addr.s_addr = addrp->sin_addr.s_addr; p_self->bound = TRUE; logit(LOG_INFO, MODULE_TAG "Bound to interface %s (IP# %s)", p_self->ifname, inet_ntoa(p_self->local_addr.sin_addr)); } else { int code = os_get_socket_error(); logit(LOG_ERR, MODULE_TAG "Failed reading IP address of interface %s: %s", p_self->ifname, strerror(code)); p_self->bound = FALSE; } close(sd); } /* remote address */ if (p_self->p_remote_host_name != NULL) { int s; char port[10]; struct addrinfo hints, *result; /* Clear DNS cache before calling getaddrinfo(). */ res_init(); /* Obtain address(es) matching host/port */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* Use AF_UNSPEC to allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ snprintf(port, sizeof(port), "%d", p_self->port); s = getaddrinfo(p_self->p_remote_host_name, port, &hints, &result); if (s != 0 || !result) { logit(LOG_WARNING, MODULE_TAG "Failed resolving hostname %s: %s", p_self->p_remote_host_name, gai_strerror(s)); rc = RC_IP_INVALID_REMOTE_ADDR; break; } /* XXX: Here we should iterate over all of the records returned by * getaddrinfo(), but with this code here in ip.c and connect() being * in tcp.c that's hardly feasible. Needs refactoring! --Troglobit */ p_self->remote_addr = *result->ai_addr; p_self->remote_len = result->ai_addrlen; freeaddrinfo(result); /* No longer needed */ } } while (0); if (rc != RC_OK) { ip_shutdown(p_self); return rc; } p_self->initialized = TRUE; return RC_OK; } /* Disconnect and some other clean up. */ RC_TYPE ip_shutdown(IP_SOCKET *p_self) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_OK; } if (p_self->socket > -1) { closesocket(p_self->socket); p_self->socket = -1; } os_ip_support_cleanup(); p_self->initialized = FALSE; return RC_OK; } RC_TYPE ip_send(IP_SOCKET *p_self, const char *p_buf, int len) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_IP_OBJECT_NOT_INITIALIZED; } if (send(p_self->socket, (char*) p_buf, len, 0) == SOCKET_ERROR) { int code = os_get_socket_error(); logit(LOG_WARNING, MODULE_TAG "Network error while sending query/update: %s", strerror(code)); return RC_IP_SEND_ERROR; } return RC_OK; } /* Receive data into user's buffer. return if the max len has been received if a timeout occures In p_recv_len the total number of bytes are returned. Note: if the recv_len is bigger than 0, no error is returned. */ RC_TYPE ip_recv(IP_SOCKET *p_self, char *p_buf, int max_recv_len, int *p_recv_len) { RC_TYPE rc = RC_OK; int remaining_buf_len = max_recv_len; int total_recv_len = 0; int recv_len = 0; if (p_self == NULL || p_buf == NULL || p_recv_len == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_IP_OBJECT_NOT_INITIALIZED; } while (remaining_buf_len > 0) { int chunk_size = remaining_buf_len > IP_DEFAULT_READ_CHUNK_SIZE ? IP_DEFAULT_READ_CHUNK_SIZE : remaining_buf_len; recv_len = recv(p_self->socket, p_buf + total_recv_len, chunk_size, 0); if (recv_len < 0) { int code = os_get_socket_error(); logit(LOG_WARNING, MODULE_TAG "Network error while waiting for reply: %s", strerror(code)); rc = RC_IP_RECV_ERROR; break; } if (recv_len == 0) { if (total_recv_len == 0) { rc = RC_IP_RECV_ERROR; } break; } total_recv_len += recv_len; remaining_buf_len = max_recv_len - total_recv_len; } *p_recv_len = total_recv_len; return rc; } /*Accessors */ RC_TYPE ip_set_port(IP_SOCKET *p_self, int p) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (p < 0 || p > IP_SOCKET_MAX_PORT) { return RC_IP_BAD_PARAMETER; } p_self->port = p; return RC_OK; } RC_TYPE ip_set_remote_name(IP_SOCKET *p_self, const char *p) { if (p_self == NULL) { return RC_INVALID_POINTER; } p_self->p_remote_host_name = p; return RC_OK; } RC_TYPE ip_set_remote_timeout(IP_SOCKET *p_self, int t) { if (p_self == NULL) { return RC_INVALID_POINTER; } p_self->timeout = t; return RC_OK; } RC_TYPE ip_set_bind_iface(IP_SOCKET *p_self, char *ifname) { if (p_self == NULL) { return RC_INVALID_POINTER; } p_self->ifname = ifname; return RC_OK; } RC_TYPE ip_get_port(IP_SOCKET *p_self, int *p_port) { if (p_self == NULL || p_port == NULL) { return RC_INVALID_POINTER; } *p_port = p_self->port; return RC_OK; } RC_TYPE ip_get_remote_name(IP_SOCKET *p_self, const char **p) { if (p_self == NULL || p == NULL) { return RC_INVALID_POINTER; } *p = p_self->p_remote_host_name; return RC_OK; } RC_TYPE ip_get_remote_timeout(IP_SOCKET *p_self, int *p) { if (p_self == NULL || p == NULL) { return RC_INVALID_POINTER; } *p = p_self->timeout; return RC_OK; } RC_TYPE ip_get_bind_iface(IP_SOCKET *p_self, char **ifname) { if (p_self == NULL || ifname == NULL) { return RC_INVALID_POINTER; } *ifname = p_self->ifname; return RC_OK; } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/main.c000066400000000000000000000045071220055527700147720ustar00rootroot00000000000000/* Small cmd line program useful for maintaining an IP address in a Dynamic DNS system. * * Copyright (C) 2003-2004 Narcis Ilisei * * 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. */ #define MODULE_TAG "" #include #include "debug_if.h" #include "dyndns.h" #include "errorcode.h" /* MAIN - Dyn DNS update entry point.*/ int inadyn_main(int argc, char* argv[]) { int restart = 0; BOOL os_handler_installed = FALSE; RC_TYPE rc = RC_OK; DYN_DNS_CLIENT *p_dyndns = NULL; do { /* create DYN_DNS_CLIENT object */ rc = dyn_dns_construct(&p_dyndns); if (rc != RC_OK) { break; } /* install signal handler */ if (!os_handler_installed) { rc = os_install_signal_handler(p_dyndns); if (rc != RC_OK) { logit(LOG_WARNING, MODULE_TAG "Failed installing OS signal handler: %s", errorcode_get_name(rc)); break; } os_handler_installed = TRUE; } rc = dyn_dns_main(p_dyndns, argc, argv); if (rc == RC_RESTART) { restart = 1; /* do some cleanup if restart requested */ rc = dyn_dns_destruct(p_dyndns); if (rc != RC_OK) { logit(LOG_WARNING, MODULE_TAG "Failed cleaning up before restart: %s, ignoring...", errorcode_get_name(rc)); } } else { /* Error, or OK. In either case exit outer loop. */ restart = 0; } } while (restart); if (rc != RC_OK) { logit(LOG_WARNING, MODULE_TAG "Failed %sstarting daemon: %s", restart ? "re" : "", errorcode_get_name(rc)); } /* Cleanup */ dyn_dns_destruct(p_dyndns); os_close_dbg_output(); return (int)rc; } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/md5.c000066400000000000000000000201221220055527700145220ustar00rootroot00000000000000/* * RFC 1321 compliant MD5 implementation * * Copyright (C) 2006-2010, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * The MD5 algorithm was designed by Ron Rivest in 1991. * * http://www.ietf.org/rfc/rfc1321.txt */ #include "md5.h" /* * 32-bit integer manipulation macros (little endian) */ #ifndef GET_ULONG_LE #define GET_ULONG_LE(n,b,i) \ { \ (n) = ( (unsigned long) (b)[(i) ] ) \ | ( (unsigned long) (b)[(i) + 1] << 8 ) \ | ( (unsigned long) (b)[(i) + 2] << 16 ) \ | ( (unsigned long) (b)[(i) + 3] << 24 ); \ } #endif #ifndef PUT_ULONG_LE #define PUT_ULONG_LE(n,b,i) \ { \ (b)[(i) ] = (unsigned char) ( (n) ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ } #endif /* * MD5 context setup */ void md5_starts( md5_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; } static void md5_process( md5_context *ctx, const unsigned char data[64] ) { unsigned long X[16], A, B, C, D; GET_ULONG_LE( X[ 0], data, 0 ); GET_ULONG_LE( X[ 1], data, 4 ); GET_ULONG_LE( X[ 2], data, 8 ); GET_ULONG_LE( X[ 3], data, 12 ); GET_ULONG_LE( X[ 4], data, 16 ); GET_ULONG_LE( X[ 5], data, 20 ); GET_ULONG_LE( X[ 6], data, 24 ); GET_ULONG_LE( X[ 7], data, 28 ); GET_ULONG_LE( X[ 8], data, 32 ); GET_ULONG_LE( X[ 9], data, 36 ); GET_ULONG_LE( X[10], data, 40 ); GET_ULONG_LE( X[11], data, 44 ); GET_ULONG_LE( X[12], data, 48 ); GET_ULONG_LE( X[13], data, 52 ); GET_ULONG_LE( X[14], data, 56 ); GET_ULONG_LE( X[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define P(a,b,c,d,k,s,t) \ { \ a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ } A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; #define F(x,y,z) (z ^ (x & (y ^ z))) P( A, B, C, D, 0, 7, 0xD76AA478 ); P( D, A, B, C, 1, 12, 0xE8C7B756 ); P( C, D, A, B, 2, 17, 0x242070DB ); P( B, C, D, A, 3, 22, 0xC1BDCEEE ); P( A, B, C, D, 4, 7, 0xF57C0FAF ); P( D, A, B, C, 5, 12, 0x4787C62A ); P( C, D, A, B, 6, 17, 0xA8304613 ); P( B, C, D, A, 7, 22, 0xFD469501 ); P( A, B, C, D, 8, 7, 0x698098D8 ); P( D, A, B, C, 9, 12, 0x8B44F7AF ); P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); P( B, C, D, A, 11, 22, 0x895CD7BE ); P( A, B, C, D, 12, 7, 0x6B901122 ); P( D, A, B, C, 13, 12, 0xFD987193 ); P( C, D, A, B, 14, 17, 0xA679438E ); P( B, C, D, A, 15, 22, 0x49B40821 ); #undef F #define F(x,y,z) (y ^ (z & (x ^ y))) P( A, B, C, D, 1, 5, 0xF61E2562 ); P( D, A, B, C, 6, 9, 0xC040B340 ); P( C, D, A, B, 11, 14, 0x265E5A51 ); P( B, C, D, A, 0, 20, 0xE9B6C7AA ); P( A, B, C, D, 5, 5, 0xD62F105D ); P( D, A, B, C, 10, 9, 0x02441453 ); P( C, D, A, B, 15, 14, 0xD8A1E681 ); P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); P( A, B, C, D, 9, 5, 0x21E1CDE6 ); P( D, A, B, C, 14, 9, 0xC33707D6 ); P( C, D, A, B, 3, 14, 0xF4D50D87 ); P( B, C, D, A, 8, 20, 0x455A14ED ); P( A, B, C, D, 13, 5, 0xA9E3E905 ); P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); P( C, D, A, B, 7, 14, 0x676F02D9 ); P( B, C, D, A, 12, 20, 0x8D2A4C8A ); #undef F #define F(x,y,z) (x ^ y ^ z) P( A, B, C, D, 5, 4, 0xFFFA3942 ); P( D, A, B, C, 8, 11, 0x8771F681 ); P( C, D, A, B, 11, 16, 0x6D9D6122 ); P( B, C, D, A, 14, 23, 0xFDE5380C ); P( A, B, C, D, 1, 4, 0xA4BEEA44 ); P( D, A, B, C, 4, 11, 0x4BDECFA9 ); P( C, D, A, B, 7, 16, 0xF6BB4B60 ); P( B, C, D, A, 10, 23, 0xBEBFBC70 ); P( A, B, C, D, 13, 4, 0x289B7EC6 ); P( D, A, B, C, 0, 11, 0xEAA127FA ); P( C, D, A, B, 3, 16, 0xD4EF3085 ); P( B, C, D, A, 6, 23, 0x04881D05 ); P( A, B, C, D, 9, 4, 0xD9D4D039 ); P( D, A, B, C, 12, 11, 0xE6DB99E5 ); P( C, D, A, B, 15, 16, 0x1FA27CF8 ); P( B, C, D, A, 2, 23, 0xC4AC5665 ); #undef F #define F(x,y,z) (y ^ (x | ~z)) P( A, B, C, D, 0, 6, 0xF4292244 ); P( D, A, B, C, 7, 10, 0x432AFF97 ); P( C, D, A, B, 14, 15, 0xAB9423A7 ); P( B, C, D, A, 5, 21, 0xFC93A039 ); P( A, B, C, D, 12, 6, 0x655B59C3 ); P( D, A, B, C, 3, 10, 0x8F0CCC92 ); P( C, D, A, B, 10, 15, 0xFFEFF47D ); P( B, C, D, A, 1, 21, 0x85845DD1 ); P( A, B, C, D, 8, 6, 0x6FA87E4F ); P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); P( C, D, A, B, 6, 15, 0xA3014314 ); P( B, C, D, A, 13, 21, 0x4E0811A1 ); P( A, B, C, D, 4, 6, 0xF7537E82 ); P( D, A, B, C, 11, 10, 0xBD3AF235 ); P( C, D, A, B, 2, 15, 0x2AD7D2BB ); P( B, C, D, A, 9, 21, 0xEB86D391 ); #undef F ctx->state[0] += A; ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; } /* * MD5 process buffer */ void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; unsigned long left; if( ilen <= 0 ) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (unsigned long) ilen; ctx->total[0] &= 0xFFFFFFFF; if( ctx->total[0] < (unsigned long) ilen ) ctx->total[1]++; if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); md5_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { md5_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), (void *) input, ilen ); } } static const unsigned char md5_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * MD5 final digest */ void md5_finish( md5_context *ctx, unsigned char output[16] ) { unsigned long last, padn; unsigned long high, low; unsigned char msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_ULONG_LE( low, msglen, 0 ); PUT_ULONG_LE( high, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); md5_update( ctx, (unsigned char *) md5_padding, padn ); md5_update( ctx, msglen, 8 ); PUT_ULONG_LE( ctx->state[0], output, 0 ); PUT_ULONG_LE( ctx->state[1], output, 4 ); PUT_ULONG_LE( ctx->state[2], output, 8 ); PUT_ULONG_LE( ctx->state[3], output, 12 ); } /* * output = MD5( input buffer ) */ void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) { md5_context ctx; md5_starts( &ctx ); md5_update( &ctx, input, ilen ); md5_finish( &ctx, output ); memset( &ctx, 0, sizeof( md5_context ) ); } inadyn-1.99.4/src/os.c000066400000000000000000000072571220055527700144740ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * Copyright (C) 2006 Steve Horbachuk * * 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. */ #include #include #include #include #include "os.h" #include "debug_if.h" #define MAXSTRING 1024 /** The dbg destination. DBG_SYS_LOG for SysLog DBG_STD_LOG for standard console */ static DBG_DEST global_mod_dbg_dest = DBG_STD_LOG; /** Returns the dbg destination. DBG_SYS_LOG for SysLog DBG_STD_LOG for standard console */ DBG_DEST get_dbg_dest(void) { return global_mod_dbg_dest; } void set_dbg_dest(DBG_DEST dest) { global_mod_dbg_dest = dest; } static char *current_time(void) { time_t now; struct tm *timeptr; static const char wday_name[7][3] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static const char mon_name[12][3] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char result[26]; time(&now); timeptr = localtime(&now); sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d:", wday_name[timeptr->tm_wday], mon_name[timeptr->tm_mon], timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, 1900 + timeptr->tm_year); return result; } void os_printf(int prio, char *fmt, ... ) { va_list args; static char message[MAXSTRING + 1]; message[MAXSTRING] = 0; va_start(args, fmt); vsnprintf(message, sizeof(message), fmt, args); va_end(args); #ifdef HAVE_OS_SYSLOG if (get_dbg_dest() == DBG_SYS_LOG) { syslog(prio, "%s",message); } else #endif { printf("%s %s\n", current_time(), message); fflush(stdout); } } /** * Opens the dbg output for the required destination. * * WARNING : Open and Close bg output are quite error prone! * They should be called din pairs! * TODO: * some simple solution that involves storing the dbg output device name (and filename) */ RC_TYPE os_open_dbg_output(DBG_DEST dest, const char *p_prg_name, const char *p_logfile_name) { RC_TYPE rc = RC_OK; set_dbg_dest(dest); switch (get_dbg_dest()) { case DBG_SYS_LOG: if (p_prg_name == NULL) { rc = RC_INVALID_POINTER; break; } rc = os_syslog_open(p_prg_name); break; case DBG_FILE_LOG: if (p_logfile_name == NULL) { rc = RC_INVALID_POINTER; break; } { FILE *pF = freopen(p_logfile_name, "ab", stdout); if (pF == NULL) { rc = RC_FILE_IO_OPEN_ERROR; } break; } case DBG_STD_LOG: default: rc = RC_OK; } return rc; } /** * Closes the dbg output device. */ RC_TYPE os_close_dbg_output(void) { RC_TYPE rc = RC_OK; switch (get_dbg_dest()) { case DBG_SYS_LOG: rc = os_syslog_close(); break; case DBG_FILE_LOG: fclose(stdout); rc = RC_OK; break; case DBG_STD_LOG: default: rc = RC_OK; } return rc; } inadyn-1.99.4/src/os_psos.c000066400000000000000000000031271220055527700155300ustar00rootroot00000000000000/* Copyright (C) 2003-2004 Narcis Ilisei 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. */ #include "os.h" #include "dyndns.h" #include #ifdef PSOS_OS void os_sleep_ms(int ms) { tm_wkafter(MS2TICKS(ms)); } int os_get_socket_error (void) { return errno; } RC_TYPE os_ip_support_startup(void) { return RC_OK; } RC_TYPE os_ip_support_cleanup(void) { return RC_OK; } /* MAIN FUNCTION */ RC_TYPE os_install_signal_handler(void* p_dyndns) { return RC_OK; } /* closes current console */ RC_TYPE close_console_window(void) { return RC_OK; } /* dummy. */ struct hostent FAR *gethostbyname(const char FAR *name ) { return NULL; } RC_TYPE os_syslog_open(const char *p_prg_name) { return RC_OK; } RC_TYPE os_syslog_close(void) { return RC_OK; } RC_TYPE os_change_persona(OS_USER_INFO *p_usr_info) { return RC_OS_CHANGE_PERSONA_FAILURE; } #endif inadyn-1.99.4/src/os_unix.c000066400000000000000000000127641220055527700155360ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * Copyright (C) 2006 Steve Horbachuk * * 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. */ #define MODULE_TAG "" #include "debug_if.h" #include "os.h" #include "dyndns.h" #ifdef UNIX_OS #include #include #include #include "debug_if.h" void os_sleep_ms(int ms) { usleep(ms*1000); } int os_get_socket_error (void) { return errno; } RC_TYPE os_ip_support_startup(void) { return RC_OK; } RC_TYPE os_ip_support_cleanup(void) { return RC_OK; } RC_TYPE os_shell_execute(char *p_cmd, char *ip, char *hostname, char *iface) { RC_TYPE rc = RC_OK; int child; child = vfork(); switch (child) { case 0: /* child */ setenv("INADYN_IP", ip, 1); setenv("INADYN_HOSTNAME", hostname, 1); if (iface) setenv("INADYN_IFACE", iface, 1); execl("/bin/sh", "sh", "-c", p_cmd, (char *) 0); exit(1); break; case -1: rc = RC_OS_FORK_FAILURE; break; default: /* parent */ break; } return rc; } /* storage for the parameter needed by the handler */ static void *global_p_signal_handler_param = NULL; /** * unix_signal_handler - The actual handler * @signo: Signal number * * Handler for registered/known signals. Most others will terminate the daemon. * * NOTE: * Since printf() is one of the possible back-ends of logit(), and printf() is not one * of the safe syscalls to be used, according to POSIX signal(7). The calls are commented, * since they are most likely also only needed for debugging. */ static void unix_signal_handler(int signo) { DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *)global_p_signal_handler_param; if (p_self == NULL) { // logit(LOG_WARNING, MODULE_TAG "Signal %d received. But handler is not installed correctly.", signo); return; } switch (signo) { case SIGHUP: // logit(LOG_DEBUG, MODULE_TAG "Signal %d received. Sending restart command.", signo); p_self->cmd = CMD_RESTART; break; case SIGINT: case SIGQUIT: case SIGALRM: case SIGTERM: // logit(LOG_DEBUG, MODULE_TAG "Signal %d received. Sending shutdown command.", signo); p_self->cmd = CMD_STOP; break; default: // logit(LOG_DEBUG, MODULE_TAG "Signal %d received, ignoring.", signo); break; } return; } /** install handler for SIGALRM and HUP, INT, QUIT, TERM. avoid receiving HUP, INT, QUIT during ALRM and TERM. */ RC_TYPE os_install_signal_handler(void *p_dyndns) { RC_TYPE rc; struct sigaction newact; newact.sa_handler = unix_signal_handler; newact.sa_flags = 0; rc = sigemptyset(&newact.sa_mask) || sigaddset(&newact.sa_mask, SIGHUP) || sigaddset(&newact.sa_mask, SIGINT) || sigaddset(&newact.sa_mask, SIGQUIT) || sigaddset(&newact.sa_mask, SIGTERM) || sigaction(SIGALRM, &newact, NULL) || sigemptyset(&newact.sa_mask) || sigaddset(&newact.sa_mask, SIGALRM) || sigaction(SIGHUP, &newact, NULL) || sigaction(SIGINT, &newact, NULL) || sigaction(SIGQUIT, &newact, NULL) || sigaction(SIGTERM, &newact, NULL); if (rc == RC_OK) { global_p_signal_handler_param = p_dyndns; } return rc; } /* closes current console July 5th, 2004 - Krev *** This function is used to close the console window to start the software as a service on Windows. On Unix, closing the console window isn't used for a daemon, but rather it forks. Modified this function to fork into a daemon mode under Unix-compatible systems. Actions: - for child: - close in and err console - become session leader - change working directory - clear the file mode creation mask - for parent just exit */ RC_TYPE close_console_window(void) { pid_t pid = fork(); if (pid < 0) { return RC_OS_FORK_FAILURE; } if (pid == 0) /* child */ { fclose(stdin); fclose(stderr); setsid(); if (-1 == chdir("/")) { logit(LOG_WARNING, MODULE_TAG "Failed changing cwd to /: %s", strerror(errno)); } umask(0); return RC_OK; } exit(0); return RC_OK; /* Never reached. */ } /* MAIN - Dyn DNS update entry point.*/ int main(int argc, char* argv[]) { return inadyn_main(argc, argv); } RC_TYPE os_syslog_open(const char *p_prg_name) { openlog(p_prg_name, LOG_PID, LOG_USER); return RC_OK; } RC_TYPE os_syslog_close(void) { closelog(); return RC_OK; } RC_TYPE os_change_persona(OS_USER_INFO *p_usr_info) { int rc; do { if (p_usr_info->gid != getgid()) { if ((rc = setgid(p_usr_info->gid)) != 0) { break; } } if (p_usr_info->uid != getuid()) { if ((rc = setuid(p_usr_info->uid)) != 0) { break; } } } while(0); if (rc != 0) { logit(LOG_WARNING, MODULE_TAG "Failed dropping privileges: %s", strerror(errno)); return RC_OS_CHANGE_PERSONA_FAILURE; } return RC_OK; } #endif /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */ inadyn-1.99.4/src/os_windows.c000066400000000000000000000127611220055527700162420ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * Copyright (C) 2006 Steve Horbachuk * * 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. */ #define MODULE_TAG "" #include "debug_if.h" #include "os.h" #include #include "dyndns.h" #ifdef _WIN32 void os_sleep_ms(int ms) { Sleep(ms); } int os_get_socket_error (void) { return WSAGetLastError(); } RC_TYPE os_ip_support_startup(void) { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ return RC_IP_OS_SOCKET_INIT_FAILED; } /* The WinSock DLL is acceptable. Proceed. */ return RC_OK; } RC_TYPE os_ip_support_cleanup(void) { WSACleanup(); return RC_OK; } /* OS SIGNALS Support */ static OS_SIGNAL_HANDLER_TYPE global_os_handler = { NULL, NULL}; typedef struct { DWORD original; int translated; } OS_EVENT_TYPE; static const OS_EVENT_TYPE os_events_table [] = { {CTRL_C_EVENT, OS_CTRL_C_SIGNAL}, {CTRL_CLOSE_EVENT, OS_CTRL_CLOSE_SIGNAL}, {CTRL_BREAK_EVENT, OS_CTRL_BREAK_SIGNAL}, {CTRL_LOGOFF_EVENT, OS_CTRL_LOGOFF_SIGNAL}, {CTRL_SHUTDOWN_EVENT, OS_CTRL_SHUTDOWN_SIGNAL}, {-1, LAST_SIGNAL} }; static int translate_os_signal(DWORD in) { const OS_EVENT_TYPE *it = os_events_table; while (it->original != -1) { if (it->original == in) { return it->translated; } ++it; } return -1; } static BOOL WINAPI os_signal_wrapper_handler( DWORD dwCtrlType) { OS_SIGNAL_TYPE signal; signal.signal = translate_os_signal(dwCtrlType); signal.p_in_data = NULL; signal.p_out_data = NULL; if (global_os_handler.p_func != NULL) { return global_os_handler.p_func(signal, global_os_handler.p_in_data) ? 1 : 0; } else { return 0; } } /** The actual signal handler for Windows. Does not respond on LOGOFF signal. Exits on shutdown ..., Ctl-C,... */ static int dyndns_win32_signal_handler_func(OS_SIGNAL_TYPE signal, void *p_in) { int ret_flag = 0; DYN_DNS_CLIENT *p_self = (DYN_DNS_CLIENT *) p_in; if (p_self == NULL) { return 0; } switch (signal.signal) { case OS_CTRL_C_SIGNAL : case OS_CTRL_CLOSE_SIGNAL : case OS_CTRL_BREAK_SIGNAL : case OS_CTRL_SHUTDOWN_SIGNAL : logit(LOG_INFO, MODULE_TAG "Signal %d received. Sending shutdown command.", signal); ret_flag = 1; p_self->cmd = CMD_STOP; break; case OS_CTRL_LOGOFF_SIGNAL : default: logit(LOG_DEBUG, MODULE_TAG "Signal %d received. NO ACTION.", signal); } return ret_flag; } /* MAIN FUNCTION */ RC_TYPE os_install_signal_handler(void *p_dyndns) { BOOL fSuccess; if (global_os_handler.p_func != NULL || p_dyndns == NULL) { return RC_OS_ERROR_INSTALLING_SIGNAL_HANDLER; } fSuccess = SetConsoleCtrlHandler( (PHANDLER_ROUTINE) os_signal_wrapper_handler, /* handler function */ TRUE); /* add to list */ if (fSuccess) { global_os_handler.p_func = dyndns_win32_signal_handler_func; global_os_handler.p_in_data = p_dyndns; return RC_OK; } else { return RC_OS_ERROR_INSTALLING_SIGNAL_HANDLER; } } /* closes current console A rather bad function. I am pretty sure that there is another way to into background under Windows. */ RC_TYPE close_console_window(void) { fclose(stdin); fclose(stderr); FreeConsole( ); return RC_OK; } RC_TYPE os_syslog_open(const char *p_prg_name) { return RC_OK; } RC_TYPE os_syslog_close(void) { return RC_OK; } /* thanks pagedude */ RC_TYPE os_shell_execute(char * p_cmd) { RC_TYPE rc = RC_OK; HANDLE hProcess = NULL; SHELLEXECUTEINFO shellInfo; ZeroMemory(&shellInfo, sizeof(shellInfo)); shellInfo.cbSize = sizeof(shellInfo); shellInfo.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; shellInfo.lpFile = p_cmd; /*shellInfo.lpParameters = args;*/ if (!ShellExecuteEx(&shellInfo)) { rc = RC_OS_FORK_FAILURE; } return rc; } static unsigned long os_get_inet_addr(char* addr) { unsigned long b3; unsigned long b2; unsigned long b1; unsigned long b0; unsigned long ipa; int n; ipa = 0x0; n = sscanf(addr, "%d.%d.%d.%d", &b3, &b2, &b1, &b0); if (n == 4) { ipa = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; } ipa = htonl(ipa); return(ipa); } /* MAIN - Dyn DNS update entry point.*/ int main(int argc, char* argv[]) { return inadyn_main(argc, argv); } RC_TYPE os_change_persona(OS_USER_INFO *p_usr_info) { return RC_OS_CHANGE_PERSONA_FAILURE; } #endif /*WIN32*/ inadyn-1.99.4/src/sha1.c000066400000000000000000000210111220055527700146670ustar00rootroot00000000000000/* * FIPS-180-1 compliant SHA-1 implementation * * Copyright (C) 2006-2010, Brainspark B.V. * * This file is part of PolarSSL (http://www.polarssl.org) * Lead Maintainer: Paul Bakker * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /* * The SHA-1 standard was published by NIST in 1993. * * http://www.itl.nist.gov/fipspubs/fip180-1.htm */ #include "sha1.h" /* * 32-bit integer manipulation macros (big endian) */ #ifndef GET_ULONG_BE #define GET_ULONG_BE(n,b,i) \ { \ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \ | ( (unsigned long) (b)[(i) + 1] << 16 ) \ | ( (unsigned long) (b)[(i) + 2] << 8 ) \ | ( (unsigned long) (b)[(i) + 3] ); \ } #endif #ifndef PUT_ULONG_BE #define PUT_ULONG_BE(n,b,i) \ { \ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ (b)[(i) + 3] = (unsigned char) ( (n) ); \ } #endif /* * SHA-1 context setup */ void sha1_starts( sha1_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; } static void sha1_process( sha1_context *ctx, const unsigned char data[64] ) { unsigned long temp, W[16], A, B, C, D, E; GET_ULONG_BE( W[ 0], data, 0 ); GET_ULONG_BE( W[ 1], data, 4 ); GET_ULONG_BE( W[ 2], data, 8 ); GET_ULONG_BE( W[ 3], data, 12 ); GET_ULONG_BE( W[ 4], data, 16 ); GET_ULONG_BE( W[ 5], data, 20 ); GET_ULONG_BE( W[ 6], data, 24 ); GET_ULONG_BE( W[ 7], data, 28 ); GET_ULONG_BE( W[ 8], data, 32 ); GET_ULONG_BE( W[ 9], data, 36 ); GET_ULONG_BE( W[10], data, 40 ); GET_ULONG_BE( W[11], data, 44 ); GET_ULONG_BE( W[12], data, 48 ); GET_ULONG_BE( W[13], data, 52 ); GET_ULONG_BE( W[14], data, 56 ); GET_ULONG_BE( W[15], data, 60 ); #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define R(t) \ ( \ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \ ( W[t & 0x0F] = S(temp,1) ) \ ) #define P(a,b,c,d,e,x) \ { \ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ } A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; E = ctx->state[4]; #define F(x,y,z) (z ^ (x & (y ^ z))) #define K 0x5A827999 P( A, B, C, D, E, W[0] ); P( E, A, B, C, D, W[1] ); P( D, E, A, B, C, W[2] ); P( C, D, E, A, B, W[3] ); P( B, C, D, E, A, W[4] ); P( A, B, C, D, E, W[5] ); P( E, A, B, C, D, W[6] ); P( D, E, A, B, C, W[7] ); P( C, D, E, A, B, W[8] ); P( B, C, D, E, A, W[9] ); P( A, B, C, D, E, W[10] ); P( E, A, B, C, D, W[11] ); P( D, E, A, B, C, W[12] ); P( C, D, E, A, B, W[13] ); P( B, C, D, E, A, W[14] ); P( A, B, C, D, E, W[15] ); P( E, A, B, C, D, R(16) ); P( D, E, A, B, C, R(17) ); P( C, D, E, A, B, R(18) ); P( B, C, D, E, A, R(19) ); #undef K #undef F #define F(x,y,z) (x ^ y ^ z) #define K 0x6ED9EBA1 P( A, B, C, D, E, R(20) ); P( E, A, B, C, D, R(21) ); P( D, E, A, B, C, R(22) ); P( C, D, E, A, B, R(23) ); P( B, C, D, E, A, R(24) ); P( A, B, C, D, E, R(25) ); P( E, A, B, C, D, R(26) ); P( D, E, A, B, C, R(27) ); P( C, D, E, A, B, R(28) ); P( B, C, D, E, A, R(29) ); P( A, B, C, D, E, R(30) ); P( E, A, B, C, D, R(31) ); P( D, E, A, B, C, R(32) ); P( C, D, E, A, B, R(33) ); P( B, C, D, E, A, R(34) ); P( A, B, C, D, E, R(35) ); P( E, A, B, C, D, R(36) ); P( D, E, A, B, C, R(37) ); P( C, D, E, A, B, R(38) ); P( B, C, D, E, A, R(39) ); #undef K #undef F #define F(x,y,z) ((x & y) | (z & (x | y))) #define K 0x8F1BBCDC P( A, B, C, D, E, R(40) ); P( E, A, B, C, D, R(41) ); P( D, E, A, B, C, R(42) ); P( C, D, E, A, B, R(43) ); P( B, C, D, E, A, R(44) ); P( A, B, C, D, E, R(45) ); P( E, A, B, C, D, R(46) ); P( D, E, A, B, C, R(47) ); P( C, D, E, A, B, R(48) ); P( B, C, D, E, A, R(49) ); P( A, B, C, D, E, R(50) ); P( E, A, B, C, D, R(51) ); P( D, E, A, B, C, R(52) ); P( C, D, E, A, B, R(53) ); P( B, C, D, E, A, R(54) ); P( A, B, C, D, E, R(55) ); P( E, A, B, C, D, R(56) ); P( D, E, A, B, C, R(57) ); P( C, D, E, A, B, R(58) ); P( B, C, D, E, A, R(59) ); #undef K #undef F #define F(x,y,z) (x ^ y ^ z) #define K 0xCA62C1D6 P( A, B, C, D, E, R(60) ); P( E, A, B, C, D, R(61) ); P( D, E, A, B, C, R(62) ); P( C, D, E, A, B, R(63) ); P( B, C, D, E, A, R(64) ); P( A, B, C, D, E, R(65) ); P( E, A, B, C, D, R(66) ); P( D, E, A, B, C, R(67) ); P( C, D, E, A, B, R(68) ); P( B, C, D, E, A, R(69) ); P( A, B, C, D, E, R(70) ); P( E, A, B, C, D, R(71) ); P( D, E, A, B, C, R(72) ); P( C, D, E, A, B, R(73) ); P( B, C, D, E, A, R(74) ); P( A, B, C, D, E, R(75) ); P( E, A, B, C, D, R(76) ); P( D, E, A, B, C, R(77) ); P( C, D, E, A, B, R(78) ); P( B, C, D, E, A, R(79) ); #undef K #undef F ctx->state[0] += A; ctx->state[1] += B; ctx->state[2] += C; ctx->state[3] += D; ctx->state[4] += E; } /* * SHA-1 process buffer */ void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) { size_t fill; unsigned long left; if( ilen <= 0 ) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (unsigned long) ilen; ctx->total[0] &= 0xFFFFFFFF; if( ctx->total[0] < (unsigned long) ilen ) ctx->total[1]++; if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); sha1_process( ctx, ctx->buffer ); input += fill; ilen -= fill; left = 0; } while( ilen >= 64 ) { sha1_process( ctx, input ); input += 64; ilen -= 64; } if( ilen > 0 ) { memcpy( (void *) (ctx->buffer + left), (void *) input, ilen ); } } static const unsigned char sha1_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * SHA-1 final digest */ void sha1_finish( sha1_context *ctx, unsigned char output[20] ) { unsigned long last, padn; unsigned long high, low; unsigned char msglen[8]; high = ( ctx->total[0] >> 29 ) | ( ctx->total[1] << 3 ); low = ( ctx->total[0] << 3 ); PUT_ULONG_BE( high, msglen, 0 ); PUT_ULONG_BE( low, msglen, 4 ); last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); sha1_update( ctx, (unsigned char *) sha1_padding, padn ); sha1_update( ctx, msglen, 8 ); PUT_ULONG_BE( ctx->state[0], output, 0 ); PUT_ULONG_BE( ctx->state[1], output, 4 ); PUT_ULONG_BE( ctx->state[2], output, 8 ); PUT_ULONG_BE( ctx->state[3], output, 12 ); PUT_ULONG_BE( ctx->state[4], output, 16 ); } /* * output = SHA-1( input buffer ) */ void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) { sha1_context ctx; sha1_starts( &ctx ); sha1_update( &ctx, input, ilen ); sha1_finish( &ctx, output ); memset( &ctx, 0, sizeof( sha1_context ) ); } inadyn-1.99.4/src/tcp.c000066400000000000000000000142621220055527700146330ustar00rootroot00000000000000/* * Copyright (C) 2003-2004 Narcis Ilisei * * 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. */ #define MODULE_TAG "" #include #include #include "debug_if.h" #include "tcp.h" /* basic resource allocations for the tcp object */ RC_TYPE tcp_construct(TCP_SOCKET *p_self) { RC_TYPE rc; if (p_self == NULL) { return RC_INVALID_POINTER; } rc = ip_construct(&p_self->super); if (rc != RC_OK) { return rc; } /*reset its part of the struct (skip IP part)*/ memset(((char*)p_self + sizeof(p_self->super)) , 0, sizeof(*p_self) - sizeof(p_self->super)); p_self->initialized = FALSE; return RC_OK; } /* Resource free. */ RC_TYPE tcp_destruct(TCP_SOCKET *p_self) { if (p_self == NULL) { return RC_OK; } if (p_self->initialized == TRUE) { tcp_shutdown(p_self); } return ip_destruct(&p_self->super); } static RC_TYPE local_set_params(TCP_SOCKET *p_self) { int timeout; /* Set default TCP specififc params */ tcp_get_remote_timeout(p_self, &timeout); if (timeout == 0) { tcp_set_remote_timeout(p_self, TCP_DEFAULT_TIMEOUT); } return RC_OK; } /* Sets up the object. - ... */ RC_TYPE tcp_initialize(TCP_SOCKET *p_self, char *msg) { RC_TYPE rc; struct timeval sv; int svlen = sizeof(sv); char host[NI_MAXHOST]; do { local_set_params(p_self); /*call the super*/ rc = ip_initialize(&p_self->super); if (rc != RC_OK) { break; } /* local object initalizations */ if (p_self->super.type == TYPE_TCP) { p_self->super.socket = socket(AF_INET, SOCK_STREAM, 0); if (p_self->super.socket == -1) { int code = os_get_socket_error(); logit(LOG_ERR, MODULE_TAG "Error creating client socket: %s", strerror(code)); rc = RC_IP_SOCKET_CREATE_ERROR; break; } /* Call to socket() OK, allow tcp_shutdown() to run to * prevent socket leak if any of the below calls fail. */ p_self->initialized = TRUE; if (p_self->super.bound == TRUE) { if (bind(p_self->super.socket, (struct sockaddr *)&p_self->super.local_addr, sizeof(struct sockaddr_in)) < 0) { int code = os_get_socket_error(); logit(LOG_WARNING, MODULE_TAG "Failed binding client socket to local address: %s", strerror(code)); rc = RC_IP_SOCKET_BIND_ERROR; break; } } } else { p_self->initialized = TRUE; /* Allow tcp_shutdown() to run. */ rc = RC_IP_BAD_PARAMETER; } /* set timeouts */ sv.tv_sec = p_self->super.timeout / 1000; /* msec to sec */ sv.tv_usec = (p_self->super.timeout % 1000) * 1000; /* reminder to usec */ setsockopt(p_self->super.socket, SOL_SOCKET, SO_RCVTIMEO, &sv, svlen); setsockopt(p_self->super.socket, SOL_SOCKET, SO_SNDTIMEO, &sv, svlen); if (!getnameinfo(&p_self->super.remote_addr, p_self->super.remote_len, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) { logit(LOG_INFO, "%s, connecting to %s(%s)", msg, p_self->super.p_remote_host_name, host); } if (0 != connect(p_self->super.socket, &p_self->super.remote_addr, p_self->super.remote_len)) { int code = os_get_socket_error(); logit(LOG_WARNING, MODULE_TAG "Failed connecting to remote server: %s", strerror(code)); rc = RC_IP_CONNECT_FAILED; break; } } while (0); if (rc != RC_OK) { tcp_shutdown(p_self); return rc; } return RC_OK; } /* Disconnect and some other clean up. */ RC_TYPE tcp_shutdown(TCP_SOCKET *p_self) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_OK; } p_self->initialized = FALSE; return ip_shutdown(&p_self->super); } /* send data*/ RC_TYPE tcp_send(TCP_SOCKET *p_self, const char *p_buf, int len) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_TCP_OBJECT_NOT_INITIALIZED; } return ip_send(&p_self->super, p_buf, len); } /* receive data*/ RC_TYPE tcp_recv(TCP_SOCKET *p_self,char *p_buf, int max_recv_len, int *p_recv_len) { if (p_self == NULL) { return RC_INVALID_POINTER; } if (!p_self->initialized) { return RC_TCP_OBJECT_NOT_INITIALIZED; } return ip_recv(&p_self->super, p_buf, max_recv_len, p_recv_len); } /* Accessors*/ RC_TYPE tcp_set_port(TCP_SOCKET *p_self, int p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return ip_set_port(&p_self->super, p); } RC_TYPE tcp_set_remote_name(TCP_SOCKET *p_self, const char* p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return ip_set_remote_name(&p_self->super, p); } RC_TYPE tcp_set_remote_timeout(TCP_SOCKET *p_self, int p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return ip_set_remote_timeout(&p_self->super, p); } RC_TYPE tcp_set_bind_iface(TCP_SOCKET *p_self, char *ifname) { if (p_self == NULL) { return RC_INVALID_POINTER; } return ip_set_bind_iface(&p_self->super, ifname); } RC_TYPE tcp_get_port(TCP_SOCKET *p_self, int *p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return ip_get_port(&p_self->super, p); } RC_TYPE tcp_get_remote_name(TCP_SOCKET *p_self, const char **p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return ip_get_remote_name(&p_self->super, p); } RC_TYPE tcp_get_remote_timeout(TCP_SOCKET *p_self, int *p) { if (p_self == NULL) { return RC_INVALID_POINTER; } return ip_get_remote_timeout(&p_self->super, p); } RC_TYPE tcp_get_bind_iface(TCP_SOCKET *p_self, char **ifname) { if (p_self == NULL || ifname == NULL) { return RC_INVALID_POINTER; } return ip_get_bind_iface(&p_self->super, ifname); } /** * Local Variables: * version-control: t * indent-tabs-mode: t * c-file-style: "ellemtel" * c-basic-offset: 8 * End: */