rp-pppoe-3.15/0000755000175000017500000000000014045237010011312 5ustar dfsdfsrp-pppoe-3.15/doc/0000755000175000017500000000000014045237010012057 5ustar dfsdfsrp-pppoe-3.15/doc/CHANGES0000644000175000017500000003357414045237010013066 0ustar dfsdfs# LIC: GPL Changes from version 3.14 to 3.15: - Release 3.15 (2021-05-07) - src/pppoe.c: Don't ignore SIGTERM and SIGINT. Send PADT and exit if one of those signals is received. - General: Switch from net-tools (ifconfig and friends) to iproute2 (ip ...) on Linux. Changes from version 3.13 to 3.14: - Release 3.14 (2020-05-26) - Delete scripts/pppoe-init-turbolinux.in - TurboLinux is defunct. - pppoe-server: Add -H and -M options for sending HURL and MOTM packets respectively. - Change VERSION macro to RP_VERSION to avoid conflict with pppd macro. - Apply all of the patches at https://github.com/nabijaczleweli/rp-pppoe/tree/patches/0006-touchups-3.14-BETA-2-v1 which fix up various compile-time warnings. - Apply all of the patches at https://github.com/nabijaczleweli/rp-pppoe/tree/patches/0004-mostly-cosmetic-3.14-BETA-1-v1 which implement the following 6 changes: - 1. Clarify a couple of comments - 2. Remove the '@' before the command that installs the plugin, in the Makefile - 3. Fix a typo in doc/HOW-TO-CONNECT - 4. Use echo instead of /bin/echo in scripts - 5. Fix potential snprintf(...) truncation - 6. Cosmetic fix to copyright printout - Apply all the patches at https://github.com/nabijaczleweli/rp-pppoe/tree/patches/0002-pppd-bugfixes-3.13-v1 which implement the following 13 changes: - 1. Don't exit if we time out waiting for PADO/PADS packets if persist option set - 2. Remove unused variable - 3. Don't error out if device is not Ethernet if doit is 0 in PPPoEDevnameHook - 4. Use one 8-bit bitfield and macros for both ver and type in PPPoEPacket - 5. Remove unnecessary casts from common.c - 6. Replace strDup() with POSIX strdup(3) - 7. Extract expiration check into time_left() function - 8. Suppress false error message on PPPoE disconnect - 9. Send PADT on PPPoE disconnect - 10. Various fixes for errors found by coverity static analysis - 11. Remove all references to cdefs.h - 12. Eliminate snprintf-related compiler warning in plugin.c - 13. Make tag parsing loop condition more accurate Changes from version 3.12 to 3.13: - Release 3.13 (2018-11-25) - Fix potential use-after-free bug - Properly detecte kernel-mode PPPoE; fix compilation problems on Debian Jessie and Debian Stretch. Changes from version 3.11 to 3.12: - Update author's name to "Dianne Skoll" - Add "-W" option to pppoe executable to explicitly set a Host-Unique value - Fix a few compiler warnings and configure script bugs. - Removed dead code Changes from Version 3.10 to 3.11: - Make the rp-pppoe.so plugin avoid calling exit() if the "persist" pppd option was given. - Permit both PPPoE server and client to specify an MTU/MRU of 1500 assuming the underlying Ethernet interface has an MTU of at least 1508. The larger MTU is negotiated per RFC 4638. NOTE: Only available with kernel-mode plugin, not user-mode pty redirector. - Get rid of hard-coded nobsdcomp, nodeflate, novj and novjccomp options in pppoe-server. - Apply patch from Philip Prindeville to allow cross-compiling. - Handle UNIT=xxx directive in pppoe-connect. (Keith Waters) - Add "-i" flag to pppoe-server to ignore PADIs if there are no free sessions. Change suggested by Miroslav Lednicky. - Ignore PADTs not destined for our ethernet address. - Add "-X " option to pppoe-server. - Cleanup Makefile.in. (Philip Prindeville) - In plugin, don't set devnam if it's already set. (Mike Ireton) - Eliminate race condition in signal handling. - pppoe-server: Add -q and -Q options to allow specification of path to pppd and pppoe programs respectively. - Add a few more sanity checks to pppoe-server packet handling. - Use -fno-strict-aliasing when compiling with gcc to avoid possible problems from -O2 optimization level. Changes from Version 3.9 to 3.10: (30 June 2008) - Fixed compilation problems on various platforms. - The Makefiles now use (standard) DESTDIR instead of (non-standard) RPM_INSTALL_ROOT to relocate installed files. - Spec file has been updated (it had languished since 3.6.) Changes from Version 3.8 to 3.9: (21 June 2008) - pppoe-server has new "-x" option to limit the number of sessions per MAC address. - Added proper timeout handling while waiting for PADO/PADS. - Fix race condition with some access concentrators that move very quickly into session mode (problem noted by Luigi Sgro) - Fixed compilation problem on BSD. - Fixed compilation problems with old versions of gcc - Remove superfluous options in scripts/pppoe-connect.in Changes from Version 3.7 to 3.8: (2 April 2006) - Adjusted code and made it possible to disable debugging code to shrink size of pppoe executable. - Fixed bug in MD5 code that caused pppoe-server to segfault on 64-bit machines. - Made various functions and variables static that didn't need to be visible outside their source files. Changes from Version 3.6 to 3.7: - Fixed typo in the firewall-standalone sample firewall script. Fix courtesy of Robert Vogelgesang - Added -O option to pppoe-server to let you specify a different default options file for pppd instead of /etc/ppp/pppoe-server-options Feature courtesy of Robert Vogelgesang - Fixed some silliness and incorrectness in configure.in. Feature courtesy of Robert Vogelgesang - Fixed a typo in pppoe-connect.in that made it fail if used with the kernel-mode plugin. - Make pppoe-server prepend "nic-" to interface name if used with kernel-mode plugin. This lets you use interfaces that don't start with "eth" more easily. Changes from Version 3.5 to 3.6: - Changed the names of commands from adsl-* to pppoe-* to more logically name the scripts. NOTE INCOMPATIBILITY: OLD NAME NEW NAME adsl-start pppoe-start adsl-stop pppoe-stop adsl-status pppoe-status adsl-connect pppoe-connect adsl-setup pppoe-setup - Changed sample firewall scripts to use iptables instead of the old ipchains command. - Updated KERNEL-MODE-PPPOE instructions to reflect more modern pppd that is commonly distributed. - Make the userland pppoe daemon run as "nobody" if possible, once session has started. - Make userland pppoe program somewhat safe if it is installed SUID or SGID. Note that I still do *NOT* recommend a SUID/SGID pppoe. - Fix long-standing bug in pppoe-server that passed arguments to pppd in the wrong order. - Fix kernel-mode plugin. It was broken by changes to pppd. The pppd maintainers fixed their version of the plugin, but neglected to inform me. Thanks a lot, guys! - Make plugin accept argument of the form "nix-XXXX" to force it to use device "XXXX" as the Ethernet interface. This allows the use of devices whose names do not start with "eth" Changes from Version 3.4 to 3.5: - Fixes for compilation on Solaris. Changes from Version 3.3 to 3.4: - INCOMPATIBILITY WITH EARLIER VERSIONS: Kernel-mode plugin now is built against latest CVS ppp source rather than Michal Ostrowski's patched version. If you use kernel-mode PPPoE, you MUST use the CVS version of the ppp source code with rp-pppoe 3.4. - Print PPPoE session number when connection terminates. Thanks to Alexander Dalloz for suggesting this. - Fixed a bug in MSS clamping -- it now works with protocol-field compression. Thanks to Gerd v. Egidy for the patch. - Ignore SIGINT and SIGTERM so LCP termination packets make it out. Changes from Version 3.2 to 3.3: - Client works on Solaris again. It was broken in 3.2. - Added DEFAULTROUTE=yes|no option to configuration file. - Server parses address pool file better. - Server address pool allows ranges of addresses on a line: a.b.c.d-e - Added "-d" (=debug) and "-P" (=check pool file syntax) options to pppoe-server. Changes from Version 3.1 to 3.2: - Client now ignores PADT's if they are from the wrong source MAC address or to the wrong destination MAC address. - Minor fixes to Makefile.in for Turbolinux. Changes from Version 3.0 to 3.1: - Improved KERNEL-MODE-PPPOE instructions - Works with patched pppd 2.4.1 - Many improvements to server: Added "-u" and "-r" options; server can now respond to request on multiple Ethernet interfaces. - SECURITY BUG FIX: Server now ignores PADT's if they are from the wrong source MAC address. You are STRONGLY RECOMMENDED to upgrade to 3.1 if you use pppoe-server in production. Changes from Version 2.8 to 3.0: - Many small improvements to server. Server now only makes one discovery socket, systemwide, with addition of "-n" option to pppoe. - Fixes for compilation problems on BSD, Solaris and some Linux platforms. - Added "-p" option to pppoe-server to allow you to specify a pool of IP addresses to assign to clients. - Added GUI system (tkpppoe). This work was funded by Iospan Wireless, Inc. The GUI includes a Set-UID wrapper (pppoe-wrapper) which allows ordinary users to control a link (if so authorized.) I believe the wrapper script is secure, but please audit the source code (gui/wrapper.c) if you have any concerns. - Changes to scripts and pppoe.conf. DNS setup is now dynamic (happens each time adsl-connect runs.) - Made relay.c check packet lengths rigorously; made it throw out Ethernet frame padding on session packets as well as discovery packets. Changes from Version 2.7 to 2.8: - Added init scripts for TurboLinux, courtesy of Yasuhiro Sumi. - Made relay.c check packet lengths rigorously; made it throw out Ethernet frame padding on discovery packets. *** NOTE: 2.7 was not released publicly Changes from Version 2.6 to 2.7: - Completely restructured source file tree. - Much internal restructuring to eliminate a bunch of global variables. - adsl-connect now executes /etc/ppp/adsl-lost whenever connection is dropped or cannot be established. - Split pppoe.c into pppoe.c and discovery.c. - Added relay agent (pppoe-relay). - Made adsl-connect script use the "-U" (host-unique) option to better support multiple PPPoE links. - Added support for kernel-mode PPPoE (EXPERIMENTAL, UNSUPPORTED!) - Added "-o" option to PPPoE server; encoded server PID in pppoe-server cookie. Changes from Version 2.5 to 2.6: - Code should now compile cleanly on Caldera and Slackware Linux - Fixed rp-pppoe.spec file to work on Mandrake and Red Hat. - Deleted some obsolete files - Fixed bug in Solaris/x86 port (thanks to Philippe Levan) - Made shell scripts nicer under Solaris (again, Philippe Levan) - Made adsl-status look under /var/run and /etc/ppp for PID files. Should fix problems with NetBSD. - Added PPPD_EXTRA to pppoe.conf; made the PID file depend on the config file name. This makes it easier to run multiple PPPoE sessions. Changes from Version 2.4 to 2.5: - Tested for zero-length TCP option-length field, and for reverse-packing of type/code bitfields. Thanks to Robert Schlabbach for pointing out these problems. - Set umask to 077 in adsl-setup.in to protect created files like /etc/ppp/pap-secrets. Changes from Version 2.3 to 2.4: - Fixed spec file to automatically add .gz extension to man files as required - Tightened firewall rules. - Better check for /var/run in adsl-status; minor shell script fixes and cleanups for NetBSD and Solaris. - Added FAQ to HOW-TO-CONNECT regarding running a script each time a connection is made. Changes from Version 2.2 to 2.3: - Fixed the init script to create/remove /var/lock/subsys/adsl (patch courtesy of Charley Carter.) - Added support (under Linux) for N_HDLC line discipline which should greatly reduce CPU usage. My tests show it cuts CPU usage in half. My 486 DX2/66 gets 800 kb/s at 22% CPU usage. - adsl-connect uses "setsid" (if available) so that adsl-stop doesn't kill its caller. There is (IMO) a bug in pppd which kills all processes in its process group if the "pty" option is used. The setsid program gets around this bug, on Linux at least. - Port to Solaris, courtesy of David Holland. - Renamed spec file from "spec" to "rp-pppoe.spec" and made some cleanups. NOTE: Red Hat, in their infinite wisdom, decided to make the new RPM compress man pages automatically. You may have problems building RPM's from source unless you get the latest rpm package and make sure it compresses man pages. Changes from Version 2.1 to 2.2: - Added "-f" option to pppoe to allow use of any Ethernet frame type for PPPoE. USE WITH CAUTION -- this is a workaround for broken DSL providers, not something you should monkey with freely! - Added pppoe-sniff program to help expose non-standard PPPoE implementations. Changes from Version 2.0 to 2.1: - Fixed minor bugs in bounds-checking - Modified adsl-status to use output of "netstat -r -n" to determine whether or not link is up. This should make it independent of locale, I hope! - Added "-k" and "-d" options to pppoe. Changes from Version 1.9 to 2.0: - Addition of pppoe-server - Massive internal code restructuring - Zealous bounds-checking everywhere. - adsl-setup now quotes user name and password in /etc/ppp/pap-secrets. - Ported to OpenBSD, FreeBSD and NetBSD, courtesy of Geoff Mottram and Yannis Sismanis. - Rearranged adsl-* shell scripts, courtesy of Heiko Schlittermann. - Fixed bug in which Host-Uniq did not work if access concentrator sent a cookie. - Addition of SuSE-specific "init" script, courtesy of Gary Cameron. Changes from Version 1.8 to 1.9: - Added some more documentation to HOW-TO-CONNECT - Demand-dialling option now works correctly - SIGHUP terminates pppoe after sending a PADT to the access concentrator - Minor cleanups to connection shell scripts Changes from Version 1.7 to 1.8: - Added demand-dialling option - Clarified HOW-TO-CONNECT - Added adsl-status script - Added "restart" and "status" options to Red Hat /etc/rc.d/init.d/adsl script - Made adsl-setup check for existence of pppd - Wildcarded external interface in firewall rules - Made pppoe send a PADT frame if connection is terminated $Id$ rp-pppoe-3.15/doc/LICENSE0000644000175000017500000004325614045237010013076 0ustar dfsdfs# LIC: GPL GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. rp-pppoe-3.15/doc/HOW-TO-CONNECT0000644000175000017500000002321614045237010014052 0ustar dfsdfs# LIC: GPL $Id$ This package lets you connect a Linux machine to an ISP that uses PPPoE. PPPoE is used by many DSL providers and some wireless providers. Follow these steps and you should have your PPPoE service up and running. 0. Install the rp-pppoe-software -------------------------------- You should have already done this by the time you're reading this. If not, go back and read README. 1. Set up your Ethernet hardware -------------------------------- First, make sure the Ethernet card you intend to use with the modem is visible to the Linux kernel. Just how to do this is beyond the scope of this document. However, if the card is the only Ethernet card in the system, executing: ip link show eth0 should display something like this: 2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000 link/ether fc:aa:15:39:a7:b3 brd ff:ff:ff:ff:ff:ff Your second line will most definately be different. As long as you see the link/ether line, your card should be working. DO NOT assign an IP address to the Ethernet card. DO NOT configure the card to come up at boot time. 2. Configure various files -------------------------- Several files need editing. The easiest way to do this is to run the following command as root: pppoe-setup Answer the questions and you should be all set. If you want to know what goes on behind the scenes, continue reading this document. If you don't care and your connection works, stop reading. :-) 3. Edit pap-secrets ------------------- Edit the "pap-secrets" file, inserting your proper user-ID and password. Install the file (or copy the relevant lines) to /etc/ppp/pap-secrets. Your ISP may use CHAP authentication. In this case, add the line to /etc/ppp/chap-secrets. 4. Edit /etc/ppp/pppoe.conf ----------------------------- The file /etc/ppp/pppoe.conf contains configuration information for the DSL connection. You need to edit the following items: - Change ETH=eth1 to the correct Ethernet device for your modem. - Change USER=bxxxnxnx@sympatico.ca to your proper DSL user-ID. Don't edit any of the other settings unless you're an expert. 5. Set up DNS ------------- If you are using DNS servers supplied by your ISP, edit the file /etc/resolv.conf to contain these lines: nameserver ip_addr_of_first_dns_server nameserver ip_addr_of_second_dns_server For example: nameserver 204.101.251.1 nameserver 204.101.251.2 6. Firewall your machine ------------------------ MAKE SURE YOU FIREWALL YOUR MACHINE. A sample firewall script is given in the shell script "firewall" To install the script: a) Copy it to /etc/rc.d/init.d/firewall b) Type: chkconfig firewall on c) Start the firewall: sh /etc/rc.d/init.d/firewall start (The above procedure works ONLY on Red Hat-like systems.) You may want to tweak the script somewhat. 7. Bring up the connection at boot time --------------------------------------- On a Red Hat system, the installation procedure should have installed a script called /etc/rc.d/init.d/pppoe. To bring up the connection at boot time, just type this command as root: chkconfig --add pppoe On non-Red-Hat systems, add this line to the end of /etc/rc.d/rc.local: /usr/sbin/pppoe-start 8. Configure LAN Hosts ---------------------- If you have a LAN behind the firewall, you have to lower the TCP maximum segment size from the normal 1460 to 1452 (or better, 1412.) You have two options: Either set the MTU of all the interfaces on other hosts on the LAN to 1452, or use the "-m 1412" option to pppoe. The "-m" option for pppoe is far simpler and makes it easier to add hosts to the LAN, but consumes some extra CPU time. If you want to manually configure the LAN hosts, here's how: In Linux, use: "ip link set eth0 mtu 1452". For best results, put this in an /etc/rc.d/rc.local script. For Windows, machines, see http://lan.cns.ksu.edu/OS/WIN95/slip95.htm. Set the MaxMTU to 1452. 9. Commands to control the PPPoE link ------------------------------------- As root, bring up the link by typing: pppoe-start As root, bring down the link by typing: pppoe-stop That's it! -- Dianne Skoll https://dianne.skoll.ca/projects/rp-pppoe/ | PROBLEMS! DIANNE, IT DOESN'T WORK! --------------------------------- Here are some problems PPPoE users have encountered. ----------------------------------------------------------------------------- A) Can't see the Ethernet interface Well, I can't really help you here. To use these instructions, you must have Linux working to the point where it recognizes your Ethernet card. If you type "ip link show ethx" and you get back a hardware address value in the line that begins with link/ether, your Ethernet card is probably OK. But I really can't help with hardware configuration issues. ----------------------------------------------------------------------------- B) Connection seems to come up, but I can't browse the web or ping anything You probably don't have DNS set up. See step 6. ----------------------------------------------------------------------------- C) Can't compile PPPoE Make sure you have "make", the C compiler and all development header files installed. I only test rp-pppoe on Linux. It might not work on *BSD and probably won't work on any other version of UNIX. ----------------------------------------------------------------------------- D) pppd complains about (i) "unknown option pty" or (ii) "pty option precludes specifying device name" (i) Your pppd is too old. You need at least 2.3.7. (ii) Your /etc/ppp/options file is not empty. Empty it! ----------------------------------------------------------------------------- E) pppoe dies with the log message "Message too long" You set the MTU of the Ethernet interface connected to the DSL modem to less than 1500. Don't do that. ----------------------------------------------------------------------------- F) Internal hosts can't see the Internet Do you have masquerading set up? I can't help you in great detail, but see the IPCHAINS-HOWTO and the IP-Masquerade mini-HOWTO. ----------------------------------------------------------------------------- G) Authentication fails Make sure you have the right secret in /etc/ppp/pap-secrets. Your ISP may be using CHAP; it won't hurt to copy the line to /etc/ppp/chap-secrets. Also, MAKE SURE that /etc/ppp/options is EMPTY. The "pppoe-connect" script supplies all required options on the command line; additional options in /etc/ppp/options may mess things up. ----------------------------------------------------------------------------- H) VPN software does not work If you are using VPN software on a Windows or Linux machine with another Linux machine running PPPoE as the gateway, you MUST NOT use the "-m" option to pppoe. This alters IP packets, which will break any VPN which uses IPSec. In /etc/ppp/pppoe.conf, set CLAMPMSS to "no". You'll also have to reduce the MTU on the hosts behind the gateway to 1452. ----------------------------------------------------------------------------- I) I can browse some web sites just fine, but others stall forever. There is probably a buggy router or firewall between you and the Web server. One possible workaround: In /etc/ppp/pppoe.conf, find the line which reads: CLAMPMSS=1412 Try lowering the 1412 until it works (go down in steps of 100 or so.) Each time you lower the value, you have to restart your connection like this: pppoe-stop; pppoe-start This should work around buggy routers which do not support Path MTU discovery. ----------------------------------------------------------------------------- J) Whenever I connect using DSL, my internal LAN no longer sees the gateway You are more than likely running a 2.0.X Linux kernel. To solve this problem, give the Ethernet card connected to the DSL modem a fake IP address. For example, if eth0 is your internal LAN card and eth1 goes to the DSL modem, do something like this: ip link set eth1 10.0.0.1/24 (You may have to choose a different IP address and prefix; experiment.) ----------------------------------------------------------------------------- K) How can I run a script every time I connect and get a new IP address? Put the script in /etc/ppp/ip-up. See the pppd(8) man page. ----------------------------------------------------------------------------- L) Nothing works! You may need to put your Ethernet card in half-duplex, 10Mb/s mode to work with the DSL modem. You may have to run a DOS program to do this, or pass special parameters to the Linux driver. Some providers object to attempts to set the MRU or MTU. Try removing "mtu 1492 mru 1492" from PPP_STD_OPTIONS in the pppoe-connect script. This problem has been seen with an ISP in Hong Kong. Your DSL provider may be using non-standard PPPoE frames or require something special in the Service-Name field. If you have two computers, you can try sniffing out these values with the "pppoe-sniff" program. Type "man pppoe-sniff" for details. If you don't have two computers, you'll have to ask your DSL provider if it uses non-standard PPPoE frames or special Service-Name fields. Good luck getting an answer... If pppoe-sniff indicates that nothing is amiss, make sure the Ethernet card associated with the DSL modem does NOT have a valid IP address. (NOTE: For 2.0 kernels, you may have to give it a fake IP address which is not on your internal subnet. Something like 192.168.42.42 might work if you are not using 192.168.42.*) If you are using synchronous PPP on a slow machine, try switching to asynchronous PPP. Make sure no entries in the routing table go through the Ethernet card connected to the DSL modem. You might want to add these lines in pppoe-connect: ip link set ethx down ip link set ethx up mtu 1500 which should reset things to sane values. rp-pppoe-3.15/doc/KERNEL-MODE-PPPOE0000644000175000017500000000661514045237010014375 0ustar dfsdfs# LIC: GPL RP-PPPoE now supports kernel-mode PPPoE on Linux kernels 2.4 or newer. However, the default "./go" build procedure does not make kernel-mode support. Here's what you need to do: 0) Make sure you are running kernel 2.4 or newer on the machine you will build rp-pppoe on. You must have the following kernel configuration settings: CONFIG_PPP=m or CONFIG_PPP=y CONFIG_PPP_ASYNC=m or CONFIG_PPP_ASYNC=y CONFIG_PPP_SYNC_TTY=m or CONFIG_PPP_SYNC_TTY=y CONFIG_PPP_DEFLATE=m or CONFIG_PPP_DEFLATE=y CONFIG_PPP_BSDCOMP=m or CONFIG_PPP_BSDCOMP=y CONFIG_PPPOE=m or CONFIG_PPPOE=y CONFIG_N_HDLC=m or CONFIG_N_HDLC=y CONFIG_UNIX98_PTYS=y You also need a /dev/ppp file: mknod --mode=664 /dev/ppp c 108 0 You might want to add these lines to /etc/modules.conf: alias char-major-108 ppp_generic alias tty-ldisc-3 ppp_async alias tty-ldisc-13 n_hdlc alias tty-ldisc-14 ppp_synctty alias net-pf-24 pppoe 1) If you are running pppd older than 2.4.0, check out the latest version of the PPP software from the CVS repository at cvs.samba.org. Here's how to do this: cvs -d :pserver:cvs@pserver.samba.org:/cvsroot login # When prompted for a password, type "cvs" # Change to the directory in which you want to store the PPP source # code. cd /path/to/checked/out/sources # Check out the source cvs -z5 -d :pserver:cvs@pserver.samba.org:/cvsroot co ppp If you are running pppd 2.4.0 or newer, and have the pppd development headers installed, you can skip steps 1 and 2. 2) The source gets checked out into a subdirectory called ppp. If the source ends up in /path/to/checked/out/sources/ppp, then call that path $PPPDIR. Build and install the checked-out ppp code according to its instructions. 3) Unpack rp-pppoe. 4) In the rp-pppoe directory, change to src/ and type: ./configure --enable-plugin=$PPPDIR where $PPPDIR, of course, refers to the checked-out "ppp" directory from cvs.samba.org. If you didn't check out the PPP software from cvs.samba.org, use: ./configure --enable-plugin This will work if the header pppd/pppd.h is located in /usr/include or /usr/local/include. 4) Type make; make install 5) Edit /etc/ppp/pppoe.conf to include this line: LINUX_PLUGIN=/etc/ppp/plugins/rp-pppoe.so After that, pppoe-start should use kernel-mode PPPoE. The rp-pppoe.so plugin adds the following command-line options to pppd: ethXXX -- Use interface ethXXX as Ethernet interface brXXX -- Use interface brXXX as Ethernet interface nic-XXXX -- Use interface XXXX as the Ethernet interface rp_pppoe_service SERVICE_NAME -- Specify desired service name rp_pppoe_ac NAME -- Specify desired access concentrator name rp_pppoe_verbose 0|1 -- Print names of access concentrators rp_pppoe_sess nnnn:aa:bb:cc:dd:ee:ff -- Attach to existing session 'nnnn' on AC with Ethernet address aa:bb:cc:dd:ee:ff This skips the discovery phase. rp_pppoe_mac aa:bb:cc:dd:ee:ff -- only accept PADOs from specified MAC address The kernel-mode PPPoE plugin permits an MTU of up to 1500 on the PPP interface providing that the MTU on the underlying Ethernet interface is at least 1508. In /etc/ppp/pppoe.conf, set MTU=1500 and MRU=1500 to enable the larger PPP MTU. The larger PPP MTU is negotiated according to RFC 4638. -- Dianne Skoll rp-pppoe-3.15/doc/PROBLEMS0000644000175000017500000000007714045237010013231 0ustar dfsdfs# LIC: GPL Problems? See the last section of HOW-TO-CONNECT. rp-pppoe-3.15/rp-pppoe.spec0000644000175000017500000000777014045237007013751 0ustar dfsdfsSummary: PPP Over Ethernet (xDSL support) Name: rp-pppoe Version: 3.15 %if %(%{expand:test %{_vendor} != mandrake ; echo $?}) Release: 1mdk %else Release: 1 %endif License: GPL Group: System Environment/Daemons Source: https://dianne.skoll.ca/projects/rp-pppoe/download/rp-pppoe-3.15.tar.gz Url: https://dianne.skoll.ca/projects/rp-pppoe/ Packager: Dianne Skoll BuildRoot: /tmp/pppoe-build Vendor: Dianne Skoll Requires: ppp >= 2.3.7 # LIC: GPL %description PPPoE (Point-to-Point Protocol over Ethernet) is a protocol used by many DSL Internet Service Providers. RP-PPPoE is a free client for Linux systems to connect to PPPoE service providers. The client is a user-mode program and does not require any kernel modifications. It is fully compliant with RFC 2516, the official PPPoE specification. %prep %setup cd src ./configure --mandir=%{_mandir} %build cd src make cd ../gui make %install umask 022 cd src make install DESTDIR=$RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT/etc/init.d test -f $RPM_BUILD_ROOT/etc/init.d/pppoe || cp ../scripts/pppoe-init $RPM_BUILD_ROOT/etc/init.d/pppoe chmod 755 $RPM_BUILD_ROOT/etc/init.d/pppoe cd ../gui make install DESTDIR=$RPM_BUILD_ROOT rm -f $RPM_BUILD_ROOT/etc/ppp/pppoe.conf-3.10 rm -f $RPM_BUILD_ROOT/etc/ppp/firewall-masq-3.10 rm -f $RPM_BUILD_ROOT/etc/ppp/firewall-standalone-3.10 rm -f $RPM_BUILD_ROOT/etc/ppp/pppoe-server-options-example %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc doc/CHANGES doc/HOW-TO-CONNECT doc/LICENSE doc/KERNEL-MODE-PPPOE README SERVPOET %config(noreplace) /etc/ppp/pppoe.conf %config(noreplace) /etc/ppp/pppoe-server-options %config(noreplace) /etc/ppp/firewall-masq %config(noreplace) /etc/ppp/firewall-standalone /etc/ppp/plugins/* /usr/sbin/pppoe /usr/sbin/pppoe-server /usr/sbin/pppoe-sniff /usr/sbin/pppoe-relay /usr/sbin/pppoe-connect /usr/sbin/pppoe-start /usr/sbin/pppoe-stop /usr/sbin/pppoe-setup /usr/sbin/pppoe-status %{_mandir}/man5/pppoe.conf.5* %{_mandir}/man8/pppoe.8* %{_mandir}/man8/pppoe-server.8* %{_mandir}/man8/pppoe-relay.8* %{_mandir}/man8/pppoe-sniff.8* %{_mandir}/man8/pppoe-connect.8* %{_mandir}/man8/pppoe-start.8* %{_mandir}/man8/pppoe-stop.8* %{_mandir}/man8/pppoe-status.8* %{_mandir}/man8/pppoe-setup.8* /etc/init.d/pppoe %package gui Summary: Tk PPP Over Ethernet Client (xDSL support) Group: System Environment/Daemons Requires: rp-pppoe Requires: tk %description gui This is a graphical wrapper around the rp-pppoe PPPoE client. PPPoE is a protocol used by many DSL Internet Service Providers. %post gui # Install entry in KDE menu if test -n "$KDEDIR" ; then mkdir -p "$KDEDIR/share/applnk/Internet" cat < "$KDEDIR/share/applnk/Internet/tkpppoe.kdelnk" # KDE Config File [KDE Desktop Entry] Name=TkPPPoE Comment=Start/Stop PPPoE connections Exec=tkpppoe Terminal=0 Type=Application EOF fi # Install entry in GNOME menus GNOMEDIR=`gnome-config --datadir 2>/dev/null` if test -n "$GNOMEDIR" ; then mkdir -p "$GNOMEDIR/gnome/apps/Internet" cat < "$GNOMEDIR/gnome/apps/Internet/tkpppoe.desktop" [Desktop Entry] Name=TkPPPoE Comment=Start/Stop PPPoE connections Exec=tkpppoe Terminal=0 Type=Application EOF fi %postun gui # Remove KDE menu entry if test -n "$KDEDIR" ; then rm -f "$KDEDIR/share/applnk/Internet/tkpppoe.kdelnk" fi # Remove GNOME menu entry GNOMEDIR=`gnome-config --datadir 2>/dev/null` if test -n "$GNOMEDIR" ; then rm -f "$GNOMEDIR/gnome/apps/Internet/tkpppoe.desktop" fi %files gui %defattr(-,root,root) %dir /etc/ppp/rp-pppoe-gui /usr/sbin/pppoe-wrapper /usr/bin/tkpppoe %{_mandir}/man1/tkpppoe.1* %{_mandir}/man1/pppoe-wrapper.1* /usr/share/tkpppoe/tkpppoe.html /usr/share/tkpppoe/mainwin-busy.png /usr/share/tkpppoe/mainwin-nonroot.png /usr/share/tkpppoe/mainwin.png /usr/share/tkpppoe/props-advanced.png /usr/share/tkpppoe/props-basic.png /usr/share/tkpppoe/props-nic.png /usr/share/tkpppoe/props-options.png /usr/share/tkpppoe/en.msg /usr/share/tkpppoe/ja.msg %changelog * Thu Jul 21 2001 Shigechika AIKAWA - merged rp-pppoe.spec and rp-pppoe-gui.spec rp-pppoe-3.15/README0000644000175000017500000000354314045237007012205 0ustar dfsdfs# LIC: GPL pppoe: a PPP-over-Ethernet redirector for pppd Copyright (C) 2001-2012 Roaring Penguin Software Inc. Copyright (C) 2018-2021 Dianne Skoll Some inspiration from an earlier client by Luke Stras. The MSS clamping was inspired by mssclampfw by Marc Boucher with acknowledgements to Rebel.com (http://www.rebel.com). However, the actual MSS clamping code is original and is licensed under the GPL, unlike the original mssclampfw. Introduction ============ pppoe is a user-space redirector which permits the use of PPPoE (Point-to-Point Over Ethernet) with Linux. PPPoE is used by many DSL service providers. Installation ============ Requirements ------------ 1) Linux 2.2.9 or later on Intel, Sparc or PowerPC. It may work on Alpha, too -- anyone care to let me know? OR Linux 2.0.36 or later. OR FreeBSD, NetBSD or OpenBSD with BPF support, though this is old, unmaintained, and may no longer work. 2) pppd 2.3.10 or later. Versions 2.3.7 and later work unless you use demand-dialling. For demand dialling, you *must* use 2.3.10 or later. QUICKSTART ---------- If you're lucky, the "quickstart" method will work. After unpacking the archive, become root and type: ./go This should configure, compile and install the software and set up your DSL connection. You'll have to answer a few questions along the way. If you want the GUI wrapper, type: ./go-gui If ./go and ./go-gui didn't work, read the rest of this README. Compiling --------- Compile and install pppd if you don't already have it. Then: 1) Unpack: $ tar xzvf rp-pppoe-xxx.tar.gz 2) Change to source directory: $ cd src 3) Configure: $ ./configure 4) Compile: $ make 4) Install (this step must be done as root) # make install 5) Now read doc/HOW-TO-CONNECT -- Dianne Skoll https://dianne.skoll.ca/projects/rp-pppoe/ rp-pppoe-3.15/gui/0000755000175000017500000000000014045237007012104 5ustar dfsdfsrp-pppoe-3.15/gui/wrapper.c0000644000175000017500000001354714045237007013742 0ustar dfsdfs/* -*-Mode: C;-*- */ /*********************************************************************** * * wrapper.c * * C wrapper designed to run SUID root for controlling PPPoE connections. * * Copyright (C) 2005 by Roaring Penguin Software Inc. * Copyright (C) 2018 Dianne Skoll * * LIC: GPL * * This program may be distributed under the terms of the GNU General * Public License, Version 2, or (at your option) any later version. ***********************************************************************/ #define _SVID_SOURCE 1 /* For putenv */ #define _POSIX_SOURCE 1 /* For fileno */ #define _BSD_SOURCE 1 /* For setreuid */ #define _DEFAULT_SOURCE 1 #include #include #include #include #include #include #define CONN_NAME_LEN 64 #define LINELEN 512 static char const *pppoe_start = PPPOE_START_PATH; static char const *pppoe_stop = PPPOE_STOP_PATH; static char const *pppoe_status = PPPOE_STATUS_PATH; /********************************************************************** *%FUNCTION: PathOK *%ARGUMENTS: * fname -- a file name. *%RETURNS: * 1 if path to fname is secure; 0 otherwise. *%DESCRIPTION: * Makes sure ownership/permissions of file and parent directories * are safe. **********************************************************************/ static int PathOK(char const *fname) { char path[LINELEN]; struct stat buf; char const *slash; if (strlen(fname) > LINELEN) { fprintf(stderr, "Pathname '%s' too long\n", fname); return 0; } /* Must be absolute path */ if (*fname != '/') { fprintf(stderr, "Unsafe path '%s' not absolute\n", fname); return 0; } /* Check root directory */ if (stat("/", &buf) < 0) { perror("stat"); return 0; } if (buf.st_uid) { fprintf(stderr, "SECURITY ALERT: Root directory (/) not owned by root\n"); return 0; } if (buf.st_mode & (S_IWGRP | S_IWOTH)) { fprintf(stderr, "SECURITY ALERT: Root directory (/) writable by group or other\n"); return 0; } /* Check each component */ slash = fname; while(*slash) { slash = strchr(slash+1, '/'); if (!slash) { slash = fname + strlen(fname); } memcpy(path, fname, slash-fname); path[slash-fname] = 0; if (stat(path, &buf) < 0) { perror("stat"); return 0; } if (buf.st_uid) { fprintf(stderr, "SECURITY ALERT: '%s' not owned by root\n", path); return 0; } if (buf.st_mode & (S_IWGRP | S_IWOTH)) { fprintf(stderr, "SECURITY ALERT: '%s' writable by group or other\n", path); return 0; } } return 1; } /********************************************************************** *%FUNCTION: CleanEnvironment *%ARGUMENTS: * envp -- environment passed to main *%RETURNS: * Nothing *%DESCRIPTION: * Deletes all environment variables; makes safe environment **********************************************************************/ static void CleanEnvironment(char *envp[]) { envp[0] = NULL; putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin"); } /********************************************************************** *%FUNCTION: main *%ARGUMENTS: * argc, argv -- usual suspects * Usage: pppoe-wrapper {start|stop|status} {connection_name} *%RETURNS: * Whatever pppoe-start, pppoe-stop or pppoe-status returns. *%DESCRIPTION: * Runs pppoe-start, pppoe-stop or pppoe-status on given connection if * non-root users are allowed to do it. **********************************************************************/ int main(int argc, char *argv[]) { int amRoot; char *cp; char fname[64+CONN_NAME_LEN]; char line[LINELEN+1]; int allowed = 0; FILE *fp; extern char **environ; /* Clean out environment */ CleanEnvironment(environ); /* Are we root? */ amRoot = (getuid() == 0); /* Validate arguments */ if (argc != 3) { fprintf(stderr, "Usage: %s {start|stop|status} connection_name\n", argv[0]); exit(1); } if (strcmp(argv[1], "start") && strcmp(argv[1], "stop") && strcmp(argv[1], "status")) { fprintf(stderr, "Usage: %s {start|stop|status} connection_name\n", argv[0]); exit(1); } /* Connection name can be at most CONN_NAME_LEN chars; alpha, num, underscore */ if (strlen(argv[2]) > CONN_NAME_LEN) { fprintf(stderr, "%s: Connection name '%s' too long.\n", argv[0], argv[2]); exit(1); } for (cp = argv[2]; *cp; cp++) { if (!strchr("abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789_-", *cp)) { fprintf(stderr, "%s: Connection name '%s' contains illegal character '%c'\n", argv[0], argv[2], *cp); exit(1); } } /* Open the connection file */ sprintf(fname, "/etc/ppp/rp-pppoe-gui/conf.%s", argv[2]); /* Check path sanity */ if (!PathOK(fname)) { exit(1); } fp = fopen(fname, "r"); if (!fp) { fprintf(stderr, "%s: Could not open '%s': %s\n", argv[0], fname, strerror(errno)); exit(1); } /* Check if non-root users can control it */ if (amRoot) { allowed = 1; } else { while (!feof(fp)) { if (!fgets(line, LINELEN, fp)) { break; } if (!strcmp(line, "NONROOT=OK\n")) { allowed = 1; break; } } } fclose(fp); if (!allowed) { fprintf(stderr, "%s: Non-root users are not permitted to control connection '%s'\n", argv[0], argv[2]); exit(1); } /* Become root with setuid() to defeat is-root checks in shell scripts */ if (setreuid(0, 0) < 0) { perror("setreuid"); exit(1); } /* It's OK -- do it. */ if (!strcmp(argv[1], "start")) { if (!PathOK(pppoe_start)) exit(1); execl(pppoe_start, "pppoe-start", fname, NULL); } else if (!strcmp(argv[1], "stop")) { if (!PathOK(pppoe_stop)) exit(1); execl(pppoe_stop, "pppoe-stop", fname, NULL); } else { if (!PathOK(pppoe_status)) exit(1); execl(pppoe_status, "pppoe-status", fname, NULL); } fprintf(stderr, "%s: execl: %s\n", argv[0], strerror(errno)); exit(1); } rp-pppoe-3.15/gui/tkpppoe.10000644000175000017500000000165714045237007013661 0ustar dfsdfs.\" $Id$ .\" LIC: GPL .TH TKPPPOE 1 "26 February 2001" .UC 4 .SH NAME tkpppoe \- Graphical interface for controlling rp-pppoe .SH SYNOPSIS .B tkpppoe .SH DESCRIPTION \fBtkpppoe\fR is a graphical program for controlling PPPoE links. It works with the RP-PPPoE package and has its own HTML manual. .SH FILES .TP .B /etc/ppp/rp-pppoe-gui/connection-info Contains connection information. This file is not human-editable. .TP .B /etc/ppp/rp-pppoe-gui/passwd Contains passwords for each connection. This file is not human-editable. .TP .B /etc/ppp/rp-pppoe-gui/conf.* These configuration files are used by \fBpppoe-start\fR. They are generated anew by \fBtkpppoe\fR each time a change is made to a connection's properties. .SH AUTHOR \fBtkpppoe\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe-start(8), pppoe-stop(8), pppoe-wrapper(8). rp-pppoe-3.15/gui/html/0000755000175000017500000000000014045237007013050 5ustar dfsdfsrp-pppoe-3.15/gui/html/props-nic.png0000644000175000017500000001002514045237007015466 0ustar dfsdfs‰PNG  IHDR¸È¥†RgAMA± üa8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2)Ý.IuIDATxœíݯŸÜÈ™`Ý},ÌŸp`ÁÀ,pà@`€AÀ€ 008`Á@Æ h£•¥R½¥ßR÷ó|̪[Ru«ûë·JjUUõUUýú¯_÷nÀA}ÿÝ÷ßÕ=ÿò¼kKŽë?÷nÀq½¼¼T‚ $(ßíÝ€Yêª8¾»»»½›0ÝYƒ²ŽÈ‡üaï†Eª—ê´q¹|P¾ùñMᇿ~H¾AÉ'‡+¾¼¼ˆH8—ú;ûP½ÌÏÊ ¹Ñ^¥y4¹0i•ŠrÔÅFc¯Lʤä¯ÿ÷?UU}ÿ§¿%ÿwõ6kËn¹p×õN×xiC{l뼷ɇFmjìò±íähþñ‡_ÿüfþõˆÓ¶Ð¬õòò[^×KÂA¼“Ì)©%û_›¥4ñ4ôeÞLÓ†Íö•|É™‡FmjìòüÆ¥äÁ}ÿ§¿…%áâÚÁÚ/'«hL`ç1Êý°ÍŽú•àP6T¬u–'k«Î’›M–½…Û¬ÿHn9lÀeر¢ç¼ùñ›b¶°œ¬2A9mô°V~2º?ŽðüËsS÷7[24YDû[Ô‰•Σsd¶Ü$Zfarõä¡ÔÛ€S[ï8²±ú“Ùï>7±“1œæù—çfû‡ûÊU”“GšÊvÔ«m‡ýPV.(" –`ÉŒÝòœ–,ûAr›c뻡ç.Ï÷¾›—aíŸS79S^NV»w½피»»›ydòKµãbÞ. ë6=33D84@1ô„¡½Œ]>ÿÉ\§vQÙ(©ÉrA¹ÙåÜuíYý»Åõ~/*ûEÚ¥ajÛ’ÞîaßdÎbÕØéw[ë²lz×»éAo ÞW§¨œ¹Í¡žZ»sÝùòçûÝÉ'/(‚ì,„˳YìŒã3]tww÷ð_ÿœ°b{ø¿šQõô·3sËÉÕ‡¶Ù,oïe©—v ù[/oåÈ’grÖÖ9åýþÏïënxÉXßo7î]£Ñ“Oæd*a¿É 03(;‘×—ÌvÂTUÕîÅ™óþá('sja®ßÝÝ=T²Nl‘rrlß¹9Rkb±ÙN~¤rÅŠr=o~|sÙ}L¸T»tºç8bEYèù—çk’ƒKRgÏ•’Seõï·Û°=œÅI#²–ÊO?mߎiNÔTà,Þýô®³äL—ìBP%@@P%@`ÄåA??®ÖŒ®ûÿ¾Ï?aËÆÁß3¶¹Døº¸<㮣|üø¸N3¾qÿÓ}ÉÓ>¿~^¹!Gq{s[ò´mŽN¡Âƒx¨6—(|]\˜Ò®÷ãÏ›}¦?>ækÇŸ¯'%«ªúüú9|CŽ–8%ñhm.¾..’1J€€ Qvúýaš±}¨z ùµ~LŽšwSß5=ñöÿvª¾ì[¤óÞßEGÉ6$œ_±ð ©µQxtÚ‡£äД›Ðæä®—mÕ ½..Uñeï3úøñ±þ¯?ÂݬX¾»¶0˜’šHjÇèª2ûJî½ÝÂΊùXï¼]Í·zÂÑ ͨM•?Ú4òøgKÎ8´ÊL ß=(YÈôöK˜Î*‹ënÉÜé×›ÍZù20¯^ýöæv›PÝÚçããýO÷÷?Ý×4KªÞûßyN•=p½,rû;í’Éý.ÒÚÌBÉÈ’c”ÉB&_ÝÌ©}Úš,›,So6W/ì¤ç‚ nöÒi̲ê@¬R‘ÚyZ5ph:[˜“ŸŠNÌ•larkó _ä²¶8(‡.ã¨ë”ö—-Ókë|Ó;úöÑäuë]”I¥±ËiF—퇒oÈØzg~}”F,9ˆ£ÚÐÙ`Õ ²þ~ÃÖþÞ¼‚–¤Ç\$tM¦w½ÛÝ“Î?Úý§u"u K•›É4¸yh³ûKâ™…ÛüºOåÈ»ÞmÉ‘ CYµ·[ކ³74ù·?6%ý÷ä¸AI—%Ôi4‚ œÿó‰òB£yæï{ÿ¶ƒö»3vFûÛ ·9ó36 ;½ïäÑ韢©¾}ó34ퟱü!îÄi“­¡ÿ‘K.L6@ïûªL¯(“c”U¯'žï—mÖ1¯R§J†Í_?Ô<ÆÜоJZ8jÅŽð=OžÆiVÉFÊw7Y²U퇆Z›¯I“­Í/T`’˜®¶=Íî?Ƚÿé¾¹²÷Ú~ât{sÛ~CF½.véÄ‹Éöëâ’´çÌ©§«ÍU”éYÔÍ8HcŽàŒoÈÛ\âò^IÑåÞÿø· œ¬:?jÜûèê÷‘/Ã%½òÎ:¯7øbÃ4î Êã º××aèw7ê‹„rt Õñ\m.á"¡+‘8ëýÇ7Ü­9ÃeÛÆ?"‚«ò÷ç¿7×g½Óc”Réà XÏׯ_;KŒQ%@ Ñõ~xxxúô´}SŽàîÍ]g‰Šàwïÿò¾¿pð‚ó·ïޮـùùá&¹Ü/s€‹5|c Êyy~Ù» p9ê¡Æ×/¯…Ïúô”ìwWÆ(‹´ìðT”‡ã‡p4*J€€ u½û·`hÏ*Óÿ{=™½„ ˜ÖÂóN‹,eÄå&Å6éÜô“9í©_ÛQÒ —v5Ú©=;®Øßc²a ö×-lX~• Å.œÎô1Êæ ßIÉv¦4ÑК|%WLîqHgƒuKV²JùBà¼FT”É*©cT¹´êàæœ &× 78ÿ À1m1F™,© «Âi{,4¶a£Ú£„‹±Åç“vílÔö“#žKm8²e®£, ŽÛ›ÛiEVrÅ9õZxt‘êo¨íóHÊLØÅÐ7±ð[9"(ë-¶·Û”Wù!Ëf•ò"khÅp%ÛlŸf)oX{•N3:Û™üªcJÌÂXßÃÆý(·W¿ó~ë ‹xýòzóÃÍ„»}“‡//ïü„ (‚ (‚òXœÉr‡ó¹{sW~†(ñôéiþFåQ,5]Ð64_Ø(‚ò@”“°#³0L'(‚ pŽ1ÊÎí=™'’S2TÃ÷§(|Zrìbh»µwä¸_§se­ÿžFò~BýМó4hãY?}6®Ö™‚²VOþµÍç5œà,9aorv³J)º²¡÷¿Ö¾3^û>ý)’Fí®³ñ¡ýVßýp]’ÉÊ/³u‘É…ŒQö§N¬R÷…ÌL†ÓÚÌ Î’s7²¶ö¿dUjŠ·Î IósÀúltoá´uYʇÿý0êùç«(G)¼‡î·ÚíoD™°¸d=¸ì¿O“ïñܬ5ªNô!YD¾Zœð[ ©(«¢²y¨þ#ÿåI>Íü GV×eý”\cGõág£°sÖe{—\Qv¦gÊ»üÓ|v¯ÙÌÏF3žÞ²ÏÕªù}wÛù*ÊL/f½ßÐÄaÉ¿3K§—gÎaõ‘XÃØñÇgª(Çž lÿ{žYqèiåíÓ8)Æ:çRÛO+o-Ë:|s6REŸ¡-tæ7Œ!¯_^טïËäbË›–£fAgr1€é%@àLc”gaÔ .ŒŠ  ¢<Å/þ!(b¥Ë€ùå¨(aG™JÅ%@0Y£ŠòptÀacá],U”A Ø¿ë]rW¾]î.‘¹§V~Ž7jƒ s”в}Ödtî7™V%oվѿ© à2ì_Q& ÍÓT29ÔœYŸ†tn­6óEMÞ°‹£T”IC%[fr¨-gnš3£p"G©(û•ców5&ã°ÙÝØYŸÊ MG%1ᤎ” NíN1¶ üŒfM‘+"áÔÝõž °ÃÛ»\¶îòæÒ‚r%‹Ìhf&)8©K Ê΄_ÕìžøÐt£% pš.Ãþc”%eZò|ÈØ¿Ë÷>ö¡Â)›%&œÔ¥U”åô‚BW”:Å@¹ý»Þ»‘@¹+ Ê# olìJ»Þ‡•¿Í2° å¼}÷öõËëÞ­ºT”嘅vdF€³0žŒYacfa˜KP–ïzï2áJw–lÿ¯Yáj-\Q^Þ„fa¶;™“™1\Ø™F1?¢Ye-\QÍA˜üßò…µÎ½x“ñgF`qËW”Cs–¬5í9ÉÙ½ó[0 #Pn­³ÞÉ~ô6“Æ´§aH6iAùY›ö,¾_`KËŸÌÉwÍ)Žõj+³0‹Ûá:Êd¹7§ØÜ¦J­ÌÂ×jÅ“9ípIÛ•/Ìï«?›˜Y­u2§pyáÂp’E³0ë¹ÞŸ0ê…®4(uŠrWz›5 ”»Ò <2³0ÂÑ\i×û°Ì¤¢<³0Â1©(ƒ¥‘2€Zº¢4RÐHT”FÊÚÒ]ï§OO·à’óE;™ð›¡QÇÜåAÉd¸H™3Ø*J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€Àw™Çn~¸Ù¬‡5XQ¾ÿËû-ÛpXéŠòí»·¯_^7n À1£¤+ÊG'ëÊô ÃÊd`‚Á“9‹dÊÓ§§·ïÞ.¸Á¥PN× (‚ »à¼íöæ¶ùûóëçÎòfIç'lpAåÈ(ª(›Ä©C§qɧ-µA€#ˆ+ÊNü}~ý|{s{{sÛ Ä )Ùl°½¼½°yf²n WXÄ2c”ó;¹™³ åzaò™JT`=¥c”k˄촇–²LPõÇG™_*$5,VQÎÌÊvç}rÞ)05Äc”ðÊ GÆ\ƒ““1¹îœ ôÌi¢-:§%y~”A ”Á“9OŸž–ÝÓâØF:(_¿¼.;kÂâØL"(¿~ýº};Ë%@@P%@à÷1Ê———ÛÀYý?A°|ðQªtIMEÑ"24ëÑ,IEND®B`‚rp-pppoe-3.15/gui/html/mainwin-nonroot.png0000644000175000017500000000306214045237007016715 0ustar dfsdfs‰PNG  IHDRÎIúÈŽógAMA± üa8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2)Ý.I’IDATxœí¯^ä0Çs÷A ‘Ȉ•È Ä>ÂÉ{\XDðÈ}„ˆHä ’GXqâD`.äï$i&M;_µdÛdÚþö—IÚ!†„Bˆãßcë0˜™szrz¢>í_öM#aæÏÏÖ0óGJ)Xj ,5†ˆ“Ö¡œy9 ÃÐ:„|z•šÙæý¬u ¤l„Ý n|©­¯ÖváöaëµaIªÇø¶G–Û9YI0xjw¬p¥ð–&šw €®3•dWåËӅ늛øZ^¾ñtÐ ÀøBHjd¤ÊÿÄWĪÝc_¦R57Ÿ,U/œÝù(kÈï@¡$@µeMÓóƒìÂ¥ z*(†a6¢§‘8+ü©[˜«ÑOvkøyw{'¾Ä5¶ž¤%i¥^˱²4gù zmeiμÍÇ´¤õä£XZj)µ< ê Ûçß}=…»¾ZÏÀ²iÒu– ¥ÜÜm¦åjHö/{}vt9¨£îKg@—R_§;vÜIEND®B`‚rp-pppoe-3.15/gui/html/mainwin.png0000644000175000017500000000357014045237007015225 0ustar dfsdfs‰PNG  IHDRiIpÂ@›gAMA± üa8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2)Ý.IØIDATxœí­z;†ÕóP`X¸ À—Px.! ° РÀ 0 —P˜K0,4(ô% FUô3+þVÞïEkíjf´^F£µ,¤óNqù}ém`$nonoÔÑñùØÕÀ`üÓÛÀ`H)|€|€ÃMo²P±ƒ2MSoøŒê;”ר¿¼ïm|öBŠa=Hyß±»Û¹…‡oï ò^<[QJ ¯®õï…ÌwŒ®dVÑg½…^ªÄI+¾©ËÄã¸<Þ[%·Ÿ¿ÏžJ•Zžj'X!û—÷—/»ü÷$xt-)ÿ¸0U2›lÎq˜þâòxovKâT’¨ÔrZ8·Ÿ¿_ï¿fu|>ê(cš&)¥¼ÐÑPgßqøvèk@mÌÎ,ÝÝ›'2è„ïàe"ñËîìø|Ô±“+v¬4‡rzRé€Õ =tO¤³<¬ÐÃ<5«‹Š;ØÓ'tIj­éÿBî#b¨OB×G–»ycÀj©=—Ñ]/>èÝç,Óq¨©[T(y)|]Ժ̺ Ô¥SËó/ f衉¹)ßÑìÍ+¡ˆW‹•ÞœÐC¼ûHX‚+ jOtã}5xóç,zêÑ¥Ë =Ú¨`á4뉩j)s–¦iÚ‹‘Ò¥:öÑͳÈw“ök´ÂYdyøò ^½Õlè1’ÈV¤vÎR™o9<X*èðæ>B,ËwÌFMÃ…ÄP$èHtè<£BGZzüÙsp¬}Ãvw; Ýàjè2[ÉAJ¹Ø/+îˆäø|4_»`PÔc<–ãÐ é;Äëí¦_¾`á ê5ß±ÙlÚÛÁãôëÔÛø Ô×Îç³U2jÜ1:O?žrªúïS)Kà±vß±ý°­$y6&ÚüËsÎ/ö@{Öî;D‰ÏÓ'„àºÁ>éðQs–Ûúøçég5c‚ª•RóЗù¸C÷X³wAÛèÎLÜa õúÀDô•ÞHÁ’ã dB2ÕWò¬nâ‰_‚áe[±\††³ÎbõaÕ±õ)Õ{‰Bouo¡ëxTåðõÀXRÁ* Âk´ÞîšÚ‡sú¼[7ÓƒÐ1û/¼F§Ûûó& éæ;FÉzf\+3ë,nβl¼à*,¨"’Ã×+ÿë)ØÌÇ:õ¨?Š·’‘Îp«{ Ír7%..Ëé× iBDÍYbf‰»¦KÓ…1Òº™àtøü¿XjCßÑgYX0:k÷XL€òðþ9K½€½¨ß›µQÚR×(–4c…MnFÕ{ëýEh0ßÑì¯OÌmk+m©kKš±Â&7£ê½ mÜ9 €|€|€CÔûRJóã4Mf¹þ/*¦JA¥ªýèX¥ûäéc«Jm¥na„ðÐÙxóxÆÐ2­&ç|#Þº›ca>µŠzÿ DHÖ†(ôV÷z÷aÐ’Í^¢â·'‡®¡%$£´¬Æ…`íV?'zlj„Å6O»Æxÿ=£à@½À]þó±bœ‚{î%ÌYôsšq„ëœçlVimèÑ5fìMŸ®9U{¤4o™íÍiÜÐC,x3ýÅæâÝa¯ˆÃMË•ºódïeùÑl¤ÒäÇS ɼ–ªÛÒ›/v¿ÈÅCRRƒ ÌûŒ¾]Ê¿”•Qõ`ªåžuó#µ=`ª…‘ÕuÝPÄa Ç@¬ º[mh ¼š]þCÇ©E\"iV~Z®4”4ógt’Ò¬RV©xûL»‹4„"¯œÐÙHóØÄ79R»÷ñÖ­:g±°¶ãg®œLÉÞê!™¦§+Þ´H”¢x_ãµÙË;!Äå÷åø|ÔE›ÍfûaÛþ·p¥”Ovq]lÊZÒ 3糜›}T½·Jøùüw‹L)åþawÒà;®p¿Ò…‡î5Xa“Aww8ãŽ.ÿ<ÐRérþà~9–4c…MnF³{ë_gi£0 î:‹'î0//Èw8Àw8Àw8üÍwtü­*VÁÿñÙM0tIMEÑ>*IEND®B`‚rp-pppoe-3.15/gui/html/props-basic.png0000644000175000017500000000721114045237007016001 0ustar dfsdfs‰PNG  IHDR¸È¥†RgAMA± üa8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2)Ý.I éIDATxœíÝ-{åFš`Í^ó4lÐ`Á‚  .`аá@ƒ€ 60`E-•ê-}}õ}_n£RétÎÓo•dUUõ§ªª~ýϯ[w`§¾þêë¯êŸ^~~Ù´'ûõ_[w`¿.—K%(B‚ ðÕÖ˜¥®Šý»»»Ûº Ó5(ëˆ|úן·îP䩺T‡ËåƒòþÛûþÆþþCòJ¾9Üñr¹ˆH8–ú;ûT]ægå„ÜhïÒ¼šÜ˜t•ŠrÔÍFcïLʤä¯ÿ÷¿UU}ý×$ÿ¸ˆºÍÚ²-º>è5NmèˆmÏ6ùÒ¨¦ÆnÛOöæé_þõo÷óïGœÖB³×åò[^×[ÂI¼ƒ]Ì)©%û_›¥4ñ4ôe^MÓ‡ÕŽ•<åÌK£š»=߸”ܹ¯ÿú°$\\;XûådÍ lÿÍ|™ÚEe£¤&Ëåj·s×µgõ{ëã.^Tîö‹´IÇ&Ô¶%£ÝÝ~ÈÅUc§?l­Ë²éCïf½‚úX¢rf›C#µöàºóåÏ»“o^P8ÙÙç³ZìŒã#Ýtww÷ôßÿž°c{ú¿šQõôÛ™Ùrr÷¡6›íí£,uj‡?Ùz{ó*{–¼’smKÞ{¬‡á%s}¿=¸÷ž|1'S û8™AÙ‰¼¾d†´¦ªªö(6Ȝǧ½\Ì©…¹~ww÷TÉJ8°EÊɱcçæBH­‰Å¦üLå+Êë¹ÿöþÜcL8«MÝsì±¢,ôòóË—0%gRg•’CeõûÇmÚŽâ YK凟>¬ßiÔUà(Þ}÷®³åH·lBP%@@P%@`ÄíAÏ?>_­]ïÿç}þ kvfŽø±Ï%Âóâ|ÆÝGùúöz¥~´ÝÞÜ–¼íù§ç+wd/Þ÷¾äm»ú@ŽØç…çÅÉ”½Ÿ|^'%«ªz}{Í×Ï?>î 6ÇóOχû@ŽØçáyqJæ(‚ P4GÙkôçÇŽÊëò{=ÿøœœ5ït¦ž3jqí?v^ª>Ÿ`ZdÜ×?Dÿ@É>$;œß±ðé·žiþC›cBŸ“‡^¶Wt:0t^œUiEÙµ×·×ú¿ªøòKgßQ‡k ƒ)©ù½W•9VòèívvÌgDçÕ9gÚì5ß„>WG¸ZrÄ©UfZøéAíÄl®¿±]Q&wY\·".[ÚohöÊ—yõîï¿{¿Î¬¦ÍÑ“§ÓN¨¡—ª²¤ýÎ úd“{›Ù(Yr޲‰¿v&7æw™ ù2L–©ÂšŒ«7v¾~Ó$woŽÒé̲:§3ôÇ„dr©ÞÙeÂç<³·ùû/r¹¶8(‡n º½¹­ÿ«~¯3êN &u^MÞ$t½{J2©4vû"Ýhâò³—–ø@æw;?øÙ¼ê}î4Xõ‚¬ܰ·t¯ 'ý÷¸IèK3}èÝYßÞÜ•„Íö’ 8s,UT®&Óáæ¥Õìsô áiílþ×§rdÈ’s”C3õÆf$¾Úë£ ÍvmÕ‡Ãø&‡{r"2sîͬk{¯Eþúöÿo[ †Þó!§¼–lÞÙ茾Ã![~U}~ábµ$SgM5‡HÿL«^ å»:V¾–,ésØþ„^¶œ¼!!9gÚaôýE™~1'9GYõFâù¡÷jó*!¶_Í&Í«á~ìh´Ý‡9ÃØðL“—q:gT> ^jè=ÔìÐ?C½-üëëÔï™*MþTõ–«m/D³æ¯x'ÝÞÜ6wöô·ƒ—õþ»÷“?­nv™Óç=kŸgÒ^3§^®6WQîddQwc'Ùƒ#~ Gìs‰óIÁÐ{ó /휦™£?ÞÜ¿#ö¹Ä™Î…¼£®ë;Ø0§ƒróË8ú&!ÕP£¾1åXÈû\ÂMB_ˆÄUï¿Üÿ¥þa'AYÍøp€±þùòÏæçúªwzŽr?YÛ[€ûôéSg‹9J€€ $†ÞOOO?|\¿+{pw×Ù¢¢øÃã÷ýƒ7œ?¼{¸fgvçæ››äv¿™³™ËËeë.踆ÞUþAP*ÊyN쟊 (#†Þí_¸^ùw ûË–Íé@§…V¡­´¢ì,̽áS*ò‹ƒ—ó   PQEÙ©¹:µX{cóÎd ˜,å Û¬~_ªlhQÜü± %lZk·\x" U8Y«0V5f{ñÅ¡ÉÝ“û=­íÈË7X·ÖÎͰÏÀ™\åö d5¶¶šS‹MÛwÙêO- §±ñ}”ÛÖ_CEå I8±ƒrWe×Ðìg‰]°¬¢9ÊþœÝ²T²Á¡ ·Z:àÚ}^üS¶Rz1§ÉÊþµ‹i—w“»µÙ¾’oaŽvƒåuåâÝö&±¸XýTY»¶úsö»Þ°o¿¼ÕYû,/—§Ç'¿Â”A ”A¹%Wrà<á|3w÷wo¿¼mÝ ¦¢¨(7cFØ«0äX…q×\ÏýSQ%@`AÙy@ÙµŸêæyh@ÞƒrÂ(t°‹9£nœ°£U¾#U”å 7¶ß?Ä*Œ@¡ƒU”ÕçQUÐY…H:RPf]HÖqaTY…(q¤ ¬5éÖ^Bg‘òÍ*Œ@Òç(“3€UÁ^nô± #ÚcP6:A3jáÆ ¬Â$ítè=7Éíýù´ê¼Ú_·¤Ùü;Ã>²ëŠ`%@@P%@@PnÉS{ávzÕûK`F8 %@@E¹«0®X… Ç*Œ»æz쟊 (‡ʱK*^{MGà|”5Q\Ï™/æ ­ÎX}¾¶bgáÆäÏýFúËHdí$eá’Šc—޵ģd„³:IPN“|ŒyyÞµƒìïU¾T$°sçzgÆÂW:Ü•Zöæ.«0ÂQ¨(*ÊÍX…vÅ*Œ9VaÜ5×s`ÿT”A 8ÌлÿHž>uÂjpJ«(ë§Fzš°¦ÃT”Cú«$–o\dÆ¡Çýª.á4VQv$WI,ß8­ýöKU/7ó9XE™,‡ÞÙ_±³1¹ÐͨUÛ]êd¥ZNã`AÙOŸ¡‹<õÆ.ê0¡'ÀYjèÝV>_ wì LJ–Cµä‚«0vÂ×*ŒpÇÊö€º³¼â"Cï’½F-ëÑaæ(K–T̯€8ª…i[JÖ€çØ%À %@@P%@@PnÉS{ásÕû|¬ÂG1”7ßܬÙ€ÝJ½¿\¹»•¨(Þ=4ÒCï>®Ü€=xx÷Ðßèª7Ào†fsW½“É pJ™+Ø*J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€€ J€ÀW™×n¾¹Y­»5XQ>~ÿ¸f?v+]Q>¼{xûåmå®ì“9J€@º¢\pv²®Lw2Ý©L&¼˜³H¦|üðñáÝ .Õ€r†ÞA ”Ü çm·7·Íϯo¯íÍ–Î'4¸ òÎdU”MâÔ¡ÓθäÛ–j`⊲¯o¯·7··7·@œ’MƒíííÍ;“uk¸;À"–™£œ?ÈÍÔ˜M(דïT¢×S:Gym™öÀR– Ê¡ñø(óË@…$p ‹U”3³²=xŸœw Làâ9ÊNxe¦# c®ßàädLî;§A€¾¢‹9M´…mÆfeÿ"LçÒMagÊ{0VéÐ{(zúÛ C*¿ãØWçô ϯ0%@@P%@`ðbÎÇ—=Òâ ¬#”o¿¼-»jÂâ ¬&”Ÿ>}Z¿»eŽ (‚ ðÇåårÙ°Õÿ[J9‡U¨T³tIMEÑ6kX? IEND®B`‚rp-pppoe-3.15/gui/html/props-advanced.png0000644000175000017500000000647614045237007016501 0ustar dfsdfs‰PNG  IHDR¸È¥†RgAMA± üa8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2)Ý.I žIDATxœíÝ­{ÜV`í>ý(0,4 0(XPX`P`P¸  À аР`àÀ… ,P«*ÒÕ=ú4~ß§ÀÖŒ®ÎÈ_ν[E@Ö?Š¢øò¿/ç.`¥^¿zýªüêùãóY+X¯ž»€õÚï÷…  J€À«s0IÙë·ÛíÎ]Âx[ Ê2"þøæÜ…½<ûb³q9PÞ|wÓÞøî—wÉ”|r¸ã~¿‘°-å{ö¡ØOÏʹQߥz4¹1é$å  ýdR&%¿üçßEQ¼þñ×ä·³(Ç,Í;rÏC—=ÅKë:b]ãÜ&4ÔÐíCëdmþøæËO7Ó?8n„j¯ýþϼ.·„‹x»˜Ó§—l¿mæRÅS×›y1U ‹+ù’3 jèöüàRrå^ÿøkØή¬ív²ˆÖμFùî—wË¨Ý v5h]ÍZc{²·jŒ6Ùöö³ü"9rXÀe8cGϸùî«f¶g;Yd‚rÜêa©ÿÅèö:ÂóÇçª+nÛgi² ˆú»¨+G§ÈŒ\%Zfcr÷䯮ÔZÀ¦îçÈÂÊÿ3ÛÓç*vò+†ã<|®Æo +×QŽ^¨:ÛA¯¶ö]Y9£dˆÌØ‚%:ò”JæýÇ 9æÐþ®ëù=·çgßšÍËpê_§®r¦;Yœ}ê]©§än·›øÉä›êŒKŠyg)¬½ÚØõÌÌa×E׺Ž2tûô'ó2Õ›ÊJŸž,”‹}œ»ì=‹¿*.;{S¹Ú7ÒY ÑÛö™í®ö$³'ö´µlËÆO½«ôÊc5šÊ‰cvÍÔê“ëÆ›??ïN>yFádc#\žÅbghoéãA»Ýîá_ÿ±c}ù¿˜Ðõ´Ç™8rr÷®1«íõ£ÌõÒ6!ÿbËíÕ£¬YòJΩ5.yßÿt_NÃû¬õýù‡{OQôè‹9™NØïäÀ˜”ÈkKfH=aŠ¢¨ÏbƒÌ¹XËÅœR˜ë»Ýî¡•°a³´“CçÎÕ…R‹Õ8ù•Êv”§sóÝÍeÏ1áReÒ=Å;Êžž?>¿„%9¸$å{v[)YÙdPnËö°ÈR"(?¼ÿ°|ãl¨T`+Þ¼}ÓØ²¥œ… J€€ J€À€=þöx²2šî~¸Ë?aÉbÖ`‹'d‹5÷¾..ϰÏQ>¾'.df×W×ç.3è;õ~üíq±÷áãûÇ|¯±d1k°ÅÒ§æÍ¥dQ‡ãa£0SX£J€@¯5ÊÆ\£½ü4tÞWŽßëñ·Çäªy²˜j¨ú·í£Ô+Ÿe®ÚõB§¨]C²àüŽ=OH{œð•æOÚƒj.—ÿ’óñÌCËhÐõº¸T½×([ïœÇ÷åEï•ûƾƒ—´OUŒ«y„̱’G¯WØØqÐ ™òJÃÍ ¡26R¯ºH²þ«%[\Ze¢™ÿzP²‘iol·0]f×h”’ÊÔ™oóÊÝïÞÞ-ù™ú+­Žž|9Õ«n<§~BêÏ¡  zP¶ÉÆ–ú·õë[ÇCr¯ú3ó%#s®Q&™|w3W—W½uGËTRe\ãM9br÷ê(bæÕx9]ÿxŒ8!£ˆ.²ü¶s}F8É´­oL>3¿qýM.§e×GOÊ÷sýÍ–yc÷yç7M~¾ätŸƒÉÔ6tû,eTçö«‡æ8!ÓËÎôã=ˆƒz´ú““AVÔ2.¿{û¡>•´ŸãCB/Íø©w}ÚÕh1ÚOkDê)ÌÕT.&SpõÐbö)æúOlܦ÷}:Gºœpê]×uUw=N:Ûí_CÏ«7+4úG\Ÿö&çÎ õÇö Ãkÿ{äz P ‚rúT·£N6Ãbòóúâë Ó#»ç™—?bÖžö+m(Sö¸s’ÿ·kC§kô®¯®Ûƒ·7& 0û~QÆw”É5Ê¢5ÏÏË›˜‡ÇJŸ§ô÷¿>^¤NìPá+M^Æi¼¢þ?šý«Î1¹DXt¬]6.Ýd†m,qf6j0IÜ®¶~#š³ÿñÝۻꓽg/f ¦œþ5ê:n½æ‹Éë«k;¿Hõ{æ”·«Íu”+™Y”e¬¤˜5Øâ ÙbÍ}\Þ+")Z£ý#Pšís”UÎ>ÈÐ‘ç ¸úÑgyÀæ ¾˜Óè.‹~ —õçg1rÿÊû÷•s¸ Ã.æôÙÞó™õo3:®¼®ÁóÕÎ[p1ü #@@P%@@PåÌüÕ^¸<þÂùœv7»ã§ã¹«f¦£è(çä.Œ°]îÂã.ŒKs=.ŒŽ («˜zwý‘žþ·ÍqFàtÎßQÖÿÚc{û ×øc‘À)¬¢£ìº7YÕº #pFgî(线MÉ]SXEGy:îÂL·Š zðŠ»0 8gP¶—üê7·IrF`yç¿êÔ^RìsîÂÌk¥AYÌt+Dwa¦;çÔ;¼ƒcÿ„rFàtÖÛQ¬„ J€€ Ê™ù«½pyVñ›9Ã]á"é(‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ Ðy»Ú«o¯–¬`µÒåýÏ÷ ×°Z‰ŽòöÍíñÓqùRÖ)=õ~úð´pkpûæ¶½ÑÅ€?u­:v^Ì):’à"e®`ë(‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (‚ (¯2]}{µX«ÕÙQÞÿ|¿d«•î(oßÜ?.`¬QÒ匫“egº’åNm20BçÅœY2åéÃÓí›Ûœ«€þL½‚ (¹œ×]_]W_އÆöjKãÛΨ1½:Ê*qÊЩg\òis °qGÙˆ¿Ãñp}u}}uÝÄ)Y Xß^ßX=3Ù·†»Ìbž5Êé“ÜLY…r¹1ùL-*p:}×(O-²ã˜Ë ÀbAùùóçåëX-k”A ”¿×(÷ûýë`«þ¶g¤Æñ2ctIMEÑ3F†‰IEND®B`‚rp-pppoe-3.15/gui/html/props-options.png0000644000175000017500000000770314045237007016421 0ustar dfsdfs‰PNG  IHDR¸È¥†RgAMA± üa8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2)Ý.I#IDATxœíÝ-{äȹ`m® ó,h8`Á€€  <`Áƒ   X8ðÀh£h¤R½¥¯nI}ß×Z%u÷ã·J²TUd}SUÕ—9w36ê»o¿û¶þééãÓY[°]8w¶ëùù¹”!A øöÜ ˜¥®Ší»¹¹9w¦ÛkPÖyÿÛÏÝ È}õ\í6.—Ê7?¼éO|ÿ÷É”œ9\ðùùYD¾ÔßÙûêy~VNÈö"ͫɉI«T”£.6{eR&%¿üïÿTUõÝ_Nþwõ:kË®¹pÓõFרµ¡-¶uŽmò¥Q«;}l;Ùšûßþøåooæ_8m ÍRÏÏ¿çu=%ÄÛÙÉœ’Z²ÿµYJOC_æ“iÚp²m%w9óÒ¨Už_¹”ܸïþúsX.®¬ýr²ŠÆÎ>5Uqµ%C“u@´¿EXé¼:GfÍM¢e&&ONJ½± صõÞGN¬þdö»ÏMìäG §yúøÔ¬¿³òp[¹Šrò(@SÙŽÚÛvØeå‚’!²` –\ÉØ5Ïiɲ¿ ’ë[ß Í_8=ßûVlÃÚNÝäLy9Y½ëÝh§äÍÍÍÌ $“_ª3)æ¥aýÑÆ¡93C„CC3 meìôù3s™ÚEe£¤&ËåÉ.ç®kÏê?-®·»xQ¹Ù/ÒY6¡¶-éínö ³«ÆN¿ÛZ—eÓ»ÞMúêmuŠÊ™ëꩵ;×/¾ßœyAádg"ÏÉbglïéò ›››û?ýß„ÛÃÿÕŒª§¿ž™kN.>´Îfz{+KíÚ.äw¶žÞ¼Ê–%Ï䬭sÊûîowu7¼d¬ï÷÷®ÑèÉ's2•°¿É˜”ÈëKfH;aªªj÷bƒÌ¹»ßÊÉœZ˜ë777÷•¬„[¤œÛwnN„ÔšXlÖ“©\±¢\ϛ޻ Gu–N÷[¬( =}|º„!98’ú;»¯”lì2(«ÿnÃö°;ÈZ"(?üúáôí˜fGMöâío;SötyÀYJ€€ J€€ Œ¸<èá—‡ÕšÑõî/ïò3œ²1[°Ç²Ç6—÷‹ãwåïë4ã+ï~|W2Ûi³…äåõe册p}u]2ÛîÞÄÂ÷‚ƒ)íz?üòp²ÏôïùZã”Ù‚’²©”¬ªêåõåobø^pHÆ(‚ P4FÙékô‡iÆö¡ê5ä—zøå!9jžlL³ªöû[i·|‘~ßÐŽtQ¿ Éç,< µöaØ+¯g®gkÿ<ߨ6g>%˜Uu0´_Uñeï3úðëCý¯?ÂÝ,X¾¹ü«% h>ëÓÚA¦Ñ_ÕÐÛמ3?Q2²äe²dË×qKUyÍ—a²LKšŒëìÑœ-&o¶Òi̲ê@¬R‘Ú™­(K;k˜SÀÖ’ŸŠQÇyÂÛW>qûE.k‹ƒrè2ŽúûÜþ•›ùb—|ó;¯&¯ÃXïš’LÛÆN_¤ͱýê¥Ô[ÁÍïY'×ЉËfÎùobçSQõ‚¬šôöå—ʯÁEB—fz×»Ý=éüÒîÏÖ‰Ô5,UTžL¦ÁÍK'ë°ÏÑ’3OýíS92dÉ1Ê¡£jßüLãÏÒ†ÝõøšË¦c^(9™Ù÷fÌ·úú·u5ûíÛæ'“-ºÞó»ºåµdØÙ “ïdU_ŸZ=Y’Ùý±Ç¶@ú‘Ô?ES}]åeÆ' /VQ-Ùé}OøD­÷ #ù1èOL6@ïû¢L?™“£¬z=ñ|×ûdóp[ÉÆç×SýåçÇ«Ô+ßnæï /fVR¾¹É2ǹýyëÌ\þö }tûUš|SõWÛ~ÍÙÿ ÷Ýïš+{ÏÞ˜-èQ©´lÚî!ßÄö{Á‘´Ÿ™S?®6WQn¤gQ7c#Ù‚==¶¹Äñöˆ¤hŒòÜ¿üûÝ« ×>[»cÐv;ô&i_ÈÛës½™`/Á [ãîAÁ ÜΠ{}ÆF³õÙWyX_$t¼7ÑEB"qÖûÏoþ|¶æPl_AYM½HNïŸOÿl~®Ïz§Ç(w÷%dû|¨Ø‹ÏŸ?w¦£J€@¢ë}ÿøáñôMØ‚›77)*J€ÿºûé®?qð‚óÛ··k6`s®¾¿JNWQ%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@PïpÞ6t×߯ë§×Ì«õ›§•6ÿíL߈m¶jš#í œÑåû¿¿Ï¼Ú<ö¾ù`_Š*ÊZ²l,y^c]Ñ䃲ýj{þüÏŇfn¯vhâP“’Í·!9sr×J*¾þÌ…;Õþµìá*lƺc”pÊÊæûV©c·ÞYmá¶špۘ΂™ÍÚD§0/Ù©&° “kìáÊ7 Žd»'s’ߺ ƒn¯ñ¨­'“oCùVÆV^cwašQ‡«=Û´ã »0¢ë=Ù¹JŒ&ÝúѶͪ§ÓªvƒO>cW§bM.ǰbP&¿o§O¨f­=T7áË\¯gÕ,ØBÄL>\Éá¶Ûõ®Z¥JÝ¡+?õÑüœ_$ÜÛ,9'+ÙÍɇK-Éám"(ç÷ÝÚ‘š_má¶’¹<§aKEɨJ–¡é“—®7‡÷MUU_þýåéãS3éù鹪ªÛ··Í”ú‚óÌõ’í™M¿¬Îº¯òðùùþî¾´¢Ì_U~!Ö Ìyýôz95ãýJ¸X§¸<èD$\¬MœÌØ2A ”A ”A ”A ”¢¿Ì Œ3ôŽ%š9»m¶ªÖÿëò¡Ç-ä§s,PQÞýt7%dÔ·ãL>ÿkÔt`šë}õø[âí¿~ž¶áÂþ…K ­CO:Ìl"ùlẪË71ꩇÀÖœgŒrÚó'<íoæ3K4X¾‰ù»œÅ9ïÔ<ãaÎRÍ£lÆÞ“ðoÙZò,ÏÎõÔC`#NTQv"iÚÿ23fÍäÎûØnòЮ…O=6¨è)Œõç™ë%_?½®×ÄBžÌ4÷)Œ¿ªÜ°ž¢³Þ·oo·P3ÑuVu„§0ŠH`Uî”A 8ÂåõÕ,eË'ý`²KÊÊw{9‡ná »¦ë ”A (£úÁU¯ôê°ÒæÂ‰›ršƒnÄÉœ³ ÏÞ€-sp`=Ïzgʽ±Ö*ÌVáƒÃ:ÓG•Zí[uêèò§¡µï(ÜFE~¯KŽgr§¦œ¾òë¥\-ÀåXfŒ²ä!\áâ–JÞx; •? m( ×Ù~)ÜDþÉe«œ÷¿Èz`FT”G/td¢¡ýü¯ÎÚÚ÷µ+ó¬ˆ9O×j×€%+z:ØÌT*ivf…gH¾Z¬ïO —c™1Êä9Q6rCÉvŽt2¥ßÂEnQ>ô«%?pJ«üe΄"®*뮞Fòq=Õ@ ›Éf”( Èגɵdl#ók›¹ˆñGèX¸¢l†#›ÿŽ]ª³† ›^ã|N²…ÉM6#?±½ø¨í–ïiù"¯Ÿ^ý½6t=\lwÊ+Ö«ï¯Ö»ÌeÕÂy²õZå¦ìÝ܇‹mß´:ôB880Çq‚r‘sÐGåàÀ‡ºåÖ¾ÿ›jϦûrœŠ`%‡ª(§qÍ wéAéj ¤ë ”A ”A ”A ”A ”A ü[ïúN¿¤+Ê»ŸîNÜ€ÍJT”·oo×{Œ ÀÞnÑ\¦ä}ÌøÝШcîÆ½îh \ŽÌl%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@@P%@àÛÌkWß_¬›5XQÞýtwÊvlVº¢¼}{ûúéõÄMØ&c”tE¹àèd]™nd¸S™ L0x2g‘LyüðxûövÁ.Õ€rºÞA ”Üçm×W×ÍÏ/¯/éÍ”Î'¬pAåÈ(ª(›Ä©C§qÉÙ–Z!ÀÄe'þ^^_®¯®¯¯®;8!%›¶§·'6s&ëÖpq€E,3F9¿“›©1›P®'&çT¢ë)£\[&d§½°”e‚r¨?>Êü2P! ¬a±ŠrfV¶;ï“óN ¬!£ì„Wf8²0æú+œœŒÉe笠¯èdNmáI›±YÙ? Ó9uSؘòŒUÚõŠžþôÂÊ/8öÕ9-Èó'ŒA ”A <™óøáqÙ--¾B€ÓHåë§×eŸš°ø N&”Ÿ?>};6Ë%@@P%@à¿c”ÏÏÏgl{õÿ-ÆFiUˆtIMEÑ,4C Y—IEND®B`‚rp-pppoe-3.15/gui/html/mainwin-busy.png0000644000175000017500000000412214045237007016177 0ustar dfsdfs‰PNG  IHDRÎIúÈŽógAMA± üa8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2)Ý.I²IDATxœí«zã8ÇÏîWP¸°0 Ð`Á€À ø,((è,0(0°Ð @`@`À<À<€ ”œ9Õݲ,_¢ßWà(–t,ÿstt± HDá7øùßϱÍH,œÛ›Û~Ô¾µ£Z’X>¿m@bù0Æ I-$µD$nÆ6 Ü3_yžm‚?s•ÙöËvlC¢²{ÞÁl^jëk9q÷¼S6òdkFÆÙáå Í©¼2ýåÞÞÜ:&)Yy¾úL¿j]cv£åiüV™¨d¯Öiê¤ë<‹AgUU )û—ýù«é«ÃÞPËæ¯R×5”e)¦¿ÖPRzSë /î !¥ù·1ƒ´m»^¯ùå÷ŸŸò+s1Ƹ°xŠ5˜™YÊufrfûýઇªz¨Pm@äUmªjS™Õy@Y–eYâG./(?—åç?¢¼Ê¢,‹Ò 6p–—@Û¶À¾±í—mäÙÐö­E–ç9cLpf_;²Ôxð±`¨·k¾úhkj¬?®©Ä]¤æEq܆r4оµè™åb­.mRpq…÷Eq_„R[þg¾{Þ)Þ¸ !€àØÞ™d«ËäÕ¼ûr ;]-ý¹èÔæØhï Õ†|eë=á}d†½'”ŸIú+I'>¬nj9€£Ÿ~El~©Ž¡;V¼Sî. Fï@ª3xÅc5yˆ*yQñÀáŸýHåõ.ýU“n ÎÂÊ+Ô±!.~Á$µh¤ÜÿÁÅb^oÇû—½<,PœvŸu¢aF zãä·»ÿûÁðºÇ§êåíÆuôœÖ@ó<ß=ï6›± q…÷§|@Ò´øTà_×’G™ìiø¹ý²å©KÌ3•X-ç5üHgԌݨŒ´!u]+ÛL¥ÕM-wÍÍ×fî Ï…¥ŒÛtL늭¿ îØøñÝwÃ[49Ø·óâo—ֵĚƒÝ4–cŽØÎ¾çµ ¯Ù¤¶%®ÔYLcÛÇiy5GÚ·žÇ¶%*¡V?Ga–RƒKs_Û&¢™ŠŒ£ÚÝÝlb Ó÷ÓØ&DeF·æÇBÊ\½Z¢'MÝk­¢(;OÐ\»ÔVVc›0V—¿ýûѯäÝ“OÆk—,´nêÆÃñ ÊœV ³&I- §4[ex|<3F[5¯”TâR fq7)ÚåL»Wá 4 hC„*¬—)4KŠū ¿<<ýž©üá å(ݤ®L~ ,Ùj€| .ðBx¥.†™íQÚ — ã>:öÙø $½ñ H 5aHTfW&ʺñ3 .†ìÑ¡»4vO;ÁfüñiàÉeÃumÍ>­/çÐÁ Z…ÙcyÏÄ^Ñîˆ1ŸŽ¡Û¼¸–)ÜyEÓfkuAdzºŸé`ÊQpئT¨K X…5 ¨äåwù}<âîi9»¤ì^ £lüïÝ#“³+i:ÆÑ†“ûc0ÀP=G0X°\™Kgÿéûij‹K}PìÂÑN•þ¬>¬®s ´©›>±šõ7@7ñ]¸ia*‰$µD$Ò&¢ëe« c1³ ˜ýjÁìXØ(oʤX-‰$µD$Ôhä‡;øÌVœJ­k‘St¡ÐÆjÑZN6]é uÅr„­²|ì¥äŒeÇÜɆÔζÊYàbcì%ÉX–±Œ~tÏ{í#Ðá—Mu ©æ­”˜kONVêLvrAlp—ý§*œ\’Ú (7 )ŽåìòÓ‘­²Šëc•QIá1ý*” 8ægmóc•ótjs’šð".áÅZ^‡éžE÷Sðämæßwÿç”|˜àºP^¹ÆÛ±uvÎþ^L(/T¤Œ=VCqp Êë˜éóHqžÔº ê þ|”ÙµpÝèl®0ïñ¥ûF…m6Z¸ÂÌãÿT~W • M‘_”êýöîN*õq)÷¨yl°véÑ¢ŽODŽTv¡l€÷­-wÁèÏÎ%kg÷j(êÞ€t‚‚ªdÙá±Å€°Ý ݱÆgT•Z …`†îÁ b 7ÉÅ¥áZ.úæäªýl8»4•/÷x ÍÉ«ÉjÓc.¡²Ú<²»#xÇá6ú*+UÞ¹ütýöÝP&™mй(:̫ɯÙ`t=Gé!Çj.®K‡‹µ´:¡s´Æ^ºMämø5®Ô”ãbÅîÕ¨'3¼žžžÖÜ@=Y×K …c‡¥DޱtQ—²Ò à¨)G¨Â܃÷±6§¾6PÂÌ«yh«çÿõÛ¯¶g# Ì3œº‘5EN—ož|w­NÊÄ.5îÉäÑ%ýJæ”=©œE‡*æ*Ð?»Õuª¬ËÅÂàa\·ÿå1‡ðEvX¿Ò»—F1w ]OëZ‘² Ã;a%-·O‹ymÖèD’Z" \nOýÚ4I^- ­W呵˜•WWŸM‹AµN;e†Ô ½³#1ò;;^Mþï@‰DR¬–ˆD’Z"Ij‰HüŠÕ"lãN$‰Áùø!;„K°tIMEÑ&D3IEND®B`‚rp-pppoe-3.15/gui/html/tkpppoe.html0000644000175000017500000001633714045237007015432 0ustar dfsdfs TkPPPoE Manual

tkpppoe - A GUI for managing PPPoE Connections

Introduction

TkPPPoE is a graphical user interface for managing PPPoE connections. It performs two different functions:
  • TkPPPoE lets you define connection properties. This step must be done as root.
  • TkPPPoE lets you start and stop PPPoE connections. This step may be done as a normal user, depending on how you configured the connection.

Defining Connections

To define connections, start TkPPPoE as root. You can do this from a terminal by typing tkpppoe, or from the KDE or GNOME menus by selecting Internet : TkPPPoE. The following window pops up:

Main Window

Because you have not yet defined any connections, the connection property window also pops up:

Connection Properties - Basic
You can pop up the connection property window at any time by clicking New Connection... You can edit the properties of an existing connection by selecting the connection's name and clicking Properties...

Basic Information

Let's fill in the basic information:
  • For Connection Name, enter a unique name for this connection. It can be anything you like, but must contain only letters, numbers, underscores or dashes. In particular, it can't contain spaces. If you have only one PPPoE connection, a good name is Default.
  • For User Name, enter the user name supplied by your ISP. Enter only the user name; do not enter an "@isp.com" part.
  • For Network, you may have to enter your ISP's domain name. (For example, isp.com.) Some DSL providers add this to your user name; others do not. You may have to experiment a bit. The two most likely choices are your ISP's domain name, or blank. Try both.
  • For Password, enter the password your ISP provided you with.

NIC and DNS

Click on the NIC and DNS tab:

Connection Properties - NIC and DNS

  • For Ethernet Interface, enter the Ethernet interface connected to the DSL modem. It is something like eth0 or eth1. Click on ... to browse a list of detected Ethernet interfaces.
  • For DNS Setup, you have three options:
    1. From Server means that the system will obtain DNS information from the PPPoE server. This is the correct choice for most ISPs.
    2. Specify means that you will enter the IP addresses of your DNS servers manually. In this case, enter the addresses in the Primary DNS and Secondary DNS entries.
    3. Do not Adjust means that you want RP-PPPoE to leave your DNS setup alone. Use this if you are running your own caching DNS server or know that you don't want the DNS setup touched.

Options

Click on the Options tab:

Connection Properties - Options

  • If you want ordinary users to be able to start and stop this connection, enable Allow use by non-root users. If you do not enable this, non-root users will be able to monitor the connection, but not control it.
  • If you want to use synchronous PPP, enable Use synchronous PPP. This is recommended as it conserves CPU usage, but may not work on some (misconfigured) Linux kernels.
  • For Firewalling, you have three options:
    1. Stand-Alone installs a simple firewall ruleset for stand-alone machines. Use this if you have only a single computer connected to the DSL modem.
    2. Masquerading installs a simple firewall ruleset for using your Linux computer as an Internet sharing device. If you have two Ethernet cards, you can connect one card to the DSL modem and the other to an internal LAN. The masquerading firewall ruleset lets internal machines share the DSL connection.
    3. None. If you already have your own firewall rules, or you wish to run servers on your machine, select None. This is not recommended unless you take steps to secure your machine, and know what you are doing.

Advanced

Click on the Advanced tab:

Connection Properties - Advanced

In most cases, you can leave AC-Name and Service-Name blank. In some cases, your ISP may require you to enter information in these fields; contact your ISP for more information.

Controlling Connections

For these examples, run tkpppoe as a normal user (not root). The main window appears like this:

Main Window - Non-root

  • To start a connection, press Start. The two LEDs flash red and grey. If the connection is established, they turn green.
  • To stop a connection, press Stop.

The two rectangles to the right of the connection name are the status LEDs. The top LED corresponds to transmitted data and the bottom to received. The LEDs are colored as follows:

  • Grey -- connection is not established.
  • Flashing red/grey -- connection is being started.
  • Green -- connection is up, but idle.
  • Yellow -- connection is up and data is being sent or received.
  • Red -- connection has been lost, but the system is trying to reestablish it.

When a connection is established, two graphs appear:

Main Window - Established Connection

The left (red) graph shows transmitted packets and the average transmission speed (in bits per second) over the sample time. The right (green) graph shows received packets.

Miscellaneous Information

  • The connection menu has an entry called User's Manual which will pop up this user manual (if you have Netscape installed.)
  • You can define multiple PPPoE connections, but you should not use more than one simultaneuously unless you feel comfortable editing scripts and setting up routing tables. By default, TkPPPoE tries to add a default route for connections. This does not work well with multiple simultaneous connections.
  • If you exit from TkPPPoE, connections which are up remain up. You have to explicitly stop connections if you want them terminated.

TkPPPoE is Copyright 2001 Roaring Penguin Software Inc and is licensed under the GNU General Public License.

Screenshots show TkPPPoE running under the XFCE desktop, a lightweight UNIX and Linux desktop. rp-pppoe-3.15/gui/tkpppoe.in0000644000175000017500000032361414045237007014127 0ustar dfsdfs#!/bin/sh # -*-Mode: TCL;-*- # LIC: GPL #-------------------------------------------------------------- # tkpppoe # # A graphical front-end for configuring and using rp-pppoe. # # Copyright (C) 2001 by Roaring Penguin Software Inc. # This file may be distributed under the terms of the GNU General Public # License, Version 2, or (at your option) any later version. # # The "Roaring Penguin" logo is a trademark of Roaring Penguin Software Inc. # #-------------------------------------------------------------- # $Id$ # the next line restarts using wish \ umask 022; \ exec wish "$0" "$@" || clear; echo "*****"; echo "Cannot find 'wish' -- you need Tcl/Tk installed to run this program"; exit 1 # Try requiring msgcat (Tcl 8.1 and later) set problem [catch {package require msgcat} err] if {!$problem} { set problem [catch {::msgcat::mcload [file join "@datadir_evaluated@" tkpppoe]} err] } if {$problem} { puts "$problem - $err" # Oops... leave as English proc m { str } { return $str } } else { proc m { str } { ::msgcat::mc $str } } # Set app name tk appname TkPPPoE # Set this to one if you want to allow multiple instances of TkPPPoE set AllowMultipleInstances 0 # Check for other instances if {"[tk appname]" != "TkPPPoE"} { # Must be another instance running... if {!$AllowMultipleInstances} { send TkPPPoE AnotherInstance exit 0 } } # Location of config directory set ConfigDir /etc/ppp/rp-pppoe-gui # Are we running as root? set Admin 0 # Location of connection info file set ConnectionInfoFile [file join $ConfigDir connection-info] # Location of password file set PasswordFile [file join $ConfigDir passwd] # Location of "already run" file set AlreadyRunFile [file join $ConfigDir gui-already-run] # Connection information set ConnectionInfo {} # Connection options set OPTS(nonroot) 0 set OPTS(sync) 1 # Location of wrapper set Wrapper "@WRAPPER@" # Timer token for UpdateConnectionState set UpdateToken {} # Update interval in milliseconds set UpdateInterval 500 # Packet counters for signalling activity set Packets(in) 0 set Packets(out) 0 set Bytes(in) 0 set Bytes(out) 0 set MeasureTime 0 # Set up some options to make it look better option add *Button.borderWidth 1 option add *Button.Pad 1 option add *Menubutton.borderWidth 1 option add *Menubutton.Pad 1 option add *Entry.Background white # Array holding help strings for windows array set HelpData {} bind HelpWin "HelpWindowEntered %W" bind HelpWin "HelpWindowLeft %W" proc AnotherInstance {} { wm deiconify . raise . } #*********************************************************************** # %PROCEDURE: HelpWindowEntered # %ARGUMENTS: # w -- window # %RETURNS: # Nothing # %DESCRIPTION: # Looks for procedure in HelpData; evals it if found. #*********************************************************************** proc HelpWindowEntered { w } { global HelpData if {[info exists HelpData($w)]} { set cmd "$HelpData($w) Enter" uplevel #0 $cmd } } #*********************************************************************** # %PROCEDURE: HelpWindowLeft # %ARGUMENTS: # w -- window # %RETURNS: # Nothing # %DESCRIPTION: # Looks for procedure in HelpData; evals it if found. #*********************************************************************** proc HelpWindowLeft { w } { global HelpData if {[info exists HelpData($w)]} { set cmd "$HelpData($w) Leave" uplevel #0 $cmd } } #*********************************************************************** # %PROCEDURE: RegisterHelpWindow # %ARGUMENTS: # w -- window we need help about # helptext -- the help text # win -- window in which to put help messages # %RETURNS: # Nothing # %DESCRIPTION: # Sets things up so help text appears in "$win" when mouse enters "$w" #*********************************************************************** proc RegisterHelpWindow {w helptext win} { global HelpData set tags [bindtags $w] if {[lsearch -exact $tags HelpWin] < 0} { lappend tags HelpWin bindtags $w $tags } set HelpData($w) [list HelpInTextWin $helptext $win] } #*********************************************************************** # %PROCEDURE: HelpInTextWin # %ARGUMENTS: # text -- help text # tw -- window in which to write text # what -- one of "Enter" or "Leave" # %RETURNS: # Nothing # %DESCRIPTION: # Clears out $tw; if $what is "Enter", puts $text in $tw. #*********************************************************************** proc HelpInTextWin {text tw what} { $tw configure -state normal $tw delete 1.0 end if {"$what" == "Enter"} { $tw insert end $text } $tw configure -state disabled } #*********************************************************************** # %PROCEDURE: drawLogo # %ARGUMENTS: # c -- canvas to draw logo in # bg -- background color of canvas # pencolor -- color of the word "Penguin" # %RETURNS: # Nothing # %DESCRIPTION: # Draws Roaring Penguin logo in a Tcl canvas #*********************************************************************** proc drawLogo { c bg {pengcolor #6699cc} } { $c create polygon 372.249 5.182 361.23 5.519 \ 346.164 8.892 316.482 20.023 305.463 17.774 296.468 \ 19.573 288.935 24.97 282.864 33.177 267.348 55.102 \ 254.531 77.814 236.204 125.26 225.635 174.844 \ 221.026 226.113 213.605 228.025 208.658 232.634 \ 225.523 240.28 250.708 243.316 282.752 242.416 \ 320.079 238.818 330.985 193.17 338.181 146.735 \ 338.743 99.963 335.483 76.577 329.524 53.191 345.602 \ 48.131 353.135 45.995 359.768 41.048 342.679 43.184 \ 324.689 40.036 334.583 28.905 348.3 18.674 372.249 \ 5.182 -fill #000000 -outline {} -width 1 -tags logo $c create line 372.249 5.182 361.23 5.519 \ 346.164 8.892 316.482 20.023 305.463 17.774 296.468 \ 19.573 288.935 24.97 282.864 33.177 267.348 55.102 \ 254.531 77.814 236.204 125.26 225.635 174.844 \ 221.026 226.113 213.605 228.025 208.658 232.634 \ 225.523 240.28 250.708 243.316 282.752 242.416 \ 320.079 238.818 330.985 193.17 338.181 146.735 \ 338.743 99.963 335.483 76.577 329.524 53.191 345.602 \ 48.131 353.135 45.995 359.768 41.048 342.679 43.184 \ 324.689 40.036 334.583 28.905 348.3 18.674 372.249 \ 5.182 -tags logo $c create polygon 298.605 109.632 290.734 \ 159.328 282.752 182.939 271.958 205.65 262.851 \ 171.133 263.75 138.752 264.537 164.5 271.958 192.833 \ 286.687 157.192 298.605 109.632 -fill #ffffff \ -outline {} -width 1 -tags logo $c create line 298.605 109.632 290.734 159.328 \ 282.752 182.939 271.958 205.65 262.851 171.133 \ 263.75 138.752 264.537 164.5 271.958 192.833 286.687 \ 157.192 298.605 109.632 -tags logo $c create polygon 312.546 30.592 315.132 35.876 \ 310.747 39.586 308.161 34.414 312.546 30.592 -fill \ #ffffff -outline {} -width 1 -tags logo $c create line 312.546 30.592 315.132 35.876 \ 310.747 39.586 308.161 34.414 312.546 30.592 -tags logo $c create polygon 328.624 54.427 322.665 58.7 \ 314.458 61.286 289.16 59.15 284.55 74.665 285.338 \ 90.181 303.214 98.951 308.499 106.259 310.523 \ 116.378 305.913 130.208 312.771 141.563 308.049 \ 167.76 299.729 192.158 279.041 238.593 313.558 \ 233.871 327.388 185.75 335.033 139.989 335.82 96.253 \ 328.624 54.427 -fill #ffffff -outline {} -width 1 -tags logo $c create line 328.624 54.427 322.665 58.7 \ 314.458 61.286 289.16 59.15 284.55 74.665 285.338 \ 90.181 303.214 98.951 308.499 106.259 310.523 \ 116.378 305.913 130.208 312.771 141.563 308.049 \ 167.76 299.729 192.158 279.041 238.593 313.558 \ 233.871 327.388 185.75 335.033 139.989 335.82 96.253 \ 328.624 54.427 -tags logo $c create polygon 53.837 185.412 54.399 185.862 \ 53.837 188.223 54.399 188.673 53.837 188.673 53.837 \ 189.572 53.837 190.472 53.387 191.034 52.938 192.833 \ 50.577 195.644 49.677 196.656 49.677 197.105 48.215 \ 198.455 47.316 198.904 46.866 198.904 44.505 200.816 \ 43.606 200.366 42.594 201.265 42.144 201.715 41.245 \ 202.277 40.795 202.727 40.345 202.277 39.783 202.277 \ 36.972 203.177 36.522 203.177 36.073 203.177 35.623 \ 203.627 34.723 203.627 34.161 203.627 34.161 204.076 \ 30.901 204.526 28.54 205.538 26.291 205.088 25.729 \ 205.088 24.829 205.088 24.38 204.526 23.93 204.526 \ 23.48 204.526 22.918 205.088 22.918 206.437 22.918 \ 206.887 22.918 207.337 22.468 207.337 22.468 208.798 \ 22.018 209.248 22.018 211.16 22.018 211.609 21.569 \ 213.521 21.119 215.769 21.569 216.781 20.669 218.13 \ 20.669 219.592 20.669 220.042 20.107 220.941 20.107 \ 221.953 20.107 223.752 19.657 225.664 19.208 226.113 \ 19.657 227.013 18.308 230.835 17.858 240.167 17.296 \ 248.15 17.296 249.05 16.846 250.062 15.947 250.062 \ 15.048 250.062 15.048 250.511 12.686 251.86 12.237 \ 251.86 11.675 251.411 11.675 250.511 11.675 246.689 \ 11.225 245.339 11.225 243.878 10.775 240.617 11.225 \ 239.268 11.225 238.818 10.775 238.256 10.325 237.357 \ 10.325 236.007 9.876 232.634 9.876 231.735 9.876 \ 231.285 9.876 230.835 9.876 230.386 9.876 229.824 \ 9.426 229.374 9.426 226.113 9.876 226.113 9.876 \ 225.664 9.426 224.202 9.426 223.752 9.426 223.302 \ 10.325 221.953 9.426 220.941 9.426 219.592 9.426 \ 219.142 9.426 218.58 9.426 217.681 9.426 217.231 \ 9.426 216.781 8.864 216.332 8.864 214.42 8.864 \ 213.97 8.414 213.521 8.414 210.148 8.414 209.248 \ 7.964 207.899 8.414 205.988 8.414 204.526 7.065 \ 201.265 7.515 200.816 9.426 201.715 10.325 201.265 \ 10.775 200.816 10.775 198.904 11.225 198.005 11.225 \ 197.555 10.775 197.555 9.876 196.094 9.426 194.744 \ 7.515 194.295 6.615 193.845 6.053 193.845 5.153 \ 193.283 3.804 191.484 3.804 190.022 3.804 189.572 \ 3.804 189.123 3.242 188.673 3.242 186.762 3.804 \ 185.412 4.254 184.85 4.704 184.4 7.964 180.24 10.325 \ 178.779 11.225 178.779 12.237 177.879 14.036 176.98 \ 15.497 175.968 21.569 173.607 22.918 173.157 23.48 \ 173.157 24.38 172.707 24.829 172.707 29.102 171.808 \ 29.551 171.808 30.001 171.358 31.35 170.796 31.913 \ 171.358 32.362 170.796 39.783 171.358 40.345 170.796 \ 42.144 171.358 47.766 174.619 48.778 176.418 49.227 \ 176.418 49.677 176.98 50.127 176.98 51.588 178.329 \ 52.038 179.228 52.488 180.69 52.038 181.14 52.038 \ 181.59 52.488 182.039 52.938 182.039 53.387 182.601 \ 53.837 183.051 53.837 183.501 53.837 185.412 -fill \ $pengcolor -outline {} -width 1 -tags logo $c create polygon 42.594 222.853 43.156 221.953 \ 41.694 222.403 39.783 224.202 39.783 224.764 39.783 \ 225.214 40.345 225.214 41.245 224.202 41.694 223.752 \ 42.594 222.853 -fill $pengcolor -outline {} -width 1 -tags logo $c create polygon 58.559 234.096 59.009 234.096 \ 59.009 234.546 58.559 234.995 58.559 235.445 57.21 \ 236.907 56.648 237.806 52.938 241.067 52.038 241.629 \ 52.038 242.079 51.026 242.529 50.577 242.978 50.127 \ 242.978 49.227 244.44 45.405 246.239 44.055 246.689 \ 43.606 246.689 43.606 247.251 42.144 247.251 41.694 \ 247.7 40.795 247.7 38.434 248.15 36.522 248.15 \ 35.173 247.7 34.161 246.689 33.711 246.239 32.812 \ 244.44 32.362 241.629 32.812 239.718 32.812 239.268 \ 33.711 234.995 36.522 229.824 35.623 228.474 35.623 \ 227.013 36.522 225.664 37.534 224.202 38.883 222.853 \ 41.694 220.492 42.594 219.592 43.156 219.592 43.606 \ 219.142 45.405 217.681 45.967 217.681 46.416 217.231 \ 48.778 215.769 52.038 214.87 53.387 214.42 54.849 \ 214.87 55.299 214.87 56.198 215.769 56.198 217.681 \ 56.198 218.58 54.399 221.953 53.837 222.853 53.837 \ 223.302 53.387 223.752 50.577 226.113 49.677 226.563 \ 47.316 228.474 43.156 230.386 41.245 230.835 40.795 \ 230.835 40.345 230.835 39.333 230.835 38.883 230.835 \ 38.883 229.824 39.783 229.374 40.795 228.474 41.694 \ 228.025 42.594 227.575 45.967 227.013 46.866 226.563 \ 50.127 224.764 51.588 223.302 52.488 221.953 52.488 \ 220.492 52.488 219.142 51.026 218.13 49.677 218.13 \ 48.778 218.13 47.766 219.142 47.316 219.142 47.316 \ 219.592 46.866 219.592 45.967 220.941 44.505 221.953 \ 44.055 222.403 43.606 222.853 42.594 223.752 41.694 \ 225.664 41.245 225.664 41.245 226.113 40.345 226.563 \ 39.333 227.575 39.333 228.474 38.434 229.374 36.522 \ 233.197 35.623 236.457 35.623 237.357 35.623 238.256 \ 35.173 241.067 35.623 242.079 36.522 243.428 37.534 \ 243.878 37.984 244.44 38.434 244.89 38.883 244.89 \ 39.783 245.339 43.156 245.339 45.967 244.44 49.227 \ 242.529 50.127 241.629 50.577 241.067 54.399 238.818 \ 54.399 238.256 54.399 237.806 56.198 236.907 58.559 \ 234.096 -fill $pengcolor -outline {} -width 1 -tags logo $c create polygon 92.289 248.6 92.739 249.05 \ 92.289 249.05 91.84 249.05 90.94 248.6 90.378 248.6 \ 89.478 247.7 89.029 247.251 88.129 246.689 87.117 \ 245.789 85.768 244.89 85.318 244.44 85.768 244.44 \ 85.318 242.529 84.756 242.079 84.756 240.617 84.756 \ 240.167 84.756 239.718 84.756 239.268 83.857 236.457 \ 83.407 234.096 83.407 233.197 83.407 231.735 83.407 \ 223.302 83.407 221.391 82.957 220.941 82.508 221.953 \ 80.596 226.113 80.146 226.563 80.146 227.013 79.697 \ 228.025 79.135 228.474 79.697 228.474 76.324 234.096 \ 75.874 234.995 75.424 236.457 74.975 236.457 74.975 \ 236.907 74.975 237.357 74.075 239.268 73.513 239.718 \ 73.063 240.167 72.613 241.067 72.164 242.529 71.714 \ 242.529 71.714 243.878 70.252 245.789 69.803 246.689 \ 68.903 246.689 68.903 247.251 67.891 247.7 66.542 \ 247.7 66.092 247.7 65.643 247.7 65.08 247.251 65.08 \ 246.689 65.08 245.789 64.631 242.079 65.08 242.079 \ 64.631 241.629 65.08 241.067 65.08 238.818 64.631 \ 237.806 64.631 236.457 64.631 234.546 64.631 233.197 \ 64.631 232.634 64.631 232.185 64.631 231.735 64.631 \ 228.924 64.631 227.575 64.631 225.664 64.631 225.214 \ 64.631 224.764 64.631 223.302 64.631 217.231 65.08 \ 216.332 65.643 215.769 69.803 214.87 70.252 215.32 \ 70.252 216.332 70.252 217.681 70.252 218.58 69.803 \ 219.142 69.803 220.492 69.353 220.941 69.353 221.391 \ 68.903 221.953 68.903 225.664 68.453 226.563 68.453 \ 228.025 68.453 228.474 67.891 228.924 67.891 230.835 \ 68.453 236.457 68.453 237.806 68.453 238.818 68.453 \ 240.617 68.453 241.067 68.903 241.067 68.903 241.629 \ 69.353 241.629 70.702 241.067 70.702 240.617 71.264 \ 240.167 71.264 239.268 72.164 238.256 73.063 236.457 \ 74.525 234.546 74.975 233.197 76.324 230.835 77.336 \ 229.824 78.235 227.575 78.235 227.013 78.685 226.563 \ 78.685 225.664 79.135 225.214 79.697 224.764 79.697 \ 224.202 80.146 222.403 81.046 220.941 81.945 217.681 \ 82.957 215.769 85.318 214.87 85.768 214.87 87.567 \ 214.42 87.567 215.769 87.117 216.332 87.567 216.781 \ 88.129 219.592 87.567 219.592 87.567 220.492 87.567 \ 221.391 87.567 224.764 87.567 225.664 87.567 226.113 \ 87.117 226.113 87.117 227.575 87.567 229.374 88.579 \ 235.445 89.029 239.268 89.029 239.718 89.029 241.067 \ 89.478 242.529 89.478 242.978 89.928 243.878 89.928 \ 244.44 90.378 244.89 90.94 246.239 92.289 248.6 \ -fill $pengcolor -outline {} -width 1 -tags logo $c create polygon 117.587 220.492 118.037 \ 222.403 117.587 222.853 117.587 224.764 116.687 \ 226.113 116.687 227.013 116.238 228.025 114.776 \ 229.374 113.877 231.285 112.865 231.735 109.154 \ 234.995 106.343 236.457 105.444 237.357 103.982 \ 237.806 103.083 238.256 102.633 238.818 102.183 \ 238.818 101.172 239.268 99.822 239.718 98.361 \ 239.268 97.461 239.718 96.562 239.268 96.0 238.818 \ 95.55 238.818 94.201 236.907 94.201 235.445 94.201 \ 233.646 94.65 233.197 94.65 232.634 95.1 232.185 \ 95.1 231.735 95.55 231.735 96.0 230.386 97.461 \ 228.025 97.461 227.575 98.361 226.563 99.822 224.764 \ 101.172 223.302 101.172 222.853 102.633 221.391 \ 103.083 220.941 104.432 219.592 103.982 218.58 \ 103.982 217.231 103.982 216.781 103.982 215.32 \ 104.432 214.42 103.982 210.148 103.982 209.698 \ 103.982 209.248 104.432 208.798 104.432 207.899 \ 104.432 205.988 104.432 205.538 104.994 203.177 \ 104.994 202.277 104.994 201.265 104.994 200.816 \ 104.994 200.366 104.994 199.916 105.894 199.467 \ 106.343 198.904 106.793 198.455 107.243 198.904 \ 108.255 198.904 108.255 199.467 108.705 199.467 \ 108.705 202.727 108.255 204.076 108.255 205.538 \ 108.255 205.988 107.805 205.988 107.805 206.887 \ 107.805 209.698 107.243 210.71 106.793 212.059 \ 106.343 214.87 106.343 215.32 106.343 215.769 \ 105.894 217.681 106.343 217.681 106.793 217.681 \ 107.243 217.231 108.705 215.32 109.604 215.32 \ 110.054 214.42 110.054 213.97 110.616 213.97 110.616 \ 214.42 111.965 214.87 112.415 214.87 112.865 215.32 \ 114.326 216.332 116.238 217.681 116.687 218.58 \ 117.137 219.592 117.587 220.042 117.587 220.492 \ -fill $pengcolor -outline {} -width 1 -tags logo $c create polygon 123.658 258.944 123.658 \ 259.394 123.658 260.293 123.658 261.755 123.658 \ 262.654 123.658 263.104 123.209 266.364 123.209 \ 267.376 122.759 269.175 122.309 269.737 121.859 \ 271.087 121.859 271.536 121.859 271.986 121.297 \ 271.986 121.297 272.548 120.847 273.448 120.398 \ 273.448 120.398 273.897 118.486 276.259 118.037 \ 276.708 117.587 277.608 117.137 278.17 116.687 \ 278.17 115.675 278.62 115.675 279.069 113.427 \ 280.419 112.865 280.981 112.415 280.981 111.965 \ 281.43 110.054 282.33 109.154 282.33 108.705 282.78 \ 108.255 282.78 107.805 283.229 104.994 283.792 \ 104.432 283.792 103.982 283.792 103.533 283.792 \ 103.083 283.792 102.633 283.792 102.183 283.792 \ 101.172 283.792 100.722 283.792 99.822 283.792 98.81 \ 283.792 96.562 282.33 96.0 282.78 95.1 281.88 94.201 \ 281.43 91.84 279.969 92.289 279.519 92.289 278.62 \ 93.751 279.069 93.751 279.519 94.201 279.519 94.65 \ 279.969 95.1 279.969 96.0 280.981 98.81 281.88 \ 101.172 281.88 101.621 281.88 102.633 281.88 103.083 \ 281.88 103.533 281.88 104.432 281.43 104.994 281.88 \ 105.444 281.43 106.793 281.43 107.805 280.981 \ 108.705 280.419 109.154 280.419 109.604 279.969 \ 110.054 279.969 110.616 279.969 111.066 279.519 \ 112.865 278.17 113.427 277.608 113.877 277.608 \ 113.877 277.158 114.326 277.158 114.326 276.708 \ 114.776 276.259 115.226 276.259 116.238 274.347 \ 116.687 274.347 116.687 273.897 117.587 272.998 \ 117.587 272.548 118.037 271.986 119.498 267.826 \ 120.398 265.015 120.398 262.204 119.948 259.843 \ 119.948 259.394 119.948 258.944 119.498 257.482 \ 118.486 254.222 118.037 253.772 117.587 251.86 \ 115.675 249.05 115.226 248.6 114.776 248.15 113.877 \ 247.251 111.965 246.239 111.515 246.239 110.616 \ 246.239 110.054 246.239 109.154 246.239 107.243 \ 247.251 106.343 247.251 105.444 247.7 104.994 247.7 \ 103.083 248.15 102.183 248.6 101.621 248.6 101.172 \ 249.05 100.722 249.499 99.822 250.062 98.361 250.062 \ 97.461 249.499 97.012 249.499 96.562 249.05 96.562 \ 248.6 97.012 248.15 99.822 245.789 100.272 245.339 \ 101.621 244.44 101.621 243.878 102.183 243.428 \ 102.633 243.428 102.633 242.978 103.982 241.629 \ 103.982 241.067 103.982 240.617 103.982 240.167 \ 105.444 239.268 108.705 236.907 108.705 236.457 \ 109.154 236.457 110.054 235.445 111.066 234.546 \ 112.415 234.096 112.865 233.646 113.427 233.646 \ 113.877 233.646 113.877 234.096 114.326 234.995 \ 114.776 235.445 114.776 236.457 114.326 237.357 \ 113.427 238.818 112.415 239.268 112.415 240.167 \ 111.965 240.167 111.515 240.617 110.054 241.629 \ 110.054 242.079 109.604 242.529 108.705 242.978 \ 110.054 242.978 113.427 242.079 114.326 242.529 \ 115.226 242.978 116.687 244.44 119.048 246.689 \ 119.498 247.7 119.498 248.15 119.948 248.6 119.948 \ 249.05 120.398 249.05 120.398 249.499 120.847 \ 249.499 120.847 250.062 121.297 250.511 121.297 \ 251.411 121.859 252.31 122.759 252.872 122.759 \ 254.222 122.759 254.671 123.658 258.494 123.658 \ 258.944 -fill $pengcolor -outline {} -width 1 -tags logo $c create polygon 147.607 215.769 148.506 215.32 \ 148.506 217.231 148.506 217.681 148.506 218.13 \ 148.956 218.58 148.506 220.492 148.506 220.941 \ 148.506 222.853 148.956 224.764 148.956 226.113 \ 148.506 226.563 148.956 226.563 148.506 228.924 \ 148.956 229.824 148.956 231.285 148.506 232.185 \ 148.956 232.634 148.956 233.646 149.405 234.995 \ 148.956 234.995 149.405 235.445 149.405 236.907 \ 149.405 237.357 149.968 238.818 150.867 240.167 \ 150.867 240.617 151.317 242.079 152.216 243.428 \ 153.228 245.339 154.128 245.789 155.027 246.239 \ 156.939 245.789 157.388 246.239 156.489 246.689 \ 155.027 247.7 154.128 247.7 153.228 247.7 152.216 \ 247.7 151.767 247.7 150.867 247.251 150.417 246.239 \ 149.405 246.239 148.056 245.339 147.607 244.44 \ 147.157 243.428 145.695 241.629 145.695 240.617 \ 145.245 240.167 145.245 239.718 144.796 238.256 \ 144.346 236.907 144.346 235.445 143.784 234.546 \ 143.784 233.197 143.784 232.185 143.784 230.835 \ 143.334 229.824 143.784 229.374 143.334 229.374 \ 143.334 228.474 142.884 230.386 141.985 231.735 \ 140.973 233.197 140.523 234.096 140.523 234.546 \ 140.523 234.995 139.624 236.457 139.174 237.806 \ 138.162 239.718 137.263 241.067 136.813 242.079 \ 135.913 242.978 134.452 244.89 134.002 245.789 \ 133.552 245.789 132.091 246.689 131.191 247.251 \ 129.73 248.15 129.28 248.15 128.38 247.7 128.38 \ 248.15 126.919 247.7 126.019 247.251 125.12 246.239 \ 125.12 245.339 124.67 244.89 124.67 244.44 124.67 \ 243.428 124.67 242.529 124.67 241.067 124.67 239.718 \ 125.12 239.268 124.67 239.268 124.67 238.256 125.12 \ 237.806 125.12 237.357 125.12 236.907 125.12 236.007 \ 125.12 234.096 125.57 233.197 125.57 232.185 126.019 \ 232.185 126.019 231.285 126.019 230.386 126.019 \ 229.374 126.469 228.474 126.469 227.013 126.469 \ 225.214 126.019 225.214 126.469 225.214 126.019 \ 223.302 126.019 221.953 126.019 220.492 125.57 \ 220.042 125.12 219.592 124.108 219.142 123.209 \ 219.142 121.859 220.042 121.297 220.042 120.398 \ 220.941 119.498 221.391 119.048 221.391 118.486 \ 221.953 118.037 221.953 118.037 221.391 118.486 \ 220.941 119.498 220.042 120.847 219.142 122.759 \ 217.681 124.108 216.781 125.12 215.769 126.469 \ 214.87 126.919 214.87 127.481 214.87 128.38 214.87 \ 128.83 214.87 129.73 214.87 129.73 215.769 130.292 \ 215.769 130.742 216.781 130.742 217.681 130.292 \ 219.142 130.292 221.953 130.292 223.302 130.292 \ 224.202 129.73 225.214 129.28 227.013 128.83 227.575 \ 129.28 227.575 129.28 228.474 128.83 229.374 129.28 \ 229.824 129.28 230.386 128.83 231.735 128.38 234.096 \ 128.38 234.995 127.931 236.457 127.931 239.268 \ 127.931 240.167 127.931 241.629 128.83 242.978 \ 129.28 243.878 129.73 244.44 130.742 244.44 131.191 \ 244.44 132.091 244.44 133.103 243.878 134.002 \ 242.978 134.902 242.079 135.351 241.067 135.913 \ 240.167 136.363 239.268 136.813 238.818 137.263 \ 237.806 137.712 236.907 138.162 235.445 138.724 \ 234.546 139.174 233.646 139.624 232.634 140.523 \ 230.835 140.973 228.924 141.535 227.013 142.435 \ 225.664 142.884 223.302 143.334 221.391 143.334 \ 220.941 143.334 219.142 144.346 217.681 144.796 \ 216.781 145.695 216.332 146.595 216.332 147.607 \ 215.769 -fill $pengcolor -outline {} -width 1 -tags logo $c create polygon 165.371 241.067 165.371 \ 241.067 164.921 243.878 164.921 246.239 163.46 \ 246.689 161.211 247.251 160.649 247.251 160.199 \ 244.44 160.199 243.878 160.199 243.428 160.199 \ 242.079 160.199 240.167 160.199 239.718 159.749 \ 239.268 160.199 237.806 159.749 237.357 159.749 \ 236.007 159.749 230.835 159.749 229.824 159.749 \ 228.924 159.749 226.113 159.749 225.664 159.749 \ 223.752 159.749 222.853 159.749 218.58 159.749 \ 218.13 159.749 217.681 160.199 217.231 161.661 \ 216.781 162.11 216.781 162.56 216.781 163.46 216.781 \ 164.022 219.142 163.46 222.403 163.46 222.853 163.46 \ 224.202 163.46 225.664 163.46 226.563 163.46 227.013 \ 163.46 228.924 163.01 230.835 163.01 232.634 163.46 \ 233.197 164.022 232.634 164.472 232.634 164.921 \ 232.185 164.921 231.735 165.371 231.735 165.821 \ 232.185 165.371 233.646 165.821 236.007 165.371 \ 238.256 165.371 238.818 165.371 240.617 165.371 \ 241.067 -fill $pengcolor -outline {} -width 1 -tags logo $c create polygon 165.821 214.42 166.833 215.32 \ 166.271 215.32 165.821 216.332 165.371 216.332 \ 165.371 216.781 165.821 217.681 165.821 218.13 \ 165.371 219.142 165.371 220.042 164.921 222.853 \ 165.371 224.764 164.921 225.664 165.371 227.575 \ 165.371 228.474 164.921 228.474 164.472 227.575 \ 164.472 226.113 164.022 224.764 164.472 224.202 \ 164.472 223.752 164.472 222.403 164.921 214.87 \ 164.472 213.521 164.472 212.959 164.472 212.509 \ 164.022 212.509 163.46 212.509 163.01 212.959 162.56 \ 212.959 161.661 212.959 161.211 212.059 161.211 \ 211.609 160.649 211.609 160.199 209.698 160.649 \ 208.349 163.46 206.437 164.472 206.437 165.821 \ 207.899 165.821 208.349 166.833 210.148 166.833 \ 210.71 165.821 211.609 165.371 212.059 165.371 \ 212.959 165.821 213.97 165.821 214.42 -fill $pengcolor \ -outline {} -width 1 -tags logo $c create polygon 201.462 248.6 201.462 249.05 \ 201.012 249.05 200.563 249.05 200.001 248.6 199.551 \ 248.6 198.651 247.7 197.752 247.251 196.74 246.689 \ 196.29 245.789 194.379 244.89 194.379 244.44 194.379 \ 242.529 193.929 242.079 193.479 240.617 193.479 \ 240.167 193.929 239.718 193.479 239.268 193.03 \ 236.457 192.58 234.096 192.58 233.197 192.58 231.735 \ 192.58 223.302 192.58 221.391 192.13 220.941 191.568 \ 221.953 189.769 226.113 189.319 226.563 189.319 \ 227.013 188.757 228.025 188.307 228.474 188.757 \ 228.474 185.497 234.096 185.047 234.995 184.597 \ 236.457 184.147 236.457 184.147 236.907 184.147 \ 237.357 183.136 239.268 182.686 239.268 182.686 \ 239.718 182.236 240.167 181.786 241.067 181.337 \ 242.529 180.887 242.529 180.887 243.878 179.425 \ 245.789 178.975 246.689 178.076 246.689 178.076 \ 247.251 177.064 247.7 175.715 247.7 175.265 247.7 \ 174.703 247.7 174.253 247.251 174.253 246.689 \ 174.253 245.789 173.804 242.079 174.253 242.079 \ 173.804 241.629 173.804 241.067 173.804 238.818 \ 173.804 237.806 173.804 236.457 173.354 234.546 \ 173.354 233.197 173.804 232.634 173.804 232.185 \ 173.804 231.735 173.804 228.924 173.354 227.575 \ 173.804 227.575 173.804 225.664 173.804 225.214 \ 173.804 224.764 173.804 223.302 173.804 217.231 \ 174.253 216.332 174.703 215.769 178.526 214.87 \ 179.425 215.32 179.425 216.332 179.425 217.681 \ 179.425 218.58 178.975 219.142 178.526 220.492 \ 178.526 220.941 178.076 221.391 178.076 221.953 \ 178.076 225.664 177.514 226.563 177.514 228.025 \ 177.064 228.474 177.064 228.924 177.064 230.835 \ 177.514 236.457 177.064 237.806 177.514 237.806 \ 177.514 238.818 177.514 240.617 177.514 241.067 \ 178.076 241.629 178.526 241.629 179.425 241.067 \ 179.875 240.617 179.875 240.167 180.325 239.268 \ 181.337 238.256 182.236 236.457 183.698 234.546 \ 184.147 233.197 185.497 230.835 186.509 229.824 \ 187.408 227.575 187.408 227.013 187.408 226.563 \ 187.858 225.664 188.307 225.214 188.757 224.764 \ 188.757 224.202 189.319 222.403 190.219 220.941 \ 191.118 217.681 192.13 215.769 194.379 214.87 \ 194.941 214.87 196.74 214.42 196.74 215.769 196.29 \ 215.769 196.29 216.332 196.29 216.781 196.74 219.592 \ 196.74 220.492 196.29 221.391 196.74 224.764 196.29 \ 225.664 196.29 226.113 196.29 227.575 196.74 229.374 \ 197.19 235.445 198.202 239.268 198.202 239.718 \ 198.202 241.067 198.202 242.529 198.651 242.978 \ 199.101 243.878 199.101 244.44 199.551 244.89 \ 200.001 246.239 201.462 248.6 -fill $pengcolor -outline \ {} -width 1 -tags logo $c create polygon 71.714 185.412 71.714 110.869 \ 81.496 110.869 82.845 110.981 83.969 111.431 85.094 \ 112.106 86.105 113.118 86.893 114.467 87.567 116.041 \ 88.017 117.39 88.242 118.065 88.467 118.852 88.579 \ 119.639 88.804 120.538 88.916 121.438 89.029 122.337 \ 89.141 123.349 89.254 124.361 89.366 125.485 89.366 \ 126.61 89.478 127.734 89.478 128.971 89.478 130.208 \ 89.478 131.444 89.478 132.456 89.478 133.468 89.478 \ 134.48 89.366 135.492 89.254 136.391 89.254 137.291 \ 89.141 138.19 89.029 139.09 88.916 139.877 88.804 \ 140.664 88.691 141.451 88.579 142.238 88.354 143.362 \ 88.129 144.374 87.904 145.386 87.567 146.398 87.342 \ 147.297 87.005 148.197 86.668 148.984 86.218 149.771 \ 87.005 151.233 87.342 152.02 87.68 152.919 87.904 \ 153.931 88.129 154.943 88.129 155.505 88.354 156.854 \ 88.354 157.641 88.354 158.428 88.467 159.328 88.467 \ 160.34 88.467 161.352 88.467 162.476 88.579 163.6 \ 88.579 164.837 88.579 166.186 88.579 166.973 88.691 \ 167.873 88.804 168.885 88.916 169.897 89.029 171.021 \ 89.029 172.258 89.029 173.719 89.029 175.068 89.029 \ 176.305 89.029 177.542 89.141 178.554 89.141 179.566 \ 89.141 180.353 89.141 181.14 89.254 181.814 89.366 \ 182.714 89.478 183.051 89.478 185.412 83.857 185.412 \ 83.857 184.738 83.744 183.951 83.744 183.276 83.744 \ 182.489 83.744 180.803 83.857 179.791 83.857 178.891 \ 83.857 177.879 83.857 176.867 83.857 175.743 83.857 \ 174.619 83.857 173.27 83.857 172.033 83.744 170.908 \ 83.744 170.009 83.632 169.109 83.632 168.322 83.52 \ 166.973 83.407 166.524 83.407 166.186 83.407 165.062 \ 83.407 164.05 83.295 163.151 83.295 162.251 83.295 \ 161.464 83.182 160.789 82.957 159.553 81.945 158.203 \ 80.596 157.754 76.886 157.754 76.886 185.412 71.714 \ 185.412 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 92.289 148.309 92.289 147.185 \ 92.289 146.061 92.289 145.049 92.402 143.924 92.402 \ 142.8 92.402 141.788 92.402 140.664 92.514 139.652 \ 92.514 138.64 92.627 137.628 92.627 136.616 92.739 \ 135.717 92.739 134.705 92.851 133.805 92.964 132.793 \ 92.964 131.894 93.076 130.995 93.301 129.196 93.414 \ 128.409 93.526 127.509 93.639 126.722 93.751 125.935 \ 93.863 125.148 93.976 124.361 94.313 122.787 94.426 \ 122.112 94.65 121.325 94.763 120.651 95.1 119.301 \ 95.55 117.615 96.112 116.041 96.674 114.692 97.236 \ 113.455 97.799 112.443 98.361 111.544 99.035 110.757 \ 99.71 110.082 100.385 109.632 101.059 109.295 \ 101.846 109.07 102.633 108.958 104.207 109.295 \ 104.882 109.632 105.556 110.082 106.231 110.757 \ 106.906 111.544 107.468 112.443 108.03 113.455 \ 108.592 114.692 109.154 116.041 109.604 117.615 \ 110.054 119.301 110.279 119.976 110.616 121.325 \ 110.841 122.112 110.953 122.787 111.178 123.574 \ 111.403 125.148 111.628 125.935 111.74 126.722 \ 111.853 127.622 111.965 128.409 112.078 129.308 \ 112.19 130.208 112.302 130.995 112.415 132.006 \ 112.64 133.805 112.752 134.817 112.865 135.717 \ 112.977 136.729 112.977 137.741 113.089 138.752 \ 113.089 139.764 113.202 140.776 113.202 141.788 \ 113.314 142.912 113.314 143.924 113.314 145.049 \ 113.427 146.061 113.427 147.185 113.427 148.309 \ 113.427 149.546 113.314 150.783 113.314 151.907 \ 113.314 153.032 113.314 154.156 113.202 155.28 \ 113.202 156.405 113.089 157.529 113.089 158.541 \ 112.977 159.553 112.865 160.565 112.752 161.576 \ 112.64 162.588 112.527 163.6 112.415 164.5 112.302 \ 165.512 112.19 166.411 112.078 167.311 111.965 \ 168.21 111.853 169.109 111.628 169.897 111.515 \ 170.796 111.403 171.583 111.178 172.37 111.066 \ 173.157 110.616 174.731 110.504 175.518 110.279 \ 176.193 110.054 176.98 109.604 178.666 109.154 \ 180.128 108.592 181.59 108.03 182.826 107.468 \ 183.951 106.906 184.963 106.231 185.75 105.556 \ 186.424 104.882 186.986 104.207 187.436 103.42 \ 187.661 102.633 187.661 101.846 187.661 101.059 \ 187.436 100.385 186.986 99.71 186.424 99.035 185.75 \ 98.361 184.963 97.799 183.951 97.236 182.826 96.674 \ 181.59 96.112 180.128 95.55 178.666 95.1 176.98 \ 94.988 176.193 94.763 175.518 94.538 174.731 94.426 \ 173.944 94.088 172.37 93.976 171.583 93.863 170.796 \ 93.639 169.897 93.526 169.109 93.414 168.21 93.301 \ 167.311 93.189 166.411 93.076 165.512 92.964 164.5 \ 92.964 163.6 92.851 162.588 92.739 161.576 92.627 \ 160.565 92.627 159.553 92.514 158.541 92.514 157.529 \ 92.514 156.405 92.402 155.28 92.402 154.156 92.402 \ 153.032 92.289 151.907 92.289 150.783 92.289 149.546 \ 92.289 148.309 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 121.859 110.869 127.481 \ 110.869 134.902 185.412 129.28 185.412 127.931 \ 171.808 120.847 171.808 119.948 185.412 114.326 \ 185.412 121.859 110.869 -fill #000000 -outline {} \ -width 1 -tags logo $c create polygon 137.263 185.412 137.263 \ 110.869 147.157 110.869 148.394 110.981 149.518 \ 111.431 150.417 112.106 151.317 113.118 152.104 \ 114.467 152.778 116.041 153.228 117.39 153.341 \ 118.065 153.566 118.852 153.903 120.538 154.015 \ 121.438 154.128 122.337 154.24 123.349 154.353 \ 124.361 154.465 125.485 154.465 126.61 154.577 \ 127.734 154.577 128.971 154.577 130.208 154.577 \ 131.444 154.577 132.456 154.577 133.468 154.577 \ 134.48 154.577 135.492 154.577 136.391 154.577 \ 137.291 154.577 138.19 154.465 139.09 154.465 \ 139.877 154.353 140.664 154.24 141.451 154.128 \ 142.238 153.903 143.362 153.678 144.374 153.341 \ 145.386 153.003 146.398 152.554 147.297 152.216 \ 148.197 151.767 148.984 151.317 149.771 152.104 \ 151.233 152.441 152.02 152.778 152.919 153.003 \ 153.931 153.228 154.943 153.341 155.505 153.453 \ 156.854 153.566 157.641 153.678 158.428 153.79 \ 159.328 153.903 160.34 154.015 161.352 154.015 \ 162.476 154.128 163.6 154.128 164.837 154.128 \ 166.186 154.128 166.973 154.128 167.873 154.128 \ 168.885 154.128 169.897 154.128 171.021 154.128 \ 172.258 154.128 173.719 154.24 175.068 154.24 \ 176.305 154.353 177.542 154.353 178.554 154.465 \ 179.566 154.577 180.353 154.69 181.14 154.69 181.814 \ 154.915 182.714 155.027 183.051 155.027 185.412 \ 149.405 185.412 149.405 184.738 149.293 183.951 \ 149.293 183.276 149.181 182.489 149.181 180.803 \ 149.068 179.791 149.068 178.891 149.068 177.879 \ 149.068 176.867 148.956 175.743 148.956 174.619 \ 148.956 173.27 148.956 172.033 148.956 170.908 \ 148.956 170.009 148.956 169.109 148.956 168.322 \ 148.956 166.973 148.956 166.524 148.956 166.186 \ 148.956 165.062 148.843 164.05 148.731 163.151 \ 148.618 162.251 148.506 161.464 148.394 160.789 \ 148.056 159.553 147.269 158.203 146.145 157.754 \ 142.435 157.754 142.435 185.412 137.263 185.412 \ -fill #000000 -outline {} -width 1 -tags logo $c create polygon 158.4 185.412 158.4 110.869 \ 164.022 110.869 164.022 185.412 158.4 185.412 -fill \ #000000 -outline {} -width 1 -tags logo $c create polygon 168.182 185.412 168.182 \ 110.869 173.804 110.869 177.514 135.267 177.739 \ 136.054 177.851 136.954 177.964 137.853 178.076 \ 138.752 178.301 139.539 178.413 140.439 178.526 \ 141.338 178.751 143.137 178.975 144.037 179.088 \ 144.824 179.2 145.723 179.313 146.623 179.425 147.41 \ 179.538 148.422 179.763 149.321 179.875 150.333 \ 180.1 151.233 180.212 152.132 180.437 153.032 180.55 \ 154.043 180.774 154.943 180.887 155.842 180.999 \ 156.742 181.224 157.754 181.337 158.653 181.337 \ 157.641 181.224 156.629 181.224 155.617 181.224 \ 154.606 181.224 153.594 181.112 152.582 181.112 \ 151.682 181.112 150.67 180.999 149.771 180.999 \ 148.759 180.999 147.86 180.887 146.96 180.887 \ 145.948 180.887 145.049 180.887 144.149 180.887 \ 143.25 180.887 142.125 180.887 141.114 180.887 \ 140.102 180.887 139.09 180.887 138.078 180.887 \ 137.178 180.887 136.166 180.887 135.267 180.887 \ 134.368 180.887 133.468 180.887 132.569 180.887 \ 131.669 180.887 130.882 180.887 130.095 180.887 \ 110.869 185.946 110.869 185.946 185.412 180.325 \ 185.412 176.165 160.565 176.052 159.778 175.94 \ 158.99 175.827 158.203 175.602 156.517 175.49 \ 155.617 175.378 154.718 175.265 153.931 175.153 \ 153.032 175.04 152.02 174.928 151.12 174.703 150.221 \ 174.591 149.321 174.478 148.422 174.366 147.41 \ 174.141 146.51 174.028 145.611 173.804 144.599 \ 173.691 143.587 173.579 142.575 173.354 141.676 \ 173.241 140.551 173.017 139.539 172.904 138.528 \ 172.904 139.539 172.904 140.551 173.017 141.563 \ 173.017 142.575 173.017 143.587 173.129 144.599 \ 173.129 145.498 173.129 146.51 173.241 147.41 \ 173.241 148.422 173.241 149.321 173.354 150.221 \ 173.354 151.233 173.354 152.132 173.354 153.144 \ 173.354 154.156 173.354 155.055 173.354 156.067 \ 173.354 156.967 173.354 157.866 173.354 158.766 \ 173.354 159.553 173.354 160.452 173.354 161.239 \ 173.354 162.026 173.354 162.926 173.354 185.412 \ 168.182 185.412 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 206.184 185.412 205.622 \ 175.968 205.397 177.092 205.172 178.217 204.948 \ 179.228 204.61 180.128 204.385 181.027 204.048 \ 181.814 203.823 182.489 203.486 183.164 203.149 \ 183.838 202.811 184.4 202.024 185.75 201.125 186.762 \ 200.113 187.436 199.101 187.661 198.089 187.549 \ 197.19 186.986 196.29 186.087 195.391 184.85 194.941 \ 184.176 194.491 183.389 194.042 182.489 193.592 \ 181.477 193.255 180.465 192.805 179.341 192.467 \ 178.217 192.13 176.98 191.905 176.193 191.68 175.406 \ 191.568 174.619 191.456 173.832 191.231 172.932 \ 191.118 172.145 191.006 171.246 190.781 169.559 \ 190.669 168.66 190.556 167.648 190.444 166.748 \ 190.331 165.736 190.219 164.725 190.106 163.825 \ 189.994 162.926 189.994 162.026 189.882 161.127 \ 189.769 160.227 189.769 159.215 189.657 158.316 \ 189.544 157.304 189.544 156.405 189.432 155.393 \ 189.432 154.381 189.319 153.369 189.319 152.357 \ 189.319 151.345 189.319 150.333 189.319 149.321 \ 189.319 148.197 189.319 146.96 189.319 145.948 \ 189.319 144.824 189.319 143.7 189.319 142.688 \ 189.432 141.563 189.432 140.551 189.544 139.539 \ 189.544 138.528 189.544 137.516 189.657 136.504 \ 189.769 135.492 189.769 134.592 189.882 133.581 \ 189.994 132.681 189.994 131.782 190.106 130.882 \ 190.219 129.983 190.331 129.083 190.556 127.397 \ 190.669 126.61 190.781 125.823 191.006 124.923 \ 191.118 124.136 191.231 123.462 191.568 121.887 \ 191.793 121.213 191.905 120.426 192.13 119.751 \ 192.58 117.952 193.142 116.378 193.704 114.917 \ 194.266 113.567 194.941 112.443 195.616 111.431 \ 196.29 110.532 196.965 109.857 197.752 109.295 \ 198.426 108.845 199.214 108.62 200.001 108.508 \ 201.799 108.958 202.699 109.407 203.374 110.194 \ 204.161 111.094 204.835 112.218 205.51 113.567 \ 206.184 115.141 206.634 116.491 206.859 117.165 \ 206.971 117.952 207.421 119.526 207.534 120.426 \ 207.758 121.325 207.871 122.225 207.983 123.124 \ 208.096 124.136 208.208 125.036 208.321 126.047 \ 208.433 127.172 208.545 128.184 208.658 129.308 \ 208.77 130.32 208.77 131.557 208.883 132.681 208.995 \ 133.805 204.273 133.805 204.161 132.681 203.936 \ 131.557 203.711 130.432 203.486 129.533 203.261 \ 128.633 202.924 127.734 202.699 126.947 202.362 \ 126.385 201.35 124.586 200.001 124.024 199.438 \ 124.136 198.989 124.361 198.426 124.923 197.977 \ 125.598 197.527 126.497 197.077 127.622 196.628 \ 128.971 196.29 130.545 196.178 131.219 195.953 \ 132.681 195.84 133.356 195.728 134.143 195.616 \ 134.93 195.503 135.829 195.278 137.516 195.278 \ 138.303 195.166 139.315 195.166 140.214 195.053 \ 141.114 195.053 142.125 194.941 143.137 194.941 \ 144.149 194.941 145.161 194.941 146.173 194.941 \ 147.297 194.941 148.309 194.941 149.546 194.941 \ 150.67 194.941 151.907 194.941 152.919 195.053 \ 154.043 195.053 155.168 195.166 156.18 195.166 \ 157.192 195.278 158.091 195.391 159.103 195.391 \ 160.002 195.503 160.902 195.616 161.801 195.728 \ 162.588 195.84 163.375 196.065 164.162 196.178 \ 164.949 196.29 165.736 196.628 167.198 197.077 \ 168.547 197.527 169.672 197.977 170.571 198.426 \ 171.246 198.989 171.808 199.438 172.145 200.001 \ 172.258 200.9 171.92 201.575 171.246 202.249 170.009 \ 202.811 168.547 203.149 167.76 203.374 166.973 \ 203.598 166.186 203.823 165.399 204.048 164.5 \ 204.273 163.488 204.385 162.476 204.498 161.464 \ 204.61 160.34 204.723 159.103 200.001 159.103 \ 200.001 145.049 209.445 145.049 209.445 185.412 \ 206.184 185.412 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 148.506 261.305 148.506 \ 263.554 143.784 263.554 143.784 261.305 143.671 \ 260.068 143.334 259.394 142.772 259.056 141.985 \ 258.944 141.085 259.056 140.523 259.394 140.074 \ 261.755 140.074 263.104 140.523 264.678 141.085 \ 265.465 141.985 266.364 146.145 270.637 147.607 \ 271.874 148.506 272.998 148.843 274.01 148.956 \ 275.359 148.956 277.158 148.843 278.507 148.506 \ 279.632 147.944 280.643 147.157 281.43 146.482 \ 281.88 145.695 282.218 144.796 282.442 143.784 \ 282.667 142.659 282.78 141.535 282.78 140.298 282.78 \ 139.286 282.78 138.387 282.667 137.6 282.442 136.925 \ 282.218 136.363 281.88 135.576 281.093 135.014 \ 280.194 134.564 278.957 134.452 277.608 134.452 \ 275.359 139.624 275.359 139.624 277.608 139.736 \ 279.069 140.074 279.969 141.535 280.419 142.659 \ 280.081 143.334 279.519 143.671 278.62 143.784 \ 277.158 143.784 275.809 143.671 275.022 143.334 \ 274.235 142.772 273.448 141.985 272.548 137.263 \ 267.376 136.251 266.364 135.351 265.465 135.014 \ 264.565 134.902 263.554 134.902 261.755 135.014 \ 260.518 135.464 259.506 136.026 258.719 136.813 \ 257.932 137.488 257.595 138.275 257.145 139.174 \ 256.92 140.186 256.695 141.31 256.583 142.435 \ 256.583 143.447 256.583 144.458 256.583 145.245 \ 256.695 145.92 256.92 147.157 257.482 147.719 \ 258.157 148.169 258.944 148.394 260.068 148.506 \ 261.305 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 165.821 270.187 165.821 \ 276.708 165.821 277.833 165.708 278.957 165.483 \ 279.856 165.259 280.643 164.921 281.318 164.472 \ 281.88 163.909 282.218 163.235 282.555 162.448 \ 282.667 161.548 282.78 160.536 282.78 159.3 282.78 \ 158.175 282.78 157.051 282.78 156.151 282.667 \ 155.364 282.555 154.69 282.218 154.128 281.88 \ 153.678 281.318 153.341 280.643 153.116 279.856 \ 152.891 278.845 152.778 277.833 152.778 276.708 \ 152.778 270.187 152.778 269.063 152.891 268.051 \ 153.116 267.264 153.341 266.589 154.128 265.465 \ 155.364 264.678 156.151 264.453 157.051 264.228 \ 158.063 264.116 159.3 264.116 160.424 264.116 \ 161.548 264.228 162.448 264.453 163.235 264.678 \ 163.909 265.015 164.472 265.465 164.921 265.915 \ 165.483 267.264 165.708 268.051 165.821 269.063 \ 165.821 270.187 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 177.514 256.583 177.514 \ 258.494 177.064 258.494 176.165 258.606 175.715 \ 258.944 175.378 259.281 175.265 259.843 175.265 \ 264.565 177.514 264.565 177.514 266.927 175.265 \ 266.927 175.265 282.78 170.543 282.78 170.543 \ 266.927 168.632 266.927 168.632 264.565 170.543 \ 264.565 170.543 261.305 170.655 259.843 170.993 \ 258.606 171.442 257.707 171.892 257.032 173.579 \ 256.358 174.703 256.133 176.165 256.133 176.727 \ 256.133 177.064 256.133 177.514 256.583 -fill \ #000000 -outline {} -width 1 -tags logo $c create polygon 185.946 259.843 185.946 \ 264.565 188.757 264.565 188.757 266.927 185.946 \ 266.927 185.946 278.62 186.171 279.407 186.509 \ 279.969 187.071 280.306 187.858 280.419 188.307 \ 280.419 188.757 280.419 188.757 282.78 188.645 \ 282.78 188.307 282.78 187.183 282.78 186.509 282.78 \ 185.159 282.78 183.923 282.555 182.911 282.33 \ 182.236 281.88 181.786 281.206 181.561 280.419 \ 181.337 279.407 181.337 278.17 181.337 266.927 \ 179.425 266.927 179.425 264.565 181.337 264.565 \ 181.337 261.305 185.946 259.843 -fill #000000 \ -outline {} -width 1 -tags logo $c create polygon 190.219 264.565 194.379 \ 264.565 196.29 279.519 196.74 279.519 199.101 \ 264.565 204.723 264.565 207.084 279.519 207.534 \ 279.519 209.895 264.565 213.605 264.565 209.895 \ 282.78 204.723 282.78 201.912 267.376 201.462 \ 267.376 199.101 282.78 193.479 282.78 190.219 \ 264.565 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 229.121 269.175 229.121 282.78 \ 224.848 282.78 224.848 280.981 224.061 281.768 \ 223.049 282.33 221.925 282.667 220.688 282.78 \ 219.564 282.78 218.44 282.555 217.54 282.33 216.866 \ 281.88 216.528 281.318 216.191 280.531 216.079 \ 279.632 215.966 278.62 215.966 275.359 216.079 \ 274.347 216.978 272.998 217.877 272.548 218.44 \ 272.211 219.114 271.986 219.789 271.761 220.688 \ 271.536 221.588 271.424 222.6 271.311 223.724 \ 271.199 224.848 271.087 224.848 269.175 224.736 \ 267.826 224.399 266.927 223.612 266.477 222.487 \ 266.364 221.7 266.477 221.138 266.927 220.688 \ 268.726 220.688 269.175 216.416 269.175 216.528 \ 267.938 216.753 266.702 217.203 265.69 217.877 \ 265.015 218.44 264.678 219.114 264.453 219.901 \ 264.228 220.801 264.116 221.925 264.116 223.049 \ 264.116 224.061 264.116 225.073 264.116 225.86 \ 264.228 226.535 264.453 227.659 265.015 228.334 \ 265.69 228.783 266.702 229.008 267.938 229.121 \ 269.175 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 243.175 264.565 243.175 \ 266.927 242.725 266.927 241.601 266.927 240.701 \ 267.151 239.914 267.489 239.352 267.826 239.015 \ 268.276 238.678 268.95 238.565 269.737 238.453 \ 270.637 238.453 282.78 233.731 282.78 233.731 \ 264.565 238.453 264.565 238.453 265.915 239.352 \ 265.128 240.364 264.565 242.163 264.116 242.725 \ 264.565 243.175 264.565 -fill #000000 -outline {} \ -width 1 -tags logo $c create polygon 258.129 270.187 258.129 \ 274.347 249.696 274.347 249.696 278.17 249.809 \ 279.294 250.146 279.969 250.708 280.643 251.607 \ 280.981 252.732 280.643 253.406 279.969 253.744 \ 279.294 253.969 278.17 253.969 276.708 258.129 \ 276.708 258.129 277.608 258.129 278.957 257.904 \ 280.081 257.454 281.093 256.779 281.88 256.217 \ 282.218 254.643 282.667 253.744 282.78 252.732 \ 282.78 251.607 282.78 250.371 282.78 249.359 282.78 \ 248.459 282.667 247.672 282.442 246.436 281.88 \ 245.986 281.318 245.649 280.643 245.424 279.856 \ 245.199 278.957 245.086 277.833 244.974 276.708 \ 244.974 270.187 245.086 269.063 245.199 268.051 \ 245.311 267.264 245.649 266.589 245.986 265.915 \ 246.436 265.465 246.998 265.015 247.672 264.678 \ 248.459 264.453 249.359 264.228 250.371 264.116 \ 251.607 264.116 252.732 264.116 253.744 264.228 \ 254.756 264.453 255.543 264.678 256.217 265.015 \ 256.779 265.465 257.229 265.915 257.566 266.589 \ 257.791 267.264 258.016 268.051 258.129 269.063 \ 258.129 270.187 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 272.183 256.583 277.355 \ 256.583 277.355 282.78 272.183 282.78 272.183 \ 256.583 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 295.569 268.726 295.569 282.78 \ 290.959 282.78 290.959 269.175 290.847 268.051 \ 290.509 267.376 289.947 266.702 289.048 266.364 \ 287.923 266.702 287.136 267.376 287.024 268.051 \ 287.136 269.175 287.136 282.78 282.527 282.78 \ 282.527 264.565 286.687 264.565 287.136 265.915 \ 288.036 265.128 289.048 264.565 290.172 264.228 \ 291.409 264.116 292.533 264.116 293.433 264.341 \ 294.107 264.565 294.669 265.015 295.344 266.477 \ 295.569 267.489 295.569 268.726 -fill #000000 \ -outline {} -width 1 -tags logo $c create polygon 312.434 269.737 312.434 \ 270.637 308.274 270.637 308.274 269.175 308.161 \ 267.826 307.824 266.927 307.262 266.477 306.363 \ 266.364 305.576 266.477 305.013 266.927 304.676 \ 267.826 304.564 269.175 304.564 278.17 304.676 \ 279.294 305.013 279.969 306.363 280.981 307.262 \ 280.643 307.824 279.969 307.937 279.294 307.824 \ 278.17 307.824 276.259 312.434 276.259 312.434 \ 277.608 312.434 278.957 312.209 280.081 311.759 \ 281.093 311.085 281.88 310.523 282.218 309.173 \ 282.667 308.386 282.78 307.374 282.78 306.363 282.78 \ 305.238 282.78 304.226 282.78 303.327 282.667 \ 302.427 282.442 301.753 282.218 301.191 281.88 \ 300.853 281.318 300.516 280.643 300.179 279.856 \ 299.954 278.957 299.841 277.833 299.841 276.708 \ 299.841 270.187 299.841 269.063 299.954 268.051 \ 300.179 267.264 300.404 266.589 301.191 265.465 \ 302.427 264.678 303.327 264.453 304.226 264.228 \ 305.238 264.116 306.363 264.116 307.374 264.116 \ 308.386 264.228 309.173 264.453 309.96 264.678 \ 310.523 265.015 311.085 265.465 311.759 266.252 \ 312.209 267.264 312.434 268.388 312.434 269.737 \ -fill #000000 -outline {} -width 1 -tags logo $c create polygon 316.706 279.069 320.866 \ 279.069 320.866 282.78 316.706 282.78 316.706 \ 279.069 -fill #000000 -outline {} -width 1 -tags logo $c create polygon 48.215 186.312 48.215 185.412 \ 47.766 184.4 47.766 183.501 47.316 183.501 47.316 \ 182.601 46.416 181.59 46.416 181.14 45.967 180.24 \ 45.405 179.791 44.955 179.228 44.055 178.329 43.606 \ 177.879 43.156 177.43 42.144 176.98 41.694 176.418 \ 41.245 175.968 38.883 175.068 36.972 174.169 36.522 \ 174.169 35.173 173.607 34.723 174.169 31.913 173.607 \ 31.913 174.169 29.551 173.607 29.551 174.169 28.54 \ 174.169 28.09 174.619 27.19 174.169 27.19 174.619 \ 26.741 174.619 25.729 175.068 23.93 175.518 22.918 \ 175.068 22.468 175.518 20.669 176.418 19.657 176.418 \ 15.048 178.779 14.036 179.228 12.686 180.24 12.237 \ 180.69 11.225 181.59 10.775 182.039 10.325 182.601 \ 10.775 182.601 10.325 184.4 10.775 184.85 11.225 \ 186.312 14.036 188.223 14.485 188.673 16.846 190.022 \ 17.296 190.472 17.296 191.034 15.947 191.933 15.048 \ 192.383 14.485 192.833 14.036 193.283 13.136 193.845 \ 12.237 194.295 12.686 195.644 12.686 196.094 12.237 \ 197.555 12.237 198.005 11.675 198.904 12.237 200.816 \ 12.237 202.277 12.237 204.526 11.675 205.988 12.237 \ 205.988 12.237 206.437 12.237 207.337 12.686 208.349 \ 12.686 209.248 13.136 209.698 12.686 211.16 13.136 \ 212.509 13.136 213.521 13.586 215.32 13.586 216.781 \ 13.586 217.681 14.036 220.492 14.485 222.403 15.048 \ 222.853 15.947 222.853 15.947 222.403 16.397 221.953 \ 16.846 216.781 17.296 215.32 17.858 211.609 18.308 \ 210.71 18.308 210.148 18.308 209.248 17.858 208.798 \ 17.858 207.899 18.308 206.437 18.308 205.538 18.308 \ 205.088 18.308 203.627 16.846 203.627 15.947 203.177 \ 15.947 202.727 15.947 202.277 16.397 201.715 16.846 \ 201.715 17.858 201.715 18.308 201.715 18.758 201.265 \ 18.308 200.816 17.858 199.916 18.308 198.455 17.858 \ 198.455 17.858 193.283 19.208 192.383 20.107 191.933 \ 21.569 191.484 22.018 191.484 22.918 192.383 22.918 \ 192.833 23.48 192.833 23.93 198.005 23.48 199.467 \ 23.93 202.277 25.279 202.277 29.551 202.727 30.001 \ 202.277 30.901 202.277 31.913 202.277 35.623 201.265 \ 36.522 201.265 36.972 200.816 37.984 200.816 38.883 \ 200.816 39.333 200.366 40.345 199.916 40.795 199.916 \ 42.594 198.455 44.055 198.005 44.055 197.555 44.505 \ 197.105 46.416 195.644 46.416 194.744 46.866 194.295 \ 47.316 193.845 47.766 193.283 47.316 192.833 48.215 \ 190.472 48.215 190.022 48.215 189.572 48.215 188.673 \ 48.215 187.211 48.215 186.762 48.215 186.312 -fill \ $bg -outline {} -width 1 -tags logo $c create polygon 76.886 142.688 81.046 142.688 \ 82.508 142.35 83.407 140.889 83.632 140.327 83.969 \ 138.865 84.082 137.965 84.194 137.066 84.307 136.054 \ 84.307 134.93 84.307 133.805 84.307 132.456 84.194 \ 131.332 84.082 130.208 83.857 129.308 83.632 128.409 \ 83.407 127.734 82.395 126.272 81.046 125.823 76.886 \ 125.823 76.886 142.688 -fill $bg -outline {} -width \ 1 -tags logo $c create polygon 97.461 148.309 97.461 149.546 \ 97.461 150.783 97.461 152.02 97.574 153.144 97.574 \ 154.268 97.686 155.28 97.686 156.405 97.799 157.416 \ 97.799 158.316 97.911 159.328 98.023 160.227 98.136 \ 161.127 98.361 162.701 98.473 163.488 98.586 164.275 \ 98.698 164.949 98.81 165.736 99.373 167.535 99.822 \ 169.109 100.497 170.234 101.059 171.133 101.846 \ 171.583 102.633 171.808 104.095 171.133 104.769 \ 170.234 105.332 169.109 105.894 167.535 106.343 \ 165.736 106.456 164.949 106.681 164.275 106.793 \ 163.488 106.906 162.701 107.018 161.914 107.243 \ 160.227 107.355 159.328 107.355 158.316 107.468 \ 157.416 107.58 156.405 107.58 155.28 107.693 154.268 \ 107.693 153.144 107.693 152.02 107.693 150.783 \ 107.805 149.546 107.805 148.309 107.805 147.073 \ 107.693 145.836 107.693 144.711 107.693 143.587 \ 107.693 142.463 107.58 141.338 107.58 140.327 \ 107.468 139.315 107.355 138.303 107.355 137.403 \ 107.243 136.504 107.131 135.604 106.906 133.918 \ 106.793 133.131 106.681 132.456 106.456 131.669 \ 106.343 130.995 105.894 129.196 105.332 127.622 \ 104.769 126.497 104.095 125.598 103.42 125.148 \ 102.633 124.923 101.846 125.148 101.059 125.598 \ 100.497 126.497 99.822 127.622 99.373 129.196 98.81 \ 130.995 98.698 131.669 98.586 132.456 98.473 133.131 \ 98.361 133.918 98.248 134.817 98.023 136.504 97.911 \ 137.403 97.799 138.303 97.799 139.315 97.686 140.327 \ 97.686 141.338 97.574 142.463 97.574 143.587 97.461 \ 144.711 97.461 145.836 97.461 147.073 97.461 148.309 \ -fill $bg -outline {} -width 1 -tags logo $c create polygon 122.309 156.292 126.919 \ 156.292 124.67 130.545 122.309 156.292 -fill $bg \ -outline {} -width 1 -tags logo $c create polygon 142.435 142.688 146.145 \ 142.688 147.607 142.35 148.506 140.889 148.731 \ 140.327 149.068 138.865 149.181 137.965 149.293 \ 137.066 149.405 136.054 149.405 134.93 149.405 \ 133.805 149.405 132.456 149.405 131.332 149.405 \ 130.208 149.293 129.308 149.181 128.409 148.956 \ 127.734 148.056 126.272 146.595 125.823 142.435 \ 125.823 142.435 142.688 -fill $bg -outline {} -width \ 1 -tags logo $c create polygon 111.515 228.924 111.515 \ 227.575 111.066 225.664 108.705 221.391 108.255 \ 220.042 108.255 219.142 108.255 218.58 108.255 \ 218.13 107.805 217.681 106.793 218.58 104.994 \ 220.941 104.432 221.953 102.633 224.202 102.183 \ 224.764 101.621 225.214 99.822 228.474 97.461 \ 233.197 97.461 234.096 97.461 234.995 97.911 235.445 \ 98.361 236.007 99.822 236.457 102.633 236.457 \ 104.432 235.445 105.894 234.995 106.343 234.546 \ 106.793 234.546 107.805 233.646 110.616 230.835 \ 111.515 229.824 111.515 229.374 111.515 228.924 \ -fill $bg -outline {} -width 1 -tags logo $c create polygon 161.211 269.175 160.986 \ 267.826 160.649 266.927 160.199 266.477 159.3 \ 266.364 158.4 266.477 157.838 266.927 157.613 \ 267.826 157.388 269.175 157.388 278.17 157.613 \ 279.294 157.838 279.969 159.3 280.981 160.199 \ 280.643 160.649 279.969 160.986 279.294 161.211 \ 278.17 161.211 269.175 -fill $bg -outline {} -width \ 1 -tags logo $c create polygon 224.848 273.448 223.836 \ 273.448 222.825 273.56 222.15 273.673 221.588 \ 273.897 220.913 274.684 220.688 275.809 220.688 \ 278.17 220.801 279.294 221.138 279.969 221.7 280.643 \ 222.487 280.981 223.612 280.643 224.399 279.969 \ 224.736 279.294 224.848 278.17 224.848 273.448 -fill \ $bg -outline {} -width 1 -tags logo $c create polygon 253.969 269.175 253.744 \ 267.826 253.406 266.927 252.732 266.477 251.607 \ 266.364 250.708 266.477 250.146 266.927 249.696 \ 269.175 249.696 272.548 253.969 272.548 253.969 \ 269.175 -fill $bg -outline {} -width 1 -tags logo } #*********************************************************************** # %PROCEDURE: LoadConnectionInfo # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Loads the connection information into the global ConnectionInfo variable #*********************************************************************** proc LoadConnectionInfo {} { global ConnectionInfoFile ConnectionInfo PasswordFile set ConnectionInfo {} if {![file exists $ConnectionInfoFile]} { return } set problem [catch { set fp [open $ConnectionInfoFile "r"] while {1} { if {[gets $fp line] < 0} { break } set line [string trim $line] if {[string match "#*" $line]} { continue } if {"$line" == ""} { continue } set ConnectionInfo $line break } close $fp } err] if {$problem} { tk_dialog .err Error "[m {Error loading configuration file:}] $err" error 0 OK } # Try loading and merging passwords if the password file is readable set passwords {} if {![file readable $PasswordFile]} { return } set fp [open $PasswordFile "r"] while {1} { if {[gets $fp line] < 0} { break } set line [string trim $line] if {[string match "#*" $line]} { continue } if {"$line" == ""} { continue } set passwords $line break } close $fp # Merge passwords foreach thing $passwords { set name [value $thing ConnectionName] set password [value $thing Password] set conn [GetConnection $name] if {"$conn" != ""} { lappend conn Password $password ReplaceConnection $conn } } } #*********************************************************************** # %PROCEDURE: GetConnection # %ARGUMENTS: # name -- name of connection # %RETURNS: # key/value pair listing connection configuration, or "" if not found. #*********************************************************************** proc GetConnection { name } { global ConnectionInfo foreach thing $ConnectionInfo { if {[value $thing ConnectionName] == "$name"} { return $thing } } return "" } #*********************************************************************** # %PROCEDURE: DeleteConnection # %ARGUMENTS: # name -- name of connection # %RETURNS: # Nothing, but deletes connection named "$name" #*********************************************************************** proc DeleteConnection { name } { global ConnectionInfo ConfigDir set newInfo {} set found 0 foreach thing $ConnectionInfo { if {[value $thing ConnectionName] == "$name"} { set found 1 } else { lappend newInfo $thing } } if {!$found} { return } set ConnectionInfo $newInfo SaveConnectionInfo # Delete the config file set fname [file join $ConfigDir conf.$name] catch { file delete $fname } BuildConnectionMenu if {[GetCurrentConnection] == $name} { if {[llength $ConnectionInfo] == 0} { SwitchConnection "" } else { set name [value [lindex $ConnectionInfo 0] ConnectionName] SwitchConnection $name } } } #*********************************************************************** # %PROCEDURE: ReplaceConnection # %ARGUMENTS: # conn -- new name/value pairs # %RETURNS: # Nothing, but replaces connection in ConnectionInfo. If no such # connection exists, appends new connection. #*********************************************************************** proc ReplaceConnection { conn } { global ConnectionInfo set name [value $conn ConnectionName] set newInfo {} set found 0 foreach thing $ConnectionInfo { if {[value $thing ConnectionName] == "$name"} { lappend newInfo $conn set found 1 } else { lappend newInfo $thing } } if {!$found} { lappend newInfo $conn } set ConnectionInfo $newInfo } proc DeletePPPoEConnection {} { set conn [GetCurrentConnection] if {"$conn" == ""} { return } set ans [tk_dialog .confirm "[m {Confirm Deletion - RP-PPPoE}]" "[m {Are you sure you wish to delete the connection}] `$conn'?" warning 0 No Yes] if {$ans} { DeleteConnection $conn } } #*********************************************************************** # %PROCEDURE: CreateMainDialog # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Creates the main window #*********************************************************************** proc CreateMainDialog {} { global ConnectionInfoFile global ConnectionInfo global Admin wm title . "RP-PPPoE" wm iconname . "PPPoE" frame .f1 label .l1 -text "Connection: " menubutton .m1 -text "" -indicatoron 1 -menu .m1.menu -relief raised menu .m1.menu -tearoff 0 pack .l1 .m1 -in .f1 -side left -expand 0 -fill x canvas .c -width 40 -height 20 pack .c -in .f1 -side left -expand 0 -fill none # Draw the LED's .c create rectangle 10 1 30 8 -outline "#808080" -fill "#A0A0A0" -tags xmitrect .c create rectangle 10 10 30 18 -outline "#808080" -fill "#A0A0A0" -tags recvrect frame .buttons button .start -text "[m {Start}]" -command "StartPPPoEConnection" button .stop -text "[m {Stop}]" -command "StopPPPoEConnection" button .exit -text "[m {Exit}]" -command "exit" canvas .graph -width 1 -height 1 if {[file writable $ConnectionInfoFile]} { set Admin 1 pack .f1 -side top -expand 1 -fill both pack .buttons -side top -expand 0 -fill x button .delete -text "[m {Delete}]" -command "DeletePPPoEConnection" button .new -text "[m {New Connection...}]" -command "NewPPPoEConnection" button .props -text "[m {Properties...}]" -command "EditConnectionProps" pack .graph -in .f1 -side left -expand 1 -fill both pack .start .stop .delete .props .new .exit -in .buttons -side left -expand 0 -fill none } else { set Admin 0 pack .f1 -side top -expand 0 -fill x pack .buttons -side top -expand 1 -fill both pack .start .stop .exit -in .buttons -side left -expand 0 -fill none pack .graph -in .buttons -side left -expand 1 -fill both } LoadConnectionInfo BuildConnectionMenu # If no connections exist, pop up new connection dialog if {[llength $ConnectionInfo] == 0} { SwitchConnection "" if {$Admin} { update idletasks NewPPPoEConnection } else { tk_dialog .note [m {Note}] "[m {Note: There are no connections defined. You must run this program as root to define connections}]" warning 0 OK } } else { set con [lindex $ConnectionInfo 0] set name [value $con ConnectionName] SwitchConnection $name } } #*********************************************************************** # %PROCEDURE: GetCurrentConnection # %ARGUMENTS: # None # %RETURNS: # The name of the current connection in the GUI. #*********************************************************************** proc GetCurrentConnection {} { .m1 cget -text } #*********************************************************************** # %PROCEDURE: value # %ARGUMENTS: # lst -- a list of key/value pairs # key -- key we're looking for # %RETURNS: # value corresponding to $key, or "" if not found. #*********************************************************************** proc value { lst key } { set idx [lsearch -exact $lst $key] if {$idx >= 0} { return [lindex $lst [expr $idx+1]] } return "" } #*********************************************************************** # %PROCEDURE: SwitchConnection # %ARGUMENTS: # name -- new connection name # %DESCRIPTION: # Makes $name the active connection #*********************************************************************** proc SwitchConnection { name } { .m1 configure -text $name SetButtonStates UpdateConnectionState 0 } #*********************************************************************** # %PROCEDURE: EditConnectionProps # %ARGUMENTS: # None # %DESCRIPTION: # Pops up edit window for current connection #*********************************************************************** proc EditConnectionProps {} { global ConnectionInfo set conn [GetCurrentConnection] NewPPPoEConnection $conn } #*********************************************************************** # %PROCEDURE: FillConnectionGui # %ARGUMENTS: # w -- connection property GUI # name -- name of connection # %DESCRIPTION: # Fills GUI with values corresponding to $name. #*********************************************************************** proc FillConnectionGui { w name } { global ConnectionInfo set found [GetConnection $name] if {"$found" != ""} { ListToSetupGui $w $found } } #*********************************************************************** # %PROCEDURE: BuildConnectionMenu # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Builds the connection menu #*********************************************************************** proc BuildConnectionMenu {} { global ConnectionInfo .m1.menu delete 0 end foreach connection $ConnectionInfo { set name [value $connection ConnectionName] .m1.menu add command -label $name -command [list SwitchConnection $name] } .m1.menu add separator .m1.menu add command -label "User's Manual" -command Help } #*********************************************************************** # %PROCEDURE: SetButtonStates # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Enables or disables buttons, as appropriate #*********************************************************************** proc SetButtonStates {} { global Admin set conn [GetCurrentConnection] if {"$conn" == ""} { .start configure -state disabled .stop configure -state disabled catch { .delete configure -state disabled .props configure -state disabled .new configure -state normal } } else { foreach {startstop updown interface} [GetConnectionStatus $conn] {break} if {"$startstop" == "started"} { .start configure -state disabled .stop configure -state normal } else { .start configure -state normal .stop configure -state disabled } catch { .delete configure -state normal .props configure -state normal .new configure -state normal } if {!$Admin} { set ok [value [GetConnection $conn] NonrootOK] if {!$ok} { .start configure -state disabled .stop configure -state disabled } } } } #*********************************************************************** # %PROCEDURE: GetEthernetInterfaces # %ARGUMENTS: # None # %RETURNS: # A list of Ethernet interfaces #*********************************************************************** proc GetEthernetInterfaces {} { set ifs {} set fp [open "|@IP@ -o link show" "r"] while {[gets $fp line] >= 0} { if {[regexp {eth[0-9]+} $line eth]} { lappend ifs $eth } } return $ifs } #*********************************************************************** # %PROCEDURE: StartPPPoEConnection # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Starts currently-selected PPPoE connection. #*********************************************************************** proc StartPPPoEConnection {} { global Wrapper global StartState global UpdateToken set conn [GetCurrentConnection] if {"$conn" == ""} { return } if {"$UpdateToken" != ""} { after cancel $UpdateToken set UpdateToken "" } catch { unset StartState } set StartState(chars) "" set StartState(status) "" set StartState(msg) "" set StartState(flip) 0 set fp [open "|$Wrapper start $conn" "r"] # Set fileevent fileevent $fp readable [list StartFPReadable $fp] LockGui $fp vwait StartState(status) UnlockGui if {$StartState(status) == "failed"} { tk_dialog .err Error "[m {Error starting connection:}] $StartState(msg)" error 0 OK } SetButtonStates UpdateConnectionState 0 } proc LockGui { fp } { .start configure -state disabled .stop configure -state normal -command [list AbortConnection $fp] .exit configure -state disabled .m1 configure -state disabled grab set .stop } proc UnlockGui {} { .start configure -state normal .stop configure -state disabled -command StopPPPoEConnection .exit configure -state normal .m1 configure -state normal grab release .stop } proc AbortConnection { fp } { global StartState catch { StopPPPoEConnection } catch { close $fp } set StartState(msg) "[m {Connection aborted by user}]" set StartState(status) "[m {failed}]" } #*********************************************************************** # %PROCEDURE: StartFPReadable # %ARGUMENTS: # fp -- file handle # %RETURNS: # Nothing # %DESCRIPTION: # Called when the "pppoe-start" file handle is readable. #*********************************************************************** proc StartFPReadable { fp } { global StartState set char [read $fp 1] if {$char == ""} { set uhoh [catch {close $fp} err] if {$uhoh} { set StartState(status) "[m {failed}]" set StartState(msg) $err } else { set StartState(status) "[m {succeeded}]" } return } append StartState(chars) $char if {$StartState(flip)} { ConnectionStateDown } else { ConnectionStateOff } set StartState(flip) [expr 1 - $StartState(flip)] } #*********************************************************************** # %PROCEDURE: StopPPPoEConnection # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Stops currently-selected PPPoE connection. #*********************************************************************** proc StopPPPoEConnection {} { global Wrapper set conn [GetCurrentConnection] if {"$conn" == ""} { return } set fp [open "|$Wrapper stop $conn" "r"] while {1} { set char [read $fp 1] if {"$char" == ""} { break; } } set uhoh [catch {close $fp} err] if {$uhoh} { # Ignore a common error if {![string match "*appears to have died*" $err]} { tk_dialog .err Error "[m {Error stopping connection:}] $err" error 0 OK } } SetButtonStates UpdateConnectionState 0 } #*********************************************************************** # %PROCEDURE: NewPPPoEConnection # %ARGUMENTS: # name -- if supplied, we're editing the existing connection "name" # %RETURNS: # Nothing # %DESCRIPTION: # Creates a new PPPoE connection #*********************************************************************** proc NewPPPoEConnection {{name ""}} { set w .newcon if {[winfo exists $w]} { wm deiconify $w raise $w return } toplevel $w if {"$name" == ""} { wm title $w "[m {New Connection}] - RP-PPPoE" wm iconname $w "[m {New Connection}]" } else { wm title $w "[m {Edit Connection}] - RP-PPPoE" wm iconname $w "[m {Edit Connection}]" } wm withdraw $w tabnotebook_create $w.tn set basic [tabnotebook_page $w.tn "[m {Basic}]"] set interface [tabnotebook_page $w.tn "[m {NIC and DNS}]"] set opts [tabnotebook_page $w.tn "[m {Options}]"] set advanced [tabnotebook_page $w.tn "[m {Advanced}]"] # ----------- BASIC PAGE ------------- label $w.lconName -text "[m {Connection Name:}] " -anchor e if {"$name" != ""} { label $w.conName -text $name -anchor w } else { entry $w.conName -width 15 RegisterHelpWindow $w.lconName "[m {Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign.}]" $w.help RegisterHelpWindow $w.conName "[m {Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign.}]" $w.help } label $w.luser -text "[m {User Name:}] " -anchor e entry $w.user -width 15 RegisterHelpWindow $w.luser "[m {Enter your user name. Do not add a domain-name after the user name.}]" $w.help RegisterHelpWindow $w.user "[m {Enter your user name. Do not add a domain-name after the user name.}]" $w.help label $w.lnet -text "[m {Network:}] " -anchor e entry $w.network -width 15 RegisterHelpWindow $w.lnet "[m {Some ISP's require you to enter their domain-name here (e.g. "sympatico.ca").}]" $w.help RegisterHelpWindow $w.network "[m {Some ISP's require you to enter their domain-name here (e.g. "sympatico.ca").}]" $w.help label $w.lpass -text "[m {Password:}] " -anchor e entry $w.pass -width 15 -show "*" RegisterHelpWindow $w.lpass "[m {Enter your password.}]" $w.help RegisterHelpWindow $w.pass "[m {Enter your password.}]" $w.help grid $w.lconName $w.conName -in $basic -sticky nsew grid $w.luser $w.user -in $basic -sticky nsew grid $w.lnet $w.network -in $basic -sticky nsew grid $w.lpass $w.pass -in $basic -sticky nsew grid columnconfigure $basic 1 -weight 1 # ----------- INTERFACES PAGE ------------- set ifs {} catch {set ifs [GetEthernetInterfaces]} label $w.lifname -text "[m {Ethernet Interface:}] " -anchor e entry $w.ifname -width 8 RegisterHelpWindow $w.lifname "[m {Enter Ethernet interface to which DSL modem is attached.}]" $w.help RegisterHelpWindow $w.ifname "[m {Enter Ethernet interface to which DSL modem is attached.}]" $w.help if {[llength $ifs] > 0} { menubutton $w.ifmb -relief raised -text "..." -menu $w.ifmb.menu RegisterHelpWindow $w.ifmb "[m {Browse detected Ethernet interface names.}]" $w.help menu $w.ifmb.menu -tearoff 0 foreach if $ifs { $w.ifmb.menu add command -label $if -command "$w.ifname delete 0 end; $w.ifname insert end [list $if]" } grid $w.lifname $w.ifname $w.ifmb -in $interface -sticky nsew } else { grid $w.lifname $w.ifname - -in $interface -sticky nsew } label $w.ldns -text "[m {DNS Setup:}] " -anchor e menubutton $w.dns -text "[m {From Server}]" -menu $w.dns.menu -relief raised -indicatoron 1 menu $w.dns.menu -tearoff 0 foreach thing [list "[m {From Server}]" "[m {Specify}]" "[m {Do not Adjust}]"] { $w.dns.menu add command -label $thing -command [list SetDNSOption $w $thing] } RegisterHelpWindow $w.ldns [m "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone."] $w.help RegisterHelpWindow $w.dns [m "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone."] $w.help label $w.ldns1 -text "[m {Primary DNS:}] " -anchor e entry $w.dns1 -width 16 RegisterHelpWindow $w.ldns1 "[m {Enter the IP address of the primary DNS server.}]" $w.help RegisterHelpWindow $w.dns1 "[m {Enter the IP address of the primary DNS server.}]" $w.help label $w.ldns2 -text "[m {Secondary DNS:}] " -anchor e entry $w.dns2 -width 16 RegisterHelpWindow $w.ldns2 "[m {Enter the IP address of the secondary DNS server.}]" $w.help RegisterHelpWindow $w.dns2 "[m {Enter the IP address of the secondary DNS server.}]" $w.help SetDNSOption $w "[m {From Server}]" grid $w.ldns $w.dns - -in $interface -sticky nsew grid $w.ldns1 $w.dns1 - -in $interface -sticky nsew grid $w.ldns2 $w.dns2 - -in $interface -sticky nsew # If only one Ethernet interface, select it by default if {[llength $ifs] == 1} { $w.ifname insert end [lindex $ifs 0] } grid columnconfigure $interface 1 -weight 1 # ----------- OPTS PAGE ------------- checkbutton $w.nonroot -text "[m {Allow use by non-root users}]" -variable OPTS(nonroot) -anchor w RegisterHelpWindow $w.nonroot "[m {If enabled, ordinary users can start and stop this connection.}]" $w.help checkbutton $w.sync -text "[m {Use synchronous PPP}]" -variable OPTS(sync) -anchor w RegisterHelpWindow $w.sync "[m {Use synchronous PPP (recommended -- easier on the CPU.)}]" $w.help label $w.lfw -text "[m {Firewalling:}] " -anchor e if {[llength $ifs] == 1} { set defaultFW "[m {Stand-Alone}]" } else { set defaultFW "[m {Masquerading}]" } menubutton $w.fw -text $defaultFW -menu $w.fw.menu -indicatoron 1 -relief raised menu $w.fw.menu -tearoff 0 foreach type [list [m "Stand-Alone"] [m "Masquerading"] [m "None"]] { $w.fw.menu add command -label $type -command [list $w.fw configure -text $type] } RegisterHelpWindow $w.lfw [m "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers."] $w.help RegisterHelpWindow $w.fw [m "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers."] $w.help grid $w.nonroot - -in $opts -sticky nsew grid $w.sync - -in $opts -sticky nsew grid $w.lfw $w.fw -in $opts -sticky nsw grid columnconfigure $opts 1 -weight 1 # ----------- ADVANCED PAGE ------------- label $w.lsn -text "[m {Service-Name:}] " -anchor e entry $w.servicename -width 24 label $w.lac -text "[m {AC-Name:}] " -anchor e entry $w.acname -width 24 RegisterHelpWindow $w.lac [m "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank."] $w.help RegisterHelpWindow $w.acname [m "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank."] $w.help grid $w.lsn $w.servicename -in $advanced -sticky nsew grid $w.lac $w.acname -in $advanced -sticky nsew RegisterHelpWindow $w.lsn [m "Enter service name if required. Most ISPs do not require this; try leaving it blank."] $w.help RegisterHelpWindow $w.servicename [m "Enter service name if required. Most ISPs do not require this; try leaving it blank."] $w.help grid columnconfigure $advanced 1 -weight 1 # ----------- BUTTONS ------------- frame $w.buttons button $w.ok -text [m "OK"] -command [list NewPPPoEConnectionOK $name $w] button $w.cancel -text [m "Cancel"] -command [list destroy $w] pack $w.ok $w.cancel -in $w.buttons -expand 0 -fill none -side left pack $w.tn -side top -expand 1 -fill both text $w.help -width 60 -wrap word -state disabled -height 6 pack $w.help -side top -expand 0 -fill both pack $w.buttons -side top -expand 0 -fill x # If we're editing existing connection, fill GUI with current values if {"$name" != ""} { FillConnectionGui $w $name } wm deiconify $w update idletasks raise $w } #*********************************************************************** # %PROCEDURE: SetDNSOption # %ARGUMENTS: # w -- connection-editing window # opt -- value of DNS option # %RETURNS: # Nothing # %DESCRIPTION: # Adjusts GUI for specified option #*********************************************************************** proc SetDNSOption { w opt } { $w.dns configure -text $opt if {"$opt" == "[m Specify]"} { $w.dns1 configure -state normal -background white $w.dns2 configure -state normal -background white } else { $w.dns1 configure -state disabled -background "#d9d9d9" $w.dns2 configure -state disabled -background "#d9d9d9" } } # ---------------------------------------------------------------------- # Tabbed notebook code from "Effective Tcl/Tk Programming" # ---------------------------------------------------------------------- # EXAMPLE: tabnotebook that can dial up pages # ---------------------------------------------------------------------- # Effective Tcl/Tk Programming # Mark Harrison, DSC Communications Corp. # Michael McLennan, Bell Labs Innovations for Lucent Technologies # Addison-Wesley Professional Computing Series # ====================================================================== # Copyright (c) 1996-1997 Lucent Technologies Inc. and Mark Harrison # ====================================================================== option add *Tabnotebook.tabs.background #666666 widgetDefault option add *Tabnotebook.margin 6 widgetDefault option add *Tabnotebook.tabColor #a6a6a6 widgetDefault option add *Tabnotebook.activeTabColor #d9d9d9 widgetDefault option add *Tabnotebook.tabFont \ -*-helvetica-bold-r-normal--*-120-* widgetDefault proc tabnotebook_create {win} { global tnInfo frame $win -class Tabnotebook canvas $win.tabs -highlightthickness 0 pack $win.tabs -fill x notebook_create $win.notebook pack $win.notebook -expand yes -fill both set tnInfo($win-tabs) "" set tnInfo($win-current) "" set tnInfo($win-pending) "" return $win } proc tabnotebook_page {win name} { global tnInfo set page [notebook_page $win.notebook $name] lappend tnInfo($win-tabs) $name if {$tnInfo($win-pending) == ""} { set id [after idle [list tabnotebook_refresh $win]] set tnInfo($win-pending) $id } return $page } proc tabnotebook_refresh {win} { global tnInfo $win.tabs delete all set margin [option get $win margin Margin] set color [option get $win tabColor Color] set font [option get $win tabFont Font] set x 2 set maxh 0 foreach name $tnInfo($win-tabs) { set id [$win.tabs create text \ [expr $x+$margin+2] [expr -0.5*$margin] \ -anchor sw -text $name -font $font \ -tags [list $name]] set bbox [$win.tabs bbox $id] set wd [expr [lindex $bbox 2]-[lindex $bbox 0]] set ht [expr [lindex $bbox 3]-[lindex $bbox 1]] if {$ht > $maxh} { set maxh $ht } $win.tabs create polygon 0 0 $x 0 \ [expr $x+$margin] [expr -$ht-$margin] \ [expr $x+$margin+$wd] [expr -$ht-$margin] \ [expr $x+$wd+2*$margin] 0 \ 2000 0 2000 10 0 10 \ -outline black -fill $color \ -tags [list $name tab tab-$name] $win.tabs raise $id $win.tabs bind $name \ [list tabnotebook_display $win $name] set x [expr $x+$wd+2*$margin] } set height [expr $maxh+2*$margin] $win.tabs move all 0 $height $win.tabs configure -width $x -height [expr $height+4] if {$tnInfo($win-current) != ""} { tabnotebook_display $win $tnInfo($win-current) } else { tabnotebook_display $win [lindex $tnInfo($win-tabs) 0] } set tnInfo($win-pending) "" } proc tabnotebook_display {win name} { global tnInfo notebook_display $win.notebook $name set normal [option get $win tabColor Color] $win.tabs itemconfigure tab -fill $normal set active [option get $win activeTabColor Color] $win.tabs itemconfigure tab-$name -fill $active $win.tabs raise $name set tnInfo($win-current) $name } # ---------------------------------------------------------------------- # EXAMPLE: simple notebook that can dial up pages # ---------------------------------------------------------------------- # Effective Tcl/Tk Programming # Mark Harrison, DSC Communications Corp. # Michael McLennan, Bell Labs Innovations for Lucent Technologies # Addison-Wesley Professional Computing Series # ====================================================================== # Copyright (c) 1996-1997 Lucent Technologies Inc. and Mark Harrison # ====================================================================== option add *Notebook.borderWidth 2 widgetDefault option add *Notebook.relief sunken widgetDefault proc notebook_create {win} { global nbInfo frame $win -class Notebook pack propagate $win 0 set nbInfo($win-count) 0 set nbInfo($win-pages) "" set nbInfo($win-current) "" return $win } proc notebook_page {win name} { global nbInfo set page "$win.page[incr nbInfo($win-count)]" lappend nbInfo($win-pages) $page set nbInfo($win-page-$name) $page frame $page if {$nbInfo($win-count) == 1} { after idle [list notebook_display $win $name] } return $page } proc notebook_display {win name} { global nbInfo set page "" if {[info exists nbInfo($win-page-$name)]} { set page $nbInfo($win-page-$name) } elseif {[winfo exists $win.page$name]} { set page $win.page$name } if {$page == ""} { error "bad notebook page \"$name\"" } notebook_fix_size $win if {$nbInfo($win-current) != ""} { pack forget $nbInfo($win-current) } pack $page -expand yes -fill both set nbInfo($win-current) $page } proc notebook_fix_size {win} { global nbInfo update idletasks set maxw 0 set maxh 0 foreach page $nbInfo($win-pages) { set w [winfo reqwidth $page] if {$w > $maxw} { set maxw $w } set h [winfo reqheight $page] if {$h > $maxh} { set maxh $h } } set bd [$win cget -borderwidth] set maxw [expr $maxw+2*$bd] set maxh [expr $maxh+2*$bd] $win configure -width $maxw -height $maxh } #*********************************************************************** # %PROCEDURE: SetupGuiToList # %ARGUMENTS: # w -- the PPPoE connection setup window # %RETURNS: # A list of (name value) pairs for the connection. # %DESCRIPTION: # Reads values from the GUI; makes a list. #*********************************************************************** proc SetupGuiToList { w } { global OPTS set ans {} if {[catch {lappend ans ConnectionName [$w.conName get]}]} { lappend ans ConnectionName [$w.conName cget -text] } lappend ans UserName [$w.user get] lappend ans NetworkName [$w.network get] lappend ans Password [$w.pass get] lappend ans Interface [$w.ifname get] lappend ans DNSType [$w.dns cget -text] lappend ans DNS1 [$w.dns1 get] lappend ans DNS2 [$w.dns2 get] lappend ans NonrootOK $OPTS(nonroot) lappend ans Sync $OPTS(sync) lappend ans FirewallType [$w.fw cget -text] lappend ans ServiceName [$w.servicename get] lappend ans ACName [$w.acname get] # Validate set name [value $ans ConnectionName] if {![regexp -nocase {^[-a-z0-9_]+$} $name]} { error [m "Connection name must be non-blank and contain only letters, digits, `_' and `-'"] } # Check DNS set type [value $ans DNSType] if {"$type" == [m "Specify"]} { set dns [value $ans DNS1] if {![regexp {[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+} "$dns"]} { error [m "Primary DNS entry must consist of four dot-separated decimal numbers"] } set dns [value $ans DNS2] if {"$dns" != "" && ![regexp {[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+} "$dns"]} { error [m "Secondary DNS entry must consist of four dot-separated decimal numbers"] } } return $ans } #*********************************************************************** # %PROCEDURE: ListToSetupGui # %ARGUMENTS: # w -- the PPPoE connection setup window # lst -- a list of name/value pairs # %RETURNS: # Nothing # %DESCRIPTION: # Updates GUI to reflect lst #*********************************************************************** proc ListToSetupGui { w lst } { global OPTS foreach {key value} $lst { switch -exact -- $key { ConnectionName { catch { $w.conName delete 0 end $w.conName insert end $value } catch { $w.conName configure -text $value } } UserName { $w.user delete 0 end $w.user insert end $value } NetworkName { $w.network delete 0 end $w.network insert end $value } Password { $w.pass delete 0 end $w.pass insert end $value } Interface { $w.ifname delete 0 end $w.ifname insert end $value } DNSType { SetDNSOption $w $value } DNS1 { set oldstate [$w.dns1 cget -state] $w.dns1 configure -state normal $w.dns1 delete 0 end $w.dns1 insert end $value $w.dns1 configure -state $oldstate } DNS2 { set oldstate [$w.dns2 cget -state] $w.dns2 configure -state normal $w.dns2 delete 0 end $w.dns2 insert end $value $w.dns2 configure -state $oldstate } NonrootOK { set OPTS(nonroot) $value } Sync { set OPTS(sync) $value } FirewallType { $w.fw configure -text $value } ServiceName { $w.servicename delete 0 end $w.servicename insert end $value } ACName { $w.acname delete 0 end $w.acname insert end $value } } } } proc NewPPPoEConnectionOK { name w } { if {[catch {set conn [SetupGuiToList $w]} err]} { tk_dialog .err "Invalid Parameters" "$err" error 0 OK return } if {"$name" == ""} { set name [value $conn ConnectionName] set tmp [GetConnection $name] if {"$tmp" != ""} { tk_dialog .err [m "Connection Exists"] [m "The connection already exists. Pick another name."] error 0 OK return } } ReplaceConnection $conn SaveConnectionInfo BuildConnectionMenu SwitchConnection $name destroy $w } proc SaveConnectionInfo {} { global ConnectionInfo ConnectionInfoFile PasswordFile set fp [open "$ConnectionInfoFile.new" "w"] puts $fp "# RP-PPPoE GUI Configuration Information." puts $fp "# This file may *look* human-editable, but it is NOT." puts $fp "# So, you with the text editor: Keep away from this file." puts $fp "#" set expunged {} set passwords {} foreach thing $ConnectionInfo { set name [value $thing ConnectionName] set password [value $thing Password] set pwindex [lsearch -exact $thing Password] set safe [lreplace $thing $pwindex [expr $pwindex+1]] set pwd [list ConnectionName $name Password $password] lappend expunged $safe lappend passwords $pwd } puts $fp $expunged close $fp set fp [open "$PasswordFile.new" "w"] exec chmod 600 "$PasswordFile.new" puts $fp "# RP-PPPoE GUI Configuration Information." puts $fp "# This file may *look* human-editable, but it is NOT." puts $fp "# So, you with the text editor: Keep away from this file." puts $fp "#" puts $fp $passwords close $fp file rename -force "$ConnectionInfoFile.new" "$ConnectionInfoFile" file rename -force "$PasswordFile.new" "$PasswordFile" # Generate config files for pppoe-start for each connection foreach thing $ConnectionInfo { GenerateConfigFile $thing } # Now update /etc/ppp/pap-secrets and /etc/ppp/chap-secrets foreach thing $ConnectionInfo { GenerateSecretsEntry $thing } } #*********************************************************************** # %PROCEDURE: ReadShellEscapedWord # %ARGUMENTS: # str -- a string # %RETURNS: # A two-element list -- the first element is a shell-escaped word # extracted from $str, just the way pppd parses /etc/ppp/pap-secrets. # The second element is the remaining portion of $str #*********************************************************************** proc ReadShellEscapedWord { str } { set ans {} set rest $str # Chew up leading spaces set rest [string trimleft $rest] # If first char is a quote, read until a quote if {"[string index $rest 0]" == "\""} { set rest [string range $rest 1 end] set nextquote [string first "\"" $rest] # If no following quote, pretend we haven't seen a quote, I guess. if {$nextquote >= 0} { set ans [string range $rest 0 [expr $nextquote-1]] set rest [string range $rest [expr $nextquote+1] end] return [list $ans $rest] } } # Not a quote; chew through the string until an unescaped space while {[string length $rest] > 0} { set char [string index $rest 0] set rest [string range $rest 1 end] # Sneaky test for whitespace in Tcl 8.0 if {"[string trim $char]" == ""} { return [list $ans $rest] } if {"$char" == "\\"} { set char [string index $rest 0] set rest [string range $rest 1 end] } append ans $char } return [list $ans $rest] } #*********************************************************************** # %PROCEDURE: GenerateSecretsEntry # %ARGUMENTS: # conn -- a connection key/value list # %RETURNS: # Nothing # %DESCRIPTION: # Adds entries to /etc/ppp/pap-secrets and /etc/ppp/chap-secrets. #*********************************************************************** proc GenerateSecretsEntry { conn } { set user [value $conn UserName] set net [value $conn NetworkName] set password [value $conn Password] if {"$net" != ""} { set user "$user@$net" } GenerateSecretsEntryForFile $user $password "/etc/ppp/pap-secrets" GenerateSecretsEntryForFile $user $password "/etc/ppp/chap-secrets" } #*********************************************************************** # %PROCEDURE: GenerateSecretsEntryForFile # %ARGUMENTS: # user -- user name # password -- password # fname -- file to add entry to. # %RETURNS: # Nothing # %DESCRIPTION: # Adds entries to /etc/ppp/pap-secrets or /etc/ppp/chap-secrets. #*********************************************************************** proc GenerateSecretsEntryForFile { user password fname } { # Copy $fname to $fname.new set out [open "$fname.new" "w"] exec chmod go-rwx "$fname.new" if {[file exists $fname]} { set in [open $fname "r"] while {[gets $in line] >= 0} { set trimmed [string trim $line] if {"$trimmed" == ""} { puts $out $line continue } if {[string match "#*" $trimmed]} { puts $out $line continue } # Read the user name off the line; copy it unless it's our # user name. foreach {word dummy} [ReadShellEscapedWord $line] {break} if {$word != $user} { puts $out $line } } close $in } # Now add our line set user [ShellEscape $user] set password [ShellEscape $password] puts $out "$user\t*\t$password\t*" close $out file rename -force $fname.new $fname } #*********************************************************************** # %PROCEDURE: ShellEscape # %ARGUMENTS: # str # %RETURNS: # A version of $str with shell meta-characters escaped #*********************************************************************** proc ShellEscape { str } { set ans "" foreach char [split $str ""] { if {[string first $char "01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_+=-@./"] >= 0} { append ans $char } else { append ans "\\$char" } } return $ans } #*********************************************************************** # %PROCEDURE: GenerateConfigFile # %ARGUMENTS: # conn -- a connection key/value list # %RETURNS: # Nothing # %DESCRIPTION: # Generates a configuration file for pppoe-start and friends under # /etc/ppp/rp-pppoe-gui #*********************************************************************** proc GenerateConfigFile { conn } { global ConfigDir set name [value $conn ConnectionName] set fname [file join $ConfigDir conf.$name] set fp [open "$fname.new" w] puts $fp "# Configuration file for connection `$name'." puts $fp "# Automatically generated. Do not edit by hand." puts $fp "" foreach {var val} $conn { switch -exact $var { UserName { set net [value $conn NetworkName] if {"$net" != ""} { set user "$val@$net" } else { set user "$val" } puts $fp [ShellEscape "USER=$user"] } Interface { puts $fp [ShellEscape "ETH=$val"] } DNSType { if {"$val" == "[m {From Server}]"} { puts $fp "DNSTYPE=SERVER" puts $fp "PEERDNS=yes" } elseif {"$val" == "[m {Specify}]"} { puts $fp "DNSTYPE=SPECIFY" puts $fp "PEERDNS=no" } else { puts $fp "DNSTYPE=NOCHANGE" puts $fp "PEERDNS=no" } } DNS1 { puts $fp [ShellEscape "DNS1=$val"] } DNS2 { puts $fp [ShellEscape "DNS2=$val"] } NonrootOK { if {$val} { puts $fp "NONROOT=OK" } } ACName { puts $fp [ShellEscape "ACNAME=$val"] } ServiceName { puts $fp [ShellEscape "SERVICENAME=$val"] } FirewallType { if {"$val" == "[m {None}]"} { puts $fp "FIREWALL=NONE" } elseif {"$val" == "[m {Masquerading}]"} { puts $fp "FIREWALL=MASQUERADE" } else { puts $fp "FIREWALL=STANDALONE" } } Sync { if {$val} { puts $fp "SYNCHRONOUS=yes" } else { puts $fp "SYNCHRONOUS=no" } } } } puts $fp "CONNECT_TIMEOUT=30" puts $fp "CONNECT_POLL=1" puts $fp "FORCEPING=\".\"" puts $fp "PIDFILE=/var/run/pppoe-$name.pid" puts $fp "CLAMPMSS=1412" puts $fp "LCP_INTERVAL=20" puts $fp "LCP_FAILURE=3" puts $fp "PPPOE_TIMEOUT=80" puts $fp "LINUX_PLUGIN=" puts $fp "DEMAND=no" puts $fp "DEFAULTROUTE=yes" close $fp file rename -force "$fname.new" "$fname" } #*********************************************************************** # %PROCEDURE: GetConnectionStatus # %ARGUMENTS: # conn -- connection name # %RETURNS: # A three-element list: # {started/stopped up/down if} # If first element is "started", then connection has been started. # If second element is "up", then connection is up. # If connection is up, third element is PPP interface. #*********************************************************************** proc GetConnectionStatus { conn } { set pidfile "/var/run/pppoe-$conn.pid" # Check for PID file if {![file readable $pidfile]} { return {stopped down ""} } set fp [open $pidfile "r"] gets $fp pid close $fp # Check if process is dead if {![file exists "/proc/$pid"]} { # The pppd might still be running... doh... if {![file readable "$pidfile.pppd"]} { return {stopped down ""} } set fp [open "$pidfile.pppd" "r"] gets $fp pid close $fp if {![file exists "/proc/$pid"]} { return {stopped down ""} } } # Now get PID of pppd if {![file readable "$pidfile.pppd"]} { return {started down ""} } set fp [open "$pidfile.pppd" "r"] gets $fp pid close $fp # Find interface to which it corresponds set pppdfiles [glob -nocomplain "/var/run/ppp*.pid"] set found {} foreach file $pppdfiles { set fp [open $file "r"] gets $fp ifpid close $fp if {$ifpid == $pid} { set found [file rootname [file tail $file]] break } } if {"$found" == ""} { return {started down ""} } return [list started up $found] } #*********************************************************************** # %PROCEDURE: UpdateConnectionState # %ARGUMENTS: # fromAfter -- if 1, was called from an "after" callback. # %RETURNS: # Nothing # %DESCRIPTION: # Updates the "LED" displays; periodically reschedules itself to keep # updating display. #*********************************************************************** proc UpdateConnectionState {{fromAfter 1}} { global UpdateToken global Packets global Bytes global UpdateInterval global MeasureTime if {$fromAfter} { set UpdateToken "" } set conn [GetCurrentConnection] if {"$conn" == ""} { ConnectionStateOff ResetGraph if {"$UpdateToken" != ""} { after cancel $UpdateToken set UpdateToken {} } return } foreach {startstop updown interface} [GetConnectionStatus $conn] {break} if {"$startstop" == "stopped"} { ConnectionStateOff ResetGraph } elseif {"$updown" == "down"} { ConnectionStateDown ResetGraph } else { # Get the packet counts set found 0 set fp [open "/proc/net/dev" "r"] while {[gets $fp line] >= 0} { if {![string match "*$interface:*" $line]} { continue } set colon [string first ":" $line] if {$colon < 0} { continue } set line [string range $line [expr $colon+1] end] set found 1 set MeasureTime [clock seconds] break } close $fp if {$found} { foreach {rbytes rpacks rerrs rdrop rfifo rframe rcomp rmulti tbytes tpacks} $line {break} if {!$fromAfter} { set Packets(in) $rpacks set Packets(out) $tpacks set Bytes(in) $rbytes set Bytes(out) $tbytes ConnectionStateUp ResetGraph } else { if {$rpacks != $Packets(in)} { ConnectionReceiveActive } else { ConnectionReceiveUp } if {$tpacks != $Packets(out)} { ConnectionTransmitActive } else { ConnectionTransmitUp } set Packets(in) $rpacks set Packets(out) $tpacks set Bytes(in) $rbytes set Bytes(out) $tbytes UpdateGraph } } else { ConnectionStateUp ResetGraph } } if {"$UpdateToken" == ""} { set UpdateToken [after $UpdateInterval UpdateConnectionState] } if {$fromAfter} { SetButtonStates } } proc ConnectionStateOff {} { .c itemconfigure xmitrect -fill "#A0A0A0" .c itemconfigure recvrect -fill "#A0A0A0" } proc ConnectionStateDown {} { .c itemconfigure xmitrect -fill "#A00000" .c itemconfigure recvrect -fill "#A00000" } proc ConnectionStateUp {} { .c itemconfigure xmitrect -fill "#00D000" .c itemconfigure recvrect -fill "#00D000" } proc ConnectionTransmitActive {} { .c itemconfigure xmitrect -fill "#FFFF00" } proc ConnectionTransmitUp {} { .c itemconfigure xmitrect -fill "#00D000" } proc ConnectionReceiveActive {} { .c itemconfigure recvrect -fill "#FFFF00" } proc ConnectionReceiveUp {} { .c itemconfigure recvrect -fill "#00D000" } proc ResetGraph {} { global GraphPoints set GraphPoints(in) {} set GraphPoints(out) {} set GraphPoints(times) {} .graph delete all UpdateGraph } proc UpdateGraph {} { global GraphPoints Bytes UpdateInterval MeasureTime lappend GraphPoints(times) $MeasureTime lappend GraphPoints(in) $Bytes(in) lappend GraphPoints(out) $Bytes(out) set w [winfo width .graph] set w2 [expr $w/2] set h [winfo height .graph] set toChop [expr [llength $GraphPoints(in)] - $w2 - 1] if {$toChop > 0} { set GraphPoints(in) [lrange $GraphPoints(in) $toChop end] } set toChop [expr [llength $GraphPoints(out)] - $w2 - 1] if {$toChop > 0} { set GraphPoints(out) [lrange $GraphPoints(out) $toChop end] } set toChop [expr [llength $GraphPoints(times)] - $w2 - 1] if {$toChop > 0} { set GraphPoints(times) [lrange $GraphPoints(times) $toChop end] } set prev [lindex $GraphPoints(in) 0] set incoords {} set outcoords {} set inmax 0 set outmax 0 foreach thing [lrange $GraphPoints(in) 1 end] { set diff [expr $thing - $prev] set prev $thing lappend incoords $diff if {$diff > $inmax} { set inmax $diff } } set prev [lindex $GraphPoints(out) 0] foreach thing [lrange $GraphPoints(out) 1 end] { set diff [expr $thing - $prev] set prev $thing lappend outcoords $diff if {$diff > $outmax} { set outmax $diff } } if {$inmax == 0} { set inmax 1 } if {$outmax == 0} { set outmax 1 } # Draw the transmit line set x 0 set hh [expr $h-4] set scaled {} foreach thing $outcoords { lappend scaled $x [expr double($h) - 2 - (double($hh) * double($thing) / double($outmax))] incr x } .graph delete all if {[llength $scaled] >= 4} { eval ".graph create line $scaled -fill #A00000" set bits [expr 8.0 * ([lindex $GraphPoints(out) end] - [lindex $GraphPoints(out) 0])] set timediff [expr [lindex $GraphPoints(times) end] - [lindex $GraphPoints(times) 0]] if {$timediff != 0} { set bps [Pretty [expr double($bits) / $timediff]] .graph create text 2 2 -anchor nw -font fixed -text "$bps" } } # Draw the receive line set x $w2 set scaled {} foreach thing $incoords { lappend scaled $x [expr double($h) - 2 - (double($hh) * double($thing) / double($inmax))] incr x } if {[llength $scaled] >= 4} { eval ".graph create line $scaled -fill #00A000" set bits [expr 8.0 * ([lindex $GraphPoints(in) end] - [lindex $GraphPoints(in) 0])] set timediff [expr [lindex $GraphPoints(times) end] - [lindex $GraphPoints(times) 0]] if {$timediff != 0} { set bps [Pretty [expr double($bits) / $timediff]] .graph create text [expr $w2+2] 2 -anchor nw -font fixed -text "$bps" } } } proc Pretty { n } { if {$n < 0} { return "***" } if {$n < 1000} { return [format "%.1f" $n] } set n [expr $n/1000.0] if {$n < 1000} { return [format "%.1fk" $n] } set n [expr $n/1000.0] if {$n < 1000} { return [format "%.1fM" $n] } set n [expr $n/1000.0] return [format "%.1fG" $n] } #*********************************************************************** # %PROCEDURE: Help # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Opens help page #*********************************************************************** proc Help {} { set file [file join "@datadir_evaluated@" tkpppoe tkpppoe.html] if {![file readable $file]} { tk_dialog .err [m "Error"] [m "Help file is not installed"] error 0 OK return } catch { exec /bin/sh -c "netscape -remote 'openURL($file)' || netscape $file" > /dev/null 2>/dev/null & } } #*********************************************************************** # %PROCEDURE: doLogo # %ARGUMENTS: # None # %RETURNS: # Nothing # %DESCRIPTION: # Does the logo thing #*********************************************************************** proc doLogo {} { global AlreadyRunFile ConfigDir if {[file exists $AlreadyRunFile]} { return } catch { file mkdir $ConfigDir } catch { close [open $AlreadyRunFile "w"] } canvas .c -width 374 -height 286 -bg #FFFFCC pack .c drawLogo .c #FFFFCC # Funky effect .c create text 4 4 -anchor nw -text [m "Welcome to RP-PPPoE"] \ -fill red -font {-family times -size -24 -weight bold} -tags pppoe .c lower pppoe .c move logo -300 0 update idletasks for {set i 0} {$i < 15} {incr i} { .c move logo 20 0 update idletasks after 25 } .c create text 4 28 -anchor nw -text "https://dianne.skoll.ca/projects/rp-pppoe/" \ -fill red -font {-family courier -size -14 -weight bold} update idletasks after 2500 } # If config dir is not readable, die if {![file readable $ConfigDir]} { wm withdraw . tk_dialog .err Error "Error: Cannot read the directory $ConfigDir. You must have permission to read this directory to use tkpppoe" error 0 OK exit 1 } doLogo catch { destroy .c } # Try creating an empty config file if none exists if {![file readable $ConnectionInfoFile]} { catch { file mkdir $ConfigDir } catch { set fp [open $ConnectionInfoFile "w"] close $fp } } CreateMainDialog rp-pppoe-3.15/gui/ja.msg0000644000175000017500000002102314045237007013204 0ustar dfsdfs# LIC: GPL ::msgcat::mcset ja "AC-Name:" "AC-Name:" ::msgcat::mcset ja "Advanced" "¹âÅÙ¤ÊÀßÄê" ::msgcat::mcset ja "Allow use by non-root users" "root°Ê³°¤Î¥æ¡¼¥¶¤Î»ÈÍѤòµö²Ä" ::msgcat::mcset ja "Are you sure you wish to delete the connection" "Are you sure you wish to delete the connection" ::msgcat::mcset ja "Basic" o"´ðËÜÀßÄê" ::msgcat::mcset ja "Browse detected Ethernet interface names." "¸¡½Ð¤µ¤ì¤¿¥¤¡¼¥µ¥Í¥Ã¥È¡¦¥¤¥ó¥¿¥Õ¥§¡¼¥¹¤Î̾Á°¤òɽ¼¨¤·¤Þ¤¹¡£" ::msgcat::mcset ja "Cancel" "¥­¥ã¥ó¥»¥ë" ::msgcat::mcset ja "Confirm Deletion - RP-PPPoE" " RP-PPPoE ºï½ü¤Î³Îǧ ¤ÎÀܳ¤òËÜÅö¤Ëºï½ü¤·¤Þ¤¹¤«¡©" ::msgcat::mcset ja "Connection aborted by user" "Connection aborted by user" ::msgcat::mcset ja "Connection Exists" "Àܳ¤Ï¸ºß¤·¤Þ¤¹¡£¤ÎÀܳ¤Ï´û¤Ë¸ºß¤·¤Þ¤¹¡£Â¾¤Î̾Á°¤òÁª¤ó¤Ç²¼¤µ¤¤¡£" ::msgcat::mcset ja "Connection Name:" "Àܳ̾: " ::msgcat::mcset ja "Connection name must be non-blank and contain only letters, digits, `_' and `-'" "Connection name must be non-blank and contain only letters, digits, `_' and `-'" ::msgcat::mcset ja "Delete" "Delete" ::msgcat::mcset ja "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." ::msgcat::mcset ja "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." ::msgcat::mcset ja "DNS Setup:" "DNS Setup:" ::msgcat::mcset ja "Do not Adjust" "Do not Adjust" ::msgcat::mcset ja "Edit Connection" "Edit Connection" ::msgcat::mcset ja "Edit Connection" "Edit Connection" ::msgcat::mcset ja "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset ja "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset ja "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." ::msgcat::mcset ja "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." ::msgcat::mcset ja "Enter Ethernet interface to which DSL modem is attached." "Enter Ethernet interface to which DSL modem is attached." ::msgcat::mcset ja "Enter Ethernet interface to which DSL modem is attached." "Enter Ethernet interface to which DSL modem is attached." ::msgcat::mcset ja "Enter service name if required. Most ISPs do not require this; try leaving it blank." "Enter service name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset ja "Enter service name if required. Most ISPs do not require this; try leaving it blank." "Enter service name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset ja "Enter the IP address of the primary DNS server." "Enter the IP address of the primary DNS server." ::msgcat::mcset ja "Enter the IP address of the primary DNS server." "Enter the IP address of the primary DNS server." ::msgcat::mcset ja "Enter the IP address of the secondary DNS server." "Enter the IP address of the secondary DNS server." ::msgcat::mcset ja "Enter the IP address of the secondary DNS server." "Enter the IP address of the secondary DNS server." ::msgcat::mcset ja "Enter your password." "Enter your password." ::msgcat::mcset ja "Enter your password." "Enter your password." ::msgcat::mcset ja "Enter your user name. Do not add a domain-name after the user name." "Enter your user name. Do not add a domain-name after the user name." ::msgcat::mcset ja "Enter your user name. Do not add a domain-name after the user name." "Enter your user name. Do not add a domain-name after the user name." ::msgcat::mcset ja "Error" "Error" ::msgcat::mcset ja "Error loading configuration file:" "Error loading configuration file:" ::msgcat::mcset ja "Error starting connection:" "Error starting connection:" ::msgcat::mcset ja "Error stopping connection:" "Error stopping connection:" ::msgcat::mcset ja "Ethernet Interface:" "Ethernet Interface:" ::msgcat::mcset ja "Exit" "Exit" ::msgcat::mcset ja "failed" "failed" ::msgcat::mcset ja "failed" "failed" ::msgcat::mcset ja "Firewalling:" "Firewalling:" ::msgcat::mcset ja "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." ::msgcat::mcset ja "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." ::msgcat::mcset ja "From Server" "From Server" ::msgcat::mcset ja "From Server" "From Server" ::msgcat::mcset ja "From Server" "From Server" ::msgcat::mcset ja "From Server" "From Server" ::msgcat::mcset ja "Help file is not installed" "Help file is not installed" ::msgcat::mcset ja "If enabled, ordinary users can start and stop this connection." "If enabled, ordinary users can start and stop this connection." ::msgcat::mcset ja "Masquerading" "Masquerading" ::msgcat::mcset ja "Masquerading" "Masquerading" ::msgcat::mcset ja "Masquerading" "Masquerading" ::msgcat::mcset ja "Network:" "Network:" ::msgcat::mcset ja "New Connection..." "New Connection..." ::msgcat::mcset ja "New Connection" "New Connection" ::msgcat::mcset ja "New Connection" "New Connection" ::msgcat::mcset ja "NIC and DNS" "NIC and DNS" ::msgcat::mcset ja "None" "None" ::msgcat::mcset ja "None" "None" ::msgcat::mcset ja "Note" "Note" ::msgcat::mcset ja "Note: There are no connections defined. You must run this program as root to define connections" "Note: There are no connections defined. You must run this program as root to define connections" ::msgcat::mcset ja "OK" "OK" ::msgcat::mcset ja "Options" "Options" ::msgcat::mcset ja "Password:" "Password:" ::msgcat::mcset ja "Primary DNS entry must consist of four dot-separated decimal numbers" "Primary DNS entry must consist of four dot-separated decimal numbers" ::msgcat::mcset ja "Primary DNS:" "Primary DNS:" ::msgcat::mcset ja "Properties..." "Properties..." ::msgcat::mcset ja "Secondary DNS entry must consist of four dot-separated decimal numbers" "Secondary DNS entry must consist of four dot-separated decimal numbers" ::msgcat::mcset ja "Secondary DNS:" "Secondary DNS:" ::msgcat::mcset ja "Service-Name:" "Service-Name:" ::msgcat::mcset ja "Some ISP's require you to enter their domain-name here (e.g. " "Some ISP's require you to enter their domain-name here (e.g. " ::msgcat::mcset ja "Some ISP's require you to enter their domain-name here (e.g. " "Some ISP's require you to enter their domain-name here (e.g. " ::msgcat::mcset ja "Specify" "Specify" ::msgcat::mcset ja "Specify" "Specify" ::msgcat::mcset ja "Specify" "Specify" ::msgcat::mcset ja "Stand-Alone" "Stand-Alone" ::msgcat::mcset ja "Stand-Alone" "Stand-Alone" ::msgcat::mcset ja "Start" "Start" ::msgcat::mcset ja "Stop" "Stop" ::msgcat::mcset ja "succeeded" "succeeded" ::msgcat::mcset ja "The connection already exists. Pick another name." "The connection already exists. Pick another name." ::msgcat::mcset ja "User Name:" "User Name:" ::msgcat::mcset ja "Use synchronous PPP (recommended -- easier on the CPU.)" "Use synchronous PPP (recommended -- easier on the CPU.)" ::msgcat::mcset ja "Use synchronous PPP" "Use synchronous PPP" ::msgcat::mcset ja "Welcome to RP-PPPoE" "Welcome to RP-PPPoE" rp-pppoe-3.15/gui/en.msg0000644000175000017500000002067014045237007013223 0ustar dfsdfs# LIC: GPL ::msgcat::mcset en "AC-Name:" "AC-Name:" ::msgcat::mcset en "Advanced" "Advanced" ::msgcat::mcset en "Allow use by non-root users" "Allow use by non-root users" ::msgcat::mcset en "Are you sure you wish to delete the connection" "Are you sure you wish to delete the connection" ::msgcat::mcset en "Basic" "Basic" ::msgcat::mcset en "Browse detected Ethernet interface names." "Browse detected Ethernet interface names." ::msgcat::mcset en "Cancel" "Cancel" ::msgcat::mcset en "Confirm Deletion - RP-PPPoE" "Confirm Deletion - RP-PPPoE" ::msgcat::mcset en "Connection aborted by user" "Connection aborted by user" ::msgcat::mcset en "Connection Exists" "Connection Exists" ::msgcat::mcset en "Connection Name:" "Connection Name:" ::msgcat::mcset en "Connection name must be non-blank and contain only letters, digits, `_' and `-'" "Connection name must be non-blank and contain only letters, digits, `_' and `-'" ::msgcat::mcset en "Delete" "Delete" ::msgcat::mcset en "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." ::msgcat::mcset en "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." "DNS server options:\n'From Server' - Let PPPoE server specify DNS servers\n'Specify' - Enter IP addresses of DNS servers yourself\n'Do not Adjust' - Leave your DNS setup alone." ::msgcat::mcset en "DNS Setup:" "DNS Setup:" ::msgcat::mcset en "Do not Adjust" "Do not Adjust" ::msgcat::mcset en "Edit Connection" "Edit Connection" ::msgcat::mcset en "Edit Connection" "Edit Connection" ::msgcat::mcset en "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset en "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." "Enter access concentrator name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset en "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." ::msgcat::mcset en "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." "Enter a name for this connection. It can contain letters, numbers, undescores and the minus-sign." ::msgcat::mcset en "Enter Ethernet interface to which DSL modem is attached." "Enter Ethernet interface to which DSL modem is attached." ::msgcat::mcset en "Enter Ethernet interface to which DSL modem is attached." "Enter Ethernet interface to which DSL modem is attached." ::msgcat::mcset en "Enter service name if required. Most ISPs do not require this; try leaving it blank." "Enter service name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset en "Enter service name if required. Most ISPs do not require this; try leaving it blank." "Enter service name if required. Most ISPs do not require this; try leaving it blank." ::msgcat::mcset en "Enter the IP address of the primary DNS server." "Enter the IP address of the primary DNS server." ::msgcat::mcset en "Enter the IP address of the primary DNS server." "Enter the IP address of the primary DNS server." ::msgcat::mcset en "Enter the IP address of the secondary DNS server." "Enter the IP address of the secondary DNS server." ::msgcat::mcset en "Enter the IP address of the secondary DNS server." "Enter the IP address of the secondary DNS server." ::msgcat::mcset en "Enter your password." "Enter your password." ::msgcat::mcset en "Enter your password." "Enter your password." ::msgcat::mcset en "Enter your user name. Do not add a domain-name after the user name." "Enter your user name. Do not add a domain-name after the user name." ::msgcat::mcset en "Enter your user name. Do not add a domain-name after the user name." "Enter your user name. Do not add a domain-name after the user name." ::msgcat::mcset en "Error" "Error" ::msgcat::mcset en "Error loading configuration file:" "Error loading configuration file:" ::msgcat::mcset en "Error starting connection:" "Error starting connection:" ::msgcat::mcset en "Error stopping connection:" "Error stopping connection:" ::msgcat::mcset en "Ethernet Interface:" "Ethernet Interface:" ::msgcat::mcset en "Exit" "Exit" ::msgcat::mcset en "failed" "failed" ::msgcat::mcset en "failed" "failed" ::msgcat::mcset en "Firewalling:" "Firewalling:" ::msgcat::mcset en "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." ::msgcat::mcset en "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." "Firewalling options:\nStand-Alone - A stand-alone machine.\nMasquerading - A gateway machine used for Internet sharing.\nNone - Use if you already have your own firewall rules or want to run servers." ::msgcat::mcset en "From Server" "From Server" ::msgcat::mcset en "From Server" "From Server" ::msgcat::mcset en "From Server" "From Server" ::msgcat::mcset en "From Server" "From Server" ::msgcat::mcset en "Help file is not installed" "Help file is not installed" ::msgcat::mcset en "If enabled, ordinary users can start and stop this connection." "If enabled, ordinary users can start and stop this connection." ::msgcat::mcset en "Masquerading" "Masquerading" ::msgcat::mcset en "Masquerading" "Masquerading" ::msgcat::mcset en "Masquerading" "Masquerading" ::msgcat::mcset en "Network:" "Network:" ::msgcat::mcset en "New Connection..." "New Connection..." ::msgcat::mcset en "New Connection" "New Connection" ::msgcat::mcset en "New Connection" "New Connection" ::msgcat::mcset en "NIC and DNS" "NIC and DNS" ::msgcat::mcset en "None" "None" ::msgcat::mcset en "None" "None" ::msgcat::mcset en "Note" "Note" ::msgcat::mcset en "Note: There are no connections defined. You must run this program as root to define connections" "Note: There are no connections defined. You must run this program as root to define connections" ::msgcat::mcset en "OK" "OK" ::msgcat::mcset en "Options" "Options" ::msgcat::mcset en "Password:" "Password:" ::msgcat::mcset en "Primary DNS entry must consist of four dot-separated decimal numbers" "Primary DNS entry must consist of four dot-separated decimal numbers" ::msgcat::mcset en "Primary DNS:" "Primary DNS:" ::msgcat::mcset en "Properties..." "Properties..." ::msgcat::mcset en "Secondary DNS entry must consist of four dot-separated decimal numbers" "Secondary DNS entry must consist of four dot-separated decimal numbers" ::msgcat::mcset en "Secondary DNS:" "Secondary DNS:" ::msgcat::mcset en "Service-Name:" "Service-Name:" ::msgcat::mcset en "Some ISP's require you to enter their domain-name here (e.g. " "Some ISP's require you to enter their domain-name here (e.g. " ::msgcat::mcset en "Some ISP's require you to enter their domain-name here (e.g. " "Some ISP's require you to enter their domain-name here (e.g. " ::msgcat::mcset en "Specify" "Specify" ::msgcat::mcset en "Specify" "Specify" ::msgcat::mcset en "Specify" "Specify" ::msgcat::mcset en "Stand-Alone" "Stand-Alone" ::msgcat::mcset en "Stand-Alone" "Stand-Alone" ::msgcat::mcset en "Start" "Start" ::msgcat::mcset en "Stop" "Stop" ::msgcat::mcset en "succeeded" "succeeded" ::msgcat::mcset en "The connection already exists. Pick another name." "The connection already exists. Pick another name." ::msgcat::mcset en "User Name:" "User Name:" ::msgcat::mcset en "Use synchronous PPP (recommended -- easier on the CPU.)" "Use synchronous PPP (recommended -- easier on the CPU.)" ::msgcat::mcset en "Use synchronous PPP" "Use synchronous PPP" ::msgcat::mcset en "Welcome to RP-PPPoE" "Welcome to RP-PPPoE" rp-pppoe-3.15/gui/Makefile.in0000644000175000017500000000376614045237007014165 0ustar dfsdfs# @configure_input@ #*********************************************************************** # # Makefile # # Makefile for GUI for Roaring Penguin's Linux user-space PPPoE client. # # Copyright (C) 2001 Roaring Penguin Software Inc. # Copyright (C) 2018-2021 Dianne Skoll # # This program may be distributed according to the terms of the GNU # General Public License, version 2 or (at your option) any later version. # # LIC: GPL # # $Id$ #*********************************************************************** DEFINES= prefix=@prefix@ exec_prefix=@exec_prefix@ mandir=@mandir@ install=@INSTALL@ install_dir=@INSTALL@ -d sbindir=@sbindir@ bindir=@bindir@ datadir=@datadir@ datarootdir=@datarootdir@ PPPOE_START_PATH=@sbindir@/pppoe-start PPPOE_STOP_PATH=@sbindir@/pppoe-stop PPPOE_STATUS_PATH=@sbindir@/pppoe-status PATHS='-DPPPOE_START_PATH="$(PPPOE_START_PATH)"' '-DPPPOE_STOP_PATH="$(PPPOE_STOP_PATH)"' '-DPPPOE_STATUS_PATH="$(PPPOE_STATUS_PATH)"' CFLAGS= @CFLAGS@ $(DEFINES) $(PATHS) all: pppoe-wrapper @echo "" @echo "Type 'make install' as root to install the software." pppoe-wrapper: wrapper.o @CC@ -o pppoe-wrapper wrapper.o wrapper.o: wrapper.c @CC@ $(CFLAGS) -c -o wrapper.o wrapper.c install: all -mkdir -p $(DESTDIR)$(sbindir) -mkdir -p $(DESTDIR)$(bindir) -mkdir -p $(DESTDIR)/etc/ppp/rp-pppoe-gui $(install) -m 4755 -s pppoe-wrapper $(DESTDIR)$(sbindir) $(install) -m 755 tkpppoe $(DESTDIR)$(bindir) -mkdir -p $(DESTDIR)$(mandir)/man1 $(install) -m 644 pppoe-wrapper.1 $(DESTDIR)$(mandir)/man1 $(install) -m 644 tkpppoe.1 $(DESTDIR)$(mandir)/man1 -mkdir -p $(DESTDIR)$(datadir)/tkpppoe for i in tkpppoe.html mainwin-busy.png mainwin-nonroot.png mainwin.png props-advanced.png props-basic.png props-nic.png props-options.png; do \ $(install) -m 644 html/$$i $(DESTDIR)$(datadir)/tkpppoe; \ done for i in en.msg ja.msg; do \ $(install) -m 644 $$i $(DESTDIR)$(datadir)/tkpppoe; \ done clean: rm -f *.o *~ pppoe-wrapper distclean: clean rm -f Makefile tkpppoe .PHONY: clean .PHONY: distclean rp-pppoe-3.15/gui/pppoe-wrapper.10000644000175000017500000000213714045237007014772 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-WRAPPER 1 "26 February 2001" .UC 4 .SH NAME pppoe-wrapper \- SUID wrapper for starting and stopping PPPoE connections. .SH SYNOPSIS .B pppoe-wrapper start linkname .P .B pppoe-wrapper stop linkname .P .B pppoe-wrapper status linkname .SH DESCRIPTION \fBpppoe-wrapper\fR is a small SUID program which allows non-root users to start and stop PPPoE links. It operates as follows: .TP .B o First, \fIlinkname\fR is sanity-checked. Too-long names and names containing illegal characters are rejected. .TP .B o Second, \fBpppoe-wrapper\fR opens the file \fB/etc/ppp/rp-pppoe-gui/conf.\fR\fIlinkname\fR for reading. If that file does not contain the line: .nf NONROOT=OK .fi then \fBpppoe-wrapper\fR fails. .TP .B o Otherwise, \fBpppoe-wrapper\fR runs \fBpppoe-start\fR, \fBpppoe-stop\fR or \fBpppoe-status\fR with the above filename as its single argument. .SH AUTHOR \fBpppoe-wrapper\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe-start(8), pppoe-stop(8), pppoe-status(8), tkpppoe(1) rp-pppoe-3.15/src/0000755000175000017500000000000014045237010012101 5ustar dfsdfsrp-pppoe-3.15/src/pppoe-server.h0000644000175000017500000001154414045237010014706 0ustar dfsdfs/********************************************************************** * * pppoe-server.h * * Definitions for PPPoE server * * Copyright (C) 2001-2012 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * * $Id$ * ***********************************************************************/ #include "pppoe.h" #include "event.h" #ifdef HAVE_L2TP #include "l2tp/l2tp.h" #endif #define MAX_USERNAME_LEN 31 /* An Ethernet interface */ typedef struct { char name[IFNAMSIZ+1]; /* Interface name */ int sock; /* Socket for discovery frames */ unsigned char mac[ETH_ALEN]; /* MAC address */ EventHandler *eh; /* Event handler for this interface */ UINT16_t mtu; /* MTU of interface */ /* Next fields are used only if we're an L2TP LAC */ #ifdef HAVE_L2TP int session_sock; /* Session socket */ EventHandler *lac_eh; /* LAC's event-handler */ #endif } Interface; #define FLAG_RECVD_PADT 1 #define FLAG_USER_SET 2 #define FLAG_IP_SET 4 #define FLAG_SENT_PADT 8 /* Only used if we are an L2TP LAC or LNS */ #define FLAG_ACT_AS_LAC 256 #define FLAG_ACT_AS_LNS 512 /* Forward declaration */ struct ClientSessionStruct; /* Dispatch table for session-related functions. We call different functions for L2TP-terminated sessions than for locally-terminated sessions. */ typedef struct PppoeSessionFunctionTable_t { /* Stop the session */ void (*stop)(struct ClientSessionStruct *ses, char const *reason); /* Return 1 if session is active, 0 otherwise */ int (*isActive)(struct ClientSessionStruct *ses); /* Describe a session in human-readable form */ char const * (*describe)(struct ClientSessionStruct *ses); } PppoeSessionFunctionTable; extern PppoeSessionFunctionTable DefaultSessionFunctionTable; /* A client session */ typedef struct ClientSessionStruct { struct ClientSessionStruct *next; /* In list of free or active sessions */ PppoeSessionFunctionTable *funcs; /* Function table */ pid_t pid; /* PID of child handling session */ Interface *ethif; /* Ethernet interface */ unsigned char myip[IPV4ALEN]; /* Local IP address */ unsigned char peerip[IPV4ALEN]; /* Desired IP address of peer */ UINT16_t sess; /* Session number */ unsigned char eth[ETH_ALEN]; /* Peer's Ethernet address */ unsigned int flags; /* Various flags */ time_t startTime; /* When session started */ char const *serviceName; /* Service name */ UINT16_t requested_mtu; /* Requested PPP_MAX_PAYLOAD per RFC 4638 */ #ifdef HAVE_LICENSE char user[MAX_USERNAME_LEN+1]; /* Authenticated user-name */ char realm[MAX_USERNAME_LEN+1]; /* Realm */ unsigned char realpeerip[IPV4ALEN]; /* Actual IP address -- may be assigned by RADIUS server */ int maxSessionsPerUser; /* Max sessions for this user */ #endif #ifdef HAVE_L2TP l2tp_session *l2tp_ses; /* L2TP session */ struct sockaddr_in tunnel_endpoint; /* L2TP endpoint */ #endif } ClientSession; /* Hack for daemonizing */ #define CLOSEFD 64 /* Max. number of interfaces to listen on */ #define MAX_INTERFACES 64 /* Max. 64 sessions by default */ #define DEFAULT_MAX_SESSIONS 64 /* An array of client sessions */ extern ClientSession *Sessions; /* Interfaces we're listening on */ extern Interface interfaces[MAX_INTERFACES]; extern int NumInterfaces; /* The number of session slots */ extern size_t NumSessionSlots; /* The number of active sessions */ extern size_t NumActiveSessions; /* Offset of first session */ extern size_t SessOffset; /* Access concentrator name */ extern char *ACName; extern unsigned char LocalIP[IPV4ALEN]; extern unsigned char RemoteIP[IPV4ALEN]; /* Do not create new sessions if free RAM < 10MB (on Linux only!) */ #define MIN_FREE_MEMORY 10000 /* Do we increment local IP for each connection? */ extern int IncrLocalIP; /* Free sessions */ extern ClientSession *FreeSessions; /* When a session is freed, it is added to the end of the free list */ extern ClientSession *LastFreeSession; /* Busy sessions */ extern ClientSession *BusySessions; extern EventSelector *event_selector; extern int GotAlarm; extern void setAlarm(unsigned int secs); extern void killAllSessions(void); extern void serverProcessPacket(Interface *i); extern void processPADT(Interface *ethif, PPPoEPacket *packet, int len); extern void processPADR(Interface *ethif, PPPoEPacket *packet, int len); extern void processPADI(Interface *ethif, PPPoEPacket *packet, int len); extern void usage(char const *msg); extern ClientSession *pppoe_alloc_session(void); extern int pppoe_free_session(ClientSession *ses); extern void sendHURLorMOTM(PPPoEConnection *conn, char const *url, UINT16_t tag); #ifdef HAVE_LICENSE extern int getFreeMem(void); #endif rp-pppoe-3.15/src/relay.h0000644000175000017500000000720614045237010013373 0ustar dfsdfs/********************************************************************** * * relay.h * * Definitions for PPPoE relay * * Copyright (C) 2001-2006 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * * $Id$ * ***********************************************************************/ #include "pppoe.h" /* Description for each active Ethernet interface */ typedef struct InterfaceStruct { char name[IFNAMSIZ+1]; /* Interface name */ int discoverySock; /* Socket for discovery frames */ int sessionSock; /* Socket for session frames */ int clientOK; /* Client requests allowed (PADI, PADR) */ int acOK; /* AC replies allowed (PADO, PADS) */ unsigned char mac[ETH_ALEN]; /* MAC address */ } PPPoEInterface; /* Session state for relay */ struct SessionHashStruct; typedef struct SessionStruct { struct SessionStruct *next; /* Free list link */ struct SessionStruct *prev; /* Free list link */ struct SessionHashStruct *acHash; /* Hash bucket for AC MAC/Session */ struct SessionHashStruct *clientHash; /* Hash bucket for client MAC/Session */ unsigned int epoch; /* Epoch when last activity was seen */ UINT16_t sesNum; /* Session number assigned by relay */ } PPPoESession; /* Hash table entry to find sessions */ typedef struct SessionHashStruct { struct SessionHashStruct *next; /* Link in hash chain */ struct SessionHashStruct *prev; /* Link in hash chain */ struct SessionHashStruct *peer; /* Peer for this session */ PPPoEInterface const *interface; /* Interface */ unsigned char peerMac[ETH_ALEN]; /* Peer's MAC address */ UINT16_t sesNum; /* Session number */ PPPoESession *ses; /* Session data */ } SessionHash; /* Function prototypes */ void relayGotSessionPacket(PPPoEInterface const *i); void relayGotDiscoveryPacket(PPPoEInterface const *i); PPPoEInterface *findInterface(int sock); unsigned int hash(unsigned char const *mac, UINT16_t sesNum); SessionHash *findSession(unsigned char const *mac, UINT16_t sesNum); void deleteHash(SessionHash *hash); PPPoESession *createSession(PPPoEInterface const *ac, PPPoEInterface const *cli, unsigned char const *acMac, unsigned char const *cliMac, UINT16_t acSes); void freeSession(PPPoESession *ses, char const *msg); void addInterface(char const *ifname, int clientOK, int acOK); void usage(char const *progname); void initRelay(int nsess); void relayLoop(void); void addHash(SessionHash *sh); void unhash(SessionHash *sh); void relayHandlePADT(PPPoEInterface const *iface, PPPoEPacket *packet, int size); void relayHandlePADI(PPPoEInterface const *iface, PPPoEPacket *packet, int size); void relayHandlePADO(PPPoEInterface const *iface, PPPoEPacket *packet, int size); void relayHandlePADR(PPPoEInterface const *iface, PPPoEPacket *packet, int size); void relayHandlePADS(PPPoEInterface const *iface, PPPoEPacket *packet, int size); int addTag(PPPoEPacket *packet, PPPoETag const *tag); int insertBytes(PPPoEPacket *packet, unsigned char *loc, void const *bytes, int length); int removeBytes(PPPoEPacket *packet, unsigned char *loc, int length); void relaySendError(unsigned char code, UINT16_t session, PPPoEInterface const *iface, unsigned char const *mac, PPPoETag const *hostUniq, char const *errMsg); void alarmHandler(int sig); void cleanSessions(void); #define MAX_INTERFACES 8 #define DEFAULT_SESSIONS 5000 /* Hash table size -- a prime number; gives load factor of around 6 for 65534 sessions */ #define HASHTAB_SIZE 18917 rp-pppoe-3.15/src/configure.in0000644000175000017500000002154614045237010014422 0ustar dfsdfsdnl Process this file with autoconf to produce a configure script. dnl LIC: GPL AC_INIT(pppoe.c) dnl pppd directory for kernel-mode PPPoE PPPD_DIR=ppp-2.4.1.pppoe2 AC_CONFIG_HEADER(config.h) AC_PREFIX_DEFAULT(/usr) dnl Checks for programs. AC_PROG_CC AC_PROG_RANLIB dnl Checks for libraries. dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(fcntl.h sys/dlpi.h sys/ioctl.h sys/time.h syslog.h unistd.h net/if_arp.h netinet/if_ether.h getopt.h sys/uio.h sys/param.h fcntl.h net/bpf.h netpacket/packet.h net/ethernet.h asm/types.h linux/if_packet.h linux/if_ether.h sys/socket.h net/if.h net/if_dl.h net/if_ether.h net/if_types.h netinet/if_ether.h net/if_types.h net/if_dl.h) AC_CHECK_HEADERS(linux/if.h, [], [], [#include]) AC_CHECK_HEADERS(linux/if_pppox.h, [], [], [ #include #include #include #include ]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_PID_T AC_HEADER_TIME AC_STRUCT_TM dnl Check for sockaddr_ll AC_MSG_CHECKING(for struct sockaddr_ll) AC_TRY_COMPILE([#include #include #include ], [struct sockaddr_ll sa;], ac_cv_struct_sockaddr_ll=yes, ac_cv_struct_sockaddr_ll=no) AC_MSG_RESULT($ac_cv_struct_sockaddr_ll) if test "$ac_cv_struct_sockaddr_ll" = yes ; then AC_DEFINE(HAVE_STRUCT_SOCKADDR_LL) fi dnl Check for N_HDLC line discipline AC_MSG_CHECKING(for N_HDLC line discipline) AC_TRY_COMPILE([ #include ], [int x = N_HDLC;], ac_cv_n_hdlc=yes, ac_cv_n_hdlc=no) AC_MSG_RESULT($ac_cv_n_hdlc) if test "$ac_cv_n_hdlc" = yes ; then AC_DEFINE(HAVE_N_HDLC) fi AC_ARG_ENABLE(plugin, [ --enable-plugin=pppd_src_path build pppd plugin], ac_cv_pluginpath=$enableval, ac_cv_pluginpath=no) AC_ARG_ENABLE(debugging, [ --disable-debugging disable debugging code], ac_cv_debugging=$enableval, ac_cv_debugging=yes) dnl If we were given "--enable-plugin" without a path, take a stab at where dnl the pppd source code might be. if test "$ac_cv_pluginpath" = "yes" ; then for i in /usr/include /usr/local/include ; do if test -r $i/pppd/pppd.h; then ac_cv_pluginpath=$i fi done fi if test "$ac_cv_pluginpath" = "yes" ; then echo "*** Could not find pppd/pppd.h anywhere... not building plugin" ac_cv_pluginpath=no fi AC_ARG_ENABLE(licenses, [ --enable-licenses=lic_path build commercial version], ac_cv_licpath=$enableval, ac_cv_licpath=no) LIC_INCDIR="" LIC_LIBDIR="" LIC_LIB="" LIC_DEFINE="" LIC_MAKEFILE_INCLUDE="" PPPOE_SERVER_DEPS="" if test "$ac_cv_licpath" != "no" ; then LIC_INCDIR="-I$ac_cv_licpath" LIC_LIBDIR="-L$ac_cv_licpath -Llicensed-only" if test -d "../../extra-libs" ; then LIC_LIB="-L../../extra-libs -ltwofish -llicensed-only -ltcl -ldl" else LIC_LIB="-ltwofish -llicensed-only -ltcl -ldl" fi PPPOE_SERVER_DEPS="licensed-only/liblicensed-only.a ../../SERVPOET-VERSION" LIC_DEFINE="-DHAVE_LICENSE=1 -DSERVPOET_VERSION='\"\$(SERVPOET_VERSION)\"'" LIC_MAKEFILE_INCLUDE="include ../../SERVPOET-VERSION" fi dnl Determine whether or not to build Linux pppd plugin LINUX_KERNELMODE_PLUGIN="" PPPD_INCDIR="" if test "$ac_cv_header_linux_if_pppox_h" = yes ; then if test "$ac_cv_pluginpath" != no ; then LINUX_KERNELMODE_PLUGIN=rp-pppoe.so AC_DEFINE(HAVE_LINUX_KERNEL_PPPOE) PPPD_INCDIR=$ac_cv_pluginpath fi fi if test "$PPPD_INCDIR" = "" ; then PPPD_INCDIR=/usr/include fi if test "$ac_cv_debugging" = "yes" ; then AC_DEFINE(DEBUGGING_ENABLED) fi AC_SUBST(LINUX_KERNELMODE_PLUGIN) AC_SUBST(PPPD_INCDIR) AC_SUBST(PPPD_H) dnl Determine whether or not to build PPPoE relay PPPOE_RELAY="" if test "`uname -s`" = "Linux" ; then PPPOE_RELAY=pppoe-relay fi AC_SUBST(PPPOE_RELAY) dnl Checks for library functions. AC_FUNC_MEMCMP AC_FUNC_SETVBUF_REVERSED AC_TYPE_SIGNAL AC_CHECK_FUNCS(select socket strerror strtol strlcpy) AC_PROG_INSTALL dnl Integer sizes AC_CHECK_SIZEOF(unsigned short) AC_CHECK_SIZEOF(unsigned int) AC_CHECK_SIZEOF(unsigned long) dnl Check for location of ip AC_PATH_PROG(IP, ip, NOTFOUND, $PATH:/bin:/sbin:/usr/bin:/usr/sbin) dnl Check for location of pppd AC_PATH_PROG(PPPD, pppd, NOTFOUND, $PATH:/sbin:/usr/sbin:/usr/local/sbin) dnl Check for setsid (probably Linux-specific) AC_PATH_PROG(SETSID, setsid, "", $PATH:/sbin:/usr/sbin:/usr/local/sbin) dnl Check for an "id" which accepts "-u" option -- hack for Solaris. AC_PATH_PROG(ID, id, "", /usr/xpg4/bin:$PATH) dnl Check for Linux-specific kernel support for PPPoE AC_MSG_CHECKING(for Linux 2.4.X kernel-mode PPPoE support) AC_CACHE_VAL(ac_cv_linux_kernel_pppoe,[ if test "`uname -s`" = "Linux" ; then if test $cross_compiling = "no"; then dnl Do a bunch of modprobes. Can't hurt; might help. modprobe ppp_generic > /dev/null 2>&1 modprobe ppp_async > /dev/null 2>&1 modprobe n_hdlc > /dev/null 2>&1 modprobe ppp_synctty > /dev/null 2>&1 modprobe pppoe > /dev/null 2>&1 fi AC_TRY_RUN([#include #include #include int main() { if (socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OE) >= 0) return 0; else return 1; } ], ac_cv_linux_kernel_pppoe=yes, ac_cv_linux_kernel_pppoe=no, [ac_cv_linux_kernel_pppoe=no; echo "cross-compiling, default: "]) else ac_cv_linux_kernel_pppoe=no fi ]) AC_MSG_RESULT($ac_cv_linux_kernel_pppoe) if test "$ac_cv_linux_kernel_pppoe" != yes ; then if test "$LINUX_KERNELMODE_PLUGIN" = rp-pppoe.so; then echo "*** Your kernel does not appear to have built-in PPPoE support," echo "*** but I will build the kernel-mode plugin anyway." fi fi dnl GCC warning level if test "$GCC" = yes; then CFLAGS="$CFLAGS -fno-strict-aliasing -Wall -Wstrict-prototypes" fi dnl If we couldn't find pppd, die if test "$PPPD" = "NOTFOUND"; then AC_MSG_WARN([*** Oops! I couldn't find pppd, the PPP daemon anywhere.]) AC_MSG_WARN([*** You must install pppd, version 2.3.10 or later.]) AC_MSG_WARN([*** I will keep going, but it may not work.]) PPPD=pppd fi dnl Figure out pppd version. 2.3.7 to 2.3.9 -- issue warning. Less than dnl 2.3.7 -- stop PPPD_VERSION=`$PPPD --version 2>&1 | awk ' /version/ {print $NF}'` case "$PPPD_VERSION" in 1.*|2.0.*|2.1.*|2.2.*|2.3.0|2.3.1|2.3.2|2.3.3|2.3.4|2.3.5|2.3.6) AC_MSG_WARN([*** Oops! Your version of pppd is $PPPD_VERSION, which is too old.]) AC_MSG_WARN([*** You need at least 2.3.7 (2.3.10 or newer recommended.]) AC_MSG_WARN([*** I will keep going, but it may not work.]) ;; 2.3.7|2.3.8|2.3.9) AC_MSG_WARN([*** Warning. Your version of pppd is $PPPD_VERSION. You will]) AC_MSG_WARN([*** not be able to use connect-on-demand. Upgrade to pppd]) AC_MSG_WARN([*** 2.3.10 or newer if you need connect-on-demand.]) ;; 2*|3*|4*|5*|6*|7*|8*|9*) ;; *) AC_MSG_WARN([*** Oops. I cannot figure out what version of pppd you have.]) AC_MSG_WARN([*** All I got back was '$PPPD_VERSION']) AC_MSG_WARN([*** I will keep going, but it may not work.]) ;; esac # Sigh... got to fix this up for tcl test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Fully resolve WRAPPER for Tcl script. WRAPPER=${sbindir}/pppoe-wrapper eval "WRAPPER=${WRAPPER}" eval "WRAPPER=${WRAPPER}" AC_SUBST(WRAPPER) # Determine what targets to build TARGETS="pppoe pppoe-server" # pppoe-sniff is built only on Linux and Solaris if test "$ac_cv_header_linux_if_packet_h" = "yes" -o "$ac_cv_header_sys_dlpi_h" = "yes" ; then TARGETS="$TARGETS pppoe-sniff" fi # pppoe-relay is built only on Linux if test "$ac_cv_header_linux_if_packet_h" = "yes" ; then TARGETS="$TARGETS pppoe-relay" fi # plugin is built only if we have kernel support if test -n "$LINUX_KERNELMODE_PLUGIN" ; then TARGETS="$TARGETS $LINUX_KERNELMODE_PLUGIN" mkdir plugin > /dev/null 2>&1 fi EXTRACONFIGS="" # Licensed stuff only for commercial distro (for now) if test -n "$LIC_DEFINE" ; then TARGETS="licensed-only $TARGETS" EXTRACONFIGS="$EXTRACONFIGS licensed-only/Makefile" fi RDYNAMIC="" # L2TP is only in commercial distro (for now) if test -n "$LIC_DEFINE" ; then TARGETS="l2tp $TARGETS" EXTRACONFIGS="$EXTRACONFIGS l2tp/Makefile l2tp/handlers/Makefile" LIC_DEFINE="$LIC_DEFINE -DHAVE_L2TP=1" LIC_LIB="$LIC_LIB -Ll2tp -ll2tp" PPPOE_SERVER_DEPS="$PPPOE_SERVER_DEPS l2tp/libl2tp.a" RDYNAMIC="-rdynamic" fi LIBEVENT=../libevent AC_SUBST(TARGETS) AC_SUBST(LIC_INCDIR) AC_SUBST(LIC_LIBDIR) AC_SUBST(LIC_LIB) AC_SUBST(LIC_MAKEFILE_INCLUDE) AC_SUBST(LIC_DEFINE) AC_SUBST(PPPOE_SERVER_DEPS) AC_SUBST(RDYNAMIC) AC_SUBST(LIBEVENT) AC_SUBST(LDFLAGS) datadir_evaluated=`eval echo $datadir` AC_SUBST(datadir_evaluated) AC_OUTPUT(Makefile libevent/Makefile ../scripts/pppoe-connect ../scripts/pppoe-start ../scripts/pppoe-stop ../scripts/pppoe-init ../scripts/pppoe-init-suse ../scripts/pppoe-setup ../gui/Makefile ../gui/tkpppoe $EXTRACONFIGS) AC_MSG_RESULT([On this platform, the following targets will be built:]) AC_MSG_RESULT([$TARGETS]) AC_MSG_RESULT([Type 'make' to compile the software.]) rp-pppoe-3.15/src/pppoe-sniff.c0000644000175000017500000001616314045237010014502 0ustar dfsdfs/*********************************************************************** * * pppoe-sniff.c * * Sniff a network for likely-looking PPPoE frames and deduce the value * to supply to PPPOE_EXTRA in /etc/ppp/pppoe.conf. USE AT YOUR OWN RISK. * * Copyright (C) 2000-2018 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #define _GNU_SOURCE 1 #include "pppoe.h" #ifdef HAVE_GETOPT_H #include #endif #include #include #include #include #ifdef USE_DLPI #include /* function declarations */ void dlpromisconreq( int fd, u_long level); void dlokack(int fd, char *bufp); #endif /* Default interface if no -I option given */ #define DEFAULT_IF "eth0" /* Global vars */ int SeenPADR = 0; int SeenSess = 0; UINT16_t SessType, DiscType; char *IfName = NULL; /* Interface name */ char *ServiceName = NULL; /* Service name */ /********************************************************************** *%FUNCTION: parsePADRTags *%ARGUMENTS: * type -- tag type * len -- tag length * data -- tag data * extra -- extra user data. *%RETURNS: * Nothing *%DESCRIPTION: * Picks interesting tags out of a PADR packet ***********************************************************************/ void parsePADRTags(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { switch(type) { case TAG_SERVICE_NAME: ServiceName = malloc(len+1); if (ServiceName) { memcpy(ServiceName, data, len); ServiceName[len] = 0; } break; } } /********************************************************************** *%FUNCTION: fatalSys *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to stderr and exits. ***********************************************************************/ void fatalSys(char const *str) { char buf[1024]; sprintf(buf, "%.256s: %.256s", str, strerror(errno)); printErr(buf); exit(1); } /********************************************************************** *%FUNCTION: rp_fatal *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message to stderr and syslog and exits. ***********************************************************************/ void rp_fatal(char const *str) { printErr(str); exit(1); } /********************************************************************** *%FUNCTION: usage *%ARGUMENTS: * argv0 -- program name *%RETURNS: * Nothing *%DESCRIPTION: * Prints usage information and exits. ***********************************************************************/ void usage(char const *argv0) { fprintf(stderr, "Usage: %s [options]\n", argv0); fprintf(stderr, "Options:\n"); fprintf(stderr, " -I if_name -- Specify interface (default %s.)\n", DEFAULT_IF); fprintf(stderr, " -V -- Print version and exit.\n"); fprintf(stderr, "\nPPPoE Version %s, Copyright (C) 2000 Roaring Penguin Software Inc.\n", RP_VERSION); fprintf(stderr, " %*s Copyright (C) 2018-2021 Dianne Skoll\n", (int) strlen(RP_VERSION), ""); fprintf(stderr, "PPPoE comes with ABSOLUTELY NO WARRANTY.\n"); fprintf(stderr, "This is free software, and you are welcome to redistribute it under the terms\n"); fprintf(stderr, "of the GNU General Public License, version 2 or any later version.\n"); fprintf(stderr, "https://dianne.skoll.ca/projects/rp-pppoe/\n"); exit(0); } #if !defined(USE_LINUX_PACKET) && !defined(USE_DLPI) int main() { fprintf(stderr, "Sorry, pppoe-sniff works only on Linux.\n"); return 1; } #else /********************************************************************** *%FUNCTION: main *%ARGUMENTS: * argc, argv -- count and values of command-line arguments *%RETURNS: * Nothing *%DESCRIPTION: * Main program ***********************************************************************/ int main(int argc, char *argv[]) { int opt; int sock; PPPoEPacket pkt; int size; #ifdef USE_DLPI long buf[MAXDLBUF]; #endif if (getuid() != geteuid() || getgid() != getegid()) { fprintf(stderr, "SECURITY WARNING: pppoe-sniff will NOT run suid or sgid. Fix your installation.\n"); exit(1); } while((opt = getopt(argc, argv, "I:V")) != -1) { switch(opt) { case 'I': SET_STRING(IfName, optarg); break; case 'V': printf("pppoe-sniff: RP-PPPoE Version %s\n", RP_VERSION); exit(0); default: usage(argv[0]); } } /* Pick a default interface name */ if (!IfName) { IfName = DEFAULT_IF; } /* Open the interface */ #ifdef USE_DLPI sock = openInterface(IfName, Eth_PPPOE_Discovery, NULL); dlpromisconreq(sock, DL_PROMISC_PHYS); dlokack(sock, (char *)buf); dlpromisconreq(sock, DL_PROMISC_SAP); dlokack(sock, (char *)buf); #else sock = openInterface(IfName, ETH_P_ALL, NULL, NULL); #endif /* We assume interface is in promiscuous mode -- use "ip link show" to ensure this */ fprintf(stderr, "Sniffing for PADR. Start your connection on another machine...\n"); while (!SeenPADR) { if (receivePacket(sock, &pkt, &size) < 0) continue; if (ntohs(pkt.length) + HDR_SIZE > size) continue; if (PPPOE_VER(pkt.vertype) != 1 || PPPOE_TYPE(pkt.vertype) != 1) continue; if (pkt.code != CODE_PADR) continue; /* Looks promising... parse it */ if (parsePacket(&pkt, parsePADRTags, NULL) < 0) { continue; } DiscType = ntohs(pkt.ethHdr.h_proto); fprintf(stderr, "\nExcellent! Sniffed a likely-looking PADR.\n"); break; } while (!SeenSess) { if (receivePacket(sock, &pkt, &size) < 0) continue; if (ntohs(pkt.length) + HDR_SIZE > size) continue; if (PPPOE_VER(pkt.vertype) != 1 || PPPOE_TYPE(pkt.vertype) != 1) continue; if (pkt.code != CODE_SESS) continue; /* Cool! */ SessType = ntohs(pkt.ethHdr.h_proto); break; } fprintf(stderr, "Wonderful! Sniffed a likely-looking session packet.\n"); if ((ServiceName == NULL || *ServiceName == 0) && DiscType == ETH_PPPOE_DISCOVERY && SessType == ETH_PPPOE_SESSION) { fprintf(stderr, "\nGreat! It looks like a standard PPPoE service.\nYou should not need anything special in the configuration file.\n"); return 0; } fprintf(stderr, "\nOK, looks like you need something special in the configuration file.\nTry this:\n\n"); if (ServiceName != NULL && *ServiceName != 0) { fprintf(stderr, "SERVICENAME='%s'\n", ServiceName); } if (DiscType != ETH_PPPOE_DISCOVERY || SessType != ETH_PPPOE_SESSION) { fprintf(stderr, " PPPOE_EXTRA='-f %x:%x'\n", DiscType, SessType); } return 0; } #endif /********************************************************************** *%FUNCTION: sysErr *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to syslog. ***********************************************************************/ void sysErr(char const *str) { char buf[1024]; sprintf(buf, "%.256s: %.256s", str, strerror(errno)); printErr(buf); } rp-pppoe-3.15/src/md5.h0000644000175000017500000000131314045237010012735 0ustar dfsdfs#ifndef MD5_H #define MD5_H /* * LIC: GPL */ #include "config.h" #if SIZEOF_UNSIGNED_INT == 4 typedef unsigned int uint32; #elif SIZEOF_UNSIGNED_LONG == 4 typedef unsigned long uint32; #else # error Could not find a 32-bit integer type #endif struct MD5Context { uint32 buf[4]; uint32 bits[2]; unsigned char in[64]; }; void MD5Init(struct MD5Context *context); void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); void MD5Final(unsigned char digest[16], struct MD5Context *context); void MD5Transform(uint32 buf[4], uint32 const in[16]); /* * This is needed to make RSAREF happy on some MS-DOS compilers. */ typedef struct MD5Context MD5_CTX; #endif /* !MD5_H */ rp-pppoe-3.15/src/md5.c0000644000175000017500000001747314045237010012746 0ustar dfsdfs/* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * LIC: GPL * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #include /* for memcpy() */ #include "md5.h" static void byteReverse(unsigned char *buf, unsigned longs); /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { uint32 t; do { t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(uint32 *) buf = t; buf += 4; } while (--longs); } /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) { uint32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (uint32 *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((uint32 *) ctx->in)[14] = ctx->bits[0]; ((uint32 *) ctx->in)[15] = ctx->bits[1]; MD5Transform(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } #ifndef ASM_MD5 /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ void MD5Transform(uint32 buf[4], uint32 const in[16]) { register uint32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } #endif rp-pppoe-3.15/src/common.c0000644000175000017500000004162714045237010013547 0ustar dfsdfs/*********************************************************************** * * common.c * * Implementation of user-space PPPoE redirector for Linux. * * Common functions used by PPPoE client and server * * Copyright (C) 2000-2012 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ /* For vsnprintf prototype */ #define _ISOC99_SOURCE 1 #define _GNU_SOURCE 1 #include "pppoe.h" #ifdef HAVE_SYSLOG_H #include #endif #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include /* Are we running SUID or SGID? */ int IsSetID = 0; static uid_t saved_uid = (uid_t) -2; static uid_t saved_gid = (uid_t) -2; /********************************************************************** *%FUNCTION: parsePacket *%ARGUMENTS: * packet -- the PPPoE discovery packet to parse * func -- function called for each tag in the packet * extra -- an opaque data pointer supplied to parsing function *%RETURNS: * 0 if everything went well; -1 if there was an error *%DESCRIPTION: * Parses a PPPoE discovery packet, calling "func" for each tag in the packet. * "func" is passed the additional argument "extra". ***********************************************************************/ int parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra) { UINT16_t len = ntohs(packet->length); unsigned char *curTag; UINT16_t tagType, tagLen; if (PPPOE_VER(packet->vertype) != 1) { syslog(LOG_ERR, "Invalid PPPoE version (%d)", PPPOE_VER(packet->vertype)); return -1; } if (PPPOE_TYPE(packet->vertype) != 1) { syslog(LOG_ERR, "Invalid PPPoE type (%d)", PPPOE_TYPE(packet->vertype)); return -1; } /* Do some sanity checks on packet */ if (len > ETH_JUMBO_LEN - PPPOE_OVERHEAD) { /* 6-byte overhead for PPPoE header */ syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len); return -1; } /* Step through the tags */ curTag = packet->payload; while (curTag - packet->payload + TAG_HDR_SIZE <= len) { /* Alignment is not guaranteed, so do this by hand... */ tagType = (curTag[0] << 8) + curTag[1]; tagLen = (curTag[2] << 8) + curTag[3]; if (tagType == TAG_END_OF_LIST) { return 0; } if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) { syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen); return -1; } func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra); curTag = curTag + TAG_HDR_SIZE + tagLen; } return 0; } /********************************************************************** *%FUNCTION: findTag *%ARGUMENTS: * packet -- the PPPoE discovery packet to parse * type -- the type of the tag to look for * tag -- will be filled in with tag contents *%RETURNS: * A pointer to the tag if one of the specified type is found; NULL * otherwise. *%DESCRIPTION: * Looks for a specific tag type. ***********************************************************************/ unsigned char * findTag(PPPoEPacket *packet, UINT16_t type, PPPoETag *tag) { UINT16_t len = ntohs(packet->length); unsigned char *curTag; UINT16_t tagType, tagLen; if (PPPOE_VER(packet->vertype) != 1) { syslog(LOG_ERR, "Invalid PPPoE version (%d)", PPPOE_VER(packet->vertype)); return NULL; } if (PPPOE_TYPE(packet->vertype) != 1) { syslog(LOG_ERR, "Invalid PPPoE type (%d)", PPPOE_TYPE(packet->vertype)); return NULL; } /* Do some sanity checks on packet */ if (len > ETH_JUMBO_LEN - 6) { /* 6-byte overhead for PPPoE header */ syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len); return NULL; } /* Step through the tags */ curTag = packet->payload; while(curTag - packet->payload < len) { /* Alignment is not guaranteed, so do this by hand... */ tagType = (((UINT16_t) curTag[0]) << 8) + (UINT16_t) curTag[1]; tagLen = (((UINT16_t) curTag[2]) << 8) + (UINT16_t) curTag[3]; if (tagType == TAG_END_OF_LIST) { return NULL; } if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) { syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen); return NULL; } if (tagType == type) { memcpy(tag, curTag, tagLen + TAG_HDR_SIZE); return curTag; } curTag = curTag + TAG_HDR_SIZE + tagLen; } return NULL; } /********************************************************************** *%FUNCTION: switchToRealID *%ARGUMENTS: * None *%RETURNS: * Nothing *%DESCRIPTION: * Sets effective user-ID and group-ID to real ones. Aborts on failure ***********************************************************************/ void switchToRealID (void) { if (IsSetID) { if (saved_uid == (uid_t) -2) saved_uid = geteuid(); if (saved_gid == (uid_t) -2) saved_gid = getegid(); if (setegid(getgid()) < 0) { printErr("setgid failed"); exit(EXIT_FAILURE); } if (seteuid(getuid()) < 0) { printErr("seteuid failed"); exit(EXIT_FAILURE); } } } /********************************************************************** *%FUNCTION: switchToEffectiveID *%ARGUMENTS: * None *%RETURNS: * Nothing *%DESCRIPTION: * Sets effective user-ID and group-ID back to saved gid/uid ***********************************************************************/ void switchToEffectiveID (void) { if (IsSetID) { if (setegid(saved_gid) < 0) { printErr("setgid failed"); exit(EXIT_FAILURE); } if (seteuid(saved_uid) < 0) { printErr("seteuid failed"); exit(EXIT_FAILURE); } } } /********************************************************************** *%FUNCTION: dropPrivs *%ARGUMENTS: * None *%RETURNS: * Nothing *%DESCRIPTION: * If effective ID is root, try to become "nobody". If that fails and * we're SUID, switch to real user-ID ***********************************************************************/ void dropPrivs(void) { struct passwd *pw = NULL; int ok = 0; if (geteuid() == 0) { pw = getpwnam("nobody"); if (pw) { if (setgid(pw->pw_gid) < 0) ok++; if (setuid(pw->pw_uid) < 0) ok++; } } if (ok < 2 && IsSetID) { setegid(getgid()); seteuid(getuid()); } } /********************************************************************** *%FUNCTION: printErr *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message to stderr and syslog. ***********************************************************************/ void printErr(char const *str) { fprintf(stderr, "pppoe: %s\n", str); syslog(LOG_ERR, "%s", str); } /********************************************************************** *%FUNCTION: computeTCPChecksum *%ARGUMENTS: * ipHdr -- pointer to IP header * tcpHdr -- pointer to TCP header *%RETURNS: * The computed TCP checksum ***********************************************************************/ UINT16_t computeTCPChecksum(unsigned char *ipHdr, unsigned char *tcpHdr) { UINT32_t sum = 0; UINT16_t count = ipHdr[2] * 256 + ipHdr[3]; UINT16_t tmp; unsigned char *addr = tcpHdr; unsigned char pseudoHeader[12]; /* Count number of bytes in TCP header and data */ count -= (ipHdr[0] & 0x0F) * 4; memcpy(pseudoHeader, ipHdr+12, 8); pseudoHeader[8] = 0; pseudoHeader[9] = ipHdr[9]; pseudoHeader[10] = (count >> 8) & 0xFF; pseudoHeader[11] = (count & 0xFF); /* Checksum the pseudo-header */ sum += * (UINT16_t *) pseudoHeader; sum += * ((UINT16_t *) (pseudoHeader+2)); sum += * ((UINT16_t *) (pseudoHeader+4)); sum += * ((UINT16_t *) (pseudoHeader+6)); sum += * ((UINT16_t *) (pseudoHeader+8)); sum += * ((UINT16_t *) (pseudoHeader+10)); /* Checksum the TCP header and data */ while (count > 1) { memcpy(&tmp, addr, sizeof(tmp)); sum += (UINT32_t) tmp; addr += sizeof(tmp); count -= sizeof(tmp); } if (count > 0) { sum += (unsigned char) *addr; } while(sum >> 16) { sum = (sum & 0xffff) + (sum >> 16); } return (UINT16_t) ((~sum) & 0xFFFF); } /********************************************************************** *%FUNCTION: clampMSS *%ARGUMENTS: * packet -- PPPoE session packet * dir -- either "incoming" or "outgoing" * clampMss -- clamp value *%RETURNS: * Nothing *%DESCRIPTION: * Clamps MSS option if TCP SYN flag is set. ***********************************************************************/ void clampMSS(PPPoEPacket *packet, char const *dir, int clampMss) { unsigned char *tcpHdr; unsigned char *ipHdr; unsigned char *opt; unsigned char *endHdr; unsigned char *mssopt = NULL; UINT16_t csum; int len, minlen; /* check PPP protocol type */ if (packet->payload[0] & 0x01) { /* 8 bit protocol type */ /* Is it IPv4? */ if (packet->payload[0] != 0x21) { /* Nope, ignore it */ return; } ipHdr = packet->payload + 1; minlen = 41; } else { /* 16 bit protocol type */ /* Is it IPv4? */ if (packet->payload[0] != 0x00 || packet->payload[1] != 0x21) { /* Nope, ignore it */ return; } ipHdr = packet->payload + 2; minlen = 42; } /* Is it too short? */ len = (int) ntohs(packet->length); if (len < minlen) { /* 20 byte IP header; 20 byte TCP header; at least 1 or 2 byte PPP protocol */ return; } /* Verify once more that it's IPv4 */ if ((ipHdr[0] & 0xF0) != 0x40) { return; } /* Is it a fragment that's not at the beginning of the packet? */ if ((ipHdr[6] & 0x1F) || ipHdr[7]) { /* Yup, don't touch! */ return; } /* Is it TCP? */ if (ipHdr[9] != 0x06) { return; } /* Get start of TCP header */ tcpHdr = ipHdr + (ipHdr[0] & 0x0F) * 4; /* Is SYN set? */ if (!(tcpHdr[13] & 0x02)) { return; } /* Compute and verify TCP checksum -- do not touch a packet with a bad checksum */ csum = computeTCPChecksum(ipHdr, tcpHdr); if (csum) { syslog(LOG_ERR, "Bad TCP checksum %x", (unsigned int) csum); /* Upper layers will drop it */ return; } /* Look for existing MSS option */ endHdr = tcpHdr + ((tcpHdr[12] & 0xF0) >> 2); opt = tcpHdr + 20; while (opt < endHdr) { if (!*opt) break; /* End of options */ switch(*opt) { case 1: opt++; break; case 2: if (opt[1] != 4) { /* Something fishy about MSS option length. */ syslog(LOG_ERR, "Bogus length for MSS option (%u) from %u.%u.%u.%u", (unsigned int) opt[1], (unsigned int) ipHdr[12], (unsigned int) ipHdr[13], (unsigned int) ipHdr[14], (unsigned int) ipHdr[15]); return; } mssopt = opt; break; default: if (opt[1] < 2) { /* Someone's trying to attack us? */ syslog(LOG_ERR, "Bogus TCP option length (%u) from %u.%u.%u.%u", (unsigned int) opt[1], (unsigned int) ipHdr[12], (unsigned int) ipHdr[13], (unsigned int) ipHdr[14], (unsigned int) ipHdr[15]); return; } opt += (opt[1]); break; } /* Found existing MSS option? */ if (mssopt) break; } /* If MSS exists and it's low enough, do nothing */ if (mssopt) { unsigned mss = mssopt[2] * 256 + mssopt[3]; if (mss <= clampMss) { return; } mssopt[2] = (((unsigned) clampMss) >> 8) & 0xFF; mssopt[3] = ((unsigned) clampMss) & 0xFF; } else { /* No MSS option. Don't add one; we'll have to use 536. */ return; } /* Recompute TCP checksum */ tcpHdr[16] = 0; tcpHdr[17] = 0; csum = computeTCPChecksum(ipHdr, tcpHdr); (* (UINT16_t *) (tcpHdr+16)) = csum; } /*********************************************************************** *%FUNCTION: sendPADT *%ARGUMENTS: * conn -- PPPoE connection * msg -- if non-NULL, extra error message to include in PADT packet. *%RETURNS: * Nothing *%DESCRIPTION: * Sends a PADT packet ***********************************************************************/ void sendPADT(PPPoEConnection *conn, char const *msg) { PPPoEPacket packet; unsigned char *cursor = packet.payload; UINT16_t plen = 0; /* Do nothing if no session established yet */ if (!conn->session) return; /* Do nothing if no discovery socket */ if (conn->discoverySocket < 0) return; memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN); memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); packet.vertype = PPPOE_VER_TYPE(1, 1); packet.code = CODE_PADT; packet.session = conn->session; /* Reset Session to zero so there is no possibility of recursive calls to this function by any signal handler */ conn->session = 0; /* If we're using Host-Uniq, copy it over */ if (conn->hostUniq) { PPPoETag hostUniq; int len = (int) strlen(conn->hostUniq); hostUniq.type = htons(TAG_HOST_UNIQ); hostUniq.length = htons(len); memcpy(hostUniq.payload, conn->hostUniq, len); CHECK_ROOM(cursor, packet.payload, len + TAG_HDR_SIZE); memcpy(cursor, &hostUniq, len + TAG_HDR_SIZE); cursor += len + TAG_HDR_SIZE; plen += len + TAG_HDR_SIZE; } /* Copy error message */ if (msg) { PPPoETag err; size_t elen = strlen(msg); err.type = htons(TAG_GENERIC_ERROR); err.length = htons(elen); strcpy((char *) err.payload, msg); memcpy(cursor, &err, elen + TAG_HDR_SIZE); cursor += elen + TAG_HDR_SIZE; plen += elen + TAG_HDR_SIZE; } /* Copy cookie and relay-ID if needed */ if (conn->cookie.type) { CHECK_ROOM(cursor, packet.payload, ntohs(conn->cookie.length) + TAG_HDR_SIZE); memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE); cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE; plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE; } if (conn->relayId.type) { CHECK_ROOM(cursor, packet.payload, ntohs(conn->relayId.length) + TAG_HDR_SIZE); memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE); cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE; plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE; } packet.length = htons(plen); sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "SENT"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif syslog(LOG_INFO,"Sent PADT"); } /*********************************************************************** *%FUNCTION: sendPADTf *%ARGUMENTS: * conn -- PPPoE connection * msg -- printf-style format string * args -- arguments for msg *%RETURNS: * Nothing *%DESCRIPTION: * Sends a PADT packet with a formatted message ***********************************************************************/ void sendPADTf(PPPoEConnection *conn, char const *fmt, ...) { char msg[512]; va_list ap; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); msg[511] = 0; sendPADT(conn, msg); } /********************************************************************** *%FUNCTION: pktLogErrs *%ARGUMENTS: * pkt -- packet type (a string) * type -- tag type * len -- tag length * data -- tag data * extra -- extra user data *%RETURNS: * Nothing *%DESCRIPTION: * Logs error tags ***********************************************************************/ void pktLogErrs(char const *pkt, UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { char const *str; char const *fmt = "%s: %s: %.*s"; switch(type) { case TAG_SERVICE_NAME_ERROR: str = "Service-Name-Error"; break; case TAG_AC_SYSTEM_ERROR: str = "System-Error"; break; default: str = "Generic-Error"; } syslog(LOG_ERR, fmt, pkt, str, (int) len, data); fprintf(stderr, fmt, pkt, str, (int) len, data); fprintf(stderr, "\n"); } /********************************************************************** *%FUNCTION: parseLogErrs *%ARGUMENTS: * type -- tag type * len -- tag length * data -- tag data * extra -- extra user data *%RETURNS: * Nothing *%DESCRIPTION: * Picks error tags out of a packet and logs them. ***********************************************************************/ void parseLogErrs(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { pktLogErrs("PADT", type, len, data, extra); } #ifndef HAVE_STRLCPY /********************************************************************** *%FUNCTION: strlcpy *%ARGUMENTS: * dst -- destination buffer * src -- source string * size -- size of destination buffer *%RETURNS: * Number of characters copied, excluding NUL terminator *%DESCRIPTION: * Copy at most size-1 characters from src to dst, * always NUL-terminating dst if size!=0. ***********************************************************************/ size_t strlcpy(char *dst, const char *src, size_t size) { const char *orig_src = src; if (size == 0) { return 0; } while (--size != 0) { if ((*dst++ = *src++) == '\0') { break; } } if (size == 0) { *dst = '\0'; } return src - orig_src - 1; } #endif rp-pppoe-3.15/src/plugin/0000755000175000017500000000000014045237010013377 5ustar dfsdfsrp-pppoe-3.15/src/pppoe.c0000644000175000017500000006442714045237010013405 0ustar dfsdfs/*********************************************************************** * * pppoe.c * * Implementation of user-space PPPoE redirector for Linux. * * Copyright (C) 2000-2015 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #define _GNU_SOURCE 1 #include "pppoe.h" #ifdef HAVE_SYSLOG_H #include #endif #ifdef HAVE_GETOPT_H #include #endif #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_UIO_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef USE_LINUX_PACKET #include #include #endif #include #ifdef HAVE_N_HDLC #ifndef N_HDLC #include #endif #endif /* Default interface if no -I option given */ #define DEFAULT_IF "eth0" /* Global variables -- options */ int optInactivityTimeout = 0; /* Inactivity timeout */ int optClampMSS = 0; /* Clamp MSS to this value */ int optSkipSession = 0; /* Perform discovery, print session info and exit */ int optFloodDiscovery = 0; /* Flood server with discovery requests. USED FOR STRESS-TESTING ONLY. DO NOT USE THE -F OPTION AGAINST A REAL ISP */ PPPoEConnection *Connection = NULL; /* Must be global -- used in signal handler */ /*********************************************************************** *%FUNCTION: sendSessionPacket *%ARGUMENTS: * conn -- PPPoE connection * packet -- the packet to send * len -- length of data to send *%RETURNS: * Nothing *%DESCRIPTION: * Transmits a session packet to the peer. ***********************************************************************/ void sendSessionPacket(PPPoEConnection *conn, PPPoEPacket *packet, int len) { packet->length = htons(len); if (optClampMSS) { clampMSS(packet, "outgoing", optClampMSS); } if (sendPacket(conn, conn->sessionSocket, packet, len + HDR_SIZE) < 0) { if (errno == ENOBUFS) { /* No buffer space is a transient error */ return; } exit(EXIT_FAILURE); } #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, packet, "SENT"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif } #ifdef USE_BPF /********************************************************************** *%FUNCTION: sessionDiscoveryPacket *%ARGUMENTS: * packet -- the discovery packet that was received *%RETURNS: * Nothing *%DESCRIPTION: * We got a discovery packet during the session stage. This most likely * means a PADT. * * The BSD version uses a single socket for both discovery and session * packets. When a packet comes in over the wire once we are in * session mode, either syncReadFromEth() or asyncReadFromEth() will * have already read the packet and determined it to be a discovery * packet before passing it here. ***********************************************************************/ static void sessionDiscoveryPacket(PPPoEPacket *packet) { /* Sanity check */ if (packet->code != CODE_PADT) { return; } /* It's a PADT, all right. Is it for us? */ if (packet->session != Connection->session) { /* Nope, ignore it */ return; } if (memcmp(packet->ethHdr.h_dest, Connection->myEth, ETH_ALEN)) { return; } if (memcmp(packet->ethHdr.h_source, Connection->peerEth, ETH_ALEN)) { return; } syslog(LOG_INFO, "Session %d terminated -- received PADT from peer", (int) ntohs(packet->session)); parsePacket(packet, parseLogErrs, NULL); sendPADT(Connection, "Received PADT from peer"); exit(EXIT_SUCCESS); } #else /********************************************************************** *%FUNCTION: sessionDiscoveryPacket *%ARGUMENTS: * conn -- PPPoE connection *%RETURNS: * Nothing *%DESCRIPTION: * We got a discovery packet during the session stage. This most likely * means a PADT. ***********************************************************************/ static void sessionDiscoveryPacket(PPPoEConnection *conn) { PPPoEPacket packet; int len; if (receivePacket(conn->discoverySocket, &packet, &len) < 0) { return; } /* Check length */ if (ntohs(packet.length) + HDR_SIZE > len) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); return; } /* Is it for our session? */ if (packet.session != conn->session) { /* Nope, ignore it */ return; } /* Is it for our Ethernet interface? */ if (memcmp(packet.ethHdr.h_dest, conn->myEth, ETH_ALEN)) { /* Nope, ignore it */ return; } /* Is it from our peer's Ethernet interface? */ if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) { /* Nope, ignore it */ return; } if (packet.code != CODE_PADT) { /* Not PADT; ignore it */ return; } #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "RCVD"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif syslog(LOG_INFO, "Session %d terminated -- received PADT from peer", (int) ntohs(packet.session)); parsePacket(&packet, parseLogErrs, NULL); sendPADT(conn, "Received PADT from peer"); exit(EXIT_SUCCESS); } #endif /* USE_BPF */ /********************************************************************** *%FUNCTION: session *%ARGUMENTS: * conn -- PPPoE connection info *%RETURNS: * Nothing *%DESCRIPTION: * Handles the "session" phase of PPPoE ***********************************************************************/ void session(PPPoEConnection *conn) { fd_set readable; PPPoEPacket packet; struct timeval tv; struct timeval *tvp = NULL; int maxFD = 0; int r; /* Drop privileges */ dropPrivs(); /* Prepare for select() */ if (conn->sessionSocket > maxFD) maxFD = conn->sessionSocket; if (conn->discoverySocket > maxFD) maxFD = conn->discoverySocket; maxFD++; /* Fill in the constant fields of the packet to save time */ memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN); memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); packet.ethHdr.h_proto = htons(Eth_PPPOE_Session); packet.vertype = PPPOE_VER_TYPE(1, 1); packet.code = CODE_SESS; packet.session = conn->session; initPPP(); #ifdef USE_BPF /* check for buffered session data */ while (BPF_BUFFER_HAS_DATA) { if (conn->synchronous) { syncReadFromEth(conn, conn->sessionSocket, optClampMSS); } else { asyncReadFromEth(conn, conn->sessionSocket, optClampMSS); } } #endif for (;;) { if (optInactivityTimeout > 0) { tv.tv_sec = optInactivityTimeout; tv.tv_usec = 0; tvp = &tv; } FD_ZERO(&readable); FD_SET(0, &readable); /* ppp packets come from stdin */ if (conn->discoverySocket >= 0) { FD_SET(conn->discoverySocket, &readable); } FD_SET(conn->sessionSocket, &readable); while(1) { r = select(maxFD, &readable, NULL, NULL, tvp); if (r >= 0 || errno != EINTR) break; } if (r < 0) { fatalSys("select (session)"); } if (r == 0) { /* Inactivity timeout */ syslog(LOG_ERR, "Inactivity timeout... something wicked happened on session %d", (int) ntohs(conn->session)); sendPADT(conn, "RP-PPPoE: Inactivity timeout"); exit(EXIT_FAILURE); } /* Handle ready sockets */ if (FD_ISSET(0, &readable)) { if (conn->synchronous) { syncReadFromPPP(conn, &packet); } else { asyncReadFromPPP(conn, &packet); } } if (FD_ISSET(conn->sessionSocket, &readable)) { do { if (conn->synchronous) { syncReadFromEth(conn, conn->sessionSocket, optClampMSS); } else { asyncReadFromEth(conn, conn->sessionSocket, optClampMSS); } } while (BPF_BUFFER_HAS_DATA); } #ifndef USE_BPF /* BSD uses a single socket, see *syncReadFromEth() */ /* for calls to sessionDiscoveryPacket() */ if (conn->discoverySocket >= 0) { if (FD_ISSET(conn->discoverySocket, &readable)) { sessionDiscoveryPacket(conn); } } #endif } } /*********************************************************************** *%FUNCTION: sigPADT *%ARGUMENTS: * src -- signal received *%RETURNS: * Nothing *%DESCRIPTION: * If an established session exists send PADT to terminate from session * from our end ***********************************************************************/ static void sigPADT(int src) { syslog(LOG_DEBUG,"Received signal %d on session %d.", (int)src, (int) ntohs(Connection->session)); sendPADTf(Connection, "RP-PPPoE: Received signal %d", src); exit(EXIT_SUCCESS); } /********************************************************************** *%FUNCTION: usage *%ARGUMENTS: * argv0 -- program name *%RETURNS: * Nothing *%DESCRIPTION: * Prints usage information and exits. ***********************************************************************/ void usage(char const *argv0) { fprintf(stderr, "Usage: %s [options]\n", argv0); fprintf(stderr, "Options:\n"); #ifdef USE_BPF fprintf(stderr, " -I if_name -- Specify interface (REQUIRED)\n"); #else fprintf(stderr, " -I if_name -- Specify interface (default %s.)\n", DEFAULT_IF); #endif #ifdef DEBUGGING_ENABLED fprintf(stderr, " -D filename -- Log debugging information in filename.\n"); #endif fprintf(stderr, " -T timeout -- Specify inactivity timeout in seconds.\n" " -t timeout -- Initial timeout for discovery packets in seconds\n" " -V -- Print version and exit.\n" " -A -- Print access concentrator names and exit.\n" " -S name -- Set desired service name.\n" " -C name -- Set desired access concentrator name.\n" " -U -- Use Host-Unique to allow multiple PPPoE sessions.\n" " -W value -- Use Host-Unique set to 'value' specifically.\n" " -s -- Use synchronous PPP encapsulation.\n" " -m MSS -- Clamp incoming and outgoing MSS options.\n" " -p pidfile -- Write process-ID to pidfile.\n" " -e sess:mac -- Skip discovery phase; use existing session.\n" " -n -- Do not open discovery socket.\n" " -k -- Kill a session with PADT (requires -e)\n" " -d -- Perform discovery, print session info and exit.\n" " -f disc:sess -- Set Ethernet frame types (hex).\n" " -h -- Print usage information.\n\n" "RP-PPPoE Version %s, Copyright (C) 2001-2018 Roaring Penguin Software Inc.\n" " %*s Copyright (C) 2018-2021 Dianne Skoll\n" "RP-PPPoE comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it under the terms\n" "of the GNU General Public License, version 2 or any later version.\n" "https://dianne.skoll.ca/projects/rp-pppoe/\n", RP_VERSION, (int) strlen(RP_VERSION), ""); exit(EXIT_SUCCESS); } /********************************************************************** *%FUNCTION: main *%ARGUMENTS: * argc, argv -- count and values of command-line arguments *%RETURNS: * Nothing *%DESCRIPTION: * Main program ***********************************************************************/ int main(int argc, char *argv[]) { int opt; int n; unsigned int m[6]; /* MAC address in -e option */ unsigned int s; /* Temporary to hold session */ FILE *pidfile; unsigned int discoveryType, sessionType; char const *options; PPPoEConnection conn; #ifdef HAVE_N_HDLC int disc = N_HDLC; long flags; #endif if (getuid() != geteuid() || getgid() != getegid()) { IsSetID = 1; } /* Initialize connection info */ memset(&conn, 0, sizeof(conn)); conn.discoverySocket = -1; conn.sessionSocket = -1; conn.discoveryTimeout = PADI_TIMEOUT; /* For signal handler */ Connection = &conn; /* Initialize syslog */ openlog("pppoe", LOG_PID, LOG_DAEMON); #ifdef DEBUGGING_ENABLED options = "I:VAT:D:hS:C:UW:sm:np:e:kdf:F:t:"; #else options = "I:VAT:hS:C:UW:sm:np:e:kdf:F:t:"; #endif while((opt = getopt(argc, argv, options)) != -1) { switch(opt) { case 't': if (sscanf(optarg, "%d", &conn.discoveryTimeout) != 1) { fprintf(stderr, "Illegal argument to -t: Should be -t timeout\n"); exit(EXIT_FAILURE); } if (conn.discoveryTimeout < 1) { conn.discoveryTimeout = 1; } break; case 'F': if (sscanf(optarg, "%d", &optFloodDiscovery) != 1) { fprintf(stderr, "Illegal argument to -F: Should be -F numFloods\n"); exit(EXIT_FAILURE); } if (optFloodDiscovery < 1) optFloodDiscovery = 1; fprintf(stderr, "WARNING: DISCOVERY FLOOD IS MEANT FOR STRESS-TESTING\n" "A PPPOE SERVER WHICH YOU OWN. DO NOT USE IT AGAINST\n" "A REAL ISP. YOU HAVE 5 SECONDS TO ABORT.\n"); sleep(5); break; case 'f': if (sscanf(optarg, "%x:%x", &discoveryType, &sessionType) != 2) { fprintf(stderr, "Illegal argument to -f: Should be disc:sess in hex\n"); exit(EXIT_FAILURE); } Eth_PPPOE_Discovery = (UINT16_t) discoveryType; Eth_PPPOE_Session = (UINT16_t) sessionType; break; case 'd': optSkipSession = 1; break; case 'k': conn.killSession = 1; break; case 'n': /* Do not even open a discovery socket -- used when invoked by pppoe-server */ conn.noDiscoverySocket = 1; break; case 'e': /* Existing session: "sess:xx:yy:zz:aa:bb:cc" where "sess" is session-ID, and xx:yy:zz:aa:bb:cc is MAC-address of peer */ n = sscanf(optarg, "%u:%2x:%2x:%2x:%2x:%2x:%2x", &s, &m[0], &m[1], &m[2], &m[3], &m[4], &m[5]); if (n != 7) { fprintf(stderr, "Illegal argument to -e: Should be sess:xx:yy:zz:aa:bb:cc\n"); exit(EXIT_FAILURE); } /* Copy MAC address of peer */ for (n=0; n<6; n++) { conn.peerEth[n] = (unsigned char) m[n]; } /* Convert session */ conn.session = htons(s); /* Skip discovery phase! */ conn.skipDiscovery = 1; break; case 'p': switchToRealID(); pidfile = fopen(optarg, "w"); if (pidfile) { fprintf(pidfile, "%lu\n", (unsigned long) getpid()); fclose(pidfile); } switchToEffectiveID(); break; case 'S': SET_STRING(conn.serviceName, optarg); break; case 'C': SET_STRING(conn.acName, optarg); break; case 's': conn.synchronous = 1; break; case 'U': if (conn.hostUniq) { fprintf(stderr, "-U and -W are mutually-exclusive and may only be used once.\n"); exit(EXIT_FAILURE); } /* Allows for a 64-bit PID */ conn.hostUniq = malloc(17); if (!conn.hostUniq) { fprintf(stderr, "Out of memory.\n"); exit(EXIT_FAILURE); } sprintf(conn.hostUniq, "%lx", (unsigned long) getpid()); break; case 'W': if (conn.hostUniq) { fprintf(stderr, "-U and -W are mutually-exclusive and may only be used once.\n"); exit(EXIT_FAILURE); } SET_STRING(conn.hostUniq, optarg); break; #ifdef DEBUGGING_ENABLED case 'D': switchToRealID(); conn.debugFile = fopen(optarg, "w"); switchToEffectiveID(); if (!conn.debugFile) { fprintf(stderr, "Could not open %s: %s\n", optarg, strerror(errno)); exit(EXIT_FAILURE); } fprintf(conn.debugFile, "rp-pppoe-%s\n", RP_VERSION); fflush(conn.debugFile); break; #endif case 'T': optInactivityTimeout = (int) strtol(optarg, NULL, 10); if (optInactivityTimeout < 0) { optInactivityTimeout = 0; } break; case 'm': optClampMSS = (int) strtol(optarg, NULL, 10); if (optClampMSS < 536) { fprintf(stderr, "-m: %d is too low (min 536)\n", optClampMSS); exit(EXIT_FAILURE); } if (optClampMSS > 1452) { fprintf(stderr, "-m: %d is too high (max 1452)\n", optClampMSS); exit(EXIT_FAILURE); } break; case 'I': SET_STRING(conn.ifName, optarg); break; case 'V': printf("RP-PPPoE Version %s\n", RP_VERSION); exit(EXIT_SUCCESS); case 'A': conn.printACNames = 1; break; case 'h': usage(argv[0]); break; default: usage(argv[0]); } } /* Pick a default interface name */ if (!conn.ifName) { #ifdef USE_BPF fprintf(stderr, "No interface specified (-I option)\n"); exit(EXIT_FAILURE); #else SET_STRING(conn.ifName, DEFAULT_IF); #endif } if (!conn.printACNames) { #ifdef HAVE_N_HDLC if (conn.synchronous) { if (ioctl(0, TIOCSETD, &disc) < 0) { printErr("Unable to set line discipline to N_HDLC. Make sure your kernel supports the N_HDLC line discipline, or do not use the SYNCHRONOUS option. Quitting."); exit(EXIT_FAILURE); } else { syslog(LOG_INFO, "Changed pty line discipline to N_HDLC for synchronous mode"); } /* There is a bug in Linux's select which returns a descriptor * as readable if N_HDLC line discipline is on, even if * it isn't really readable. This return happens only when * select() times out. To avoid blocking forever in read(), * make descriptor 0 non-blocking */ flags = fcntl(0, F_GETFL); if (flags < 0) fatalSys("fcntl(F_GETFL)"); if (fcntl(0, F_SETFL, (long) flags | O_NONBLOCK) < 0) { fatalSys("fcntl(F_SETFL)"); } } #endif } if (optFloodDiscovery) { for (n=0; n < optFloodDiscovery; n++) { if (conn.printACNames) { fprintf(stderr, "Sending discovery flood %d\n", n+1); } conn.discoverySocket = openInterface(conn.ifName, Eth_PPPOE_Discovery, conn.myEth, NULL); discovery(&conn); conn.discoveryState = STATE_SENT_PADI; close(conn.discoverySocket); } exit(EXIT_SUCCESS); } /* Open session socket before discovery phase, to avoid losing session */ /* packets sent by peer just after PADS packet (noted on some Cisco */ /* server equipment). */ /* Opening this socket just before waitForPADS in the discovery() */ /* function would be more appropriate, but it would mess-up the code */ if (!optSkipSession) conn.sessionSocket = openInterface(conn.ifName, Eth_PPPOE_Session, conn.myEth, NULL); /* Skip discovery and don't open discovery socket? */ if (conn.skipDiscovery && conn.noDiscoverySocket) { conn.discoveryState = STATE_SESSION; } else { conn.discoverySocket = openInterface(conn.ifName, Eth_PPPOE_Discovery, conn.myEth, NULL); discovery(&conn); } if (optSkipSession) { printf("%u:%02x:%02x:%02x:%02x:%02x:%02x\n", ntohs(conn.session), conn.peerEth[0], conn.peerEth[1], conn.peerEth[2], conn.peerEth[3], conn.peerEth[4], conn.peerEth[5]); exit(EXIT_SUCCESS); } /* Set signal handlers: send PADT on HUP, TERM and INT */ signal(SIGTERM, sigPADT); signal(SIGINT, sigPADT); signal(SIGHUP, sigPADT); session(&conn); return 0; } /********************************************************************** *%FUNCTION: fatalSys *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to stderr and syslog and exits. ***********************************************************************/ void fatalSys(char const *str) { char buf[1024]; sprintf(buf, "%.256s: Session %d: %.256s", str, (int) ntohs(Connection->session), strerror(errno)); printErr(buf); sendPADTf(Connection, "RP-PPPoE: System call error: %s", strerror(errno)); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: sysErr *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to syslog. ***********************************************************************/ void sysErr(char const *str) { char buf[1024]; sprintf(buf, "%.256s: %.256s", str, strerror(errno)); printErr(buf); } /********************************************************************** *%FUNCTION: rp_fatal *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message to stderr and syslog and exits. ***********************************************************************/ void rp_fatal(char const *str) { printErr(str); sendPADTf(Connection, "RP-PPPoE: Session %d: %.256s", (int) ntohs(Connection->session), str); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: asyncReadFromEth *%ARGUMENTS: * conn -- PPPoE connection info * sock -- Ethernet socket * clampMss -- if non-zero, do MSS-clamping *%RETURNS: * Nothing *%DESCRIPTION: * Reads a packet from the Ethernet interface and sends it to async PPP * device. ***********************************************************************/ void asyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss) { PPPoEPacket packet; int len; int plen; int i; unsigned char pppBuf[4096]; unsigned char *ptr = pppBuf; unsigned char c; UINT16_t fcs; unsigned char header[2] = {FRAME_ADDR, FRAME_CTRL}; unsigned char tail[2]; #ifdef USE_BPF int type; #endif if (receivePacket(sock, &packet, &len) < 0) { return; } /* Check length */ if (ntohs(packet.length) + HDR_SIZE > len) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); return; } #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "RCVD"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif #ifdef USE_BPF /* Make sure this is a session packet before processing further */ type = etherType(&packet); if (type == Eth_PPPOE_Discovery) { sessionDiscoveryPacket(&packet); } else if (type != Eth_PPPOE_Session) { return; } #endif /* Sanity check */ if (packet.code != CODE_SESS) { syslog(LOG_ERR, "Unexpected packet code %d", (int) packet.code); return; } if (PPPOE_VER(packet.vertype) != 1) { syslog(LOG_ERR, "Unexpected packet version %d", PPPOE_VER(packet.vertype)); return; } if (PPPOE_TYPE(packet.vertype) != 1) { syslog(LOG_ERR, "Unexpected packet type %d", PPPOE_TYPE(packet.vertype)); return; } if (memcmp(packet.ethHdr.h_dest, conn->myEth, ETH_ALEN)) { return; } if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) { /* Not for us -- must be another session. This is not an error, so don't log anything. */ return; } if (packet.session != conn->session) { /* Not for us -- must be another session. This is not an error, so don't log anything. */ return; } plen = ntohs(packet.length); if (plen + HDR_SIZE > len) { syslog(LOG_ERR, "Bogus length field in session packet %d (%d)", (int) plen, (int) len); return; } /* Clamp MSS */ if (clampMss) { clampMSS(&packet, "incoming", clampMss); } /* Compute FCS */ fcs = pppFCS16(PPPINITFCS16, header, 2); fcs = pppFCS16(fcs, packet.payload, plen) ^ 0xffff; tail[0] = fcs & 0x00ff; tail[1] = (fcs >> 8) & 0x00ff; /* Build a buffer to send to PPP */ *ptr++ = FRAME_FLAG; *ptr++ = FRAME_ADDR; *ptr++ = FRAME_ESC; *ptr++ = FRAME_CTRL ^ FRAME_ENC; for (i=0; i len) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); return; } #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "RCVD"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif #ifdef USE_BPF /* Make sure this is a session packet before processing further */ type = etherType(&packet); if (type == Eth_PPPOE_Discovery) { sessionDiscoveryPacket(&packet); } else if (type != Eth_PPPOE_Session) { return; } #endif /* Sanity check */ if (packet.code != CODE_SESS) { syslog(LOG_ERR, "Unexpected packet code %d", (int) packet.code); return; } if (PPPOE_VER(packet.vertype) != 1) { syslog(LOG_ERR, "Unexpected packet version %d", PPPOE_VER(packet.vertype)); return; } if (PPPOE_TYPE(packet.vertype) != 1) { syslog(LOG_ERR, "Unexpected packet type %d", PPPOE_TYPE(packet.vertype)); return; } if (memcmp(packet.ethHdr.h_dest, conn->myEth, ETH_ALEN)) { /* Not for us -- must be another session. This is not an error, so don't log anything. */ return; } if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) { /* Not for us -- must be another session. This is not an error, so don't log anything. */ return; } if (packet.session != conn->session) { /* Not for us -- must be another session. This is not an error, so don't log anything. */ return; } plen = ntohs(packet.length); if (plen + HDR_SIZE > len) { syslog(LOG_ERR, "Bogus length field in session packet %d (%d)", (int) plen, (int) len); return; } /* Clamp MSS */ if (clampMss) { clampMSS(&packet, "incoming", clampMss); } /* Ship it out */ vec[0].iov_base = (void *) dummy; dummy[0] = FRAME_ADDR; dummy[1] = FRAME_CTRL; vec[0].iov_len = 2; vec[1].iov_base = (void *) packet.payload; vec[1].iov_len = plen; if (writev(1, vec, 2) < 0) { fatalSys("syncReadFromEth: write"); } } rp-pppoe-3.15/src/debug.c0000644000175000017500000000777114045237010013347 0ustar dfsdfs/*********************************************************************** * * debug.c * * Implementation of user-space PPPoE redirector for Linux. * * Functions for printing debugging information * * Copyright (C) 2000 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #include "pppoe.h" #ifdef DEBUGGING_ENABLED #include #include #include #include /********************************************************************** *%FUNCTION: dumpHex *%ARGUMENTS: * fp -- file to dump to * buf -- buffer to dump * len -- length of data *%RETURNS: * Nothing *%DESCRIPTION: * Dumps buffer to fp in an easy-to-read format ***********************************************************************/ void dumpHex(FILE *fp, unsigned char const *buf, int len) { int i; int base; if (!fp) return; /* do NOT dump PAP packets */ if (len >= 2 && buf[0] == 0xC0 && buf[1] == 0x23) { fprintf(fp, "(PAP Authentication Frame -- Contents not dumped)\n"); return; } for (base=0; baselength); /* Sheesh... printing times is a pain... */ struct timeval tv; time_t now; int millisec; struct tm *lt; char timebuf[256]; UINT16_t type = etherType(packet); if (!fp) return; gettimeofday(&tv, NULL); now = (time_t) tv.tv_sec; millisec = tv.tv_usec / 1000; lt = localtime(&now); strftime(timebuf, 256, "%H:%M:%S", lt); fprintf(fp, "%s.%03d %s PPPoE ", timebuf, millisec, dir); if (type == Eth_PPPOE_Discovery) { fprintf(fp, "Discovery (%x) ", (unsigned) type); } else if (type == Eth_PPPOE_Session) { fprintf(fp, "Session (%x) ", (unsigned) type); } else { fprintf(fp, "Unknown (%x) ", (unsigned) type); } switch(packet->code) { case CODE_PADI: fprintf(fp, "PADI "); break; case CODE_PADO: fprintf(fp, "PADO "); break; case CODE_PADR: fprintf(fp, "PADR "); break; case CODE_PADS: fprintf(fp, "PADS "); break; case CODE_PADT: fprintf(fp, "PADT "); break; case CODE_PADM: fprintf(fp, "PADM "); break; case CODE_PADN: fprintf(fp, "PADN "); break; case CODE_SESS: fprintf(fp, "SESS "); break; } fprintf(fp, "sess-id %d length %d\n", (int) ntohs(packet->session), len); /* Ugly... I apologize... */ fprintf(fp, "SourceAddr %02x:%02x:%02x:%02x:%02x:%02x " "DestAddr %02x:%02x:%02x:%02x:%02x:%02x\n", (unsigned) packet->ethHdr.h_source[0], (unsigned) packet->ethHdr.h_source[1], (unsigned) packet->ethHdr.h_source[2], (unsigned) packet->ethHdr.h_source[3], (unsigned) packet->ethHdr.h_source[4], (unsigned) packet->ethHdr.h_source[5], (unsigned) packet->ethHdr.h_dest[0], (unsigned) packet->ethHdr.h_dest[1], (unsigned) packet->ethHdr.h_dest[2], (unsigned) packet->ethHdr.h_dest[3], (unsigned) packet->ethHdr.h_dest[4], (unsigned) packet->ethHdr.h_dest[5]); dumpHex(fp, packet->payload, ntohs(packet->length)); } #endif /* DEBUGGING_ENABLED */ rp-pppoe-3.15/src/pppoe.h0000644000175000017500000002551014045237010013400 0ustar dfsdfs/*********************************************************************** * * pppoe.h * * Declaration of various PPPoE constants * * Copyright (C) 2000-2012 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * * $Id$ * ***********************************************************************/ #include "config.h" extern int IsSetID; #if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H) #define _POSIX_SOURCE 1 /* For sigaction defines */ #endif #include /* For FILE */ #include /* For pid_t */ /* How do we access raw Ethernet devices? */ #undef USE_LINUX_PACKET #undef USE_BPF #if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H) #define USE_LINUX_PACKET 1 #elif defined(HAVE_SYS_DLPI_H) #define USE_DLPI #elif defined(HAVE_NET_BPF_H) #define USE_BPF 1 #endif /* Sanity check */ #if !defined(USE_BPF) && !defined(USE_LINUX_PACKET) && !defined(USE_DLPI) #error Unknown method for accessing raw Ethernet frames #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NET_IF_TYPES_H #include #endif #ifdef HAVE_NET_IF_DL_H #include #endif /* I'm not sure why this is needed... I do not have OpenBSD */ #if defined(__OpenBSD__) #include #include #endif #ifdef USE_BPF extern int bpfSize; struct PPPoEPacketStruct; void sessionDiscoveryPacket(struct PPPoEPacketStruct *packet); #define BPF_BUFFER_IS_EMPTY (bpfSize <= 0) #define BPF_BUFFER_HAS_DATA (bpfSize > 0) #define ethhdr ether_header #define h_dest ether_dhost #define h_source ether_shost #define h_proto ether_type #define ETH_DATA_LEN ETHERMTU #define ETH_ALEN ETHER_ADDR_LEN #else #undef USE_BPF #define BPF_BUFFER_IS_EMPTY 1 #define BPF_BUFFER_HAS_DATA 0 #endif #ifdef USE_DLPI #include #define ethhdr ether_header #define ETH_DATA_LEN ETHERMTU #define ETH_ALEN ETHERADDRL #define h_dest ether_dhost.ether_addr_octet #define h_source ether_shost.ether_addr_octet #define h_proto ether_type /* cloned from dltest.h */ #define MAXDLBUF 8192 #define MAXDLADDR 1024 #define MAXWAIT 15 #define OFFADDR(s, n) (u_char*)((char*)(s) + (int)(n)) #define CASERET(s) case s: return ("s") #endif /* Define various integer types -- assumes a char is 8 bits */ #if SIZEOF_UNSIGNED_SHORT == 2 typedef unsigned short UINT16_t; #elif SIZEOF_UNSIGNED_INT == 2 typedef unsigned int UINT16_t; #else #error Could not find a 16-bit integer type #endif #if SIZEOF_UNSIGNED_SHORT == 4 typedef unsigned short UINT32_t; #elif SIZEOF_UNSIGNED_INT == 4 typedef unsigned int UINT32_t; #elif SIZEOF_UNSIGNED_LONG == 4 typedef unsigned long UINT32_t; #else #error Could not find a 32-bit integer type #endif #ifdef HAVE_LINUX_IF_ETHER_H #include #endif #include #ifdef HAVE_NETINET_IF_ETHER_H #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifndef HAVE_SYS_DLPI_H #include #endif #endif /* Ethernet frame types according to RFC 2516 */ #define ETH_PPPOE_DISCOVERY 0x8863 #define ETH_PPPOE_SESSION 0x8864 /* But some brain-dead peers disobey the RFC, so frame types are variables */ extern UINT16_t Eth_PPPOE_Discovery; extern UINT16_t Eth_PPPOE_Session; extern void switchToRealID(void); extern void switchToEffectiveID(void); extern void dropPrivs(void); /* PPPoE codes */ #define CODE_PADI 0x09 #define CODE_PADO 0x07 #define CODE_PADR 0x19 #define CODE_PADS 0x65 #define CODE_PADT 0xA7 /* Extensions from draft-carrel-info-pppoe-ext-00 */ /* I do NOT like PADM or PADN, but they are here for completeness */ #define CODE_PADM 0xD3 #define CODE_PADN 0xD4 #define CODE_SESS 0x00 /* PPPoE Tags */ #define TAG_END_OF_LIST 0x0000 #define TAG_SERVICE_NAME 0x0101 #define TAG_AC_NAME 0x0102 #define TAG_HOST_UNIQ 0x0103 #define TAG_AC_COOKIE 0x0104 #define TAG_VENDOR_SPECIFIC 0x0105 #define TAG_RELAY_SESSION_ID 0x0110 #define TAG_PPP_MAX_PAYLOAD 0x0120 #define TAG_SERVICE_NAME_ERROR 0x0201 #define TAG_AC_SYSTEM_ERROR 0x0202 #define TAG_GENERIC_ERROR 0x0203 /* Extensions from draft-carrel-info-pppoe-ext-00 */ /* I do NOT like these tags one little bit */ #define TAG_HURL 0x111 #define TAG_MOTM 0x112 #define TAG_IP_ROUTE_ADD 0x121 /* Discovery phase states */ #define STATE_SENT_PADI 0 #define STATE_RECEIVED_PADO 1 #define STATE_SENT_PADR 2 #define STATE_SESSION 3 #define STATE_TERMINATED 4 /* How many PADI/PADS attempts? */ #define MAX_PADI_ATTEMPTS 3 /* Initial timeout for PADO/PADS */ #define PADI_TIMEOUT 5 /* States for scanning PPP frames */ #define STATE_WAITFOR_FRAME_ADDR 0 #define STATE_DROP_PROTO 1 #define STATE_BUILDING_PACKET 2 /* Special PPP frame characters */ #define FRAME_ESC 0x7D #define FRAME_FLAG 0x7E #define FRAME_ADDR 0xFF #define FRAME_CTRL 0x03 #define FRAME_ENC 0x20 #define IPV4ALEN 4 #define SMALLBUF 256 /* Allow for 1500-byte PPPoE data which makes the Ethernet packet size bigger by 8 bytes */ #define ETH_JUMBO_LEN (ETH_DATA_LEN+8) /* A PPPoE Packet, including Ethernet headers */ typedef struct PPPoEPacketStruct { struct ethhdr ethHdr; /* Ethernet header */ unsigned int vertype:8; /* PPPoE Version (high nibble) and Type (low nibble) (must both be 1) */ unsigned int code:8; /* PPPoE code */ unsigned int session:16; /* PPPoE session */ unsigned int length:16; /* Payload length */ unsigned char payload[ETH_JUMBO_LEN]; /* A bit of room to spare */ } PPPoEPacket; #define PPPOE_VER(vt) ((vt) >> 4) #define PPPOE_TYPE(vt) ((vt) & 0xf) #define PPPOE_VER_TYPE(v, t) (((v) << 4) | (t)) /* Header size of a PPPoE packet */ #define PPPOE_OVERHEAD 6 /* type, code, session, length */ #define HDR_SIZE (sizeof(struct ethhdr) + PPPOE_OVERHEAD) #define MAX_PPPOE_PAYLOAD (ETH_JUMBO_LEN - PPPOE_OVERHEAD) #define PPP_OVERHEAD 2 #define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - PPP_OVERHEAD) #define TOTAL_OVERHEAD (PPPOE_OVERHEAD + PPP_OVERHEAD) /* Normal PPPoE MTU without jumbo frames */ #define ETH_PPPOE_MTU (ETH_DATA_LEN - TOTAL_OVERHEAD) /* PPPoE Tag */ typedef struct PPPoETagStruct { unsigned int type:16; /* tag type */ unsigned int length:16; /* Length of payload */ unsigned char payload[ETH_JUMBO_LEN]; /* A LOT of room to spare */ } PPPoETag; /* Header size of a PPPoE tag */ #define TAG_HDR_SIZE 4 /* Chunk to read from stdin */ #define READ_CHUNK 4096 /* Function passed to parsePacket */ typedef void ParseFunc(UINT16_t type, UINT16_t len, unsigned char *data, void *extra); #define PPPINITFCS16 0xffff /* Initial FCS value */ /* Keep track of the state of a connection -- collect everything in one spot */ typedef struct PPPoEConnectionStruct { int discoveryState; /* Where we are in discovery */ int discoverySocket; /* Raw socket for discovery frames */ int sessionSocket; /* Raw socket for session frames */ unsigned char myEth[ETH_ALEN]; /* My MAC address */ unsigned char peerEth[ETH_ALEN]; /* Peer's MAC address */ #ifdef PLUGIN unsigned char req_peer_mac[ETH_ALEN]; /* required peer MAC address */ unsigned char req_peer; /* require mac addr to match req_peer_mac */ #endif UINT16_t session; /* Session ID */ char *ifName; /* Interface name */ char *serviceName; /* Desired service name, if any */ char *acName; /* Desired AC name, if any */ int synchronous; /* Use synchronous PPP */ char *hostUniq; /* Host-Uniq tag, if any */ int printACNames; /* Just print AC names */ int skipDiscovery; /* Skip discovery */ int noDiscoverySocket; /* Don't even open discovery socket */ int killSession; /* Kill session and exit */ FILE *debugFile; /* Debug file for dumping packets */ int numPADOs; /* Number of PADO packets received */ PPPoETag cookie; /* We have to send this if we get it */ PPPoETag relayId; /* Ditto */ int PADSHadError; /* If PADS had an error tag */ int discoveryTimeout; /* Timeout for discovery packets */ #ifdef PLUGIN int seenMaxPayload; int mtu; int mru; #endif } PPPoEConnection; /* Structure used to determine acceptable PADO or PADS packet */ struct PacketCriteria { PPPoEConnection *conn; int acNameOK; int serviceNameOK; int seenACName; int seenServiceName; int gotError; }; /* Function Prototypes */ UINT16_t etherType(PPPoEPacket *packet); int openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr, UINT16_t *mtu); int sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size); int receivePacket(int sock, PPPoEPacket *pkt, int *size); void fatalSys(char const *str); void rp_fatal(char const *str); void printErr(char const *str); void sysErr(char const *str); #ifdef DEBUGGING_ENABLED void dumpPacket(FILE *fp, PPPoEPacket *packet, char const *dir); void dumpHex(FILE *fp, unsigned char const *buf, int len); #endif int parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra); void parseLogErrs(UINT16_t typ, UINT16_t len, unsigned char *data, void *xtra); void pktLogErrs(char const *pkt, UINT16_t typ, UINT16_t len, unsigned char *data, void *xtra); void syncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet); void asyncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet); void asyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss); void syncReadFromEth(PPPoEConnection *conn, int sock, int clampMss); void sendPADT(PPPoEConnection *conn, char const *msg); void sendPADTf(PPPoEConnection *conn, char const *fmt, ...); void sendSessionPacket(PPPoEConnection *conn, PPPoEPacket *packet, int len); void initPPP(void); void clampMSS(PPPoEPacket *packet, char const *dir, int clampMss); UINT16_t computeTCPChecksum(unsigned char *ipHdr, unsigned char *tcpHdr); UINT16_t pppFCS16(UINT16_t fcs, unsigned char *cp, int len); void discovery(PPPoEConnection *conn); unsigned char *findTag(PPPoEPacket *packet, UINT16_t tagType, PPPoETag *tag); #ifndef HAVE_STRLCPY size_t strlcpy(char *dst, const char *src, size_t size); #endif #define SET_STRING(var, val) do { if (var) free(var); var = strdup(val); if (!var) rp_fatal("strdup failed"); } while(0); #define CHECK_ROOM(cursor, start, len) \ do {\ if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \ syslog(LOG_ERR, "Would create too-long packet"); \ return; \ } \ } while(0) /* True if Ethernet address is broadcast or multicast */ #define NOT_UNICAST(e) ((e[0] & 0x01) != 0) #define BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) == 0xFF) #define NOT_BROADCAST(e) ((e[0] & e[1] & e[2] & e[3] & e[4] & e[5]) != 0xFF) rp-pppoe-3.15/src/install-sh0000755000175000017500000001124514045237010014110 0ustar dfsdfs#! /bin/sh # # install - install a program, script, or datafile # This comes from X11R5. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. # # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 rp-pppoe-3.15/src/relay.c0000644000175000017500000013036014045237010013364 0ustar dfsdfs/*********************************************************************** * * relay.c * * Implementation of PPPoE relay * * Copyright (C) 2001-2018 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * * $Id$ * ***********************************************************************/ #define _GNU_SOURCE 1 /* For SA_RESTART */ #include "config.h" #include #if defined(HAVE_LINUX_IF_H) #include #elif defined(HAVE_NET_IF_H) #include #endif #include #include "relay.h" #ifdef HAVE_SYSLOG_H #include #endif #ifdef HAVE_GETOPT_H #include #endif #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_UIO_H #include #endif #ifdef HAVE_UNISTD_H #include #endif /* Interfaces (max MAX_INTERFACES) */ PPPoEInterface Interfaces[MAX_INTERFACES]; int NumInterfaces; /* Relay info */ int NumSessions; int MaxSessions; PPPoESession *AllSessions; PPPoESession *FreeSessions; PPPoESession *ActiveSessions; SessionHash *AllHashes; SessionHash *FreeHashes; SessionHash *Buckets[HASHTAB_SIZE]; volatile unsigned int Epoch = 0; volatile unsigned int CleanCounter = 0; /* How often to clean up stale sessions? */ #define MIN_CLEAN_PERIOD 30 /* Minimum period to run cleaner */ #define TIMEOUT_DIVISOR 20 /* How often to run cleaner per timeout period */ unsigned int CleanPeriod = MIN_CLEAN_PERIOD; /* How long a session can be idle before it is cleaned up? */ unsigned int IdleTimeout = MIN_CLEAN_PERIOD * TIMEOUT_DIVISOR; /* Pipe for breaking select() to initiate periodic cleaning */ int CleanPipe[2]; /* Our relay: if_index followed by peer_mac */ #define MY_RELAY_TAG_LEN (sizeof(int) + ETH_ALEN) /* Hack for daemonizing */ #define CLOSEFD 64 /********************************************************************** *%FUNCTION: keepDescriptor *%ARGUMENTS: * fd -- a file descriptor *%RETURNS: * 1 if descriptor should NOT be closed during daemonizing; 0 otherwise. ***********************************************************************/ static int keepDescriptor(int fd) { int i; if (fd == CleanPipe[0] || fd == CleanPipe[1]) return 1; for (i=0; ipayload, tag, ntohs(tag->length) + TAG_HDR_SIZE); } /********************************************************************** *%FUNCTION: insertBytes *%ARGUMENTS: * packet -- a PPPoE packet * loc -- location at which to insert bytes of data * bytes -- the data to insert * len -- length of data to insert *%RETURNS: * -1 if no room in packet; len otherwise. *%DESCRIPTION: * Inserts "len" bytes of data at location "loc" in "packet", moving all * other data up to make room. ***********************************************************************/ int insertBytes(PPPoEPacket *packet, unsigned char *loc, void const *bytes, int len) { int toMove; int plen = ntohs(packet->length); /* Sanity checks */ if (loc < packet->payload || loc > packet->payload + plen || len + plen > MAX_PPPOE_PAYLOAD) { return -1; } toMove = (packet->payload + plen) - loc; memmove(loc+len, loc, toMove); memcpy(loc, bytes, len); packet->length = htons(plen + len); return len; } /********************************************************************** *%FUNCTION: removeBytes *%ARGUMENTS: * packet -- a PPPoE packet * loc -- location at which to remove bytes of data * len -- length of data to remove *%RETURNS: * -1 if there was a problem, len otherwise *%DESCRIPTION: * Removes "len" bytes of data from location "loc" in "packet", moving all * other data down to close the gap ***********************************************************************/ int removeBytes(PPPoEPacket *packet, unsigned char *loc, int len) { int toMove; int plen = ntohs(packet->length); /* Sanity checks */ if (len < 0 || len > plen || loc < packet->payload || loc + len > packet->payload + plen) { return -1; } toMove = ((packet->payload + plen) - loc) - len; memmove(loc, loc+len, toMove); packet->length = htons(plen - len); return len; } /********************************************************************** *%FUNCTION: usage *%ARGUMENTS: * argv0 -- program name *%RETURNS: * Nothing *%DESCRIPTION: * Prints usage information and exits. ***********************************************************************/ void usage(char const *argv0) { fprintf(stderr, "Usage: %s [options]\n", argv0); fprintf(stderr, "Options:\n"); fprintf(stderr, " -S if_name -- Specify interface for PPPoE Server\n"); fprintf(stderr, " -C if_name -- Specify interface for PPPoE Client\n"); fprintf(stderr, " -B if_name -- Specify interface for both clients and server\n"); fprintf(stderr, " -n nsess -- Maxmimum number of sessions to relay\n"); fprintf(stderr, " -i timeout -- Idle timeout in seconds (0 = no timeout)\n"); fprintf(stderr, " -F -- Do not fork into background\n"); fprintf(stderr, " -h -- Print this help message\n"); fprintf(stderr, "\nPPPoE Version %s, Copyright (C) 2001-2006 Roaring Penguin Software Inc.\n", RP_VERSION); fprintf(stderr, " %*s Copyright (C) 2018-2021 Dianne Skoll\n", (int) strlen(RP_VERSION), ""); fprintf(stderr, "PPPoE comes with ABSOLUTELY NO WARRANTY.\n"); fprintf(stderr, "This is free software, and you are welcome to redistribute it under the terms\n"); fprintf(stderr, "of the GNU General Public License, version 2 or any later version.\n"); fprintf(stderr, "https://dianne.skoll.ca/projects/rp-pppoe/\n"); exit(EXIT_SUCCESS); } /********************************************************************** *%FUNCTION: main *%ARGUMENTS: * argc, argv -- usual suspects *%RETURNS: * EXIT_SUCCESS or EXIT_FAILURE *%DESCRIPTION: * Main program. Options: * -C ifname -- Use interface for PPPoE clients * -S ifname -- Use interface for PPPoE servers * -B ifname -- Use interface for both clients and servers * -n sessions -- Maximum of "n" sessions ***********************************************************************/ int main(int argc, char *argv[]) { int opt; int nsess = DEFAULT_SESSIONS; struct sigaction sa; int beDaemon = 1; if (getuid() != geteuid() || getgid() != getegid()) { fprintf(stderr, "SECURITY WARNING: pppoe-relay will NOT run suid or sgid. Fix your installation.\n"); exit(1); } openlog("pppoe-relay", LOG_PID, LOG_DAEMON); while((opt = getopt(argc, argv, "hC:S:B:n:i:F")) != -1) { switch(opt) { case 'h': usage(argv[0]); break; case 'F': beDaemon = 0; break; case 'C': addInterface(optarg, 1, 0); break; case 'S': addInterface(optarg, 0, 1); break; case 'B': addInterface(optarg, 1, 1); break; case 'i': if (sscanf(optarg, "%u", &IdleTimeout) != 1) { fprintf(stderr, "Illegal argument to -i: should be -i timeout\n"); exit(EXIT_FAILURE); } CleanPeriod = IdleTimeout / TIMEOUT_DIVISOR; if (CleanPeriod < MIN_CLEAN_PERIOD) CleanPeriod = MIN_CLEAN_PERIOD; break; case 'n': if (sscanf(optarg, "%d", &nsess) != 1) { fprintf(stderr, "Illegal argument to -n: should be -n #sessions\n"); exit(EXIT_FAILURE); } if (nsess < 1 || nsess > 65534) { fprintf(stderr, "Illegal argument to -n: must range from 1 to 65534\n"); exit(EXIT_FAILURE); } break; default: usage(argv[0]); } } #ifdef USE_LINUX_PACKET #ifndef HAVE_STRUCT_SOCKADDR_LL fprintf(stderr, "The PPPoE relay does not work on Linux 2.0 kernels.\n"); exit(EXIT_FAILURE); #endif #endif /* Check that at least two interfaces were defined */ if (NumInterfaces < 2) { fprintf(stderr, "%s: Must define at least two interfaces\n", argv[0]); exit(EXIT_FAILURE); } /* Make a pipe for the cleaner */ if (pipe(CleanPipe) < 0) { fatalSys("pipe"); } /* Set up alarm handler */ sa.sa_handler = alarmHandler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGALRM, &sa, NULL) < 0) { fatalSys("sigaction"); } /* Allocate memory for sessions, etc. */ initRelay(nsess); /* Daemonize -- UNIX Network Programming, Vol. 1, Stevens */ if (beDaemon) { int i; i = fork(); if (i < 0) { fatalSys("fork"); } else if (i != 0) { /* parent */ exit(0); } setsid(); signal(SIGHUP, SIG_IGN); i = fork(); if (i < 0) { fatalSys("fork"); } else if (i != 0) { exit(0); } chdir("/"); closelog(); for (i=0; i= MAX_INTERFACES) { fprintf(stderr, "Too many interfaces (%d max)\n", MAX_INTERFACES); exit(EXIT_FAILURE); } i = &Interfaces[NumInterfaces++]; strncpy(i->name, ifname, IFNAMSIZ); i->name[IFNAMSIZ] = 0; i->discoverySock = openInterface(ifname, Eth_PPPOE_Discovery, i->mac, NULL); i->sessionSock = openInterface(ifname, Eth_PPPOE_Session, NULL, NULL); i->clientOK = clientOK; i->acOK = acOK; } /********************************************************************** *%FUNCTION: initRelay *%ARGUMENTS: * nsess -- maximum allowable number of sessions *%RETURNS: * Nothing *%DESCRIPTION: * Initializes relay hash table and session tables. ***********************************************************************/ void initRelay(int nsess) { int i; NumSessions = 0; MaxSessions = nsess; AllSessions = calloc(MaxSessions, sizeof(PPPoESession)); if (!AllSessions) { rp_fatal("Unable to allocate memory for PPPoE session table"); } AllHashes = calloc(MaxSessions*2, sizeof(SessionHash)); if (!AllHashes) { rp_fatal("Unable to allocate memory for PPPoE hash table"); } /* Initialize sessions in a linked list */ AllSessions[0].prev = NULL; if (MaxSessions > 1) { AllSessions[0].next = &AllSessions[1]; } else { AllSessions[0].next = NULL; } for (i=1; i 1) { AllSessions[MaxSessions-1].prev = &AllSessions[MaxSessions-2]; AllSessions[MaxSessions-1].next = NULL; } FreeSessions = AllSessions; ActiveSessions = NULL; /* Initialize session numbers which we hand out */ for (i=0; i= MaxSessions) { printErr("Maximum number of sessions reached -- cannot create new session"); return NULL; } /* Grab a free session */ sess = FreeSessions; FreeSessions = sess->next; NumSessions++; /* Link it to the active list */ sess->next = ActiveSessions; if (sess->next) { sess->next->prev = sess; } ActiveSessions = sess; sess->prev = NULL; sess->epoch = Epoch; /* Get two hash entries */ acHash = FreeHashes; cliHash = acHash->next; FreeHashes = cliHash->next; acHash->peer = cliHash; cliHash->peer = acHash; sess->acHash = acHash; sess->clientHash = cliHash; acHash->interface = ac; cliHash->interface = cli; memcpy(acHash->peerMac, acMac, ETH_ALEN); acHash->sesNum = acSes; acHash->ses = sess; memcpy(cliHash->peerMac, cliMac, ETH_ALEN); cliHash->sesNum = sess->sesNum; cliHash->ses = sess; addHash(acHash); addHash(cliHash); /* Log */ syslog(LOG_INFO, "Opened session: server=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d), client=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d)", acHash->peerMac[0], acHash->peerMac[1], acHash->peerMac[2], acHash->peerMac[3], acHash->peerMac[4], acHash->peerMac[5], acHash->interface->name, ntohs(acHash->sesNum), cliHash->peerMac[0], cliHash->peerMac[1], cliHash->peerMac[2], cliHash->peerMac[3], cliHash->peerMac[4], cliHash->peerMac[5], cliHash->interface->name, ntohs(cliHash->sesNum)); return sess; } /********************************************************************** *%FUNCTION: freeSession *%ARGUMENTS: * ses -- session to free * msg -- extra message to log on syslog. *%RETURNS: * Nothing *%DESCRIPTION: * Frees data used by a PPPoE session -- adds hashes and session back * to the free list ***********************************************************************/ void freeSession(PPPoESession *ses, char const *msg) { syslog(LOG_INFO, "Closed session: server=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d), client=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d): %s", ses->acHash->peerMac[0], ses->acHash->peerMac[1], ses->acHash->peerMac[2], ses->acHash->peerMac[3], ses->acHash->peerMac[4], ses->acHash->peerMac[5], ses->acHash->interface->name, ntohs(ses->acHash->sesNum), ses->clientHash->peerMac[0], ses->clientHash->peerMac[1], ses->clientHash->peerMac[2], ses->clientHash->peerMac[3], ses->clientHash->peerMac[4], ses->clientHash->peerMac[5], ses->clientHash->interface->name, ntohs(ses->clientHash->sesNum), msg); /* Unlink from active sessions */ if (ses->prev) { ses->prev->next = ses->next; } else { ActiveSessions = ses->next; } if (ses->next) { ses->next->prev = ses->prev; } /* Link onto free list -- this is a singly-linked list, so we do not care about prev */ ses->next = FreeSessions; FreeSessions = ses; unhash(ses->acHash); unhash(ses->clientHash); NumSessions--; } /********************************************************************** *%FUNCTION: unhash *%ARGUMENTS: * sh -- session hash to free *%RETURNS: * Nothing *%DESCRIPTION: * Frees a session hash -- takes it out of hash table and puts it on * free list. ***********************************************************************/ void unhash(SessionHash *sh) { unsigned int b = hash(sh->peerMac, sh->sesNum) % HASHTAB_SIZE; if (sh->prev) { sh->prev->next = sh->next; } else { Buckets[b] = sh->next; } if (sh->next) { sh->next->prev = sh->prev; } /* Add to free list (singly-linked) */ sh->next = FreeHashes; FreeHashes = sh; } /********************************************************************** *%FUNCTION: addHash *%ARGUMENTS: * sh -- a session hash *%RETURNS: * Nothing *%DESCRIPTION: * Adds a SessionHash to the hash table ***********************************************************************/ void addHash(SessionHash *sh) { unsigned int b = hash(sh->peerMac, sh->sesNum) % HASHTAB_SIZE; sh->next = Buckets[b]; sh->prev = NULL; if (sh->next) { sh->next->prev = sh; } Buckets[b] = sh; } /********************************************************************** *%FUNCTION: hash *%ARGUMENTS: * mac -- an Ethernet address * sesNum -- a session number *%RETURNS: * A hash value combining Ethernet address with session number. * Currently very simplistic; we may need to experiment with different * hash values. ***********************************************************************/ unsigned int hash(unsigned char const *mac, UINT16_t sesNum) { unsigned int ans1 = ((unsigned int) mac[0]) | (((unsigned int) mac[1]) << 8) | (((unsigned int) mac[2]) << 16) | (((unsigned int) mac[3]) << 24); unsigned int ans2 = ((unsigned int) sesNum) | (((unsigned int) mac[4]) << 16) | (((unsigned int) mac[5]) << 24); return ans1 ^ ans2; } /********************************************************************** *%FUNCTION: findSession *%ARGUMENTS: * mac -- an Ethernet address * sesNum -- a session number *%RETURNS: * The session hash for peer address "mac", session number sesNum ***********************************************************************/ SessionHash * findSession(unsigned char const *mac, UINT16_t sesNum) { unsigned int b = hash(mac, sesNum) % HASHTAB_SIZE; SessionHash *sh = Buckets[b]; while(sh) { if (!memcmp(mac, sh->peerMac, ETH_ALEN) && sesNum == sh->sesNum) { return sh; } sh = sh->next; } return NULL; } /********************************************************************** *%FUNCTION: fatalSys *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to stderr and syslog and exits. ***********************************************************************/ void fatalSys(char const *str) { char buf[1024]; sprintf(buf, "%.256s: %.256s", str, strerror(errno)); printErr(buf); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: sysErr *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to syslog. ***********************************************************************/ void sysErr(char const *str) { char buf[1024]; sprintf(buf, "%.256s: %.256s", str, strerror(errno)); printErr(buf); } /********************************************************************** *%FUNCTION: rp_fatal *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message to stderr and syslog and exits. ***********************************************************************/ void rp_fatal(char const *str) { printErr(str); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: relayLoop *%ARGUMENTS: * None *%RETURNS: * Nothing *%DESCRIPTION: * Runs the relay loop. This function never returns ***********************************************************************/ void relayLoop() { fd_set readable, readableCopy; int maxFD; int i, r; int sock; /* Build the select set */ FD_ZERO(&readable); maxFD = 0; for (i=0; i maxFD) maxFD = sock; FD_SET(sock, &readable); sock = Interfaces[i].sessionSock; if (sock > maxFD) maxFD = sock; FD_SET(sock, &readable); if (CleanPipe[0] > maxFD) maxFD = CleanPipe[0]; FD_SET(CleanPipe[0], &readable); } maxFD++; for(;;) { readableCopy = readable; for(;;) { r = select(maxFD, &readableCopy, NULL, NULL, NULL); if (r >= 0 || errno != EINTR) break; } if (r < 0) { sysErr("select (relayLoop)"); continue; } /* Handle session packets first */ for (i=0; idiscoverySock, &packet, &size) < 0) { return; } /* Ignore unknown code/version */ if (PPPOE_VER(packet.vertype) != 1 || PPPOE_TYPE(packet.vertype) != 1) { return; } /* Validate length */ if (ntohs(packet.length) + HDR_SIZE > size) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); return; } /* Drop Ethernet frame padding */ if (size > ntohs(packet.length) + HDR_SIZE) { size = ntohs(packet.length) + HDR_SIZE; } switch(packet.code) { case CODE_PADT: relayHandlePADT(iface, &packet, size); break; case CODE_PADI: relayHandlePADI(iface, &packet, size); break; case CODE_PADO: relayHandlePADO(iface, &packet, size); break; case CODE_PADR: relayHandlePADR(iface, &packet, size); break; case CODE_PADS: relayHandlePADS(iface, &packet, size); break; default: syslog(LOG_ERR, "Discovery packet on %s with unknown code %d", iface->name, (int) packet.code); } } /********************************************************************** *%FUNCTION: relayGotSessionPacket *%ARGUMENTS: * iface -- interface on which packet is waiting *%RETURNS: * Nothing *%DESCRIPTION: * Receives and processes a session packet. ***********************************************************************/ void relayGotSessionPacket(PPPoEInterface const *iface) { PPPoEPacket packet; int size; SessionHash *sh; PPPoESession *ses; if (receivePacket(iface->sessionSock, &packet, &size) < 0) { return; } /* Ignore unknown code/version */ if (PPPOE_VER(packet.vertype) != 1 || PPPOE_TYPE(packet.vertype) != 1) { return; } /* Must be a session packet */ if (packet.code != CODE_SESS) { syslog(LOG_ERR, "Session packet with code %d", (int) packet.code); return; } /* Ignore session packets whose destination address isn't ours */ if (memcmp(packet.ethHdr.h_dest, iface->mac, ETH_ALEN)) { return; } /* Validate length */ if (ntohs(packet.length) + HDR_SIZE > size) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); return; } /* Drop Ethernet frame padding */ if (size > ntohs(packet.length) + HDR_SIZE) { size = ntohs(packet.length) + HDR_SIZE; } /* We're in business! Find the hash */ sh = findSession(packet.ethHdr.h_source, packet.session); if (!sh) { /* Don't log this. Someone could be running the client and the relay on the same box. */ return; } /* Relay it */ ses = sh->ses; ses->epoch = Epoch; sh = sh->peer; packet.session = sh->sesNum; memcpy(packet.ethHdr.h_source, sh->interface->mac, ETH_ALEN); memcpy(packet.ethHdr.h_dest, sh->peerMac, ETH_ALEN); #if 0 fprintf(stderr, "Relaying %02x:%02x:%02x:%02x:%02x:%02x(%s:%d) to %02x:%02x:%02x:%02x:%02x:%02x(%s:%d)\n", sh->peer->peerMac[0], sh->peer->peerMac[1], sh->peer->peerMac[2], sh->peer->peerMac[3], sh->peer->peerMac[4], sh->peer->peerMac[5], sh->peer->interface->name, ntohs(sh->peer->sesNum), sh->peerMac[0], sh->peerMac[1], sh->peerMac[2], sh->peerMac[3], sh->peerMac[4], sh->peerMac[5], sh->interface->name, ntohs(sh->sesNum)); #endif sendPacket(NULL, sh->interface->sessionSock, &packet, size); } /********************************************************************** *%FUNCTION: relayHandlePADT *%ARGUMENTS: * iface -- interface on which packet was received * packet -- the PADT packet *%RETURNS: * Nothing *%DESCRIPTION: * Receives and processes a PADT packet. ***********************************************************************/ void relayHandlePADT(PPPoEInterface const *iface, PPPoEPacket *packet, int size) { SessionHash *sh; PPPoESession *ses; /* Destination address must be interface's MAC address */ if (memcmp(packet->ethHdr.h_dest, iface->mac, ETH_ALEN)) { return; } sh = findSession(packet->ethHdr.h_source, packet->session); if (!sh) { return; } /* Relay the PADT to the peer */ sh = sh->peer; ses = sh->ses; packet->session = sh->sesNum; memcpy(packet->ethHdr.h_source, sh->interface->mac, ETH_ALEN); memcpy(packet->ethHdr.h_dest, sh->peerMac, ETH_ALEN); sendPacket(NULL, sh->interface->sessionSock, packet, size); /* Destroy the session */ freeSession(ses, "Received PADT"); } /********************************************************************** *%FUNCTION: relayHandlePADI *%ARGUMENTS: * iface -- interface on which packet was received * packet -- the PADI packet *%RETURNS: * Nothing *%DESCRIPTION: * Receives and processes a PADI packet. ***********************************************************************/ void relayHandlePADI(PPPoEInterface const *iface, PPPoEPacket *packet, int size) { PPPoETag tag; unsigned char *loc; int i, r; int ifIndex; /* Can a client legally be behind this interface? */ if (!iface->clientOK) { syslog(LOG_ERR, "PADI packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not permitted", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Source address must be unicast */ if (NOT_UNICAST(packet->ethHdr.h_source)) { syslog(LOG_ERR, "PADI packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not from a unicast address", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Destination address must be broadcast */ if (NOT_BROADCAST(packet->ethHdr.h_dest)) { syslog(LOG_ERR, "PADI packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not to a broadcast address", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Get array index of interface */ ifIndex = iface - Interfaces; loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag); if (!loc) { tag.type = htons(TAG_RELAY_SESSION_ID); tag.length = htons(MY_RELAY_TAG_LEN); memcpy(tag.payload, &ifIndex, sizeof(ifIndex)); memcpy(tag.payload+sizeof(ifIndex), packet->ethHdr.h_source, ETH_ALEN); /* Add a relay tag if there's room */ r = addTag(packet, &tag); if (r < 0) return; size += r; } else { /* We do not re-use relay-id tags. Drop the frame. The RFC says the relay agent SHOULD return a Generic-Error tag, but this does not make sense for PADI packets. */ return; } /* Broadcast the PADI on all AC-capable interfaces except the interface on which it came */ for (i=0; i < NumInterfaces; i++) { if (iface == &Interfaces[i]) continue; if (!Interfaces[i].acOK) continue; memcpy(packet->ethHdr.h_source, Interfaces[i].mac, ETH_ALEN); sendPacket(NULL, Interfaces[i].discoverySock, packet, size); } } /********************************************************************** *%FUNCTION: relayHandlePADO *%ARGUMENTS: * iface -- interface on which packet was received * packet -- the PADO packet *%RETURNS: * Nothing *%DESCRIPTION: * Receives and processes a PADO packet. ***********************************************************************/ void relayHandlePADO(PPPoEInterface const *iface, PPPoEPacket *packet, int size) { PPPoETag tag; unsigned char *loc; int ifIndex; int acIndex; /* Can a server legally be behind this interface? */ if (!iface->acOK) { syslog(LOG_ERR, "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not permitted", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } acIndex = iface - Interfaces; /* Source address can't be broadcast */ if (BROADCAST(packet->ethHdr.h_source)) { syslog(LOG_ERR, "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s from a broadcast address", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Destination address must be interface's MAC address */ if (memcmp(packet->ethHdr.h_dest, iface->mac, ETH_ALEN)) { return; } /* Find relay tag */ loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag); if (!loc) { syslog(LOG_ERR, "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* If it's the wrong length, ignore it */ if (ntohs(tag.length) != MY_RELAY_TAG_LEN) { syslog(LOG_ERR, "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have correct length Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Extract interface index */ memcpy(&ifIndex, tag.payload, sizeof(ifIndex)); if (ifIndex < 0 || ifIndex >= NumInterfaces || !Interfaces[ifIndex].clientOK || iface == &Interfaces[ifIndex]) { syslog(LOG_ERR, "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s has invalid interface in Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Replace Relay-ID tag with opposite-direction tag */ memcpy(loc+TAG_HDR_SIZE, &acIndex, sizeof(acIndex)); memcpy(loc+TAG_HDR_SIZE+sizeof(ifIndex), packet->ethHdr.h_source, ETH_ALEN); /* Set destination address to MAC address in relay ID */ memcpy(packet->ethHdr.h_dest, tag.payload + sizeof(ifIndex), ETH_ALEN); /* Set source address to MAC address of interface */ memcpy(packet->ethHdr.h_source, Interfaces[ifIndex].mac, ETH_ALEN); /* Send the PADO to the proper client */ sendPacket(NULL, Interfaces[ifIndex].discoverySock, packet, size); } /********************************************************************** *%FUNCTION: relayHandlePADR *%ARGUMENTS: * iface -- interface on which packet was received * packet -- the PADR packet *%RETURNS: * Nothing *%DESCRIPTION: * Receives and processes a PADR packet. ***********************************************************************/ void relayHandlePADR(PPPoEInterface const *iface, PPPoEPacket *packet, int size) { PPPoETag tag; unsigned char *loc; int ifIndex; int cliIndex; /* Can a client legally be behind this interface? */ if (!iface->clientOK) { syslog(LOG_ERR, "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not permitted", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } cliIndex = iface - Interfaces; /* Source address must be unicast */ if (NOT_UNICAST(packet->ethHdr.h_source)) { syslog(LOG_ERR, "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not from a unicast address", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Destination address must be interface's MAC address */ if (memcmp(packet->ethHdr.h_dest, iface->mac, ETH_ALEN)) { return; } /* Find relay tag */ loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag); if (!loc) { syslog(LOG_ERR, "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* If it's the wrong length, ignore it */ if (ntohs(tag.length) != MY_RELAY_TAG_LEN) { syslog(LOG_ERR, "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have correct length Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Extract interface index */ memcpy(&ifIndex, tag.payload, sizeof(ifIndex)); if (ifIndex < 0 || ifIndex >= NumInterfaces || !Interfaces[ifIndex].acOK || iface == &Interfaces[ifIndex]) { syslog(LOG_ERR, "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s has invalid interface in Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Replace Relay-ID tag with opposite-direction tag */ memcpy(loc+TAG_HDR_SIZE, &cliIndex, sizeof(cliIndex)); memcpy(loc+TAG_HDR_SIZE+sizeof(ifIndex), packet->ethHdr.h_source, ETH_ALEN); /* Set destination address to MAC address in relay ID */ memcpy(packet->ethHdr.h_dest, tag.payload + sizeof(ifIndex), ETH_ALEN); /* Set source address to MAC address of interface */ memcpy(packet->ethHdr.h_source, Interfaces[ifIndex].mac, ETH_ALEN); /* Send the PADR to the proper access concentrator */ sendPacket(NULL, Interfaces[ifIndex].discoverySock, packet, size); } /********************************************************************** *%FUNCTION: relayHandlePADS *%ARGUMENTS: * iface -- interface on which packet was received * packet -- the PADS packet *%RETURNS: * Nothing *%DESCRIPTION: * Receives and processes a PADS packet. ***********************************************************************/ void relayHandlePADS(PPPoEInterface const *iface, PPPoEPacket *packet, int size) { PPPoETag tag; unsigned char *loc; int ifIndex; PPPoESession *ses = NULL; SessionHash *sh; /* Can a server legally be behind this interface? */ if (!iface->acOK) { syslog(LOG_ERR, "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not permitted", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Source address must be unicast */ if (NOT_UNICAST(packet->ethHdr.h_source)) { syslog(LOG_ERR, "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not from a unicast address", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Destination address must be interface's MAC address */ if (memcmp(packet->ethHdr.h_dest, iface->mac, ETH_ALEN)) { return; } /* Find relay tag */ loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag); if (!loc) { syslog(LOG_ERR, "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* If it's the wrong length, ignore it */ if (ntohs(tag.length) != MY_RELAY_TAG_LEN) { syslog(LOG_ERR, "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have correct length Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* Extract interface index */ memcpy(&ifIndex, tag.payload, sizeof(ifIndex)); if (ifIndex < 0 || ifIndex >= NumInterfaces || !Interfaces[ifIndex].clientOK || iface == &Interfaces[ifIndex]) { syslog(LOG_ERR, "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s has invalid interface in Relay-Session-Id tag", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], iface->name); return; } /* If session ID is zero, it's the AC respoding with an error. Just relay it; do not create a session */ if (packet->session != htons(0)) { /* Check for existing session */ sh = findSession(packet->ethHdr.h_source, packet->session); if (sh) ses = sh->ses; /* If already an existing session, assume it's a duplicate PADS. Send the frame, but do not create a new session. Is this the right thing to do? Arguably, should send an error to the client and a PADT to the server, because this could happen due to a server crash and reboot. */ if (!ses) { /* Create a new session */ ses = createSession(iface, &Interfaces[ifIndex], packet->ethHdr.h_source, loc + TAG_HDR_SIZE + sizeof(ifIndex), packet->session); if (!ses) { /* Can't allocate session -- send error PADS to client and PADT to server */ PPPoETag hostUniq, *hu; if (findTag(packet, TAG_HOST_UNIQ, &hostUniq)) { hu = &hostUniq; } else { hu = NULL; } relaySendError(CODE_PADS, htons(0), &Interfaces[ifIndex], loc + TAG_HDR_SIZE + sizeof(ifIndex), hu, "RP-PPPoE: Relay: Unable to allocate session"); relaySendError(CODE_PADT, packet->session, iface, packet->ethHdr.h_source, NULL, "RP-PPPoE: Relay: Unable to allocate session"); return; } } /* Replace session number */ packet->session = ses->sesNum; } /* Remove relay-ID tag */ removeBytes(packet, loc, MY_RELAY_TAG_LEN + TAG_HDR_SIZE); size -= (MY_RELAY_TAG_LEN + TAG_HDR_SIZE); /* Set destination address to MAC address in relay ID */ memcpy(packet->ethHdr.h_dest, tag.payload + sizeof(ifIndex), ETH_ALEN); /* Set source address to MAC address of interface */ memcpy(packet->ethHdr.h_source, Interfaces[ifIndex].mac, ETH_ALEN); /* Send the PADS to the proper client */ sendPacket(NULL, Interfaces[ifIndex].discoverySock, packet, size); } /********************************************************************** *%FUNCTION: relaySendError *%ARGUMENTS: * code -- PPPoE packet code (PADS or PADT, typically) * session -- PPPoE session number * iface -- interface on which to send frame * mac -- Ethernet address to which frame should be sent * hostUniq -- if non-NULL, a hostUniq tag to add to error frame * errMsg -- error message to insert into Generic-Error tag. *%RETURNS: * Nothing *%DESCRIPTION: * Sends either a PADS or PADT packet with a Generic-Error tag and an * error message. ***********************************************************************/ void relaySendError(unsigned char code, UINT16_t session, PPPoEInterface const *iface, unsigned char const *mac, PPPoETag const *hostUniq, char const *errMsg) { PPPoEPacket packet; PPPoETag errTag; int size; memcpy(packet.ethHdr.h_source, iface->mac, ETH_ALEN); memcpy(packet.ethHdr.h_dest, mac, ETH_ALEN); packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); packet.vertype = PPPOE_VER_TYPE(1, 1); packet.code = code; packet.session = session; packet.length = htons(0); if (hostUniq) { if (addTag(&packet, hostUniq) < 0) return; } errTag.type = htons(TAG_GENERIC_ERROR); errTag.length = htons(strlen(errMsg)); strcpy((char *) errTag.payload, errMsg); if (addTag(&packet, &errTag) < 0) return; size = ntohs(packet.length) + HDR_SIZE; if (code == CODE_PADT) { sendPacket(NULL, iface->discoverySock, &packet, size); } else { sendPacket(NULL, iface->sessionSock, &packet, size); } } /********************************************************************** *%FUNCTION: alarmHandler *%ARGUMENTS: * sig -- signal number *%RETURNS: * Nothing *%DESCRIPTION: * SIGALRM handler. Increments Epoch; if necessary, writes a byte of * data to the alarm pipe to trigger the stale-session cleaner. ***********************************************************************/ void alarmHandler(int sig) { alarm(1); Epoch++; CleanCounter++; if (CleanCounter == CleanPeriod) { write(CleanPipe[1], "", 1); } } /********************************************************************** *%FUNCTION: cleanSessions *%ARGUMENTS: * None *%RETURNS: * Nothing *%DESCRIPTION: * Goes through active sessions and cleans sessions idle for longer * than IdleTimeout seconds. ***********************************************************************/ void cleanSessions(void) { PPPoESession *cur, *next; cur = ActiveSessions; while(cur) { next = cur->next; if (Epoch - cur->epoch > IdleTimeout) { /* Send PADT to each peer */ relaySendError(CODE_PADT, cur->acHash->sesNum, cur->acHash->interface, cur->acHash->peerMac, NULL, "RP-PPPoE: Relay: Session exceeded idle timeout"); relaySendError(CODE_PADT, cur->clientHash->sesNum, cur->clientHash->interface, cur->clientHash->peerMac, NULL, "RP-PPPoE: Relay: Session exceeded idle timeout"); freeSession(cur, "Idle Timeout"); } cur = next; } } rp-pppoe-3.15/src/pppoe-server.c0000644000175000017500000020223514045237010014700 0ustar dfsdfs/*********************************************************************** * * pppoe-server.c * * Implementation of a user-space PPPoE server * * Copyright (C) 2000-2012 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * $Id$ * * LIC: GPL * ***********************************************************************/ #include "config.h" #include #if defined(HAVE_LINUX_IF_H) #include #elif defined(HAVE_NET_IF_H) #include #endif #if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H) #define _POSIX_SOURCE 1 /* For sigaction defines */ #endif #include "pppoe-server.h" #include "md5.h" #ifdef HAVE_SYSLOG_H #include #endif #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_GETOPT_H #include #endif #ifdef HAVE_SYS_WAIT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #include #include #ifdef HAVE_LICENSE #include "license.h" #include "licensed-only/servfuncs.h" static struct License const *ServerLicense; static struct License const *ClusterLicense; #else #define control_session_started(x) (void) 0 #define control_session_terminated(x) (void) 0 #define control_exit() (void) 0 #define realpeerip peerip #endif #ifdef HAVE_L2TP extern PppoeSessionFunctionTable L2TPSessionFunctionTable; extern void pppoe_to_l2tp_add_interface(EventSelector *es, Interface *interface); #endif static void InterfaceHandler(EventSelector *es, int fd, unsigned int flags, void *data); static void startPPPD(ClientSession *sess); static void sendErrorPADS(int sock, unsigned char *source, unsigned char *dest, int errorTag, char *errorMsg); #define CHECK_ROOM(cursor, start, len) \ do {\ if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \ syslog(LOG_ERR, "Would create too-long packet"); \ return; \ } \ } while(0) static void PppoeStopSession(ClientSession *ses, char const *reason); static int PppoeSessionIsActive(ClientSession *ses); /* Service-Names we advertise */ #define MAX_SERVICE_NAMES 64 static int NumServiceNames = 0; static char const *ServiceNames[MAX_SERVICE_NAMES]; PppoeSessionFunctionTable DefaultSessionFunctionTable = { PppoeStopSession, PppoeSessionIsActive, NULL }; /* An array of client sessions */ ClientSession *Sessions = NULL; ClientSession *FreeSessions = NULL; ClientSession *LastFreeSession = NULL; ClientSession *BusySessions = NULL; /* Interfaces we're listening on */ Interface interfaces[MAX_INTERFACES]; int NumInterfaces = 0; /* The number of session slots */ size_t NumSessionSlots; /* Maximum number of sessions per MAC address */ int MaxSessionsPerMac; /* Number of active sessions */ size_t NumActiveSessions = 0; /* Offset of first session */ size_t SessOffset = 0; /* Event Selector */ EventSelector *event_selector; /* Use Linux kernel-mode PPPoE? */ static int UseLinuxKernelModePPPoE = 0; /* Requested max_ppp_payload */ static UINT16_t max_ppp_payload = 0; /* File with PPPD options */ static char *pppoptfile = NULL; static char *pppd_path = PPPD_PATH; static char *pppoe_path = PPPOE_PATH; static char *motd_string = NULL; static char *hurl_string = NULL; static int Debug = 0; static int CheckPoolSyntax = 0; /* Synchronous mode */ static int Synchronous = 0; /* Ignore PADI if no free sessions */ static int IgnorePADIIfNoFreeSessions = 0; static int KidPipe[2] = {-1, -1}; static int LockFD = -1; /* Random seed for cookie generation */ #define SEED_LEN 16 #define MD5_LEN 16 #define COOKIE_LEN (MD5_LEN + sizeof(pid_t)) /* Cookie is 16-byte MD5 + PID of server */ static unsigned char CookieSeed[SEED_LEN]; #define MAXLINE 512 /* Default interface if no -I option given */ #define DEFAULT_IF "eth0" /* Access concentrator name */ char *ACName = NULL; /* Options to pass to pppoe process */ char PppoeOptions[SMALLBUF] = ""; /* Our local IP address */ unsigned char LocalIP[IPV4ALEN] = {10, 0, 0, 1}; /* Counter optionally STARTS here */ unsigned char RemoteIP[IPV4ALEN] = {10, 67, 15, 1}; /* Counter STARTS here */ /* Do we increment local IP for each connection? */ int IncrLocalIP = 0; /* Do we randomize session numbers? */ int RandomizeSessionNumbers = 0; /* Do we pass the "unit" option to pppd? (2.4 or greater) */ int PassUnitOptionToPPPD = 0; static PPPoETag hostUniq; static PPPoETag relayId; static PPPoETag receivedCookie; static PPPoETag requestedService; #define HOSTNAMELEN 256 static int count_sessions_from_mac(unsigned char *eth) { int n=0; ClientSession *s = BusySessions; while(s) { if (!memcmp(eth, s->eth, ETH_ALEN)) n++; s = s->next; } return n; } /********************************************************************** *%FUNCTION: childHandler *%ARGUMENTS: * pid -- pid of child * status -- exit status * ses -- which session terminated *%RETURNS: * Nothing *%DESCRIPTION: * Called synchronously when a child dies. Remove from busy list. ***********************************************************************/ static void childHandler(pid_t pid, int status, void *s) { ClientSession *session = s; /* Temporary structure for sending PADT's. */ PPPoEConnection conn; #ifdef HAVE_L2TP /* We're acting as LAC, so when child exits, become a PPPoE <-> L2TP relay */ if (session->flags & FLAG_ACT_AS_LAC) { syslog(LOG_INFO, "Session %u for client " "%02x:%02x:%02x:%02x:%02x:%02x handed off to LNS %s", (unsigned int) ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], inet_ntoa(session->tunnel_endpoint.sin_addr)); session->pid = 0; session->funcs = &L2TPSessionFunctionTable; return; } #endif memset(&conn, 0, sizeof(conn)); conn.hostUniq = NULL; syslog(LOG_INFO, "Session %u closed for client " "%02x:%02x:%02x:%02x:%02x:%02x (%d.%d.%d.%d) on %s", (unsigned int) ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], (int) session->realpeerip[0], (int) session->realpeerip[1], (int) session->realpeerip[2], (int) session->realpeerip[3], session->ethif->name); memcpy(conn.myEth, session->ethif->mac, ETH_ALEN); conn.discoverySocket = session->ethif->sock; conn.session = session->sess; memcpy(conn.peerEth, session->eth, ETH_ALEN); if (!(session->flags & FLAG_SENT_PADT)) { if (session->flags & FLAG_RECVD_PADT) { sendPADT(&conn, "RP-PPPoE: Received PADT from peer"); } else { sendPADT(&conn, "RP-PPPoE: Child pppd process terminated"); } session->flags |= FLAG_SENT_PADT; } session->serviceName = ""; control_session_terminated(session); if (pppoe_free_session(session) < 0) { return; } } /********************************************************************** *%FUNCTION: incrementIPAddress (static) *%ARGUMENTS: * addr -- a 4-byte array representing IP address *%RETURNS: * Nothing *%DESCRIPTION: * Increments addr in-place ***********************************************************************/ static void incrementIPAddress(unsigned char ip[IPV4ALEN]) { ip[3]++; if (!ip[3]) { ip[2]++; if (!ip[2]) { ip[1]++; if (!ip[1]) { ip[0]++; } } } } /********************************************************************** *%FUNCTION: killAllSessions *%ARGUMENTS: * None *%RETURNS: * Nothing *%DESCRIPTION: * Kills all pppd processes (and hence all PPPoE sessions) ***********************************************************************/ void killAllSessions(void) { ClientSession *sess = BusySessions; while(sess) { sess->funcs->stop(sess, "Shutting Down"); sess = sess->next; } #ifdef HAVE_L2TP pppoe_close_l2tp_tunnels(); #endif } /********************************************************************** *%FUNCTION: parseAddressPool *%ARGUMENTS: * fname -- name of file containing IP address pool. * install -- if true, install IP addresses in sessions. *%RETURNS: * Number of valid IP addresses found. *%DESCRIPTION: * Reads a list of IP addresses from a file. ***********************************************************************/ static int parseAddressPool(char const *fname, int install) { FILE *fp = fopen(fname, "r"); int numAddrs = 0; unsigned int a, b, c, d; unsigned int e, f, g, h; char line[MAXLINE]; if (!fp) { sysErr("Cannot open address pool file"); exit(1); } while (!feof(fp)) { if (!fgets(line, MAXLINE, fp)) { break; } if ((sscanf(line, "%u.%u.%u.%u:%u.%u.%u.%u", &a, &b, &c, &d, &e, &f, &g, &h) == 8) && a < 256 && b < 256 && c < 256 && d < 256 && e < 256 && f < 256 && g < 256 && h < 256) { /* Both specified (local:remote) */ if (install) { Sessions[numAddrs].myip[0] = (unsigned char) a; Sessions[numAddrs].myip[1] = (unsigned char) b; Sessions[numAddrs].myip[2] = (unsigned char) c; Sessions[numAddrs].myip[3] = (unsigned char) d; Sessions[numAddrs].peerip[0] = (unsigned char) e; Sessions[numAddrs].peerip[1] = (unsigned char) f; Sessions[numAddrs].peerip[2] = (unsigned char) g; Sessions[numAddrs].peerip[3] = (unsigned char) h; #ifdef HAVE_LICENSE memcpy(Sessions[numAddrs].realpeerip, Sessions[numAddrs].peerip, IPV4ALEN); #endif } numAddrs++; } else if ((sscanf(line, "%u.%u.%u.%u-%u", &a, &b, &c, &d, &e) == 5) && a < 256 && b < 256 && c < 256 && d < 256 && e < 256) { /* Remote specied as a.b.c.d-e. Example: 1.2.3.4-8 yields: 1.2.3.4, 1.2.3.5, 1.2.3.6, 1.2.3.7, 1.2.3.8 */ /* Swap d and e so that e >= d */ if (e < d) { f = d; d = e; e = f; } if (install) { while (d <= e) { Sessions[numAddrs].peerip[0] = (unsigned char) a; Sessions[numAddrs].peerip[1] = (unsigned char) b; Sessions[numAddrs].peerip[2] = (unsigned char) c; Sessions[numAddrs].peerip[3] = (unsigned char) d; #ifdef HAVE_LICENSE memcpy(Sessions[numAddrs].realpeerip, Sessions[numAddrs].peerip, IPV4ALEN); #endif d++; numAddrs++; } } else { numAddrs += (e-d) + 1; } } else if ((sscanf(line, "%u.%u.%u.%u", &a, &b, &c, &d) == 4) && a < 256 && b < 256 && c < 256 && d < 256) { /* Only remote specified */ if (install) { Sessions[numAddrs].peerip[0] = (unsigned char) a; Sessions[numAddrs].peerip[1] = (unsigned char) b; Sessions[numAddrs].peerip[2] = (unsigned char) c; Sessions[numAddrs].peerip[3] = (unsigned char) d; #ifdef HAVE_LICENSE memcpy(Sessions[numAddrs].realpeerip, Sessions[numAddrs].peerip, IPV4ALEN); #endif } numAddrs++; } } fclose(fp); if (!numAddrs) { rp_fatal("No valid ip addresses found in pool file"); } return numAddrs; } /********************************************************************** *%FUNCTION: parsePADITags *%ARGUMENTS: * type -- tag type * len -- tag length * data -- tag data * extra -- extra user data. *%RETURNS: * Nothing *%DESCRIPTION: * Picks interesting tags out of a PADI packet ***********************************************************************/ void parsePADITags(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { switch(type) { case TAG_PPP_MAX_PAYLOAD: if (len == sizeof(max_ppp_payload)) { memcpy(&max_ppp_payload, data, sizeof(max_ppp_payload)); max_ppp_payload = ntohs(max_ppp_payload); if (max_ppp_payload <= ETH_PPPOE_MTU) { max_ppp_payload = 0; } } break; case TAG_SERVICE_NAME: /* Copy requested service name */ requestedService.type = htons(type); requestedService.length = htons(len); memcpy(requestedService.payload, data, len); break; case TAG_RELAY_SESSION_ID: relayId.type = htons(type); relayId.length = htons(len); memcpy(relayId.payload, data, len); break; case TAG_HOST_UNIQ: hostUniq.type = htons(type); hostUniq.length = htons(len); memcpy(hostUniq.payload, data, len); break; } } /********************************************************************** *%FUNCTION: parsePADRTags *%ARGUMENTS: * type -- tag type * len -- tag length * data -- tag data * extra -- extra user data. *%RETURNS: * Nothing *%DESCRIPTION: * Picks interesting tags out of a PADR packet ***********************************************************************/ void parsePADRTags(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { switch(type) { case TAG_PPP_MAX_PAYLOAD: if (len == sizeof(max_ppp_payload)) { memcpy(&max_ppp_payload, data, sizeof(max_ppp_payload)); max_ppp_payload = ntohs(max_ppp_payload); if (max_ppp_payload <= ETH_PPPOE_MTU) { max_ppp_payload = 0; } } break; case TAG_RELAY_SESSION_ID: relayId.type = htons(type); relayId.length = htons(len); memcpy(relayId.payload, data, len); break; case TAG_HOST_UNIQ: hostUniq.type = htons(type); hostUniq.length = htons(len); memcpy(hostUniq.payload, data, len); break; case TAG_AC_COOKIE: receivedCookie.type = htons(type); receivedCookie.length = htons(len); memcpy(receivedCookie.payload, data, len); break; case TAG_SERVICE_NAME: requestedService.type = htons(type); requestedService.length = htons(len); memcpy(requestedService.payload, data, len); break; } } /********************************************************************** *%FUNCTION: fatalSys *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to stderr and syslog and exits. ***********************************************************************/ void fatalSys(char const *str) { char buf[SMALLBUF]; snprintf(buf, SMALLBUF, "%s: %s", str, strerror(errno)); printErr(buf); control_exit(); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: sysErr *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to syslog. ***********************************************************************/ void sysErr(char const *str) { char buf[1024]; sprintf(buf, "%.256s: %.256s", str, strerror(errno)); printErr(buf); } /********************************************************************** *%FUNCTION: rp_fatal *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message to stderr and syslog and exits. ***********************************************************************/ void rp_fatal(char const *str) { printErr(str); control_exit(); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: genCookie *%ARGUMENTS: * peerEthAddr -- peer Ethernet address (6 bytes) * myEthAddr -- my Ethernet address (6 bytes) * seed -- random cookie seed to make things tasty (16 bytes) * cookie -- buffer which is filled with server PID and * md5 sum of previous items *%RETURNS: * Nothing *%DESCRIPTION: * Forms the md5 sum of peer MAC address, our MAC address and seed, useful * in a PPPoE Cookie tag. ***********************************************************************/ void genCookie(unsigned char const *peerEthAddr, unsigned char const *myEthAddr, unsigned char const *seed, unsigned char *cookie) { struct MD5Context ctx; pid_t pid = getpid(); MD5Init(&ctx); MD5Update(&ctx, peerEthAddr, ETH_ALEN); MD5Update(&ctx, myEthAddr, ETH_ALEN); MD5Update(&ctx, seed, SEED_LEN); MD5Final(cookie, &ctx); memcpy(cookie+MD5_LEN, &pid, sizeof(pid)); } /********************************************************************** *%FUNCTION: processPADI *%ARGUMENTS: * ethif -- Interface * packet -- PPPoE PADI packet * len -- length of received packet *%RETURNS: * Nothing *%DESCRIPTION: * Sends a PADO packet back to client ***********************************************************************/ void processPADI(Interface *ethif, PPPoEPacket *packet, int len) { PPPoEPacket pado; PPPoETag acname; PPPoETag servname; PPPoETag cookie; size_t acname_len; unsigned char *cursor = pado.payload; UINT16_t plen; int sock = ethif->sock; int i; int ok = 0; unsigned char *myAddr = ethif->mac; /* Ignore PADI's which don't come from a unicast address */ if (NOT_UNICAST(packet->ethHdr.h_source)) { syslog(LOG_ERR, "PADI packet from non-unicast source address"); return; } /* If no free sessions and "-i" flag given, ignore */ if (IgnorePADIIfNoFreeSessions && !FreeSessions) { syslog(LOG_INFO, "PADI ignored - No free session slots available"); return; } /* If number of sessions per MAC is limited, check here and don't send PADO if already max number of sessions. */ if (MaxSessionsPerMac) { if (count_sessions_from_mac(packet->ethHdr.h_source) >= MaxSessionsPerMac) { syslog(LOG_INFO, "PADI: Client %02x:%02x:%02x:%02x:%02x:%02x attempted to create more than %d session(s)", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], MaxSessionsPerMac); return; } } acname.type = htons(TAG_AC_NAME); acname_len = strlen(ACName); acname.length = htons(acname_len); memcpy(acname.payload, ACName, acname_len); relayId.type = 0; hostUniq.type = 0; requestedService.type = 0; max_ppp_payload = 0; parsePacket(packet, parsePADITags, NULL); /* If PADI specified non-default service name, and we do not offer that service, DO NOT send PADO */ if (requestedService.type) { int slen = ntohs(requestedService.length); if (slen) { for (i=0; iethHdr.h_source, myAddr, CookieSeed, cookie.payload); /* Construct a PADO packet */ memcpy(pado.ethHdr.h_dest, packet->ethHdr.h_source, ETH_ALEN); memcpy(pado.ethHdr.h_source, myAddr, ETH_ALEN); pado.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); pado.vertype = PPPOE_VER_TYPE(1, 1); pado.code = CODE_PADO; pado.session = 0; plen = TAG_HDR_SIZE + acname_len; CHECK_ROOM(cursor, pado.payload, acname_len+TAG_HDR_SIZE); memcpy(cursor, &acname, acname_len + TAG_HDR_SIZE); cursor += acname_len + TAG_HDR_SIZE; /* If we asked for an MTU, handle it */ if (max_ppp_payload > ETH_PPPOE_MTU && ethif->mtu > 0) { /* Shrink payload to fit */ if (max_ppp_payload > ethif->mtu - TOTAL_OVERHEAD) { max_ppp_payload = ethif->mtu - TOTAL_OVERHEAD; } if (max_ppp_payload > ETH_JUMBO_LEN - TOTAL_OVERHEAD) { max_ppp_payload = ETH_JUMBO_LEN - TOTAL_OVERHEAD; } if (max_ppp_payload > ETH_PPPOE_MTU) { PPPoETag maxPayload; UINT16_t mru = htons(max_ppp_payload); maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); maxPayload.length = htons(sizeof(mru)); memcpy(maxPayload.payload, &mru, sizeof(mru)); CHECK_ROOM(cursor, pado.payload, sizeof(mru) + TAG_HDR_SIZE); memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); cursor += sizeof(mru) + TAG_HDR_SIZE; plen += sizeof(mru) + TAG_HDR_SIZE; } } /* If no service-names specified on command-line, just send default zero-length name. Otherwise, add all service-name tags */ servname.type = htons(TAG_SERVICE_NAME); if (!NumServiceNames) { servname.length = 0; CHECK_ROOM(cursor, pado.payload, TAG_HDR_SIZE); memcpy(cursor, &servname, TAG_HDR_SIZE); cursor += TAG_HDR_SIZE; plen += TAG_HDR_SIZE; } else { for (i=0; imac; /* Ignore PADT's not directed at us */ if (memcmp(packet->ethHdr.h_dest, myAddr, ETH_ALEN)) return; /* Get session's index */ i = ntohs(packet->session) - 1 - SessOffset; if (i >= NumSessionSlots) return; if (Sessions[i].sess != packet->session) { syslog(LOG_ERR, "Session index %u doesn't match session number %u", (unsigned int) i, (unsigned int) ntohs(packet->session)); return; } /* If source MAC does not match, do not kill session */ if (memcmp(packet->ethHdr.h_source, Sessions[i].eth, ETH_ALEN)) { syslog(LOG_WARNING, "PADT for session %u received from " "%02X:%02X:%02X:%02X:%02X:%02X; should be from " "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned int) ntohs(packet->session), packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], Sessions[i].eth[0], Sessions[i].eth[1], Sessions[i].eth[2], Sessions[i].eth[3], Sessions[i].eth[4], Sessions[i].eth[5]); return; } Sessions[i].flags |= FLAG_RECVD_PADT; parsePacket(packet, parseLogErrs, NULL); Sessions[i].funcs->stop(&Sessions[i], "Received PADT"); } /********************************************************************** *%FUNCTION: processPADR *%ARGUMENTS: * ethif -- Ethernet interface * packet -- PPPoE PADR packet * len -- length of received packet *%RETURNS: * Nothing *%DESCRIPTION: * Sends a PADS packet back to client and starts a PPP session if PADR * packet is OK. ***********************************************************************/ void processPADR(Interface *ethif, PPPoEPacket *packet, int len) { unsigned char cookieBuffer[COOKIE_LEN]; ClientSession *cliSession; pid_t child; PPPoEPacket pads; unsigned char *cursor = pads.payload; UINT16_t plen; int i; int sock = ethif->sock; unsigned char *myAddr = ethif->mac; int slen = 0; char const *serviceName = NULL; /* Temporary structure for sending PADM's. */ PPPoEConnection conn; #ifdef HAVE_LICENSE int freemem; #endif /* Initialize some globals */ relayId.type = 0; hostUniq.type = 0; receivedCookie.type = 0; requestedService.type = 0; /* Ignore PADR's not directed at us */ if (memcmp(packet->ethHdr.h_dest, myAddr, ETH_ALEN)) return; /* Ignore PADR's from non-unicast addresses */ if (NOT_UNICAST(packet->ethHdr.h_source)) { syslog(LOG_ERR, "PADR packet from non-unicast source address"); return; } /* If number of sessions per MAC is limited, check here and don't send PADS if already max number of sessions. */ if (MaxSessionsPerMac) { if (count_sessions_from_mac(packet->ethHdr.h_source) >= MaxSessionsPerMac) { syslog(LOG_INFO, "PADR: Client %02x:%02x:%02x:%02x:%02x:%02x attempted to create more than %d session(s)", packet->ethHdr.h_source[0], packet->ethHdr.h_source[1], packet->ethHdr.h_source[2], packet->ethHdr.h_source[3], packet->ethHdr.h_source[4], packet->ethHdr.h_source[5], MaxSessionsPerMac); return; } } max_ppp_payload = 0; parsePacket(packet, parsePADRTags, NULL); /* Check that everything's cool */ if (!receivedCookie.type) { /* Drop it -- do not send error PADS */ return; } /* Is cookie kosher? */ if (receivedCookie.length != htons(COOKIE_LEN)) { /* Drop it -- do not send error PADS */ return; } genCookie(packet->ethHdr.h_source, myAddr, CookieSeed, cookieBuffer); if (memcmp(receivedCookie.payload, cookieBuffer, COOKIE_LEN)) { /* Drop it -- do not send error PADS */ return; } /* Check service name */ if (!requestedService.type) { syslog(LOG_ERR, "Received PADR packet with no SERVICE_NAME tag"); sendErrorPADS(sock, myAddr, packet->ethHdr.h_source, TAG_SERVICE_NAME_ERROR, "RP-PPPoE: Server: No service name tag"); return; } slen = ntohs(requestedService.length); if (slen) { /* Check supported services */ for(i=0; iethHdr.h_source, TAG_SERVICE_NAME_ERROR, "RP-PPPoE: Server: Invalid service name tag"); return; } } else { serviceName = ""; } #ifdef HAVE_LICENSE /* Are we licensed for this many sessions? */ if (License_NumLicenses("PPPOE-SESSIONS") <= NumActiveSessions) { syslog(LOG_ERR, "Insufficient session licenses (%02x:%02x:%02x:%02x:%02x:%02x)", (unsigned int) packet->ethHdr.h_source[0], (unsigned int) packet->ethHdr.h_source[1], (unsigned int) packet->ethHdr.h_source[2], (unsigned int) packet->ethHdr.h_source[3], (unsigned int) packet->ethHdr.h_source[4], (unsigned int) packet->ethHdr.h_source[5]); sendErrorPADS(sock, myAddr, packet->ethHdr.h_source, TAG_AC_SYSTEM_ERROR, "RP-PPPoE: Server: No session licenses available"); return; } #endif /* Enough free memory? */ #ifdef HAVE_LICENSE freemem = getFreeMem(); if (freemem < MIN_FREE_MEMORY) { syslog(LOG_WARNING, "Insufficient free memory to create session: Want %d, have %d", MIN_FREE_MEMORY, freemem); sendErrorPADS(sock, myAddr, packet->ethHdr.h_source, TAG_AC_SYSTEM_ERROR, "RP-PPPoE: Insufficient free RAM"); return; } #endif /* Looks cool... find a slot for the session */ cliSession = pppoe_alloc_session(); if (!cliSession) { syslog(LOG_ERR, "No client slots available (%02x:%02x:%02x:%02x:%02x:%02x)", (unsigned int) packet->ethHdr.h_source[0], (unsigned int) packet->ethHdr.h_source[1], (unsigned int) packet->ethHdr.h_source[2], (unsigned int) packet->ethHdr.h_source[3], (unsigned int) packet->ethHdr.h_source[4], (unsigned int) packet->ethHdr.h_source[5]); sendErrorPADS(sock, myAddr, packet->ethHdr.h_source, TAG_AC_SYSTEM_ERROR, "RP-PPPoE: Server: No client slots available"); return; } /* Set up client session peer Ethernet address */ memcpy(cliSession->eth, packet->ethHdr.h_source, ETH_ALEN); cliSession->ethif = ethif; cliSession->flags = 0; cliSession->funcs = &DefaultSessionFunctionTable; cliSession->startTime = time(NULL); cliSession->serviceName = serviceName; /* Create child process, send PADS packet back */ child = fork(); if (child < 0) { sendErrorPADS(sock, myAddr, packet->ethHdr.h_source, TAG_AC_SYSTEM_ERROR, "RP-PPPoE: Server: Unable to start session process"); pppoe_free_session(cliSession); return; } if (child != 0) { /* In the parent process. Mark pid in session slot */ cliSession->pid = child; Event_HandleChildExit(event_selector, child, childHandler, cliSession); control_session_started(cliSession); return; } /* In the child process */ /* Reset signal handlers to default */ signal(SIGTERM, SIG_DFL); signal(SIGINT, SIG_DFL); /* Close all file descriptors except for socket */ closelog(); if (LockFD >= 0) close(LockFD); for (i=0; iethHdr.h_source, ETH_ALEN); memcpy(pads.ethHdr.h_source, myAddr, ETH_ALEN); pads.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); pads.vertype = PPPOE_VER_TYPE(1, 1); pads.code = CODE_PADS; pads.session = cliSession->sess; plen = 0; /* Copy requested service name tag back in. If requested-service name length is zero, and we have non-zero services, use first service-name as default */ if (!slen && NumServiceNames) { slen = strlen(ServiceNames[0]); memcpy(&requestedService.payload, ServiceNames[0], slen); requestedService.length = htons(slen); } memcpy(cursor, &requestedService, TAG_HDR_SIZE+slen); cursor += TAG_HDR_SIZE+slen; plen += TAG_HDR_SIZE+slen; /* If we asked for an MTU, handle it */ if (max_ppp_payload > ETH_PPPOE_MTU && ethif->mtu > 0) { /* Shrink payload to fit */ if (max_ppp_payload > ethif->mtu - TOTAL_OVERHEAD) { max_ppp_payload = ethif->mtu - TOTAL_OVERHEAD; } if (max_ppp_payload > ETH_JUMBO_LEN - TOTAL_OVERHEAD) { max_ppp_payload = ETH_JUMBO_LEN - TOTAL_OVERHEAD; } if (max_ppp_payload > ETH_PPPOE_MTU) { PPPoETag maxPayload; UINT16_t mru = htons(max_ppp_payload); maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); maxPayload.length = htons(sizeof(mru)); memcpy(maxPayload.payload, &mru, sizeof(mru)); CHECK_ROOM(cursor, pads.payload, sizeof(mru) + TAG_HDR_SIZE); memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); cursor += sizeof(mru) + TAG_HDR_SIZE; plen += sizeof(mru) + TAG_HDR_SIZE; cliSession->requested_mtu = max_ppp_payload; } } if (relayId.type) { memcpy(cursor, &relayId, ntohs(relayId.length) + TAG_HDR_SIZE); cursor += ntohs(relayId.length) + TAG_HDR_SIZE; plen += ntohs(relayId.length) + TAG_HDR_SIZE; } if (hostUniq.type) { memcpy(cursor, &hostUniq, ntohs(hostUniq.length) + TAG_HDR_SIZE); cursor += ntohs(hostUniq.length) + TAG_HDR_SIZE; plen += ntohs(hostUniq.length) + TAG_HDR_SIZE; } pads.length = htons(plen); sendPacket(NULL, sock, &pads, (int) (plen + HDR_SIZE)); if (hurl_string || motd_string) { memset(&conn, 0, sizeof(conn)); conn.hostUniq = NULL; memcpy(conn.myEth, cliSession->ethif->mac, ETH_ALEN); conn.discoverySocket = sock; conn.session = cliSession->sess; memcpy(conn.peerEth, cliSession->eth, ETH_ALEN); if (hurl_string != NULL) sendHURLorMOTM(&conn, hurl_string, TAG_HURL); if (motd_string != NULL) sendHURLorMOTM(&conn, motd_string, TAG_MOTM); } /* Close sock; don't need it any more */ close(sock); startPPPD(cliSession); } /********************************************************************** *%FUNCTION: termHandler *%ARGUMENTS: * sig -- signal number *%RETURNS: * Nothing *%DESCRIPTION: * Called by SIGTERM or SIGINT. Causes all sessions to be killed! ***********************************************************************/ static void termHandler(int sig) { syslog(LOG_INFO, "Terminating on signal %d -- killing all PPPoE sessions", sig); killAllSessions(); control_exit(); exit(0); } /********************************************************************** *%FUNCTION: usage *%ARGUMENTS: * argv0 -- argv[0] from main *%RETURNS: * Nothing *%DESCRIPTION: * Prints usage instructions ***********************************************************************/ void usage(char const *argv0) { fprintf(stderr, "Usage: %s [options]\n", argv0); fprintf(stderr, "Options:\n"); #ifdef USE_BPF fprintf(stderr, " -I if_name -- Specify interface (REQUIRED)\n"); #else fprintf(stderr, " -I if_name -- Specify interface (default %s.)\n", DEFAULT_IF); #endif fprintf(stderr, " -T timeout -- Specify inactivity timeout in seconds.\n"); fprintf(stderr, " -C name -- Set access concentrator name.\n"); fprintf(stderr, " -m MSS -- Clamp incoming and outgoing MSS options.\n"); fprintf(stderr, " -L ip -- Set local IP address.\n"); fprintf(stderr, " -l -- Increment local IP address for each session.\n"); fprintf(stderr, " -R ip -- Set start address of remote IP pool.\n"); fprintf(stderr, " -S name -- Advertise specified service-name.\n"); fprintf(stderr, " -O fname -- Use PPPD options from specified file\n"); fprintf(stderr, " (default %s).\n", PPPOE_SERVER_OPTIONS); fprintf(stderr, " -p fname -- Optain IP address pool from specified file.\n"); fprintf(stderr, " -N num -- Allow 'num' concurrent sessions.\n"); fprintf(stderr, " -o offset -- Assign session numbers starting at offset+1.\n"); fprintf(stderr, " -f disc:sess -- Set Ethernet frame types (hex).\n"); fprintf(stderr, " -s -- Use synchronous PPP mode.\n"); fprintf(stderr, " -X pidfile -- Write PID and lock pidfile.\n"); fprintf(stderr, " -q /path/pppd -- Specify full path to pppd.\n"); fprintf(stderr, " -Q /path/pppoe -- Specify full path to pppoe.\n"); #ifdef HAVE_LINUX_KERNEL_PPPOE fprintf(stderr, " -k -- Use kernel-mode PPPoE.\n"); #endif fprintf(stderr, " -u -- Pass 'unit' option to pppd.\n"); fprintf(stderr, " -r -- Randomize session numbers.\n"); fprintf(stderr, " -d -- Debug session creation.\n"); fprintf(stderr, " -x n -- Limit to 'n' sessions/MAC address.\n"); fprintf(stderr, " -P -- Check pool file for correctness and exit.\n"); #ifdef HAVE_LICENSE fprintf(stderr, " -c secret:if:port -- Enable clustering on interface 'if'.\n"); fprintf(stderr, " -1 -- Allow only one session per user.\n"); #endif fprintf(stderr, " -i -- Ignore PADI if no free sessions.\n"); fprintf(stderr, " -M msg -- Send MSG in a MOTM tag in PADM packet after PADS.\n"); fprintf(stderr, " -H url -- Send URL in a HURL tag in PADM packet after PADS.\n"); fprintf(stderr, " -h -- Print usage information.\n\n"); fprintf(stderr, "PPPoE-Server Version %s, Copyright (C) 2001-2009 Roaring Penguin Software Inc.\n", RP_VERSION); fprintf(stderr, " %*s Copyright (C) 2018-2021 Dianne Skoll\n", (int) strlen(RP_VERSION), ""); #ifndef HAVE_LICENSE fprintf(stderr, "PPPoE-Server comes with ABSOLUTELY NO WARRANTY.\n"); fprintf(stderr, "This is free software, and you are welcome to redistribute it\n"); fprintf(stderr, "under the terms of the GNU General Public License, version 2\n"); fprintf(stderr, "or (at your option) any later version.\n"); #endif fprintf(stderr, "https://dianne.skoll.ca/projects/rp-pppoe/\n"); } /********************************************************************** *%FUNCTION: main *%ARGUMENTS: * argc, argv -- usual suspects *%RETURNS: * Exit status *%DESCRIPTION: * Main program of PPPoE server ***********************************************************************/ int main(int argc, char **argv) { FILE *fp; int i, j; int opt; int d[IPV4ALEN]; int beDaemon = 1; int found; unsigned int discoveryType, sessionType; char *addressPoolFname = NULL; char *pidfile = NULL; char c; #ifdef HAVE_LICENSE int use_clustering = 0; #endif #ifndef HAVE_LINUX_KERNEL_PPPOE char *options = "X:ix:hI:C:L:R:T:m:FN:f:O:o:sp:lrudPc:S:1q:Q:H:M:"; #else char *options = "X:ix:hI:C:L:R:T:m:FN:f:O:o:skp:lrudPc:S:1q:Q:H:M:"; #endif if (getuid() != geteuid() || getgid() != getegid()) { fprintf(stderr, "SECURITY WARNING: pppoe-server will NOT run suid or sgid. Fix your installation.\n"); exit(1); } memset(interfaces, 0, sizeof(interfaces)); /* Initialize syslog */ openlog("pppoe-server", LOG_PID, LOG_DAEMON); /* Default number of session slots */ NumSessionSlots = DEFAULT_MAX_SESSIONS; MaxSessionsPerMac = 0; /* No limit */ NumActiveSessions = 0; /* Parse command-line options */ while((opt = getopt(argc, argv, options)) != -1) { switch(opt) { case 'i': IgnorePADIIfNoFreeSessions = 1; break; case 'x': if (sscanf(optarg, "%d", &MaxSessionsPerMac) != 1) { usage(argv[0]); exit(EXIT_FAILURE); } if (MaxSessionsPerMac < 0) { MaxSessionsPerMac = 0; } break; #ifdef HAVE_LINUX_KERNEL_PPPOE case 'k': UseLinuxKernelModePPPoE = 1; break; #endif case 'S': if (NumServiceNames == MAX_SERVICE_NAMES) { fprintf(stderr, "Too many '-S' options (%d max)", MAX_SERVICE_NAMES); exit(1); } ServiceNames[NumServiceNames] = strdup(optarg); if (!ServiceNames[NumServiceNames]) { fprintf(stderr, "Out of memory"); exit(1); } NumServiceNames++; break; case 'q': pppd_path = strdup(optarg); if (!pppd_path) { fprintf(stderr, "Out of memory"); exit(1); } break; case 'Q': pppoe_path = strdup(optarg); if (!pppoe_path) { fprintf(stderr, "Out of memory"); exit(1); } break; case 'M': if (motd_string) { free(motd_string); motd_string = NULL; } motd_string = strdup(optarg); if (!motd_string) { fprintf(stderr, "Out of memory"); exit(1); } break; case 'H': if (hurl_string) { free(hurl_string); hurl_string = NULL; } hurl_string = strdup(optarg); if (!hurl_string) { fprintf(stderr, "Out of memory"); exit(1); } break; case 'c': #ifndef HAVE_LICENSE fprintf(stderr, "Clustering capability not available.\n"); exit(1); #else cluster_handle_option(optarg); use_clustering = 1; break; #endif case 'd': Debug = 1; break; case 'P': CheckPoolSyntax = 1; break; case 'u': PassUnitOptionToPPPD = 1; break; case 'r': RandomizeSessionNumbers = 1; break; case 'l': IncrLocalIP = 1; break; case 'p': SET_STRING(addressPoolFname, optarg); break; case 'X': SET_STRING(pidfile, optarg); break; case 's': Synchronous = 1; /* Pass the Synchronous option on to pppoe */ snprintf(PppoeOptions + strlen(PppoeOptions), SMALLBUF-strlen(PppoeOptions), " -s"); break; case 'f': if (sscanf(optarg, "%x:%x", &discoveryType, &sessionType) != 2) { fprintf(stderr, "Illegal argument to -f: Should be disc:sess in hex\n"); exit(EXIT_FAILURE); } Eth_PPPOE_Discovery = (UINT16_t) discoveryType; Eth_PPPOE_Session = (UINT16_t) sessionType; /* This option gets passed to pppoe */ snprintf(PppoeOptions + strlen(PppoeOptions), SMALLBUF-strlen(PppoeOptions), " -%c %s", opt, optarg); break; case 'F': beDaemon = 0; break; case 'N': if (sscanf(optarg, "%d", &opt) != 1) { usage(argv[0]); exit(EXIT_FAILURE); } if (opt <= 0) { fprintf(stderr, "-N: Value must be positive\n"); exit(EXIT_FAILURE); } NumSessionSlots = opt; break; case 'O': SET_STRING(pppoptfile, optarg); break; case 'o': if (sscanf(optarg, "%d", &opt) != 1) { usage(argv[0]); exit(EXIT_FAILURE); } if (opt < 0) { fprintf(stderr, "-o: Value must be non-negative\n"); exit(EXIT_FAILURE); } SessOffset = (size_t) opt; break; case 'I': if (NumInterfaces >= MAX_INTERFACES) { fprintf(stderr, "Too many -I options (max %d)\n", MAX_INTERFACES); exit(EXIT_FAILURE); } found = 0; for (i=0; i 255) { usage(argv[0]); exit(EXIT_FAILURE); } if (opt == 'L') { LocalIP[i] = (unsigned char) d[i]; } else { RemoteIP[i] = (unsigned char) d[i]; } } break; case 'T': case 'm': /* These just get passed to pppoe */ snprintf(PppoeOptions + strlen(PppoeOptions), SMALLBUF-strlen(PppoeOptions), " -%c %s", opt, optarg); break; case 'h': usage(argv[0]); exit(EXIT_SUCCESS); case '1': #ifdef HAVE_LICENSE MaxSessionsPerUser = 1; #else fprintf(stderr, "-1 option not valid.\n"); exit(1); #endif break; } } if (!pppoptfile) { pppoptfile = PPPOE_SERVER_OPTIONS; } #ifdef HAVE_LICENSE License_SetVersion(SERVPOET_VERSION); License_ReadBundleFile("/etc/rp/bundle.txt"); License_ReadFile("/etc/rp/license.txt"); ServerLicense = License_GetFeature("PPPOE-SERVER"); if (!ServerLicense) { fprintf(stderr, "License: GetFeature failed: %s\n", License_ErrorMessage()); exit(1); } #endif #ifdef USE_LINUX_PACKET #ifndef HAVE_STRUCT_SOCKADDR_LL fprintf(stderr, "The PPPoE server does not work on Linux 2.0 kernels.\n"); exit(EXIT_FAILURE); #endif #endif if (!NumInterfaces) { strcpy(interfaces[0].name, DEFAULT_IF); NumInterfaces = 1; } if (!ACName) { ACName = malloc(HOSTNAMELEN); if (gethostname(ACName, HOSTNAMELEN) < 0) { fatalSys("gethostname"); } } /* If address pool filename given, count number of addresses */ if (addressPoolFname) { NumSessionSlots = parseAddressPool(addressPoolFname, 0); if (CheckPoolSyntax) { printf("%lu\n", (unsigned long) NumSessionSlots); exit(0); } } /* Max 65534 - SessOffset sessions */ if (NumSessionSlots + SessOffset > 65534) { fprintf(stderr, "-N and -o options must add up to at most 65534\n"); exit(EXIT_FAILURE); } /* Allocate memory for sessions */ Sessions = calloc(NumSessionSlots, sizeof(ClientSession)); if (!Sessions) { rp_fatal("Cannot allocate memory for session slots"); } /* Fill in local addresses first (let pool file override later */ for (i=0; i> 8) & 0xFF; for (i=2; i> (i % 9)) & 0xFF; } } if (RandomizeSessionNumbers) { int *permutation; int tmp; permutation = malloc(sizeof(int) * NumSessionSlots); if (!permutation) { fprintf(stderr, "Could not allocate memory to randomize session numbers\n"); exit(EXIT_FAILURE); } for (i=0; isess)), ses->myip[0], ses->myip[1], ses->myip[2], ses->myip[3], ses->peerip[0], ses->peerip[1], ses->peerip[2], ses->peerip[3]); ses = ses->next; } exit(0); } /* Open all the interfaces */ for (i=0; i= 0) { close(KidPipe[0]); KidPipe[0] = -1; } /* Point stdin/stdout/stderr to /dev/null */ for (i=0; i<3; i++) { close(i); } i = open("/dev/null", O_RDWR); if (i >= 0) { dup2(i, 0); dup2(i, 1); dup2(i, 2); if (i > 2) close(i); } } if (pidfile) { FILE *foo = NULL; if (KidPipe[1] >= 0) foo = fdopen(KidPipe[1], "w"); struct flock fl; char buf[64]; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; LockFD = open(pidfile, O_RDWR|O_CREAT, 0666); if (LockFD < 0) { syslog(LOG_INFO, "Could not open PID file %s: %s", pidfile, strerror(errno)); if (foo) fprintf(foo, "ECould not open PID file %s: %s\n", pidfile, strerror(errno)); exit(1); } if (fcntl(LockFD, F_SETLK, &fl) < 0) { syslog(LOG_INFO, "Could not lock PID file %s: Is another process running?", pidfile); if (foo) fprintf(foo, "ECould not lock PID file %s: Is another process running?\n", pidfile); exit(1); } ftruncate(LockFD, 0); snprintf(buf, sizeof(buf), "%lu\n", (unsigned long) getpid()); write(LockFD, buf, strlen(buf)); /* Do not close fd... use it to retain lock */ } /* Set signal handlers for SIGTERM and SIGINT */ if (Event_HandleSignal(event_selector, SIGTERM, termHandler) < 0 || Event_HandleSignal(event_selector, SIGINT, termHandler) < 0) { fatalSys("Event_HandleSignal"); } /* Tell parent all is cool */ if (KidPipe[1] >= 0) { write(KidPipe[1], "X", 1); close(KidPipe[1]); KidPipe[1] = -1; } for(;;) { i = Event_HandleEvent(event_selector); if (i < 0) { fatalSys("Event_HandleEvent"); } #ifdef HAVE_LICENSE if (License_Expired(ServerLicense)) { syslog(LOG_INFO, "Server license has expired -- killing all PPPoE sessions"); killAllSessions(); control_exit(); exit(0); } #endif } return 0; } void serverProcessPacket(Interface *i) { int len; PPPoEPacket packet; int sock = i->sock; if (receivePacket(sock, &packet, &len) < 0) { return; } if (len < HDR_SIZE) { /* Impossible - ignore */ return; } /* Sanity check on packet */ if (PPPOE_VER(packet.vertype) != 1 || PPPOE_TYPE(packet.vertype) != 1) { /* Syslog an error */ return; } /* Check length */ if (ntohs(packet.length) + HDR_SIZE > len) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); return; } switch(packet.code) { case CODE_PADI: processPADI(i, &packet, len); break; case CODE_PADR: processPADR(i, &packet, len); break; case CODE_PADT: /* Kill the child */ processPADT(i, &packet, len); break; case CODE_SESS: /* Ignore SESS -- children will handle them */ break; case CODE_PADO: case CODE_PADS: /* Ignore PADO and PADS totally */ break; default: /* Syslog an error */ break; } } /********************************************************************** *%FUNCTION: sendErrorPADS *%ARGUMENTS: * sock -- socket to write to * source -- source Ethernet address * dest -- destination Ethernet address * errorTag -- error tag * errorMsg -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Sends a PADS packet with an error message ***********************************************************************/ void sendErrorPADS(int sock, unsigned char *source, unsigned char *dest, int errorTag, char *errorMsg) { PPPoEPacket pads; unsigned char *cursor = pads.payload; UINT16_t plen; PPPoETag err; int elen = strlen(errorMsg); memcpy(pads.ethHdr.h_dest, dest, ETH_ALEN); memcpy(pads.ethHdr.h_source, source, ETH_ALEN); pads.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); pads.vertype = PPPOE_VER_TYPE(1, 1); pads.code = CODE_PADS; pads.session = htons(0); plen = 0; err.type = htons(errorTag); err.length = htons(elen); memcpy(err.payload, errorMsg, elen); memcpy(cursor, &err, TAG_HDR_SIZE+elen); cursor += TAG_HDR_SIZE + elen; plen += TAG_HDR_SIZE + elen; if (relayId.type) { memcpy(cursor, &relayId, ntohs(relayId.length) + TAG_HDR_SIZE); cursor += ntohs(relayId.length) + TAG_HDR_SIZE; plen += ntohs(relayId.length) + TAG_HDR_SIZE; } if (hostUniq.type) { memcpy(cursor, &hostUniq, ntohs(hostUniq.length) + TAG_HDR_SIZE); cursor += ntohs(hostUniq.length) + TAG_HDR_SIZE; plen += ntohs(hostUniq.length) + TAG_HDR_SIZE; } pads.length = htons(plen); sendPacket(NULL, sock, &pads, (int) (plen + HDR_SIZE)); } /********************************************************************** *%FUNCTION: startPPPDUserMode *%ARGUMENTS: * session -- client session record *%RETURNS: * Nothing *%DESCRIPTION: * Starts PPPD for user-mode PPPoE ***********************************************************************/ void startPPPDUserMode(ClientSession *session) { /* Leave some room */ char *argv[64]; char buffer[2 * SMALLBUF]; int c = 0; argv[c++] = "pppd"; argv[c++] = "pty"; /* Let's hope service-name does not have ' in it... */ snprintf(buffer, sizeof(buffer), "%s -n -I %s -e %u:%02x:%02x:%02x:%02x:%02x:%02x%s -S '%s'", pppoe_path, session->ethif->name, (unsigned int) ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], PppoeOptions, session->serviceName); argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "file"; argv[c++] = pppoptfile; snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d:%d.%d.%d.%d", (int) session->myip[0], (int) session->myip[1], (int) session->myip[2], (int) session->myip[3], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3]); syslog(LOG_INFO, "Session %u created for client %02x:%02x:%02x:%02x:%02x:%02x (%d.%d.%d.%d) on %s using Service-Name '%s'", (unsigned int) ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3], session->ethif->name, session->serviceName); argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "nodetach"; argv[c++] = "noaccomp"; argv[c++] = "nopcomp"; argv[c++] = "default-asyncmap"; if (Synchronous) { argv[c++] = "sync"; } if (PassUnitOptionToPPPD) { argv[c++] = "unit"; sprintf(buffer, "%u", (unsigned int) (ntohs(session->sess) - 1)); argv[c++] = buffer; } if (session->requested_mtu > 1492) { sprintf(buffer, "%u", (unsigned int) session->requested_mtu); argv[c++] = "mru"; argv[c++] = buffer; argv[c++] = "mtu"; argv[c++] = buffer; } else { argv[c++] = "mru"; argv[c++] = "1492"; argv[c++] = "mtu"; argv[c++] = "1492"; } argv[c++] = NULL; execv(pppd_path, argv); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: startPPPDLinuxKernelMode *%ARGUMENTS: * session -- client session record *%RETURNS: * Nothing *%DESCRIPTION: * Starts PPPD for kernel-mode PPPoE on Linux ***********************************************************************/ void startPPPDLinuxKernelMode(ClientSession *session) { /* Leave some room */ char *argv[32]; int c = 0; char buffer[SMALLBUF]; argv[c++] = "pppd"; argv[c++] = "plugin"; argv[c++] = PLUGIN_PATH; /* Add "nic-" to interface name */ snprintf(buffer, SMALLBUF, "nic-%s", session->ethif->name); argv[c++] = strdup(buffer); if (!argv[c-1]) { exit(EXIT_FAILURE); } snprintf(buffer, SMALLBUF, "%u:%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int) ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5]); argv[c++] = "rp_pppoe_sess"; argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "rp_pppoe_service"; argv[c++] = (char *) session->serviceName; argv[c++] = "file"; argv[c++] = pppoptfile; snprintf(buffer, SMALLBUF, "%d.%d.%d.%d:%d.%d.%d.%d", (int) session->myip[0], (int) session->myip[1], (int) session->myip[2], (int) session->myip[3], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3]); syslog(LOG_INFO, "Session %u created for client %02x:%02x:%02x:%02x:%02x:%02x (%d.%d.%d.%d) on %s using Service-Name '%s'", (unsigned int) ntohs(session->sess), session->eth[0], session->eth[1], session->eth[2], session->eth[3], session->eth[4], session->eth[5], (int) session->peerip[0], (int) session->peerip[1], (int) session->peerip[2], (int) session->peerip[3], session->ethif->name, session->serviceName); argv[c++] = strdup(buffer); if (!argv[c-1]) { /* TODO: Send a PADT */ exit(EXIT_FAILURE); } argv[c++] = "nodetach"; argv[c++] = "noaccomp"; argv[c++] = "nopcomp"; argv[c++] = "default-asyncmap"; if (PassUnitOptionToPPPD) { argv[c++] = "unit"; sprintf(buffer, "%u", (unsigned int) (ntohs(session->sess) - 1 - SessOffset)); argv[c++] = buffer; } if (session->requested_mtu > 1492) { sprintf(buffer, "%u", (unsigned int) session->requested_mtu); argv[c++] = "mru"; argv[c++] = buffer; argv[c++] = "mtu"; argv[c++] = buffer; } else { argv[c++] = "mru"; argv[c++] = "1492"; argv[c++] = "mtu"; argv[c++] = "1492"; } argv[c++] = NULL; execv(pppd_path, argv); exit(EXIT_FAILURE); } /********************************************************************** *%FUNCTION: startPPPD *%ARGUMENTS: * session -- client session record *%RETURNS: * Nothing *%DESCRIPTION: * Starts PPPD ***********************************************************************/ void startPPPD(ClientSession *session) { if (UseLinuxKernelModePPPoE) startPPPDLinuxKernelMode(session); else startPPPDUserMode(session); } /********************************************************************** * %FUNCTION: InterfaceHandler * %ARGUMENTS: * es -- event selector (ignored) * fd -- file descriptor which is readable * flags -- ignored * data -- Pointer to the Interface structure * %RETURNS: * Nothing * %DESCRIPTION: * Handles a packet ready at an interface ***********************************************************************/ void InterfaceHandler(EventSelector *es, int fd, unsigned int flags, void *data) { serverProcessPacket((Interface *) data); } /********************************************************************** * %FUNCTION: PppoeStopSession * %ARGUMENTS: * ses -- the session * reason -- reason session is being stopped. * %RETURNS: * Nothing * %DESCRIPTION: * Kills pppd. ***********************************************************************/ static void PppoeStopSession(ClientSession *ses, char const *reason) { /* Temporary structure for sending PADT's. */ PPPoEConnection conn; memset(&conn, 0, sizeof(conn)); conn.hostUniq = NULL; memcpy(conn.myEth, ses->ethif->mac, ETH_ALEN); conn.discoverySocket = ses->ethif->sock; conn.session = ses->sess; memcpy(conn.peerEth, ses->eth, ETH_ALEN); sendPADT(&conn, reason); ses->flags |= FLAG_SENT_PADT; if (ses->pid) { kill(ses->pid, SIGTERM); } ses->funcs = &DefaultSessionFunctionTable; } /********************************************************************** * %FUNCTION: PppoeSessionIsActive * %ARGUMENTS: * ses -- the session * %RETURNS: * True if session is active, false if not. ***********************************************************************/ static int PppoeSessionIsActive(ClientSession *ses) { return (ses->pid != 0); } #ifdef HAVE_LICENSE /********************************************************************** * %FUNCTION: getFreeMem * %ARGUMENTS: * None * %RETURNS: * The amount of free RAM in kilobytes, or -1 if it could not be * determined * %DESCRIPTION: * Reads Linux-specific /proc/meminfo file and extracts free RAM ***********************************************************************/ int getFreeMem(void) { char buf[512]; int memfree=0, buffers=0, cached=0; FILE *fp = fopen("/proc/meminfo", "r"); if (!fp) return -1; while (fgets(buf, sizeof(buf), fp)) { if (!strncmp(buf, "MemFree:", 8)) { if (sscanf(buf, "MemFree: %d", &memfree) != 1) { fclose(fp); return -1; } } else if (!strncmp(buf, "Buffers:", 8)) { if (sscanf(buf, "Buffers: %d", &buffers) != 1) { fclose(fp); return -1; } } else if (!strncmp(buf, "Cached:", 7)) { if (sscanf(buf, "Cached: %d", &cached) != 1) { fclose(fp); return -1; } } } fclose(fp); /* return memfree + buffers + cached; */ return memfree; } #endif /********************************************************************** * %FUNCTION: pppoe_alloc_session * %ARGUMENTS: * None * %RETURNS: * NULL if no session is available, otherwise a ClientSession structure. * %DESCRIPTION: * Allocates a ClientSession structure and removes from free list, puts * on busy list ***********************************************************************/ ClientSession * pppoe_alloc_session(void) { ClientSession *ses = FreeSessions; if (!ses) return NULL; /* Remove from free sessions list */ if (ses == LastFreeSession) { LastFreeSession = NULL; } FreeSessions = ses->next; /* Put on busy sessions list */ ses->next = BusySessions; BusySessions = ses; /* Initialize fields to sane values */ ses->funcs = &DefaultSessionFunctionTable; ses->pid = 0; ses->ethif = NULL; memset(ses->eth, 0, ETH_ALEN); ses->flags = 0; ses->startTime = time(NULL); ses->serviceName = ""; ses->requested_mtu = 0; #ifdef HAVE_LICENSE memset(ses->user, 0, MAX_USERNAME_LEN+1); memset(ses->realm, 0, MAX_USERNAME_LEN+1); memset(ses->realpeerip, 0, IPV4ALEN); #endif #ifdef HAVE_L2TP ses->l2tp_ses = NULL; #endif NumActiveSessions++; return ses; } /********************************************************************** * %FUNCTION: pppoe_free_session * %ARGUMENTS: * ses -- session to free * %RETURNS: * 0 if OK, -1 if error * %DESCRIPTION: * Places a ClientSession on the free list. ***********************************************************************/ int pppoe_free_session(ClientSession *ses) { ClientSession *cur, *prev; cur = BusySessions; prev = NULL; while (cur) { if (ses == cur) break; prev = cur; cur = cur->next; } if (!cur) { syslog(LOG_ERR, "pppoe_free_session: Could not find session %p on busy list", (void *) ses); return -1; } /* Remove from busy sessions list */ if (prev) { prev->next = ses->next; } else { BusySessions = ses->next; } /* Add to end of free sessions */ ses->next = NULL; if (LastFreeSession) { LastFreeSession->next = ses; LastFreeSession = ses; } else { FreeSessions = ses; LastFreeSession = ses; } /* Initialize fields to sane values */ ses->funcs = &DefaultSessionFunctionTable; ses->pid = 0; memset(ses->eth, 0, ETH_ALEN); ses->flags = 0; #ifdef HAVE_L2TP ses->l2tp_ses = NULL; #endif NumActiveSessions--; return 0; } /********************************************************************** * %FUNCTION: sendHURLorMOTM * %ARGUMENTS: * conn -- PPPoE connection * url -- a URL, which *MUST* begin with "http://" or it won't be sent, or * a message. * tag -- one of TAG_HURL or TAG_MOTM * %RETURNS: * Nothing * %DESCRIPTION: * Sends a PADM packet contaning a HURL or MOTM tag to the victim...er, peer. ***********************************************************************/ void sendHURLorMOTM(PPPoEConnection *conn, char const *url, UINT16_t tag) { PPPoEPacket packet; PPPoETag hurl; size_t elen; unsigned char *cursor = packet.payload; UINT16_t plen = 0; if (!conn->session) return; if (conn->discoverySocket < 0) return; if (tag == TAG_HURL) { if (strncmp(url, "http://", 7) && strncmp(url, "https://", 8)) { syslog(LOG_WARNING, "sendHURL(%s): URL must begin with http:// or https://", url); return; } } else { tag = TAG_MOTM; } memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN); memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); packet.vertype = PPPOE_VER_TYPE(1, 1); packet.code = CODE_PADM; packet.session = conn->session; elen = strlen(url); if (elen > 256) { syslog(LOG_WARNING, "MOTM or HURL too long: %d", (int) elen); return; } hurl.type = htons(tag); hurl.length = htons(elen); strcpy((char *) hurl.payload, url); memcpy(cursor, &hurl, elen + TAG_HDR_SIZE); cursor += elen + TAG_HDR_SIZE; plen += elen + TAG_HDR_SIZE; packet.length = htons(plen); sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "SENT"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif } rp-pppoe-3.15/src/discovery.c0000644000175000017500000005264314045237010014266 0ustar dfsdfs/*********************************************************************** * * discovery.c * * Perform PPPoE discovery * * Copyright (C) 1999-2015 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * LIC: GPL * ***********************************************************************/ #define _GNU_SOURCE 1 #include "pppoe.h" #ifdef HAVE_SYSLOG_H #include #endif #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #include #ifdef HAVE_SYS_UIO_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef USE_LINUX_PACKET #include #include #endif #include #ifdef PLUGIN #include "pppd/pppd.h" #include "pppd/fsm.h" #include "pppd/lcp.h" #else int persist = 0; #endif /* Structure used by parseForHostUniq */ struct HostUniqInfo { char *hostUniq; int forMe; }; /* Calculate time remaining until *expire_at into *tv, returns 0 if now >= *expire_at */ static int time_left(struct timeval *tv, struct timeval *expire_at) { struct timeval now; if (gettimeofday(&now, NULL) < 0) { fatalSys("gettimeofday (time_left)"); } tv->tv_sec = expire_at->tv_sec - now.tv_sec; tv->tv_usec = expire_at->tv_usec - now.tv_usec; if (tv->tv_usec < 0) { tv->tv_usec += 1000000; if (tv->tv_sec) { tv->tv_sec--; } else { /* Timed out */ return 0; } } if (tv->tv_sec <= 0 && tv->tv_usec <= 0) { /* Timed out */ return 0; } return 1; } /********************************************************************** *%FUNCTION: parseForHostUniq *%ARGUMENTS: * type -- tag type * len -- tag length * data -- tag data. * extra -- user-supplied pointer. This is assumed to be a pointer to a * HostUniqInfo structure *%RETURNS: * Nothing *%DESCRIPTION: * If a HostUnique tag is found which matches our PID, sets *extra to 1. ***********************************************************************/ static void parseForHostUniq(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { struct HostUniqInfo *hi = (struct HostUniqInfo *) extra; if (!hi->hostUniq) return; if (type == TAG_HOST_UNIQ && len == strlen(hi->hostUniq) && !memcmp(data, hi->hostUniq, len)) { hi->forMe = 1; } } /********************************************************************** *%FUNCTION: packetIsForMe *%ARGUMENTS: * conn -- PPPoE connection info * packet -- a received PPPoE packet *%RETURNS: * 1 if packet is for this PPPoE daemon; 0 otherwise. *%DESCRIPTION: * If we are using the Host-Unique tag, verifies that packet contains * our unique identifier. ***********************************************************************/ static int packetIsForMe(PPPoEConnection *conn, PPPoEPacket *packet) { struct HostUniqInfo hi; /* If packet is not directed to our MAC address, forget it */ if (memcmp(packet->ethHdr.h_dest, conn->myEth, ETH_ALEN)) return 0; /* If we're not using the Host-Unique tag, then accept the packet */ if (!conn->hostUniq) return 1; hi.hostUniq = conn->hostUniq; hi.forMe = 0; parsePacket(packet, parseForHostUniq, &hi); return hi.forMe; } /********************************************************************** *%FUNCTION: parsePADOTags *%ARGUMENTS: * type -- tag type * len -- tag length * data -- tag data * extra -- extra user data. Should point to a PacketCriteria structure * which gets filled in according to selected AC name and service * name. *%RETURNS: * Nothing *%DESCRIPTION: * Picks interesting tags out of a PADO packet ***********************************************************************/ static void parsePADOTags(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { struct PacketCriteria *pc = (struct PacketCriteria *) extra; PPPoEConnection *conn = pc->conn; int i; #ifdef PLUGIN UINT16_t mru; #endif switch(type) { case TAG_AC_NAME: pc->seenACName = 1; if (conn->printACNames) { printf("Access-Concentrator: %.*s\n", (int) len, data); } if (conn->acName && len == strlen(conn->acName) && !strncmp((char *) data, conn->acName, len)) { pc->acNameOK = 1; } break; case TAG_SERVICE_NAME: pc->seenServiceName = 1; if (conn->printACNames && len > 0) { printf(" Service-Name: %.*s\n", (int) len, data); } if (conn->serviceName && len == strlen(conn->serviceName) && !strncmp((char *) data, conn->serviceName, len)) { pc->serviceNameOK = 1; } break; case TAG_AC_COOKIE: if (conn->printACNames) { printf("Got a cookie:"); /* Print first 20 bytes of cookie */ for (i=0; icookie.type = htons(type); conn->cookie.length = htons(len); memcpy(conn->cookie.payload, data, len); break; case TAG_RELAY_SESSION_ID: if (conn->printACNames) { printf("Got a Relay-ID:"); /* Print first 20 bytes of relay ID */ for (i=0; irelayId.type = htons(type); conn->relayId.length = htons(len); memcpy(conn->relayId.payload, data, len); break; case TAG_SERVICE_NAME_ERROR: if (conn->printACNames) { printf("Got a Service-Name-Error tag: %.*s\n", (int) len, data); } else { pktLogErrs("PADO", type, len, data, extra); pc->gotError = 1; if (!persist) { exit(1); } } break; case TAG_AC_SYSTEM_ERROR: if (conn->printACNames) { printf("Got a System-Error tag: %.*s\n", (int) len, data); } else { pktLogErrs("PADO", type, len, data, extra); pc->gotError = 1; if (!persist) { exit(1); } } break; case TAG_GENERIC_ERROR: if (conn->printACNames) { printf("Got a Generic-Error tag: %.*s\n", (int) len, data); } else { pktLogErrs("PADO", type, len, data, extra); pc->gotError = 1; if (!persist) { exit(1); } } break; #ifdef PLUGIN case TAG_PPP_MAX_PAYLOAD: if (len == sizeof(mru)) { memcpy(&mru, data, sizeof(mru)); mru = ntohs(mru); if (mru >= ETH_PPPOE_MTU) { if (lcp_allowoptions[0].mru > mru) lcp_allowoptions[0].mru = mru; if (lcp_wantoptions[0].mru > mru) lcp_wantoptions[0].mru = mru; conn->seenMaxPayload = 1; } } break; #endif } } /********************************************************************** *%FUNCTION: parsePADSTags *%ARGUMENTS: * type -- tag type * len -- tag length * data -- tag data * extra -- extra user data (pointer to PPPoEConnection structure) *%RETURNS: * Nothing *%DESCRIPTION: * Picks interesting tags out of a PADS packet ***********************************************************************/ static void parsePADSTags(UINT16_t type, UINT16_t len, unsigned char *data, void *extra) { #ifdef PLUGIN UINT16_t mru; #endif PPPoEConnection *conn = (PPPoEConnection *) extra; switch(type) { case TAG_SERVICE_NAME: syslog(LOG_DEBUG, "PADS: Service-Name: '%.*s'", (int) len, data); break; case TAG_GENERIC_ERROR: case TAG_AC_SYSTEM_ERROR: case TAG_SERVICE_NAME_ERROR: pktLogErrs("PADS", type, len, data, extra); conn->PADSHadError = 1; break; case TAG_RELAY_SESSION_ID: conn->relayId.type = htons(type); conn->relayId.length = htons(len); memcpy(conn->relayId.payload, data, len); break; #ifdef PLUGIN case TAG_PPP_MAX_PAYLOAD: if (len == sizeof(mru)) { memcpy(&mru, data, sizeof(mru)); mru = ntohs(mru); if (mru >= ETH_PPPOE_MTU) { if (lcp_allowoptions[0].mru > mru) lcp_allowoptions[0].mru = mru; if (lcp_wantoptions[0].mru > mru) lcp_wantoptions[0].mru = mru; conn->seenMaxPayload = 1; } } break; #endif } } /*********************************************************************** *%FUNCTION: sendPADI *%ARGUMENTS: * conn -- PPPoEConnection structure *%RETURNS: * Nothing *%DESCRIPTION: * Sends a PADI packet ***********************************************************************/ static void sendPADI(PPPoEConnection *conn) { PPPoEPacket packet; unsigned char *cursor = packet.payload; PPPoETag *svc = (PPPoETag *) (&packet.payload); UINT16_t namelen = 0; UINT16_t plen; int omit_service_name = 0; if (conn->serviceName) { namelen = (UINT16_t) strlen(conn->serviceName); if (!strcmp(conn->serviceName, "NO-SERVICE-NAME-NON-RFC-COMPLIANT")) { omit_service_name = 1; } } /* Set destination to Ethernet broadcast address */ memset(packet.ethHdr.h_dest, 0xFF, ETH_ALEN); memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); packet.vertype = PPPOE_VER_TYPE(1, 1); packet.code = CODE_PADI; packet.session = 0; if (!omit_service_name) { plen = TAG_HDR_SIZE + namelen; CHECK_ROOM(cursor, packet.payload, plen); svc->type = TAG_SERVICE_NAME; svc->length = htons(namelen); if (conn->serviceName) { memcpy(svc->payload, conn->serviceName, strlen(conn->serviceName)); } cursor += namelen + TAG_HDR_SIZE; } else { plen = 0; } /* If we're using Host-Uniq, copy it over */ if (conn->hostUniq) { PPPoETag hostUniq; int len = (int) strlen(conn->hostUniq); hostUniq.type = htons(TAG_HOST_UNIQ); hostUniq.length = htons(len); memcpy(hostUniq.payload, conn->hostUniq, len); CHECK_ROOM(cursor, packet.payload, len + TAG_HDR_SIZE); memcpy(cursor, &hostUniq, len + TAG_HDR_SIZE); cursor += len + TAG_HDR_SIZE; plen += len + TAG_HDR_SIZE; } #ifdef PLUGIN /* Add our maximum MTU/MRU */ if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { PPPoETag maxPayload; UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); maxPayload.length = htons(sizeof(mru)); memcpy(maxPayload.payload, &mru, sizeof(mru)); CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); cursor += sizeof(mru) + TAG_HDR_SIZE; plen += sizeof(mru) + TAG_HDR_SIZE; } #endif packet.length = htons(plen); sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "SENT"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif } /********************************************************************** *%FUNCTION: waitForPADO *%ARGUMENTS: * conn -- PPPoEConnection structure * timeout -- how long to wait (in seconds) *%RETURNS: * Nothing *%DESCRIPTION: * Waits for a PADO packet and copies useful information ***********************************************************************/ static void waitForPADO(PPPoEConnection *conn, int timeout) { fd_set readable; int r; struct timeval tv; struct timeval expire_at; PPPoEPacket packet; int len; struct PacketCriteria pc; pc.conn = conn; #ifdef PLUGIN conn->seenMaxPayload = 0; #endif if (gettimeofday(&expire_at, NULL) < 0) { fatalSys("gettimeofday (waitForPADO)"); } expire_at.tv_sec += timeout; do { if (BPF_BUFFER_IS_EMPTY) { if(!time_left(&tv, &expire_at)) { /* Timed out */ return; } FD_ZERO(&readable); FD_SET(conn->discoverySocket, &readable); while(1) { r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); if (r >= 0 || errno != EINTR) break; } if (r < 0) { fatalSys("select (waitForPADO)"); } if (r == 0) { /* Timed out */ return; } } /* Get the packet */ receivePacket(conn->discoverySocket, &packet, &len); /* Check length */ if (ntohs(packet.length) + HDR_SIZE > len) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); continue; } #ifdef USE_BPF /* If it's not a Discovery packet, loop again */ if (etherType(&packet) != Eth_PPPOE_Discovery) continue; #endif #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "RCVD"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif /* If it's not for us, loop again */ if (!packetIsForMe(conn, &packet)) continue; if (packet.code == CODE_PADO) { if (BROADCAST(packet.ethHdr.h_source)) { printErr("Ignoring PADO packet from broadcast MAC address"); continue; } #ifdef PLUGIN if (conn->req_peer && memcmp(packet.ethHdr.h_source, conn->req_peer_mac, ETH_ALEN) != 0) { warn("Ignoring PADO packet from wrong MAC address"); continue; } #endif pc.gotError = 0; pc.seenACName = 0; pc.seenServiceName = 0; pc.acNameOK = (conn->acName) ? 0 : 1; pc.serviceNameOK = (conn->serviceName) ? 0 : 1; parsePacket(&packet, parsePADOTags, &pc); if (pc.gotError) { printErr("Error in PADO packet"); continue; } if (!pc.seenACName) { printErr("Ignoring PADO packet with no AC-Name tag"); continue; } if (!pc.seenServiceName) { printErr("Ignoring PADO packet with no Service-Name tag"); continue; } conn->numPADOs++; if (pc.acNameOK && pc.serviceNameOK) { memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN); if (conn->printACNames) { printf("AC-Ethernet-Address: %02x:%02x:%02x:%02x:%02x:%02x\n", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5]); printf("--------------------------------------------------\n"); continue; } conn->discoveryState = STATE_RECEIVED_PADO; break; } } } while (conn->discoveryState != STATE_RECEIVED_PADO); } /*********************************************************************** *%FUNCTION: sendPADR *%ARGUMENTS: * conn -- PPPoE connection structur *%RETURNS: * Nothing *%DESCRIPTION: * Sends a PADR packet ***********************************************************************/ static void sendPADR(PPPoEConnection *conn) { PPPoEPacket packet; PPPoETag *svc = (PPPoETag *) packet.payload; unsigned char *cursor = packet.payload; UINT16_t namelen = 0; UINT16_t plen; if (conn->serviceName) { namelen = (UINT16_t) strlen(conn->serviceName); } plen = TAG_HDR_SIZE + namelen; CHECK_ROOM(cursor, packet.payload, plen); memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN); memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN); packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery); packet.vertype = PPPOE_VER_TYPE(1, 1); packet.code = CODE_PADR; packet.session = 0; svc->type = TAG_SERVICE_NAME; svc->length = htons(namelen); if (conn->serviceName) { memcpy(svc->payload, conn->serviceName, namelen); } cursor += namelen + TAG_HDR_SIZE; /* If we're using Host-Uniq, copy it over */ if (conn->hostUniq) { PPPoETag hostUniq; int len = (int) strlen(conn->hostUniq); hostUniq.type = htons(TAG_HOST_UNIQ); hostUniq.length = htons(len); memcpy(hostUniq.payload, conn->hostUniq, len); CHECK_ROOM(cursor, packet.payload, len + TAG_HDR_SIZE); memcpy(cursor, &hostUniq, len + TAG_HDR_SIZE); cursor += len + TAG_HDR_SIZE; plen += len + TAG_HDR_SIZE; } /* Copy cookie and relay-ID if needed */ if (conn->cookie.type) { CHECK_ROOM(cursor, packet.payload, ntohs(conn->cookie.length) + TAG_HDR_SIZE); memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE); cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE; plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE; } if (conn->relayId.type) { CHECK_ROOM(cursor, packet.payload, ntohs(conn->relayId.length) + TAG_HDR_SIZE); memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE); cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE; plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE; } #ifdef PLUGIN /* Add our maximum MTU/MRU */ if (MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru) > ETH_PPPOE_MTU) { PPPoETag maxPayload; UINT16_t mru = htons(MIN(lcp_allowoptions[0].mru, lcp_wantoptions[0].mru)); maxPayload.type = htons(TAG_PPP_MAX_PAYLOAD); maxPayload.length = htons(sizeof(mru)); memcpy(maxPayload.payload, &mru, sizeof(mru)); CHECK_ROOM(cursor, packet.payload, sizeof(mru) + TAG_HDR_SIZE); memcpy(cursor, &maxPayload, sizeof(mru) + TAG_HDR_SIZE); cursor += sizeof(mru) + TAG_HDR_SIZE; plen += sizeof(mru) + TAG_HDR_SIZE; } #endif packet.length = htons(plen); sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE)); #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "SENT"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif } /********************************************************************** *%FUNCTION: waitForPADS *%ARGUMENTS: * conn -- PPPoE connection info * timeout -- how long to wait (in seconds) *%RETURNS: * Nothing *%DESCRIPTION: * Waits for a PADS packet and copies useful information ***********************************************************************/ static void waitForPADS(PPPoEConnection *conn, int timeout) { fd_set readable; int r; struct timeval tv; struct timeval expire_at; PPPoEPacket packet; int len; if (gettimeofday(&expire_at, NULL) < 0) { fatalSys("gettimeofday (waitForPADS)"); } expire_at.tv_sec += timeout; do { if (BPF_BUFFER_IS_EMPTY) { if(!time_left(&tv, &expire_at)) { /* Timed out */ return; } FD_ZERO(&readable); FD_SET(conn->discoverySocket, &readable); while(1) { r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv); if (r >= 0 || errno != EINTR) break; } if (r < 0) { fatalSys("select (waitForPADS)"); } if (r == 0) { /* Timed out */ return; } } /* Get the packet */ receivePacket(conn->discoverySocket, &packet, &len); /* Check length */ if (ntohs(packet.length) + HDR_SIZE > len) { syslog(LOG_ERR, "Bogus PPPoE length field (%u)", (unsigned int) ntohs(packet.length)); continue; } #ifdef USE_BPF /* If it's not a Discovery packet, loop again */ if (etherType(&packet) != Eth_PPPOE_Discovery) continue; #endif #ifdef DEBUGGING_ENABLED if (conn->debugFile) { dumpPacket(conn->debugFile, &packet, "RCVD"); fprintf(conn->debugFile, "\n"); fflush(conn->debugFile); } #endif /* If it's not from the AC, it's not for me */ if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue; /* If it's not for us, loop again */ if (!packetIsForMe(conn, &packet)) continue; /* Is it PADS? */ if (packet.code == CODE_PADS) { /* Parse for goodies */ conn->PADSHadError = 0; parsePacket(&packet, parsePADSTags, conn); if (!conn->PADSHadError) { conn->discoveryState = STATE_SESSION; break; } } } while (conn->discoveryState != STATE_SESSION); /* Don't bother with ntohs; we'll just end up converting it back... */ conn->session = packet.session; syslog(LOG_INFO, "PPP session is %d (0x%x)", (int) ntohs(conn->session), (unsigned int) ntohs(conn->session)); /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */ if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) { syslog(LOG_ERR, "Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session)); } } /********************************************************************** *%FUNCTION: discovery *%ARGUMENTS: * conn -- PPPoE connection info structure *%RETURNS: * Nothing *%DESCRIPTION: * Performs the PPPoE discovery phase ***********************************************************************/ void discovery(PPPoEConnection *conn) { int padiAttempts; int padrAttempts; int timeout = conn->discoveryTimeout; /* Skip discovery? */ if (conn->skipDiscovery) { conn->discoveryState = STATE_SESSION; if (conn->killSession) { sendPADT(conn, "RP-PPPoE: Session killed manually"); exit(0); } return; } SEND_PADI: padiAttempts = 0; do { padiAttempts++; if (padiAttempts > MAX_PADI_ATTEMPTS) { printErr("Timeout waiting for PADO packets"); if (persist) { padiAttempts = 0; timeout = conn->discoveryTimeout; } else { return; } } sendPADI(conn); conn->discoveryState = STATE_SENT_PADI; waitForPADO(conn, timeout); /* If we're just probing for access concentrators, don't do exponential backoff. This reduces the time for an unsuccessful probe to 15 seconds. */ if (!conn->printACNames) { timeout *= 2; } if (conn->printACNames && conn->numPADOs) { break; } } while (conn->discoveryState == STATE_SENT_PADI); /* If we're only printing access concentrator names, we're done */ if (conn->printACNames) { exit(0); } timeout = conn->discoveryTimeout; padrAttempts = 0; do { padrAttempts++; if (padrAttempts > MAX_PADI_ATTEMPTS) { printErr("Timeout waiting for PADS packets"); if (persist) { padrAttempts = 0; timeout = conn->discoveryTimeout; /* Go back to sending PADI again */ goto SEND_PADI; } else { return; } } sendPADR(conn); conn->discoveryState = STATE_SENT_PADR; waitForPADS(conn, timeout); timeout *= 2; } while (conn->discoveryState == STATE_SENT_PADR); #ifdef PLUGIN if (!conn->seenMaxPayload) { /* RFC 4638: MUST limit MTU/MRU to 1492 */ if (lcp_allowoptions[0].mru > ETH_PPPOE_MTU) lcp_allowoptions[0].mru = ETH_PPPOE_MTU; if (lcp_wantoptions[0].mru > ETH_PPPOE_MTU) lcp_wantoptions[0].mru = ETH_PPPOE_MTU; } #endif /* We're done. */ conn->discoveryState = STATE_SESSION; return; } rp-pppoe-3.15/src/plugin.c0000644000175000017500000003734114045237010013553 0ustar dfsdfs/*********************************************************************** * * plugin.c * * pppd plugin for kernel-mode PPPoE on Linux * * Copyright (C) 2001-2012 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * Portions copyright 2000 Michal Ostrowski and Jamal Hadi Salim. * * Much code and many ideas derived from pppoe plugin by Michal * Ostrowski and Jamal Hadi Salim, which carries this copyright: * * Copyright 2000 Michal Ostrowski , * Jamal Hadi Salim * Borrows heavily from the PPPoATM plugin by Mitchell Blank Jr., * which is based in part on work from Jens Axboe and Paul Mackerras. * * 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. * * LIC: GPL * ***********************************************************************/ #define _GNU_SOURCE 1 #include "pppoe.h" #include "pppd/pppd.h" #include "pppd/fsm.h" #include "pppd/lcp.h" #include "pppd/ipcp.h" #include "pppd/ccp.h" /* #include "pppd/pathnames.h" */ #include #include #include #include #include #if defined(HAVE_LINUX_IF_H) #include #elif defined(HAVE_NET_IF_H) #include #endif #include #include #include #include #include #include #include #include #include #include #include #ifndef _ROOT_PATH #define _ROOT_PATH "" #endif #define _PATH_ETHOPT _ROOT_PATH "/etc/ppp/options." char pppd_version[] = VERSION; static int seen_devnam[2] = {0, 0}; static char *pppoe_reqd_mac = NULL; /* From sys-linux.c in pppd -- MUST FIX THIS! */ extern int new_style_driver; char *pppd_pppoe_service = NULL; static char *acName = NULL; static char *existingSession = NULL; static int printACNames = 0; static int PPPoEDevnameHook(char *cmd, char **argv, int doit); static option_t Options[] = { { "device name", o_wild, (void *) &PPPoEDevnameHook, "PPPoE device name", OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG | OPT_A2STRVAL | OPT_STATIC, devnam}, { "rp_pppoe_service", o_string, &pppd_pppoe_service, "Desired PPPoE service name" }, { "rp_pppoe_ac", o_string, &acName, "Desired PPPoE access concentrator name" }, { "rp_pppoe_sess", o_string, &existingSession, "Attach to existing session (sessid:macaddr)" }, { "rp_pppoe_verbose", o_int, &printACNames, "Be verbose about discovered access concentrators"}, { "rp_pppoe_mac", o_string, &pppoe_reqd_mac, "Only connect to specified MAC address" }, { NULL } }; static PPPoEConnection *conn = NULL; /********************************************************************** * %FUNCTION: PPPOEInitDevice * %ARGUMENTS: * None * %RETURNS: * * %DESCRIPTION: * Initializes PPPoE device. ***********************************************************************/ static int PPPOEInitDevice(void) { conn = malloc(sizeof(PPPoEConnection)); if (!conn) { fatal("Could not allocate memory for PPPoE session"); } memset(conn, 0, sizeof(PPPoEConnection)); if (acName) { SET_STRING(conn->acName, acName); } if (pppd_pppoe_service) { SET_STRING(conn->serviceName, pppd_pppoe_service); } if (strlen(devnam) > IFNAMSIZ) { fatal("Device name %s is too long - max length %d", devnam, (int) IFNAMSIZ); } SET_STRING(conn->ifName, devnam); conn->discoverySocket = -1; conn->sessionSocket = -1; conn->hostUniq = malloc(17); if (!conn->hostUniq) { fatal("Out of Memory"); } snprintf(conn->hostUniq, 17, "%lx", (unsigned long) getpid()); conn->printACNames = printACNames; conn->discoveryTimeout = PADI_TIMEOUT; return 1; } /********************************************************************** * %FUNCTION: PPPOEConnectDevice * %ARGUMENTS: * None * %RETURNS: * Non-negative if all goes well; -1 otherwise * %DESCRIPTION: * Connects PPPoE device. ***********************************************************************/ static int PPPOEConnectDevice(void) { struct sockaddr_pppox sp; struct ifreq ifr; int s; /* Restore configuration */ lcp_allowoptions[0].mru = conn->mtu; lcp_wantoptions[0].mru = conn->mru; /* Update maximum MRU */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { error("Can't get MTU for %s: %m", conn->ifName); return -1; } strlcpy(ifr.ifr_name, conn->ifName, sizeof(ifr.ifr_name)); if (ioctl(s, SIOCGIFMTU, &ifr) < 0) { error("Can't get MTU for %s: %m", conn->ifName); close(s); return -1; } close(s); if (lcp_allowoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD) { lcp_allowoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD; } if (lcp_wantoptions[0].mru > ifr.ifr_mtu - TOTAL_OVERHEAD) { lcp_wantoptions[0].mru = ifr.ifr_mtu - TOTAL_OVERHEAD; } /* Open session socket before discovery phase, to avoid losing session */ /* packets sent by peer just after PADS packet (noted on some Cisco */ /* server equipment). */ /* Opening this socket just before waitForPADS in the discovery() */ /* function would be more appropriate, but it would mess-up the code */ conn->sessionSocket = socket(AF_PPPOX, SOCK_STREAM, PX_PROTO_OE); if (conn->sessionSocket < 0) { error("Failed to create PPPoE socket: %m"); return -1; } if (acName) { SET_STRING(conn->acName, acName); } if (pppd_pppoe_service) { SET_STRING(conn->serviceName, pppd_pppoe_service); } strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); if (existingSession) { unsigned int mac[ETH_ALEN]; int i, ses; if (sscanf(existingSession, "%d:%x:%x:%x:%x:%x:%x", &ses, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != 7) { fatal("Illegal value for rp_pppoe_sess option"); } conn->session = htons(ses); for (i=0; ipeerEth[i] = (unsigned char) mac[i]; } } else { conn->discoverySocket = openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth, NULL); discovery(conn); if (conn->discoveryState != STATE_SESSION) { error("Unable to complete PPPoE Discovery"); close(conn->discoverySocket); conn->discoverySocket = -1; return -1; } } /* Set PPPoE session-number for further consumption */ ppp_session_number = ntohs(conn->session); sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; sp.sa_addr.pppoe.sid = conn->session; memset(sp.sa_addr.pppoe.dev, 0, IFNAMSIZ); memcpy(sp.sa_addr.pppoe.dev, conn->ifName, strlen(conn->ifName)); memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN); /* Set remote_number for ServPoET */ sprintf(remote_number, "%02X:%02X:%02X:%02X:%02X:%02X", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5]); warn("Connected to %02X:%02X:%02X:%02X:%02X:%02X via interface %s", (unsigned) conn->peerEth[0], (unsigned) conn->peerEth[1], (unsigned) conn->peerEth[2], (unsigned) conn->peerEth[3], (unsigned) conn->peerEth[4], (unsigned) conn->peerEth[5], conn->ifName); script_setenv("MACREMOTE", remote_number, 0); if (connect(conn->sessionSocket, (struct sockaddr *) &sp, sizeof(struct sockaddr_pppox)) < 0) { error("Failed to connect PPPoE socket: %d %m", errno); return -1; } return conn->sessionSocket; } static void PPPOESendConfig(int mtu, u_int32_t asyncmap, int pcomp, int accomp) { int sock; struct ifreq ifr; if (mtu > MAX_PPPOE_MTU) { warn("Couldn't increase MTU to %d", mtu); mtu = MAX_PPPOE_MTU; } sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { warn("Couldn't create IP socket: %m"); return; } strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ifr.ifr_mtu = mtu; if (ioctl(sock, SIOCSIFMTU, &ifr) < 0) { warn("ioctl(SIOCSIFMTU): %m"); return; } (void) close (sock); } static void PPPOERecvConfig(int mru, u_int32_t asyncmap, int pcomp, int accomp) { if (mru > MAX_PPPOE_MTU) { warn("Couldn't increase MRU to %d", mru); } } /********************************************************************** * %FUNCTION: PPPOEDisconnectDevice * %ARGUMENTS: * None * %RETURNS: * Nothing * %DESCRIPTION: * Disconnects PPPoE device ***********************************************************************/ static void PPPOEDisconnectDevice(void) { struct sockaddr_pppox sp; sp.sa_family = AF_PPPOX; sp.sa_protocol = PX_PROTO_OE; sp.sa_addr.pppoe.sid = 0; memset(sp.sa_addr.pppoe.dev, 0, IFNAMSIZ); memcpy(sp.sa_addr.pppoe.dev, conn->ifName, strlen(conn->ifName)); memcpy(sp.sa_addr.pppoe.remote, conn->peerEth, ETH_ALEN); if (connect(conn->sessionSocket, (struct sockaddr *) &sp, sizeof(struct sockaddr_pppox)) < 0 && errno != EALREADY) { fatal("Failed to disconnect PPPoE socket: %d %m", errno); return; } close(conn->sessionSocket); if (conn->discoverySocket >= 0) { sendPADT(conn, NULL); close(conn->discoverySocket); } /* Do NOT free conn; if pppd persist is on, we'll need it again */ } static void PPPOEDeviceOptions(void) { char buf[MAXPATHLEN]; strlcpy(buf, _PATH_ETHOPT, MAXPATHLEN); strlcat(buf, devnam, MAXPATHLEN); if(!options_from_file(buf, 0, 0, 1)) exit(EXIT_OPTION_ERROR); } struct channel pppoe_channel; /********************************************************************** * %FUNCTION: PPPoEDevnameHook * %ARGUMENTS: * cmd -- the command (actually, the device name) * argv -- argument vector * doit -- if non-zero, set device name. Otherwise, just check if possible * %RETURNS: * 1 if we will handle this device; 0 otherwise. * %DESCRIPTION: * Checks if name is a valid interface name; if so, returns 1. Also * sets up devnam (string representation of device). ***********************************************************************/ static int PPPoEDevnameHook(char *cmd, char **argv, int doit) { int r = 1; int fd; struct ifreq ifr; int seen_idx = doit ? 1 : 0; /* If "devnam" has already been set, ignore. This prevents kernel from doing modprobes against random pppd arguments that happen to begin with "nic-", "eth" or "br" Ideally, "nix-ethXXX" should be supplied immediately after "plugin rp-pppoe.so" Patch based on suggestion from Mike Ireton. */ if (seen_devnam[seen_idx]) { return 0; } /* Only do it if name is "ethXXX" or "brXXX" or what was specified by rp_pppoe_dev option (ugh). */ /* Can also specify nic-XXXX in which case the nic- is stripped off. */ if (!strncmp(cmd, "nic-", 4)) { cmd += 4; } else { if (strncmp(cmd, "eth", 3) && strncmp(cmd, "br", 2)) { return 0; } } /* Open a socket */ if ((fd = socket(PF_PACKET, SOCK_RAW, 0)) < 0) { r = 0; } /* Try getting interface index */ if (r) { strlcpy(ifr.ifr_name, cmd, IFNAMSIZ); if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { r = 0; } else { if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { r = 0; } else { if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { if (doit) error("Interface %s not Ethernet", cmd); r = 0; } } } } /* Close socket */ close(fd); if (r) { seen_devnam[seen_idx] = 1; if (doit) { strlcpy(devnam, cmd, sizeof(devnam)); if (the_channel != &pppoe_channel) { the_channel = &pppoe_channel; modem = 0; lcp_allowoptions[0].neg_accompression = 0; lcp_wantoptions[0].neg_accompression = 0; lcp_allowoptions[0].neg_asyncmap = 0; lcp_wantoptions[0].neg_asyncmap = 0; lcp_allowoptions[0].neg_pcompression = 0; lcp_wantoptions[0].neg_pcompression = 0; ipcp_allowoptions[0].neg_vj=0; ipcp_wantoptions[0].neg_vj=0; ccp_allowoptions[0].deflate = 0 ; ccp_wantoptions[0].deflate = 0 ; ccp_allowoptions[0].bsd_compress = 0; ccp_wantoptions[0].bsd_compress = 0; PPPOEInitDevice(); } } return 1; } return r; } /********************************************************************** * %FUNCTION: plugin_init * %ARGUMENTS: * None * %RETURNS: * Nothing * %DESCRIPTION: * Initializes hooks for pppd plugin ***********************************************************************/ void plugin_init(void) { if (!ppp_available() && !new_style_driver) { fatal("Linux kernel does not support PPPoE -- are you running 2.4.x?"); } add_options(Options); info("RP-PPPoE plugin version %s compiled against pppd %s", RP_VERSION, VERSION); } /********************************************************************** *%FUNCTION: fatalSys *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to stderr and syslog and exits. * ***********************************************************************/ void fatalSys(char const *str) { char buf[1024]; int i = errno; sprintf(buf, "%.256s: %.256s", str, strerror(i)); printErr(buf); sprintf(buf, "RP-PPPoE: %.256s: %.256s", str, strerror(i)); sendPADT(conn, buf); exit(1); } /********************************************************************** *%FUNCTION: rp_fatal *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message to stderr and syslog and exits. ***********************************************************************/ void rp_fatal(char const *str) { printErr(str); sendPADTf(conn, "RP-PPPoE: %.256s", str); exit(1); } /********************************************************************** *%FUNCTION: sysErr *%ARGUMENTS: * str -- error message *%RETURNS: * Nothing *%DESCRIPTION: * Prints a message plus the errno value to syslog. ***********************************************************************/ void sysErr(char const *str) { rp_fatal(str); } void pppoe_check_options(void) { unsigned int mac[ETH_ALEN]; int i; if (pppoe_reqd_mac != NULL) { if (sscanf(pppoe_reqd_mac, "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) != ETH_ALEN) { option_error("cannot parse pppoe-mac option value"); exit(EXIT_OPTION_ERROR); } for (i = 0; i < 6; ++i) conn->req_peer_mac[i] = mac[i]; conn->req_peer = 1; } lcp_allowoptions[0].neg_accompression = 0; lcp_wantoptions[0].neg_accompression = 0; lcp_allowoptions[0].neg_asyncmap = 0; lcp_wantoptions[0].neg_asyncmap = 0; lcp_allowoptions[0].neg_pcompression = 0; lcp_wantoptions[0].neg_pcompression = 0; if (lcp_allowoptions[0].mru > MAX_PPPOE_MTU) { lcp_allowoptions[0].mru = MAX_PPPOE_MTU; } if (lcp_wantoptions[0].mru > MAX_PPPOE_MTU) { lcp_wantoptions[0].mru = MAX_PPPOE_MTU; } /* Save configuration */ conn->mtu = lcp_allowoptions[0].mru; conn->mru = lcp_wantoptions[0].mru; ccp_allowoptions[0].deflate = 0; ccp_wantoptions[0].deflate = 0; ipcp_allowoptions[0].neg_vj = 0; ipcp_wantoptions[0].neg_vj = 0; ccp_allowoptions[0].bsd_compress = 0; ccp_wantoptions[0].bsd_compress = 0; } struct channel pppoe_channel = { .options = Options, .process_extra_options = &PPPOEDeviceOptions, .check_options = &pppoe_check_options, .connect = &PPPOEConnectDevice, .disconnect = &PPPOEDisconnectDevice, .establish_ppp = &generic_establish_ppp, .disestablish_ppp = &generic_disestablish_ppp, .send_config = &PPPOESendConfig, .recv_config = &PPPOERecvConfig, .close = NULL, .cleanup = NULL }; rp-pppoe-3.15/src/libevent/0000755000175000017500000000000014045237010013711 5ustar dfsdfsrp-pppoe-3.15/src/libevent/event_sig.c0000644000175000017500000001721414045237010016045 0ustar dfsdfs/*********************************************************************** * * event_sig.c * * Code for handling signals nicely (synchronously) and for dealing * with reaping child processes. * * Copyright (C) 2002 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This software may be distributed under the terms of the GNU General * Public License, Version 2, or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #define _POSIX_SOURCE 1 /* For sigaction defines */ #include #include #include #include #include #include #include "event.h" #include "hash.h" /* Kludge for figuring out NSIG */ #ifdef NSIG #define MAX_SIGNALS NSIG #elif defined(_NSIG) #define MAX_SIGNALS _NSIG #else #define MAX_SIGNALS 256 /* Should be safe... */ #endif /* A structure for a "synchronous" signal handler */ struct SynchronousSignalHandler { int fired; /* Have we received this signal? */ void (*handler)(int sig); /* Handler function */ }; /* A structure for calling back when a child dies */ struct ChildEntry { hash_bucket hash; void (*handler)(pid_t pid, int status, void *data); pid_t pid; void *data; }; static struct SynchronousSignalHandler SignalHandlers[MAX_SIGNALS]; static int Pipe[2] = {-1, -1}; static pid_t MyPid = (pid_t) -1; static EventHandler *PipeHandler = NULL; static hash_table child_process_table; static unsigned int child_hash(void *data) { return (unsigned int) ((struct ChildEntry *) data)->pid; } static int child_compare(void *d1, void *d2) { return ((struct ChildEntry *)d1)->pid != ((struct ChildEntry *)d2)->pid; } /********************************************************************** * %FUNCTION: DoPipe * %ARGUMENTS: * es -- event selector * fd -- readable file descriptor * flags -- flags from event system * data -- ignored * %RETURNS: * Nothing * %DESCRIPTION: * Called when an async signal handler wants attention. This function * fires all "synchronous" signal handlers. ***********************************************************************/ static void DoPipe(EventSelector *es, int fd, unsigned int flags, void *data) { char buf[64]; int i; sigset_t set; /* Clear pipe */ while (read(fd, buf, 64) == 64) { ; } /* Fire handlers */ for (i=0; i MAX_SIGNALS) { /* Ooops... */ return; } if (getpid() != MyPid) { /* Spuriously-caught signal caught in child! */ return; } /* If there's no handler, ignore it */ if (!SignalHandlers[sig].handler) { return; } SignalHandlers[sig].fired = 1; int errno_save = errno; write(Pipe[1], &sig, 1); errno = errno_save; } /********************************************************************** * %FUNCTION: child_handler * %ARGUMENTS: * sig -- signal number (whoop-dee-doo) * %RETURNS: * Nothing * %DESCRIPTION: * Called *SYNCHRONOUSLY* to reap dead children. SIGCHLD is blocked * during the execution of this function. ***********************************************************************/ static void child_handler(int sig) { int status; int pid; struct ChildEntry *ce; struct ChildEntry candidate; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { candidate.pid = (pid_t) pid; ce = hash_find(&child_process_table, &candidate); if (ce) { hash_remove(&child_process_table, ce); if (ce->handler) { ce->handler(pid, status, ce->data); } free(ce); } } } /********************************************************************** * %FUNCTION: SetupPipes (static) * %ARGUMENTS: * es -- event selector * %RETURNS: * 0 on success; -1 on failure * %DESCRIPTION: * Sets up pipes with an event handler to handle IPC from a signal handler ***********************************************************************/ static int SetupPipes(EventSelector *es) { int flags; int i; /* If already done, do nothing */ if (PipeHandler) return 0; MyPid = getpid(); /* Initialize the child-process hash table */ hash_init(&child_process_table, offsetof(struct ChildEntry, hash), child_hash, child_compare); /* Open pipe to self */ if (pipe(Pipe) < 0) { return -1; } /* Make pipes non-blocking */ for (i=0; i<=1; i++) { flags = fcntl(Pipe[i], F_GETFL, 0); if (flags != -1) { flags = fcntl(Pipe[i], F_SETFL, flags | O_NONBLOCK); } if (flags == -1) { close(Pipe[0]); close(Pipe[1]); return -1; } } PipeHandler = Event_AddHandler(es, Pipe[0], EVENT_FLAG_READABLE, DoPipe, NULL); if (!PipeHandler) { int old_errno = errno; close(Pipe[0]); close(Pipe[1]); errno = old_errno; return -1; } return 0; } /********************************************************************** * %FUNCTION: Event_HandleSignal * %ARGUMENTS: * es -- event selector * sig -- signal number * handler -- handler to call when signal is raised. Handler is called * "synchronously" as events are processed by event loop. * %RETURNS: * 0 on success, -1 on error. * %DESCRIPTION: * Sets up a "synchronous" signal handler. ***********************************************************************/ int Event_HandleSignal(EventSelector *es, int sig, void (*handler)(int sig)) { struct sigaction act; if (SetupPipes(es) < 0) return -1; act.sa_handler = sig_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif if (sig == SIGCHLD) { act.sa_flags |= SA_NOCLDSTOP; } if (sigaction(sig, &act, NULL) < 0) return -1; SignalHandlers[sig].handler = handler; return 0; } /********************************************************************** * %FUNCTION: Event_HandleChildExit * %ARGUMENTS: * es -- event selector * pid -- process-ID of child to wait for * handler -- function to call when child exits * data -- data to pass to handler when child exits * %RETURNS: * 0 on success, -1 on failure. * %DESCRIPTION: * Sets things up so that when a child exits, handler() will be called * with the pid of the child and "data" as arguments. The call will * be synchronous (part of the normal event loop on es). ***********************************************************************/ int Event_HandleChildExit(EventSelector *es, pid_t pid, void (*handler)(pid_t, int, void *), void *data) { struct ChildEntry *ce; sigset_t set; if (Event_HandleSignal(es, SIGCHLD, child_handler) < 0) return -1; ce = malloc(sizeof(struct ChildEntry)); if (!ce) return -1; ce->pid = pid; ce->data = data; ce->handler = handler; /* Critical section: Don't let SIGCHLD mess hash_insert */ sigemptyset(&set); sigaddset(&set, SIGCHLD); sigprocmask(SIG_BLOCK, &set, NULL); hash_insert(&child_process_table, ce); sigprocmask(SIG_UNBLOCK, &set, NULL); return 0; } rp-pppoe-3.15/src/libevent/event.c0000644000175000017500000003757014045237010015212 0ustar dfsdfs/*********************************************************************** * * event.c * * Abstraction of select call into "event-handling" to make programming * easier. * * Copyright (C) 2001 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #include "event.h" #include #include static void DestroySelector(EventSelector *es); static void DestroyHandler(EventHandler *eh); static void DoPendingChanges(EventSelector *es); /********************************************************************** * %FUNCTION: Event_CreateSelector * %ARGUMENTS: * None * %RETURNS: * A newly-allocated EventSelector, or NULL if out of memory. * %DESCRIPTION: * Creates a new EventSelector. ***********************************************************************/ EventSelector * Event_CreateSelector(void) { EventSelector *es = malloc(sizeof(EventSelector)); if (!es) return NULL; es->handlers = NULL; es->nestLevel = 0; es->destroyPending = 0; es->opsPending = 0; EVENT_DEBUG(("CreateSelector() -> %p\n", (void *) es)); return es; } /********************************************************************** * %FUNCTION: Event_DestroySelector * %ARGUMENTS: * es -- EventSelector to destroy * %RETURNS: * Nothing * %DESCRIPTION: * Destroys an EventSelector. Destruction may be delayed if we * are in the HandleEvent function. ***********************************************************************/ void Event_DestroySelector(EventSelector *es) { if (es->nestLevel) { es->destroyPending = 1; es->opsPending = 1; return; } DestroySelector(es); } /********************************************************************** * %FUNCTION: Event_HandleEvent * %ARGUMENTS: * es -- EventSelector * %RETURNS: * 0 if OK, non-zero on error. errno is set appropriately. * %DESCRIPTION: * Handles a single event (uses select() to wait for an event.) ***********************************************************************/ int Event_HandleEvent(EventSelector *es) { fd_set readfds, writefds; fd_set *rd, *wr; unsigned int flags; struct timeval abs_timeout, now; struct timeval timeout; struct timeval *tm; EventHandler *eh; int r = 0; int errno_save = 0; int foundTimeoutEvent = 0; int foundReadEvent = 0; int foundWriteEvent = 0; int maxfd = -1; int pastDue; /* Avoid compiler warning */ abs_timeout.tv_sec = 0; abs_timeout.tv_usec = 0; EVENT_DEBUG(("Enter Event_HandleEvent(es=%p)\n", (void *) es)); /* Build the select sets */ FD_ZERO(&readfds); FD_ZERO(&writefds); eh = es->handlers; for (eh=es->handlers; eh; eh=eh->next) { if (eh->flags & EVENT_FLAG_DELETED) continue; if (eh->flags & EVENT_FLAG_READABLE) { foundReadEvent = 1; FD_SET(eh->fd, &readfds); if (eh->fd > maxfd) maxfd = eh->fd; } if (eh->flags & EVENT_FLAG_WRITEABLE) { foundWriteEvent = 1; FD_SET(eh->fd, &writefds); if (eh->fd > maxfd) maxfd = eh->fd; } if (eh->flags & EVENT_TIMER_BITS) { if (!foundTimeoutEvent) { abs_timeout = eh->tmout; foundTimeoutEvent = 1; } else { if (eh->tmout.tv_sec < abs_timeout.tv_sec || (eh->tmout.tv_sec == abs_timeout.tv_sec && eh->tmout.tv_usec < abs_timeout.tv_usec)) { abs_timeout = eh->tmout; } } } } if (foundReadEvent) { rd = &readfds; } else { rd = NULL; } if (foundWriteEvent) { wr = &writefds; } else { wr = NULL; } if (foundTimeoutEvent) { gettimeofday(&now, NULL); /* Convert absolute timeout to relative timeout for select */ timeout.tv_usec = abs_timeout.tv_usec - now.tv_usec; timeout.tv_sec = abs_timeout.tv_sec - now.tv_sec; if (timeout.tv_usec < 0) { timeout.tv_usec += 1000000; timeout.tv_sec--; } if (timeout.tv_sec < 0 || (timeout.tv_sec == 0 && timeout.tv_usec < 0)) { timeout.tv_sec = 0; timeout.tv_usec = 0; } tm = &timeout; } else { tm = NULL; } if (foundReadEvent || foundWriteEvent || foundTimeoutEvent) { for(;;) { r = select(maxfd+1, rd, wr, NULL, tm); if (r < 0) { if (errno == EINTR) continue; } break; } } if (foundTimeoutEvent) gettimeofday(&now, NULL); errno_save = errno; es->nestLevel++; if (r >= 0) { /* Call handlers */ for (eh=es->handlers; eh; eh=eh->next) { /* Pending delete for this handler? Ignore it */ if (eh->flags & EVENT_FLAG_DELETED) continue; flags = 0; if ((eh->flags & EVENT_FLAG_READABLE) && FD_ISSET(eh->fd, &readfds)) { flags |= EVENT_FLAG_READABLE; } if ((eh->flags & EVENT_FLAG_WRITEABLE) && FD_ISSET(eh->fd, &writefds)) { flags |= EVENT_FLAG_WRITEABLE; } if (eh->flags & EVENT_TIMER_BITS) { pastDue = (eh->tmout.tv_sec < now.tv_sec || (eh->tmout.tv_sec == now.tv_sec && eh->tmout.tv_usec <= now.tv_usec)); if (pastDue) { flags |= EVENT_TIMER_BITS; if (eh->flags & EVENT_FLAG_TIMER) { /* Timer events are only called once */ es->opsPending = 1; eh->flags |= EVENT_FLAG_DELETED; } } } /* Do callback */ if (flags) { EVENT_DEBUG(("Enter callback: eh=%p flags=%u fd=%d\n", eh, flags, eh->fd)); eh->fn(es, eh->fd, flags, eh->data); EVENT_DEBUG(("Leave callback: eh=%p flags=%u fd=%d\n", eh, flags, eh->fd)); } } } es->nestLevel--; if (!es->nestLevel && es->opsPending) { DoPendingChanges(es); } errno = errno_save; return r; } /********************************************************************** * %FUNCTION: Event_AddHandler * %ARGUMENTS: * es -- event selector * fd -- file descriptor to watch * flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE * fn -- callback function to call when event is triggered * data -- extra data to pass to callback function * %RETURNS: * A newly-allocated EventHandler, or NULL. ***********************************************************************/ EventHandler * Event_AddHandler(EventSelector *es, int fd, unsigned int flags, EventCallbackFunc fn, void *data) { EventHandler *eh; /* Specifically disable timer and deleted flags */ flags &= (~(EVENT_TIMER_BITS | EVENT_FLAG_DELETED)); /* Bad file descriptor */ if (fd < 0) { errno = EBADF; return NULL; } eh = malloc(sizeof(EventHandler)); if (!eh) return NULL; eh->fd = fd; eh->flags = flags; eh->tmout.tv_usec = 0; eh->tmout.tv_sec = 0; eh->fn = fn; eh->data = data; /* Add immediately. This is safe even if we are in a handler. */ eh->next = es->handlers; es->handlers = eh; EVENT_DEBUG(("Event_AddHandler(es=%p, fd=%d, flags=%u) -> %p\n", es, fd, flags, eh)); return eh; } /********************************************************************** * %FUNCTION: Event_AddHandlerWithTimeout * %ARGUMENTS: * es -- event selector * fd -- file descriptor to watch * flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE * t -- Timeout after which to call handler, even if not readable/writable. * If t.tv_sec < 0, calls normal Event_AddHandler with no timeout. * fn -- callback function to call when event is triggered * data -- extra data to pass to callback function * %RETURNS: * A newly-allocated EventHandler, or NULL. ***********************************************************************/ EventHandler * Event_AddHandlerWithTimeout(EventSelector *es, int fd, unsigned int flags, struct timeval t, EventCallbackFunc fn, void *data) { EventHandler *eh; struct timeval now; /* If timeout is negative, just do normal non-timing-out event */ if (t.tv_sec < 0 || t.tv_usec < 0) { return Event_AddHandler(es, fd, flags, fn, data); } /* Specifically disable timer and deleted flags */ flags &= (~(EVENT_FLAG_TIMER | EVENT_FLAG_DELETED)); flags |= EVENT_FLAG_TIMEOUT; /* Bad file descriptor? */ if (fd < 0) { errno = EBADF; return NULL; } /* Bad timeout? */ if (t.tv_usec >= 1000000) { errno = EINVAL; return NULL; } eh = malloc(sizeof(EventHandler)); if (!eh) return NULL; /* Convert time interval to absolute time */ gettimeofday(&now, NULL); t.tv_sec += now.tv_sec; t.tv_usec += now.tv_usec; if (t.tv_usec >= 1000000) { t.tv_usec -= 1000000; t.tv_sec++; } eh->fd = fd; eh->flags = flags; eh->tmout = t; eh->fn = fn; eh->data = data; /* Add immediately. This is safe even if we are in a handler. */ eh->next = es->handlers; es->handlers = eh; EVENT_DEBUG(("Event_AddHandlerWithTimeout(es=%p, fd=%d, flags=%u, t=%d/%d) -> %p\n", es, fd, flags, t.tv_sec, t.tv_usec, eh)); return eh; } /********************************************************************** * %FUNCTION: Event_AddTimerHandler * %ARGUMENTS: * es -- event selector * t -- time interval after which to trigger event * fn -- callback function to call when event is triggered * data -- extra data to pass to callback function * %RETURNS: * A newly-allocated EventHandler, or NULL. ***********************************************************************/ EventHandler * Event_AddTimerHandler(EventSelector *es, struct timeval t, EventCallbackFunc fn, void *data) { EventHandler *eh; struct timeval now; /* Check time interval for validity */ if (t.tv_sec < 0 || t.tv_usec < 0 || t.tv_usec >= 1000000) { errno = EINVAL; return NULL; } eh = malloc(sizeof(EventHandler)); if (!eh) return NULL; /* Convert time interval to absolute time */ gettimeofday(&now, NULL); t.tv_sec += now.tv_sec; t.tv_usec += now.tv_usec; if (t.tv_usec >= 1000000) { t.tv_usec -= 1000000; t.tv_sec++; } eh->fd = -1; eh->flags = EVENT_FLAG_TIMER; eh->tmout = t; eh->fn = fn; eh->data = data; /* Add immediately. This is safe even if we are in a handler. */ eh->next = es->handlers; es->handlers = eh; EVENT_DEBUG(("Event_AddTimerHandler(es=%p, t=%d/%d) -> %p\n", es, t.tv_sec,t.tv_usec, eh)); return eh; } /********************************************************************** * %FUNCTION: Event_DelHandler * %ARGUMENTS: * es -- event selector * eh -- event handler * %RETURNS: * 0 if OK, non-zero if there is an error * %DESCRIPTION: * Deletes the event handler eh ***********************************************************************/ int Event_DelHandler(EventSelector *es, EventHandler *eh) { /* Scan the handlers list */ EventHandler *cur, *prev; EVENT_DEBUG(("Event_DelHandler(es=%p, eh=%p)\n", es, eh)); for (cur=es->handlers, prev=NULL; cur; prev=cur, cur=cur->next) { if (cur == eh) { if (es->nestLevel) { eh->flags |= EVENT_FLAG_DELETED; es->opsPending = 1; return 0; } else { if (prev) prev->next = cur->next; else es->handlers = cur->next; DestroyHandler(cur); return 0; } } } /* Handler not found */ return 1; } /********************************************************************** * %FUNCTION: DestroySelector * %ARGUMENTS: * es -- an event selector * %RETURNS: * Nothing * %DESCRIPTION: * Destroys selector and all associated handles. ***********************************************************************/ void DestroySelector(EventSelector *es) { EventHandler *cur, *next; for (cur=es->handlers; cur; cur=next) { next = cur->next; DestroyHandler(cur); } free(es); } /********************************************************************** * %FUNCTION: DestroyHandler * %ARGUMENTS: * eh -- an event handler * %RETURNS: * Nothing * %DESCRIPTION: * Destroys handler ***********************************************************************/ void DestroyHandler(EventHandler *eh) { EVENT_DEBUG(("DestroyHandler(eh=%p)\n", eh)); free(eh); } /********************************************************************** * %FUNCTION: DoPendingChanges * %ARGUMENTS: * es -- an event selector * %RETURNS: * Nothing * %DESCRIPTION: * Makes all pending insertions and deletions happen. ***********************************************************************/ void DoPendingChanges(EventSelector *es) { EventHandler *cur, *prev, *next; es->opsPending = 0; /* If selector is to be deleted, do it and skip everything else */ if (es->destroyPending) { DestroySelector(es); return; } /* Do deletions */ cur = es->handlers; prev = NULL; while(cur) { if (!(cur->flags & EVENT_FLAG_DELETED)) { prev = cur; cur = cur->next; continue; } /* Unlink from list */ if (prev) { prev->next = cur->next; } else { es->handlers = cur->next; } next = cur->next; DestroyHandler(cur); cur = next; } } /********************************************************************** * %FUNCTION: Event_GetCallback * %ARGUMENTS: * eh -- the event handler * %RETURNS: * The callback function ***********************************************************************/ EventCallbackFunc Event_GetCallback(EventHandler *eh) { return eh->fn; } /********************************************************************** * %FUNCTION: Event_GetData * %ARGUMENTS: * eh -- the event handler * %RETURNS: * The "data" field. ***********************************************************************/ void * Event_GetData(EventHandler *eh) { return eh->data; } /********************************************************************** * %FUNCTION: Event_SetCallbackAndData * %ARGUMENTS: * eh -- the event handler * fn -- new callback function * data -- new data value * %RETURNS: * Nothing * %DESCRIPTION: * Sets the callback function and data fields. ***********************************************************************/ void Event_SetCallbackAndData(EventHandler *eh, EventCallbackFunc fn, void *data) { eh->fn = fn; eh->data = data; } #ifdef DEBUG_EVENT #include #include FILE *Event_DebugFP = NULL; /********************************************************************** * %FUNCTION: Event_DebugMsg * %ARGUMENTS: * fmt, ... -- format string * %RETURNS: * Nothing * %DESCRIPTION: * Writes a debug message to the debug file. ***********************************************************************/ void Event_DebugMsg(char const *fmt, ...) { va_list ap; struct timeval now; if (!Event_DebugFP) return; gettimeofday(&now, NULL); fprintf(Event_DebugFP, "%03d.%03d ", (int) now.tv_sec % 1000, (int) now.tv_usec / 1000); va_start(ap, fmt); vfprintf(Event_DebugFP, fmt, ap); va_end(ap); fflush(Event_DebugFP); } #endif /********************************************************************** * %FUNCTION: Event_EnableDebugging * %ARGUMENTS: * fname -- name of file to log debug messages to * %RETURNS: * 1 if debugging was enabled; 0 otherwise. ***********************************************************************/ int Event_EnableDebugging(char const *fname) { #ifndef DEBUG_EVENT return 0; #else Event_DebugFP = fopen(fname, "w"); return (Event_DebugFP != NULL); #endif } /********************************************************************** * %FUNCTION: Event_ChangeTimeout * %ARGUMENTS: * h -- event handler * t -- new timeout * %RETURNS: * Nothing * %DESCRIPTION: * Changes timeout of event handler to be "t" seconds in the future. ***********************************************************************/ void Event_ChangeTimeout(EventHandler *h, struct timeval t) { struct timeval now; /* Check time interval for validity */ if (t.tv_sec < 0 || t.tv_usec < 0 || t.tv_usec >= 1000000) { return; } /* Convert time interval to absolute time */ gettimeofday(&now, NULL); t.tv_sec += now.tv_sec; t.tv_usec += now.tv_usec; if (t.tv_usec >= 1000000) { t.tv_usec -= 1000000; t.tv_sec++; } h->tmout = t; } rp-pppoe-3.15/src/libevent/event.h0000644000175000017500000000607014045237010015206 0ustar dfsdfs/*********************************************************************** * * event.h * * Abstraction of select call into "event-handling" to make programming * easier. * * Copyright (C) 2001 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * $Id$ * * LIC: GPL * ***********************************************************************/ #define DEBUG_EVENT #ifndef INCLUDE_EVENT_H #define INCLUDE_EVENT_H 1 /* Solaris moans if we don't do this... */ #ifdef __sun #define __EXTENSIONS__ 1 #endif struct EventSelector_t; /* Callback function */ typedef void (*EventCallbackFunc)(struct EventSelector_t *es, int fd, unsigned int flags, void *data); #include "eventpriv.h" /* Create an event selector */ extern EventSelector *Event_CreateSelector(void); /* Destroy the event selector */ extern void Event_DestroySelector(EventSelector *es); /* Handle one event */ extern int Event_HandleEvent(EventSelector *es); /* Add a handler for a ready file descriptor */ extern EventHandler *Event_AddHandler(EventSelector *es, int fd, unsigned int flags, EventCallbackFunc fn, void *data); /* Add a handler for a ready file descriptor with associated timeout*/ extern EventHandler *Event_AddHandlerWithTimeout(EventSelector *es, int fd, unsigned int flags, struct timeval t, EventCallbackFunc fn, void *data); /* Add a timer handler */ extern EventHandler *Event_AddTimerHandler(EventSelector *es, struct timeval t, EventCallbackFunc fn, void *data); /* Change the timeout of a timer handler */ void Event_ChangeTimeout(EventHandler *handler, struct timeval t); /* Delete a handler */ extern int Event_DelHandler(EventSelector *es, EventHandler *eh); /* Retrieve callback function from a handler */ extern EventCallbackFunc Event_GetCallback(EventHandler *eh); /* Retrieve data field from a handler */ extern void *Event_GetData(EventHandler *eh); /* Set callback and data to new values */ extern void Event_SetCallbackAndData(EventHandler *eh, EventCallbackFunc fn, void *data); /* Handle a signal synchronously in event loop */ int Event_HandleSignal(EventSelector *es, int sig, void (*handler)(int sig)); /* Reap children synchronously in event loop */ int Event_HandleChildExit(EventSelector *es, pid_t pid, void (*handler)(pid_t, int, void *), void *data); extern int Event_EnableDebugging(char const *fname); #ifdef DEBUG_EVENT extern void Event_DebugMsg(char const *fmt, ...); #define EVENT_DEBUG(x) Event_DebugMsg x #else #define EVENT_DEBUG(x) ((void) 0) #endif /* Flags */ #define EVENT_FLAG_READABLE 1 #define EVENT_FLAG_WRITEABLE 2 #define EVENT_FLAG_WRITABLE EVENT_FLAG_WRITEABLE /* This is strictly a timer event */ #define EVENT_FLAG_TIMER 4 /* This is a read or write event with an associated timeout */ #define EVENT_FLAG_TIMEOUT 8 #define EVENT_TIMER_BITS (EVENT_FLAG_TIMER | EVENT_FLAG_TIMEOUT) #endif rp-pppoe-3.15/src/libevent/event_tcp.c0000644000175000017500000003442414045237010016053 0ustar dfsdfs/*********************************************************************** * * event_tcp.c -- implementation of event-driven socket I/O. * * Copyright (C) 2001 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #include "event_tcp.h" #include #include #include #include #include #include static void free_state(EventTcpState *state); typedef struct EventTcpConnectState_t { int fd; EventHandler *conn; EventTcpConnectFunc f; void *data; } EventTcpConnectState; /********************************************************************** * %FUNCTION: handle_accept * %ARGUMENTS: * es -- event selector * fd -- socket * flags -- ignored * data -- the accept callback function * %RETURNS: * Nothing * %DESCRIPTION: * Calls accept; if a connection arrives, calls the accept callback * function with connected descriptor ***********************************************************************/ static void handle_accept(EventSelector *es, int fd, unsigned int flags, void *data) { int conn; EventTcpAcceptFunc f; EVENT_DEBUG(("tcp_handle_accept(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data)); conn = accept(fd, NULL, NULL); if (conn < 0) return; f = (EventTcpAcceptFunc) data; f(es, conn); } /********************************************************************** * %FUNCTION: handle_connect * %ARGUMENTS: * es -- event selector * fd -- socket * flags -- ignored * data -- the accept callback function * %RETURNS: * Nothing * %DESCRIPTION: * Calls accept; if a connection arrives, calls the accept callback * function with connected descriptor ***********************************************************************/ static void handle_connect(EventSelector *es, int fd, unsigned int flags, void *data) { int error = 0; socklen_t len = sizeof(error); EventTcpConnectState *state = (EventTcpConnectState *) data; EVENT_DEBUG(("tcp_handle_connect(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data)); /* Cancel writable event */ Event_DelHandler(es, state->conn); state->conn = NULL; /* Timeout? */ if (flags & EVENT_FLAG_TIMEOUT) { errno = ETIMEDOUT; state->f(es, fd, EVENT_TCP_FLAG_TIMEOUT, state->data); free(state); return; } /* Check for pending error */ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { state->f(es, fd, EVENT_TCP_FLAG_IOERROR, state->data); free(state); return; } if (error) { errno = error; state->f(es, fd, EVENT_TCP_FLAG_IOERROR, state->data); free(state); return; } /* It looks cool! */ state->f(es, fd, EVENT_TCP_FLAG_COMPLETE, state->data); free(state); } /********************************************************************** * %FUNCTION: EventTcp_CreateAcceptor * %ARGUMENTS: * es -- event selector * socket -- listening socket * f -- function to call when a connection is accepted * data -- extra data to pass to f. * %RETURNS: * An event handler on success, NULL on failure. * %DESCRIPTION: * Sets up an accepting socket and calls "f" whenever a new * connection arrives. ***********************************************************************/ EventHandler * EventTcp_CreateAcceptor(EventSelector *es, int socket, EventTcpAcceptFunc f) { int flags; EVENT_DEBUG(("EventTcp_CreateAcceptor(es=%p, socket=%d)\n", es, socket)); /* Make sure socket is non-blocking */ flags = fcntl(socket, F_GETFL, 0); if (flags == -1) { return NULL; } if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) == -1) { return NULL; } return Event_AddHandler(es, socket, EVENT_FLAG_READABLE, handle_accept, (void *) f); } /********************************************************************** * %FUNCTION: free_state * %ARGUMENTS: * state -- EventTcpState to free * %RETURNS: * Nothing * %DESCRIPTION: * Frees all state associated with the TcpEvent. ***********************************************************************/ static void free_state(EventTcpState *state) { if (!state) return; EVENT_DEBUG(("tcp_free_state(state=%p)\n", state)); if (state->buf) free(state->buf); if (state->eh) Event_DelHandler(state->es, state->eh); free(state); } /********************************************************************** * %FUNCTION: handle_readable * %ARGUMENTS: * es -- event selector * fd -- the readable socket * flags -- ignored * data -- the EventTcpState object * %RETURNS: * Nothing * %DESCRIPTION: * Continues to fill buffer. Calls callback when done. ***********************************************************************/ static void handle_readable(EventSelector *es, int fd, unsigned int flags, void *data) { EventTcpState *state = (EventTcpState *) data; int done = state->cur - state->buf; int togo = state->len - done; int nread = 0; int flag; EVENT_DEBUG(("tcp_handle_readable(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data)); /* Timed out? */ if (flags & EVENT_FLAG_TIMEOUT) { errno = ETIMEDOUT; (state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_TIMEOUT, state->data); free_state(state); return; } if (state->delim < 0) { /* Not looking for a delimiter */ /* togo had better not be zero here! */ nread = read(fd, state->cur, togo); if (nread <= 0) { /* Change connection reset to EOF if we have read at least one char */ if (nread < 0 && errno == ECONNRESET && done > 0) { nread = 0; } flag = (nread) ? EVENT_TCP_FLAG_IOERROR : EVENT_TCP_FLAG_EOF; /* error or EOF */ (state->f)(es, state->socket, state->buf, done, flag, state->data); free_state(state); return; } state->cur += nread; done += nread; if (done >= state->len) { /* Read enough! */ (state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_COMPLETE, state->data); free_state(state); return; } } else { /* Looking for a delimiter */ while ( (togo > 0) && (nread = read(fd, state->cur, 1)) == 1) { togo--; done++; state->cur++; if (*(state->cur - 1) == state->delim) break; } if (nread <= 0) { /* Error or EOF -- check for EAGAIN */ if (nread < 0 && errno == EAGAIN) return; } /* Some other error, or EOF, or delimiter, or read enough */ if (nread < 0) { flag = EVENT_TCP_FLAG_IOERROR; } else if (nread == 0) { flag = EVENT_TCP_FLAG_EOF; } else { flag = EVENT_TCP_FLAG_COMPLETE; } (state->f)(es, state->socket, state->buf, done, flag, state->data); free_state(state); return; } } /********************************************************************** * %FUNCTION: handle_writeable * %ARGUMENTS: * es -- event selector * fd -- the writeable socket * flags -- ignored * data -- the EventTcpState object * %RETURNS: * Nothing * %DESCRIPTION: * Continues to fill buffer. Calls callback when done. ***********************************************************************/ static void handle_writeable(EventSelector *es, int fd, unsigned int flags, void *data) { EventTcpState *state = (EventTcpState *) data; int done = state->cur - state->buf; int togo = state->len - done; int n; /* Timed out? */ if (flags & EVENT_FLAG_TIMEOUT) { errno = ETIMEDOUT; (state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_TIMEOUT, state->data); free_state(state); return; } /* togo had better not be zero here! */ n = write(fd, state->cur, togo); EVENT_DEBUG(("tcp_handle_writeable(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data)); if (n <= 0) { /* error */ if (state->f) { (state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_IOERROR, state->data); } else { close(fd); } free_state(state); return; } state->cur += n; done += n; if (done >= state->len) { /* Written enough! */ if (state->f) { (state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_COMPLETE, state->data); } else { close(fd); } free_state(state); return; } } /********************************************************************** * %FUNCTION: EventTcp_ReadBuf * %ARGUMENTS: * es -- event selector * socket -- socket to read from * len -- maximum number of bytes to read * delim -- delimiter at which to stop reading, or -1 if we should * read exactly len bytes * f -- function to call on EOF or when all bytes have been read * timeout -- if non-zero, timeout in seconds after which we cancel * operation. * data -- extra data to pass to function f. * %RETURNS: * A new EventTcpState token or NULL on error * %DESCRIPTION: * Sets up a handler to fill a buffer from a socket. ***********************************************************************/ EventTcpState * EventTcp_ReadBuf(EventSelector *es, int socket, int len, int delim, EventTcpIOFinishedFunc f, int timeout, void *data) { EventTcpState *state; int flags; struct timeval t; EVENT_DEBUG(("EventTcp_ReadBuf(es=%p, socket=%d, len=%d, delim=%d, timeout=%d)\n", es, socket, len, delim, timeout)); if (len <= 0) return NULL; if (socket < 0) return NULL; /* Make sure socket is non-blocking */ flags = fcntl(socket, F_GETFL, 0); if (flags == -1) { return NULL; } if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) == -1) { return NULL; } state = malloc(sizeof(EventTcpState)); if (!state) return NULL; memset(state, 0, sizeof(EventTcpState)); state->socket = socket; state->buf = malloc(len); if (!state->buf) { free_state(state); return NULL; } state->cur = state->buf; state->len = len; state->f = f; state->es = es; if (timeout <= 0) { t.tv_sec = -1; t.tv_usec = -1; } else { t.tv_sec = timeout; t.tv_usec = 0; } state->eh = Event_AddHandlerWithTimeout(es, socket, EVENT_FLAG_READABLE, t, handle_readable, (void *) state); if (!state->eh) { free_state(state); return NULL; } state->data = data; state->delim = delim; EVENT_DEBUG(("EventTcp_ReadBuf() -> %p\n", state)); return state; } /********************************************************************** * %FUNCTION: EventTcp_WriteBuf * %ARGUMENTS: * es -- event selector * socket -- socket to read from * buf -- buffer to write * len -- number of bytes to write * f -- function to call on EOF or when all bytes have been read * timeout -- timeout after which to cancel operation * data -- extra data to pass to function f. * %RETURNS: * A new EventTcpState token or NULL on error * %DESCRIPTION: * Sets up a handler to fill a buffer from a socket. ***********************************************************************/ EventTcpState * EventTcp_WriteBuf(EventSelector *es, int socket, char *buf, int len, EventTcpIOFinishedFunc f, int timeout, void *data) { EventTcpState *state; int flags; struct timeval t; EVENT_DEBUG(("EventTcp_WriteBuf(es=%p, socket=%d, len=%d, timeout=%d)\n", es, socket, len, timeout)); if (len <= 0) return NULL; if (socket < 0) return NULL; /* Make sure socket is non-blocking */ flags = fcntl(socket, F_GETFL, 0); if (flags == -1) { return NULL; } if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) == -1) { return NULL; } state = malloc(sizeof(EventTcpState)); if (!state) return NULL; memset(state, 0, sizeof(EventTcpState)); state->socket = socket; state->buf = malloc(len); if (!state->buf) { free_state(state); return NULL; } memcpy(state->buf, buf, len); state->cur = state->buf; state->len = len; state->f = f; state->es = es; if (timeout <= 0) { t.tv_sec = -1; t.tv_usec = -1; } else { t.tv_sec = timeout; t.tv_usec = 0; } state->eh = Event_AddHandlerWithTimeout(es, socket, EVENT_FLAG_WRITEABLE, t, handle_writeable, (void *) state); if (!state->eh) { free_state(state); return NULL; } state->data = data; state->delim = -1; EVENT_DEBUG(("EventTcp_WriteBuf() -> %p\n", state)); return state; } /********************************************************************** * %FUNCTION: EventTcp_Connect * %ARGUMENTS: * es -- event selector * fd -- descriptor to connect * addr -- address to connect to * addrlen -- length of address * f -- function to call with connected socket * data -- extra data to pass to f * %RETURNS: * Nothing * %DESCRIPTION: * Does a non-blocking connect on fd ***********************************************************************/ void EventTcp_Connect(EventSelector *es, int fd, struct sockaddr const *addr, socklen_t addrlen, EventTcpConnectFunc f, int timeout, void *data) { int flags; int n; EventTcpConnectState *state; struct timeval t; /* Make sure socket is non-blocking */ flags = fcntl(fd, F_GETFL, 0); if (flags == -1 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { f(es, fd, EVENT_TCP_FLAG_IOERROR, data); return; } n = connect(fd, addr, addrlen); if (n < 0) { if (errno != EINPROGRESS) { f(es, fd, EVENT_TCP_FLAG_IOERROR, data); return; } } if (n == 0) { /* Connect succeeded immediately */ f(es, fd, EVENT_TCP_FLAG_COMPLETE, data); return; } state = malloc(sizeof(*state)); if (!state) { f(es, fd, EVENT_TCP_FLAG_IOERROR, data); return; } state->f = f; state->fd = fd; state->data = data; if (timeout <= 0) { t.tv_sec = -1; t.tv_usec = -1; } else { t.tv_sec = timeout; t.tv_usec = 0; } state->conn = Event_AddHandlerWithTimeout(es, fd, EVENT_FLAG_WRITEABLE, t, handle_connect, (void *) state); if (!state->conn) { free(state); f(es, fd, EVENT_TCP_FLAG_IOERROR, data); return; } } /********************************************************************** * %FUNCTION: EventTcp_CancelPending * %ARGUMENTS: * s -- an EventTcpState * %RETURNS: * Nothing * %DESCRIPTION: * Cancels the pending event handler ***********************************************************************/ void EventTcp_CancelPending(EventTcpState *s) { free_state(s); } rp-pppoe-3.15/src/libevent/hash.h0000644000175000017500000000262414045237010015011 0ustar dfsdfs/*********************************************************************** * * hash.h * * Hash table utilities * * Copyright (C) 2002 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * LIC: GPL * ***********************************************************************/ #ifndef HASH_H #define HASH_H #include /* Fixed-size hash tables for now */ #define HASHTAB_SIZE 67 /* A hash bucket */ typedef struct hash_bucket_t { struct hash_bucket_t *next; struct hash_bucket_t *prev; unsigned int hashval; } hash_bucket; /* A hash table */ typedef struct hash_table_t { hash_bucket *buckets[HASHTAB_SIZE]; size_t hash_offset; unsigned int (*compute_hash)(void *data); int (*compare)(void *item1, void *item2); size_t num_entries; } hash_table; /* Functions */ void hash_init(hash_table *tab, size_t hash_offset, unsigned int (*compute)(void *data), int (*compare)(void *item1, void *item2)); void hash_insert(hash_table *tab, void *item); void hash_remove(hash_table *tab, void *item); void *hash_find(hash_table *tab, void *item); void *hash_find_next(hash_table *tab, void *item); size_t hash_num_entries(hash_table *tab); /* Iteration functions */ void *hash_start(hash_table *tab, void **cursor); void *hash_next(hash_table *tab, void **cursor); /* Utility function: hashpjw for strings */ unsigned int hash_pjw(char const *str); #endif rp-pppoe-3.15/src/libevent/event_tcp.h0000644000175000017500000000402414045237010016051 0ustar dfsdfs/*********************************************************************** * * event-tcp.h * * Event-driven TCP functions to allow for single-threaded "concurrent" * server. * * Copyright (C) 2001 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #ifndef INCLUDE_EVENT_TCP_H #define INCLUDE_EVENT_TCP_H 1 #include "event.h" #include typedef void (*EventTcpAcceptFunc)(EventSelector *es, int fd); typedef void (*EventTcpConnectFunc)(EventSelector *es, int fd, int flag, void *data); typedef void (*EventTcpIOFinishedFunc)(EventSelector *es, int fd, char *buf, int len, int flag, void *data); #define EVENT_TCP_FLAG_COMPLETE 0 #define EVENT_TCP_FLAG_IOERROR 1 #define EVENT_TCP_FLAG_EOF 2 #define EVENT_TCP_FLAG_TIMEOUT 3 typedef struct EventTcpState_t { int socket; char *buf; char *cur; int len; int delim; EventTcpIOFinishedFunc f; EventSelector *es; EventHandler *eh; void *data; } EventTcpState; extern EventHandler *EventTcp_CreateAcceptor(EventSelector *es, int socket, EventTcpAcceptFunc f); extern void EventTcp_Connect(EventSelector *es, int fd, struct sockaddr const *addr, socklen_t addrlen, EventTcpConnectFunc f, int timeout, void *data); extern EventTcpState *EventTcp_ReadBuf(EventSelector *es, int socket, int len, int delim, EventTcpIOFinishedFunc f, int timeout, void *data); extern EventTcpState *EventTcp_WriteBuf(EventSelector *es, int socket, char *buf, int len, EventTcpIOFinishedFunc f, int timeout, void *data); extern void EventTcp_CancelPending(EventTcpState *s); #endif rp-pppoe-3.15/src/libevent/eventpriv.h0000644000175000017500000000315114045237010016104 0ustar dfsdfs/*********************************************************************** * * eventpriv.h * * Abstraction of select call into "event-handling" to make programming * easier. This header includes "private" definitions which users * of the event-handling code should not care about. * * Copyright (C) 2001 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * $Id$ * * LIC: GPL * ***********************************************************************/ #ifndef INCLUDE_EVENTPRIV_H #define INCLUDE_EVENTPRIV_H 1 #include #include #include /* Handler structure */ typedef struct EventHandler_t { struct EventHandler_t *next; /* Link in list */ int fd; /* File descriptor for select */ unsigned int flags; /* Select on read or write; enable timeout */ struct timeval tmout; /* Absolute time for timeout */ EventCallbackFunc fn; /* Callback function */ void *data; /* Extra data to pass to callback */ } EventHandler; /* Selector structure */ typedef struct EventSelector_t { EventHandler *handlers; /* Linked list of EventHandlers */ int nestLevel; /* Event-handling nesting level */ int opsPending; /* True if operations are pending */ int destroyPending; /* If true, a destroy is pending */ } EventSelector; /* Private flags */ #define EVENT_FLAG_DELETED 256 #endif rp-pppoe-3.15/src/libevent/hash.c0000644000175000017500000001642714045237010015012 0ustar dfsdfs/*********************************************************************** * * hash.c * * Implementation of hash tables. Each item inserted must include * a hash_bucket member. * * Copyright (C) 2002 Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This software may be distributed under the terms of the GNU General * Public License, Version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #include "hash.h" #include #define BITS_IN_int ( sizeof(int) * CHAR_BIT ) #define THREE_QUARTERS ((int) ((BITS_IN_int * 3) / 4)) #define ONE_EIGHTH ((int) (BITS_IN_int / 8)) #define HIGH_BITS ( ~((unsigned int)(~0) >> ONE_EIGHTH )) #define GET_BUCKET(tab, data) ((hash_bucket *) ((char *) (data) + (tab)->hash_offset)) #define GET_ITEM(tab, bucket) ((void *) (((char *) (void *) bucket) - (tab)->hash_offset)) static void *hash_next_cursor(hash_table *tab, hash_bucket *b); /********************************************************************** * %FUNCTION: hash_init * %ARGUMENTS: * tab -- hash table * hash_offset -- offset of hash_bucket data member in inserted items * compute -- pointer to function to compute hash value * compare -- pointer to comparison function. Returns 0 if items are equal, * non-zero otherwise. * %RETURNS: * Nothing * %DESCRIPTION: * Initializes a hash table. ***********************************************************************/ void hash_init(hash_table *tab, size_t hash_offset, unsigned int (*compute)(void *data), int (*compare)(void *item1, void *item2)) { size_t i; tab->hash_offset = hash_offset; tab->compute_hash = compute; tab->compare = compare; for (i=0; ibuckets[i] = NULL; } tab->num_entries = 0; } /********************************************************************** * %FUNCTION: hash_insert * %ARGUMENTS: * tab -- hash table to insert into * item -- the item we're inserting * %RETURNS: * Nothing * %DESCRIPTION: * Inserts an item into the hash table. It must not currently be in any * hash table. ***********************************************************************/ void hash_insert(hash_table *tab, void *item) { hash_bucket *b = GET_BUCKET(tab, item); unsigned int val = tab->compute_hash(item); b->hashval = val; val %= HASHTAB_SIZE; b->prev = NULL; b->next = tab->buckets[val]; if (b->next) { b->next->prev = b; } tab->buckets[val] = b; tab->num_entries++; } /********************************************************************** * %FUNCTION: hash_remove * %ARGUMENTS: * tab -- hash table * item -- item in hash table * %RETURNS: * Nothing * %DESCRIPTION: * Removes item from hash table ***********************************************************************/ void hash_remove(hash_table *tab, void *item) { hash_bucket *b = GET_BUCKET(tab, item); unsigned int val = b->hashval % HASHTAB_SIZE; if (b->prev) { b->prev->next = b->next; } else { tab->buckets[val] = b->next; } if (b->next) { b->next->prev = b->prev; } tab->num_entries--; } /********************************************************************** * %FUNCTION: hash_find * %ARGUMENTS: * tab -- hash table * item -- item equal to one we're seeking (in the compare-function sense) * %RETURNS: * A pointer to the item in the hash table, or NULL if no such item * %DESCRIPTION: * Searches hash table for item. ***********************************************************************/ void * hash_find(hash_table *tab, void *item) { unsigned int val = tab->compute_hash(item) % HASHTAB_SIZE; hash_bucket *b; for (b = tab->buckets[val]; b; b = b->next) { void *item2 = GET_ITEM(tab, b); if (!tab->compare(item, item2)) return item2; } return NULL; } /********************************************************************** * %FUNCTION: hash_find_next * %ARGUMENTS: * tab -- hash table * item -- an item returned by hash_find or hash_find_next * %RETURNS: * A pointer to the next equal item in the hash table, or NULL if no such item * %DESCRIPTION: * Searches hash table for anoter item equivalent to this one. Search * starts from item. ***********************************************************************/ void * hash_find_next(hash_table *tab, void *item) { hash_bucket *b = GET_BUCKET(tab, item); for (b = b->next; b; b = b->next) { void *item2 = GET_ITEM(tab, b); if (!tab->compare(item, item2)) return item2; } return NULL; } /********************************************************************** * %FUNCTION: hash_start * %ARGUMENTS: * tab -- hash table * cursor -- a void pointer to keep track of location * %RETURNS: * "first" entry in hash table, or NULL if table is empty * %DESCRIPTION: * Starts an iterator -- sets cursor so hash_next will return next entry. ***********************************************************************/ void * hash_start(hash_table *tab, void **cursor) { int i; for (i=0; ibuckets[i]) { /* Point cursor to NEXT item so it is valid even if current item is free'd */ *cursor = hash_next_cursor(tab, tab->buckets[i]); return GET_ITEM(tab, tab->buckets[i]); } } *cursor = NULL; return NULL; } /********************************************************************** * %FUNCTION: hash_next * %ARGUMENTS: * tab -- hash table * cursor -- cursor into hash table * %RETURNS: * Next item in table, or NULL. * %DESCRIPTION: * Steps cursor to next item in table. ***********************************************************************/ void * hash_next(hash_table *tab, void **cursor) { hash_bucket *b; if (!*cursor) return NULL; b = (hash_bucket *) *cursor; *cursor = hash_next_cursor(tab, b); return GET_ITEM(tab, b); } /********************************************************************** * %FUNCTION: hash_next_cursor * %ARGUMENTS: * tab -- a hash table * b -- a hash bucket * %RETURNS: * Cursor value for bucket following b in hash table. ***********************************************************************/ static void * hash_next_cursor(hash_table *tab, hash_bucket *b) { unsigned int i; if (!b) return NULL; if (b->next) return b->next; i = b->hashval % HASHTAB_SIZE; for (++i; ibuckets[i]) return tab->buckets[i]; } return NULL; } size_t hash_num_entries(hash_table *tab) { return tab->num_entries; } /********************************************************************** * %FUNCTION: hash_pjw * %ARGUMENTS: * str -- a zero-terminated string * %RETURNS: * A hash value using the hashpjw algorithm * %DESCRIPTION: * An adaptation of Peter Weinberger's (PJW) generic hashing * algorithm based on Allen Holub's version. Accepts a pointer * to a datum to be hashed and returns an unsigned integer. ***********************************************************************/ unsigned int hash_pjw(char const * str) { unsigned int hash_value, i; for (hash_value = 0; *str; ++str) { hash_value = ( hash_value << ONE_EIGHTH ) + *str; if (( i = hash_value & HIGH_BITS ) != 0 ) { hash_value = ( hash_value ^ ( i >> THREE_QUARTERS )) & ~HIGH_BITS; } } return hash_value; } rp-pppoe-3.15/src/libevent/Makefile.in0000644000175000017500000000156714045237010015767 0ustar dfsdfs# Generated automatically from Makefile.in by configure. # $Id$ # # Makefile for event-handling library # # Copyright 2002 Roaring Penguin Software Inc. # Copyright (C) 2018-2021 Dianne Skoll # # This software may be distributed according to the terms of the GNU # General Public License, version 2 or (at your option) any later version. # LIC: GPL OBJS=event.o event_tcp.o hash.o event_sig.o SRCS=$(OBJS:.o=.c) HDRS=event.h event_tcp.h eventpriv.h hash.h CFLAGS=@CFLAGS@ -I.. $(DEFINES) AR=ar all: libevent.a libevent.a: $(OBJS) rm -f libevent.a $(AR) -cq libevent.a $(OBJS) @RANLIB@ libevent.a event.o: event.c $(HDRS) @CC@ $(CFLAGS) -c -o $@ $< hash.o: hash.c $(HDRS) @CC@ $(CFLAGS) -c -o $@ $< event_sig.o: event_sig.c $(HDRS) @CC@ $(CFLAGS) -c -o $@ $< event_tcp.o: event_tcp.c $(HDRS) @CC@ $(CFLAGS) -c -o $@ $< clean: FORCE rm -f *.a *.o *~ FORCE: .phony: FORCE rp-pppoe-3.15/src/configure0000755000175000017500000052443114045237010014021 0ustar dfsdfs#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="pppoe.c" ac_default_prefix=/usr # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS datadir_evaluated LIBEVENT RDYNAMIC PPPOE_SERVER_DEPS LIC_DEFINE LIC_MAKEFILE_INCLUDE LIC_LIB LIC_LIBDIR LIC_INCDIR TARGETS WRAPPER ID SETSID PPPD IP INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM LIBOBJS PPPOE_RELAY PPPD_H PPPD_INCDIR LINUX_KERNELMODE_PLUGIN EGREP GREP CPP RANLIB OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_plugin enable_debugging enable_licenses ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-plugin=pppd_src_path build pppd plugin --disable-debugging disable debugging code --enable-licenses=lic_path build commercial version Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu PPPD_DIR=ppp-2.4.1.pppoe2 ac_config_headers="$ac_config_headers config.h" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if ${ac_cv_header_sys_wait_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fcntl.h sys/dlpi.h sys/ioctl.h sys/time.h syslog.h unistd.h net/if_arp.h netinet/if_ether.h getopt.h sys/uio.h sys/param.h fcntl.h net/bpf.h netpacket/packet.h net/ethernet.h asm/types.h linux/if_packet.h linux/if_ether.h sys/socket.h net/if.h net/if_dl.h net/if_ether.h net/if_types.h netinet/if_ether.h net/if_types.h net/if_dl.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in linux/if.h do : ac_fn_c_check_header_compile "$LINENO" "linux/if.h" "ac_cv_header_linux_if_h" "#include " if test "x$ac_cv_header_linux_if_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LINUX_IF_H 1 _ACEOF fi done for ac_header in linux/if_pppox.h do : ac_fn_c_check_header_compile "$LINENO" "linux/if_pppox.h" "ac_cv_header_linux_if_pppox_h" " #include #include #include #include " if test "x$ac_cv_header_linux_if_pppox_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LINUX_IF_PPPOX_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_ll" >&5 $as_echo_n "checking for struct sockaddr_ll... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { struct sockaddr_ll sa; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_sockaddr_ll=yes else ac_cv_struct_sockaddr_ll=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_sockaddr_ll" >&5 $as_echo "$ac_cv_struct_sockaddr_ll" >&6; } if test "$ac_cv_struct_sockaddr_ll" = yes ; then $as_echo "#define HAVE_STRUCT_SOCKADDR_LL 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for N_HDLC line discipline" >&5 $as_echo_n "checking for N_HDLC line discipline... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int x = N_HDLC; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_n_hdlc=yes else ac_cv_n_hdlc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_n_hdlc" >&5 $as_echo "$ac_cv_n_hdlc" >&6; } if test "$ac_cv_n_hdlc" = yes ; then $as_echo "#define HAVE_N_HDLC 1" >>confdefs.h fi # Check whether --enable-plugin was given. if test "${enable_plugin+set}" = set; then : enableval=$enable_plugin; ac_cv_pluginpath=$enableval else ac_cv_pluginpath=no fi # Check whether --enable-debugging was given. if test "${enable_debugging+set}" = set; then : enableval=$enable_debugging; ac_cv_debugging=$enableval else ac_cv_debugging=yes fi if test "$ac_cv_pluginpath" = "yes" ; then for i in /usr/include /usr/local/include ; do if test -r $i/pppd/pppd.h; then ac_cv_pluginpath=$i fi done fi if test "$ac_cv_pluginpath" = "yes" ; then echo "*** Could not find pppd/pppd.h anywhere... not building plugin" ac_cv_pluginpath=no fi # Check whether --enable-licenses was given. if test "${enable_licenses+set}" = set; then : enableval=$enable_licenses; ac_cv_licpath=$enableval else ac_cv_licpath=no fi LIC_INCDIR="" LIC_LIBDIR="" LIC_LIB="" LIC_DEFINE="" LIC_MAKEFILE_INCLUDE="" PPPOE_SERVER_DEPS="" if test "$ac_cv_licpath" != "no" ; then LIC_INCDIR="-I$ac_cv_licpath" LIC_LIBDIR="-L$ac_cv_licpath -Llicensed-only" if test -d "../../extra-libs" ; then LIC_LIB="-L../../extra-libs -ltwofish -llicensed-only -ltcl -ldl" else LIC_LIB="-ltwofish -llicensed-only -ltcl -ldl" fi PPPOE_SERVER_DEPS="licensed-only/liblicensed-only.a ../../SERVPOET-VERSION" LIC_DEFINE="-DHAVE_LICENSE=1 -DSERVPOET_VERSION='\"\$(SERVPOET_VERSION)\"'" LIC_MAKEFILE_INCLUDE="include ../../SERVPOET-VERSION" fi LINUX_KERNELMODE_PLUGIN="" PPPD_INCDIR="" if test "$ac_cv_header_linux_if_pppox_h" = yes ; then if test "$ac_cv_pluginpath" != no ; then LINUX_KERNELMODE_PLUGIN=rp-pppoe.so $as_echo "#define HAVE_LINUX_KERNEL_PPPOE 1" >>confdefs.h PPPD_INCDIR=$ac_cv_pluginpath fi fi if test "$PPPD_INCDIR" = "" ; then PPPD_INCDIR=/usr/include fi if test "$ac_cv_debugging" = "yes" ; then $as_echo "#define DEBUGGING_ENABLED 1" >>confdefs.h fi PPPOE_RELAY="" if test "`uname -s`" = "Linux" ; then PPPOE_RELAY=pppoe-relay fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 $as_echo_n "checking for working memcmp... " >&6; } if ${ac_cv_func_memcmp_working+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_memcmp_working=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_memcmp_working=yes else ac_cv_func_memcmp_working=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 $as_echo "$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac if ${ac_cv_func_setvbuf_reversed+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_func_setvbuf_reversed=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF for ac_func in select socket strerror strtol strlcpy do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short" >&5 $as_echo_n "checking size of unsigned short... " >&6; } if ${ac_cv_sizeof_unsigned_short+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned short))" "ac_cv_sizeof_unsigned_short" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_short" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned short) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_short=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_short" >&5 $as_echo "$ac_cv_sizeof_unsigned_short" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_SHORT $ac_cv_sizeof_unsigned_short _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5 $as_echo_n "checking size of unsigned int... " >&6; } if ${ac_cv_sizeof_unsigned_int+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_int" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_int=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5 $as_echo "$ac_cv_sizeof_unsigned_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5 $as_echo_n "checking size of unsigned long... " >&6; } if ${ac_cv_sizeof_unsigned_long+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5 $as_echo "$ac_cv_sizeof_unsigned_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long _ACEOF # Extract the first word of "ip", so it can be a program name with args. set dummy ip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_IP+:} false; then : $as_echo_n "(cached) " >&6 else case $IP in [\\/]* | ?:[\\/]*) ac_cv_path_IP="$IP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:/bin:/sbin:/usr/bin:/usr/sbin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_IP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_IP" && ac_cv_path_IP="NOTFOUND" ;; esac fi IP=$ac_cv_path_IP if test -n "$IP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $IP" >&5 $as_echo "$IP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "pppd", so it can be a program name with args. set dummy pppd; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PPPD+:} false; then : $as_echo_n "(cached) " >&6 else case $PPPD in [\\/]* | ?:[\\/]*) ac_cv_path_PPPD="$PPPD" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:/sbin:/usr/sbin:/usr/local/sbin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PPPD="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PPPD" && ac_cv_path_PPPD="NOTFOUND" ;; esac fi PPPD=$ac_cv_path_PPPD if test -n "$PPPD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PPPD" >&5 $as_echo "$PPPD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "setsid", so it can be a program name with args. set dummy setsid; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SETSID+:} false; then : $as_echo_n "(cached) " >&6 else case $SETSID in [\\/]* | ?:[\\/]*) ac_cv_path_SETSID="$SETSID" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:/sbin:/usr/sbin:/usr/local/sbin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SETSID="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_SETSID" && ac_cv_path_SETSID="""" ;; esac fi SETSID=$ac_cv_path_SETSID if test -n "$SETSID"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SETSID" >&5 $as_echo "$SETSID" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "id", so it can be a program name with args. set dummy id; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ID+:} false; then : $as_echo_n "(cached) " >&6 else case $ID in [\\/]* | ?:[\\/]*) ac_cv_path_ID="$ID" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/usr/xpg4/bin:$PATH" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ID="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_ID" && ac_cv_path_ID="""" ;; esac fi ID=$ac_cv_path_ID if test -n "$ID"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ID" >&5 $as_echo "$ID" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Linux 2.4.X kernel-mode PPPoE support" >&5 $as_echo_n "checking for Linux 2.4.X kernel-mode PPPoE support... " >&6; } if ${ac_cv_linux_kernel_pppoe+:} false; then : $as_echo_n "(cached) " >&6 else if test "`uname -s`" = "Linux" ; then if test $cross_compiling = "no"; then modprobe ppp_generic > /dev/null 2>&1 modprobe ppp_async > /dev/null 2>&1 modprobe n_hdlc > /dev/null 2>&1 modprobe ppp_synctty > /dev/null 2>&1 modprobe pppoe > /dev/null 2>&1 fi if test "$cross_compiling" = yes; then : ac_cv_linux_kernel_pppoe=no; echo "cross-compiling, default: " else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main() { if (socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OE) >= 0) return 0; else return 1; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_linux_kernel_pppoe=yes else ac_cv_linux_kernel_pppoe=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi else ac_cv_linux_kernel_pppoe=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_linux_kernel_pppoe" >&5 $as_echo "$ac_cv_linux_kernel_pppoe" >&6; } if test "$ac_cv_linux_kernel_pppoe" != yes ; then if test "$LINUX_KERNELMODE_PLUGIN" = rp-pppoe.so; then echo "*** Your kernel does not appear to have built-in PPPoE support," echo "*** but I will build the kernel-mode plugin anyway." fi fi if test "$GCC" = yes; then CFLAGS="$CFLAGS -fno-strict-aliasing -Wall -Wstrict-prototypes" fi if test "$PPPD" = "NOTFOUND"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Oops! I couldn't find pppd, the PPP daemon anywhere." >&5 $as_echo "$as_me: WARNING: *** Oops! I couldn't find pppd, the PPP daemon anywhere." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** You must install pppd, version 2.3.10 or later." >&5 $as_echo "$as_me: WARNING: *** You must install pppd, version 2.3.10 or later." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** I will keep going, but it may not work." >&5 $as_echo "$as_me: WARNING: *** I will keep going, but it may not work." >&2;} PPPD=pppd fi PPPD_VERSION=`$PPPD --version 2>&1 | awk ' /version/ {print $NF}'` case "$PPPD_VERSION" in 1.*|2.0.*|2.1.*|2.2.*|2.3.0|2.3.1|2.3.2|2.3.3|2.3.4|2.3.5|2.3.6) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Oops! Your version of pppd is $PPPD_VERSION, which is too old." >&5 $as_echo "$as_me: WARNING: *** Oops! Your version of pppd is $PPPD_VERSION, which is too old." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** You need at least 2.3.7 (2.3.10 or newer recommended." >&5 $as_echo "$as_me: WARNING: *** You need at least 2.3.7 (2.3.10 or newer recommended." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** I will keep going, but it may not work." >&5 $as_echo "$as_me: WARNING: *** I will keep going, but it may not work." >&2;} ;; 2.3.7|2.3.8|2.3.9) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Warning. Your version of pppd is $PPPD_VERSION. You will" >&5 $as_echo "$as_me: WARNING: *** Warning. Your version of pppd is $PPPD_VERSION. You will" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** not be able to use connect-on-demand. Upgrade to pppd" >&5 $as_echo "$as_me: WARNING: *** not be able to use connect-on-demand. Upgrade to pppd" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** 2.3.10 or newer if you need connect-on-demand." >&5 $as_echo "$as_me: WARNING: *** 2.3.10 or newer if you need connect-on-demand." >&2;} ;; 2*|3*|4*|5*|6*|7*|8*|9*) ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** Oops. I cannot figure out what version of pppd you have." >&5 $as_echo "$as_me: WARNING: *** Oops. I cannot figure out what version of pppd you have." >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** All I got back was '$PPPD_VERSION'" >&5 $as_echo "$as_me: WARNING: *** All I got back was '$PPPD_VERSION'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** I will keep going, but it may not work." >&5 $as_echo "$as_me: WARNING: *** I will keep going, but it may not work." >&2;} ;; esac # Sigh... got to fix this up for tcl test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Fully resolve WRAPPER for Tcl script. WRAPPER=${sbindir}/pppoe-wrapper eval "WRAPPER=${WRAPPER}" eval "WRAPPER=${WRAPPER}" # Determine what targets to build TARGETS="pppoe pppoe-server" # pppoe-sniff is built only on Linux and Solaris if test "$ac_cv_header_linux_if_packet_h" = "yes" -o "$ac_cv_header_sys_dlpi_h" = "yes" ; then TARGETS="$TARGETS pppoe-sniff" fi # pppoe-relay is built only on Linux if test "$ac_cv_header_linux_if_packet_h" = "yes" ; then TARGETS="$TARGETS pppoe-relay" fi # plugin is built only if we have kernel support if test -n "$LINUX_KERNELMODE_PLUGIN" ; then TARGETS="$TARGETS $LINUX_KERNELMODE_PLUGIN" mkdir plugin > /dev/null 2>&1 fi EXTRACONFIGS="" # Licensed stuff only for commercial distro (for now) if test -n "$LIC_DEFINE" ; then TARGETS="licensed-only $TARGETS" EXTRACONFIGS="$EXTRACONFIGS licensed-only/Makefile" fi RDYNAMIC="" # L2TP is only in commercial distro (for now) if test -n "$LIC_DEFINE" ; then TARGETS="l2tp $TARGETS" EXTRACONFIGS="$EXTRACONFIGS l2tp/Makefile l2tp/handlers/Makefile" LIC_DEFINE="$LIC_DEFINE -DHAVE_L2TP=1" LIC_LIB="$LIC_LIB -Ll2tp -ll2tp" PPPOE_SERVER_DEPS="$PPPOE_SERVER_DEPS l2tp/libl2tp.a" RDYNAMIC="-rdynamic" fi LIBEVENT=../libevent datadir_evaluated=`eval echo $datadir` ac_config_files="$ac_config_files Makefile libevent/Makefile ../scripts/pppoe-connect ../scripts/pppoe-start ../scripts/pppoe-stop ../scripts/pppoe-init ../scripts/pppoe-init-suse ../scripts/pppoe-setup ../gui/Makefile ../gui/tkpppoe $EXTRACONFIGS" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "libevent/Makefile") CONFIG_FILES="$CONFIG_FILES libevent/Makefile" ;; "../scripts/pppoe-connect") CONFIG_FILES="$CONFIG_FILES ../scripts/pppoe-connect" ;; "../scripts/pppoe-start") CONFIG_FILES="$CONFIG_FILES ../scripts/pppoe-start" ;; "../scripts/pppoe-stop") CONFIG_FILES="$CONFIG_FILES ../scripts/pppoe-stop" ;; "../scripts/pppoe-init") CONFIG_FILES="$CONFIG_FILES ../scripts/pppoe-init" ;; "../scripts/pppoe-init-suse") CONFIG_FILES="$CONFIG_FILES ../scripts/pppoe-init-suse" ;; "../scripts/pppoe-setup") CONFIG_FILES="$CONFIG_FILES ../scripts/pppoe-setup" ;; "../gui/Makefile") CONFIG_FILES="$CONFIG_FILES ../gui/Makefile" ;; "../gui/tkpppoe") CONFIG_FILES="$CONFIG_FILES ../gui/tkpppoe" ;; "$EXTRACONFIGS") CONFIG_FILES="$CONFIG_FILES $EXTRACONFIGS" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: On this platform, the following targets will be built:" >&5 $as_echo "On this platform, the following targets will be built:" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TARGETS" >&5 $as_echo "$TARGETS" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: Type 'make' to compile the software." >&5 $as_echo "Type 'make' to compile the software." >&6; } rp-pppoe-3.15/src/Makefile.in0000644000175000017500000003275514045237010014162 0ustar dfsdfs# @configure_input@ #*********************************************************************** # # Makefile # # Makefile for Roaring Penguin's Linux user-space PPPoE client. # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018-2021 Dianne Skoll # # This program may be distributed according to the terms of the GNU # General Public License, version 2 or (at your option) any later version. # # LIC: GPL # # $Id$ #*********************************************************************** # Version is set ONLY IN THE MAKEFILE! Don't delete this! RP_VERSION=3.15 DEFINES= prefix=@prefix@ exec_prefix=@exec_prefix@ mandir=@mandir@ docdir=@prefix@/share/doc/rp-pppoe-$(RP_VERSION) install=@INSTALL@ install_dir=@INSTALL@ -d sbindir=@sbindir@ datarootdir=@datarootdir@ # Plugin for pppd on Linux LINUX_KERNELMODE_PLUGIN=@LINUX_KERNELMODE_PLUGIN@ PPPD_INCDIR=@PPPD_INCDIR@ # Licensed version LIC_INCDIR=@LIC_INCDIR@ LIC_LIBDIR=@LIC_LIBDIR@ LIC_LIB=@LIC_LIB@ LIC_DEFINE=@LIC_DEFINE@ # PPPoE relay -- currently only supported on Linux PPPOE_RELAY=@PPPOE_RELAY@ # Program paths PPPOE_PATH=$(sbindir)/pppoe PPPD_PATH=@PPPD@ # Include ServPoET version if we're building for ServPoET @LIC_MAKEFILE_INCLUDE@ # Kernel-mode plugin gets installed here. PLUGIN_DIR=/etc/ppp/plugins PLUGIN_PATH=$(PLUGIN_DIR)/rp-pppoe.so # Configuration file paths PPPOESERVER_PPPD_OPTIONS=/etc/ppp/pppoe-server-options PATHS='-DPPPOE_PATH="$(PPPOE_PATH)"' '-DPPPD_PATH="$(PPPD_PATH)"' \ '-DPLUGIN_PATH="$(PLUGIN_PATH)"' \ '-DPPPOE_SERVER_OPTIONS="$(PPPOESERVER_PPPD_OPTIONS)"' CFLAGS= @CFLAGS@ $(LIC_INCDIR) $(DEFINES) $(LIC_DEFINE) $(PATHS) -Ilibevent TARGETS=@TARGETS@ PPPOE_SERVER_LIBS=$(LIC_LIBDIR) $(LIC_LIB) LDFLAGS= @LDFLAGS@ all: $(TARGETS) @echo "" @echo "Type 'make install' as root to install the software." pppoe-sniff: pppoe-sniff.o if.o common.o debug.o @CC@ -o $@ $^ $(LDFLAGS) pppoe-server: pppoe-server.o if.o debug.o common.o md5.o libevent/libevent.a @PPPOE_SERVER_DEPS@ @CC@ -o $@ @RDYNAMIC@ $^ $(LDFLAGS) $(PPPOE_SERVER_LIBS) -Llibevent -levent # Experimental code from Savoir Faire Linux. I do not consider it # production-ready, so not part of the official distribution. #pppoe-bridge: pppoe-bridge.o ppp.o modem.o rs232.o if.o debug.o common.o md5.o libevent/libevent.a @PPPOE_SERVER_DEPS@ # @CC@ -o $@ @RDYNAMIC@ $^ $(LDFLAGS) $(PPPOE_SERVER_LIBS) -Llibevent -levent pppoe: pppoe.o if.o debug.o common.o ppp.o discovery.o @CC@ -o $@ $^ $(LDFLAGS) pppoe-relay: relay.o if.o debug.o common.o @CC@ -o $@ $^ $(LDFLAGS) pppoe.o: pppoe.c pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< discovery.o: discovery.c pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< ppp.o: ppp.c pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< md5.o: md5.c md5.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< pppoe-server.o: pppoe-server.c pppoe.h @PPPOE_SERVER_DEPS@ @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< # Experimental code from Savoir Faire Linux. I do not consider it # production-ready, so not part of the official distribution. #pppoe-bridge.o: pppoe-bridge.c pppoe.h @PPPOE_SERVER_DEPS@ # @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< pppoe-sniff.o: pppoe-sniff.c pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< if.o: if.c pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< libevent/libevent.a: cd libevent && $(MAKE) DEFINES="$(DEFINES)" common.o: common.c pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< debug.o: debug.c pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< relay.o: relay.c relay.h pppoe.h @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< # Experimental code from Savoir Faire Linux. I do not consider it # production-ready, so not part of the official distribution. #modem.o: modem.c modem.h # @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< #rs232.o: rs232.c rs232.h # @CC@ $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -c -o $@ $< # Linux-specific plugin rp-pppoe.so: plugin/plugin.o plugin/libplugin.a @CC@ -o $@ -shared $^ $(LDFLAGS) plugin/plugin.o: plugin.c @CC@ -DPLUGIN=1 '-DRP_VERSION="$(RP_VERSION)"' $(CFLAGS) -I$(PPPD_INCDIR) -c -o $@ -fPIC $< plugin/libplugin.a: plugin/discovery.o plugin/if.o plugin/common.o plugin/debug.o ar -rc $@ $^ plugin/discovery.o: discovery.c @CC@ -DPLUGIN=1 $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -I$(PPPD_INCDIR) -c -o $@ -fPIC $< plugin/if.o: if.c @CC@ -DPLUGIN=1 $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -I$(PPPD_INCDIR) -c -o $@ -fPIC $< plugin/debug.o: debug.c @CC@ -DPLUGIN=1 $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -I$(PPPD_INCDIR) -c -o $@ -fPIC $< plugin/common.o: common.c @CC@ -DPLUGIN=1 $(CFLAGS) '-DRP_VERSION="$(RP_VERSION)"' -I$(PPPD_INCDIR) -c -o $@ -fPIC $< install: all -mkdir -p $(DESTDIR)$(sbindir) $(install) -m 755 pppoe $(DESTDIR)$(sbindir) $(install) -m 755 pppoe-server $(DESTDIR)$(sbindir) if test -x licensed-only/pppoe-server-control ; then $(install) -m 755 licensed-only/pppoe-server-control $(DESTDIR)$(sbindir); fi if test -x pppoe-relay ; then $(install) -m 755 pppoe-relay $(DESTDIR)$(sbindir); fi if test -x pppoe-sniff; then $(install) -m 755 pppoe-sniff $(DESTDIR)$(sbindir); fi $(install) -m 755 ../scripts/pppoe-connect $(DESTDIR)$(sbindir) $(install) -m 755 ../scripts/pppoe-start $(DESTDIR)$(sbindir) $(install) -m 755 ../scripts/pppoe-status $(DESTDIR)$(sbindir) $(install) -m 755 ../scripts/pppoe-stop $(DESTDIR)$(sbindir) $(install) -m 755 ../scripts/pppoe-setup $(DESTDIR)$(sbindir) -mkdir -p $(DESTDIR)$(docdir) $(install) -m 644 ../doc/CHANGES $(DESTDIR)$(docdir) $(install) -m 644 ../doc/KERNEL-MODE-PPPOE $(DESTDIR)$(docdir) $(install) -m 644 ../doc/HOW-TO-CONNECT $(DESTDIR)$(docdir) $(install) -m 644 ../doc/LICENSE $(DESTDIR)$(docdir) $(install) -m 644 ../README $(DESTDIR)$(docdir) $(install) -m 644 ../SERVPOET $(DESTDIR)$(docdir) $(install) -m 644 ../configs/pap-secrets $(DESTDIR)$(docdir) -mkdir -p $(DESTDIR)$(mandir)/man8 for i in $(TARGETS) ; do \ if test -f ../man/$$i.8 ; then \ $(install) -m 644 ../man/$$i.8 $(DESTDIR)$(mandir)/man8 || exit 1; \ fi; \ done $(install) -m 644 ../man/pppoe-start.8 $(DESTDIR)$(mandir)/man8 $(install) -m 644 ../man/pppoe-stop.8 $(DESTDIR)$(mandir)/man8 $(install) -m 644 ../man/pppoe-status.8 $(DESTDIR)$(mandir)/man8 $(install) -m 644 ../man/pppoe-connect.8 $(DESTDIR)$(mandir)/man8 $(install) -m 644 ../man/pppoe-setup.8 $(DESTDIR)$(mandir)/man8 -mkdir -p $(DESTDIR)$(mandir)/man5 $(install) -m 644 ../man/pppoe.conf.5 $(DESTDIR)$(mandir)/man5 -mkdir -p $(DESTDIR)/etc/ppp -mkdir -p $(DESTDIR)$(PLUGIN_DIR) -echo "# Directory created by rp-pppoe for kernel-mode plugin" > $(DESTDIR)$(PLUGIN_DIR)/README if test -r rp-pppoe.so; then $(install) -m 755 rp-pppoe.so $(DESTDIR)$(PLUGIN_DIR); fi @for i in pppoe.conf firewall-standalone firewall-masq ; do \ if [ ! -f $(DESTDIR)/etc/ppp/$$i ] ; then \ $(install) -m 644 ../configs/$$i $(DESTDIR)/etc/ppp ; \ else \ echo "NOT overwriting existing $(DESTDIR)/etc/ppp/$$i" ;\ $(install) -m 644 ../configs/$$i $(DESTDIR)/etc/ppp/$$i-$(RP_VERSION) ;\ fi ;\ done @if [ ! -f $(DESTDIR)$(PPPOESERVER_PPPD_OPTIONS) ] ; then \ $(install) -m 644 ../configs/pppoe-server-options $(DESTDIR)$(PPPOESERVER_PPPD_OPTIONS) ; \ else \ echo "NOT overwriting existing $(DESTDIR)$(PPPOESERVER_PPPD_OPTIONS)"; \ $(install) -m 644 ../configs/pppoe-server-options $(DESTDIR)$(PPPOESERVER_PPPD_OPTIONS)-example ; \ fi @if [ -f /etc/redhat-release ] ; then \ echo "Looks like a Red Hat system; installing $(DESTDIR)/etc/rc.d/init.d/pppoe" ; \ mkdir -p $(DESTDIR)/etc/rc.d/init.d ;\ $(install) -m 755 ../scripts/pppoe-init $(DESTDIR)/etc/rc.d/init.d/pppoe ; \ fi @if [ -f /etc/SuSE-release ] ; then \ echo "Looks like a SuSE Linux system; installing $(DESTDIR)/etc/rc.d/init.d/pppoe" ; \ mkdir -p $(DESTDIR)/etc/rc.d/init.d ;\ $(install) -m 755 ../scripts/pppoe-init-suse $(DESTDIR)/etc/rc.d/init.d/pppoe ; \ fi @if [ -f l2tp/handlers/sync-pppd.so ] ; then \ mkdir -p $(DESTDIR)/usr/lib/l2tp/plugins ; \ $(install) -m 755 l2tp/handlers/sync-pppd.so $(DESTDIR)/usr/lib/l2tp/plugins ; \ mkdir -p $(DESTDIR)/etc/l2tp ; \ $(install) -m 600 l2tp/l2tp.conf $(DESTDIR)/etc/l2tp/l2tp.conf.example ; \ fi @echo "" @echo "Type 'pppoe-setup' to configure the software." servpoet-tgz: distro-servpoet cd .. && tar cvf servpoet-$(RP_VERSION)$(BETA).tar servpoet-$(RP_VERSION)$(BETA) gzip -f -v -9 ../servpoet-$(RP_VERSION)$(BETA).tar rm -rf ../servpoet-$(RP_VERSION)$(BETA) tgz: distro cd .. && tar cvf rp-pppoe-$(RP_VERSION)$(BETA).tar rp-pppoe-$(RP_VERSION)$(BETA) gzip -f -v -9 ../rp-pppoe-$(RP_VERSION)$(BETA).tar rm -rf ../rp-pppoe-$(RP_VERSION)$(BETA) distro-servpoet: distro cp ../servpoet.spec ../rp-pppoe-$(RP_VERSION)$(BETA) $(MAKE) -C licensed-only distro RP_VERSION=$(RP_VERSION) BETA=$(BETA) mv ../rp-pppoe-$(RP_VERSION)$(BETA) ../servpoet-$(RP_VERSION)$(BETA) distro: rm -rf ../rp-pppoe-$(RP_VERSION)$(BETA) mkdir ../rp-pppoe-$(RP_VERSION)$(BETA) for i in README SERVPOET go go-gui rp-pppoe.spec ; do \ cp ../$$i ../rp-pppoe-$(RP_VERSION)$(BETA) || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/gui for i in en.msg ja.msg Makefile.in tkpppoe.in wrapper.c tkpppoe.1 pppoe-wrapper.1 ; do \ cp ../gui/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/gui || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/gui/html for i in mainwin-busy.png mainwin-nonroot.png mainwin.png props-advanced.png props-basic.png props-nic.png props-options.png tkpppoe.html ; do \ cp ../gui/html/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/gui/html || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/configs for i in firewall-masq firewall-standalone pap-secrets pppoe-server-options pppoe.conf ; do \ cp ../configs/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/configs || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/doc for i in CHANGES KERNEL-MODE-PPPOE HOW-TO-CONNECT LICENSE PROBLEMS ; do \ cp ../doc/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/doc || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/man for i in pppoe-connect.8 pppoe-setup.8 pppoe-start.8 pppoe-status.8 pppoe-stop.8 pppoe-server.8 pppoe-sniff.8 pppoe.8 pppoe-relay.8 pppoe.conf.5 ; do \ cp ../man/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/man || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/scripts for i in pppoe-connect.in pppoe-init-suse.in pppoe-init.in pppoe-setup.in pppoe-start.in pppoe-stop.in pppoe-status ; do \ cp ../scripts/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/scripts || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/src for i in Makefile.in install-sh common.c config.h.in configure configure.in debug.c discovery.c if.c md5.c md5.h ppp.c pppoe-server.c pppoe-sniff.c pppoe.c pppoe.h pppoe-server.h plugin.c relay.c relay.h ; do \ cp ../src/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/src || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/src/libevent for i in Makefile.in event.c event.h event_tcp.c event_tcp.h eventpriv.h hash.c hash.h event_sig.c ; do \ cp ../src/libevent/$$i ../rp-pppoe-$(RP_VERSION)$(BETA)/src/libevent || exit 1; \ done mkdir ../rp-pppoe-$(RP_VERSION)$(BETA)/src/plugin distro-beta: beta-check $(MAKE) distro BETA=-BETA-$(BETA) tgz-beta: beta-check $(MAKE) tgz BETA=-BETA-$(BETA) beta-check: @if test "$(BETA)" = "" ; then \ echo "Usage: make distro-beta BETA="; \ exit 1; \ fi rpms: tgz cp ../rp-pppoe-$(RP_VERSION).tar.gz /usr/src/redhat/SOURCES gpg --detach-sign /usr/src/redhat/SOURCES/rp-pppoe-$(RP_VERSION).tar.gz cd ..; \ rpm -ba rp-pppoe.spec rpm --addsign /usr/src/redhat/SRPMS/rp-pppoe-$(RP_VERSION)-1.src.rpm \ /usr/src/redhat/RPMS/i386/rp-pppoe-$(RP_VERSION)-1.i386.rpm \ /usr/src/redhat/RPMS/i386/rp-pppoe-gui-$(RP_VERSION)-1.i386.rpm servpoet-rpms: servpoet-tgz cp ../servpoet-$(RP_VERSION).tar.gz /usr/src/redhat/SOURCES cd .. && rpm -ba servpoet.spec clean: rm -f *.o pppoe-relay pppoe pppoe-sniff pppoe-server core rp-pppoe.so plugin/*.o plugin/libplugin.a *~ test -f licensed-only/Makefile && $(MAKE) -C licensed-only clean || true test -f libevent/Makefile && $(MAKE) -C libevent clean || true test -f l2tp/Makefile && $(MAKE) -C l2tp clean || true distclean: clean rm -f Makefile config.h config.cache config.log config.status rm -f libevent/Makefile rm -f ../scripts/pppoe-connect ../scripts/pppoe-start ../scripts/pppoe-stop ../scripts/pppoe-init ../scripts/pppoe-setup ../scripts/pppoe-init-suse update-version: sed -e 's/^Version: .*$$/Version: $(RP_VERSION)/' ../rp-pppoe.spec > ../rp-pppoe.spec.new && mv ../rp-pppoe.spec.new ../rp-pppoe.spec sed -e 's+^Source: .*$$+Source: https://dianne.skoll.ca/projects/rp-pppoe/download/rp-pppoe-$(RP_VERSION).tar.gz+' ../rp-pppoe.spec > ../rp-pppoe.spec.new && mv ../rp-pppoe.spec.new ../rp-pppoe.spec test -f ../servpoet.spec && sed -e 's/^Version: .*$$/Version: $(RP_VERSION)/' ../servpoet.spec > ../servpoet.spec.new && mv ../servpoet.spec.new ../servpoet.spec || true test -f ../servpoet.spec && sed -e 's+^Source: .*$$+Source: https://dianne.skoll.ca/projects/rp-pppoe/download/servpoet-$(RP_VERSION).tar.gz+' ../servpoet.spec > ../servpoet.spec.new && mv ../servpoet.spec.new ../servpoet.spec || true # Convenience target for Dianne! Don't try to use this one. km: ./configure --enable-plugin=/home/dfs/Archive/PPP/ppp-2.4.0.pppoe4-patched-dfs licensed-only: $(MAKE) -C licensed-only all RP_VERSION=$(RP_VERSION) SERVPOET_VERSION=$(SERVPOET_VERSION) l2tp: libevent/libevent.a $(MAKE) -C l2tp all .PHONY: update-version .PHONY: clean .PHONY: distclean .PHONY: rpms .PHONY: licensed-only .PHONY: distro .PHONY: l2tp rp-pppoe-3.15/src/if.c0000644000175000017500000007206514045237010012655 0ustar dfsdfs/*********************************************************************** * * if.c * * Implementation of user-space PPPoE redirector for Linux. * * Functions for opening a raw socket and reading/writing raw Ethernet frames. * * Copyright (C) 2000-2012 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #include "pppoe.h" #if defined(HAVE_LINUX_IF_H) #include #elif defined(HAVE_NET_IF_H) #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_NETPACKET_PACKET_H #include #elif defined(HAVE_LINUX_IF_PACKET_H) #include #endif #ifdef HAVE_NET_ETHERNET_H #include #endif #ifdef HAVE_ASM_TYPES_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYSLOG_H #include #endif #include #include #include #ifdef HAVE_NET_IF_ARP_H #include #endif #ifdef USE_DLPI #include #include #include #include #include #include #include #include #include #include #include #include /* function declarations */ static void dlpromisconreq( int fd, u_long level); void dlinforeq(int fd); void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen); void dlinfoack(int fd, char *bufp); void dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest); void dlattachreq(int fd, u_long ppa); void dlokack(int fd, char *bufp); void dlbindack(int fd, char *bufp); int strioctl(int fd, int cmd, int timout, int len, char *dp); void strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller); void sigalrm(int sig); void expecting(int prim, union DL_primitives *dlp); static char *dlprim(u_long prim); /* #define DL_DEBUG */ static int dl_abssaplen; static int dl_saplen; static int dl_addrlen; #endif #ifdef USE_BPF #include #include static unsigned char *bpfBuffer; /* Packet filter buffer */ static int bpfLength = 0; /* Packet filter buffer length */ int bpfSize = 0; /* Number of unread bytes in buffer */ static int bpfOffset = 0; /* Current offset in bpfBuffer */ #endif /* Initialize frame types to RFC 2516 values. Some broken peers apparently use different frame types... sigh... */ UINT16_t Eth_PPPOE_Discovery = ETH_PPPOE_DISCOVERY; UINT16_t Eth_PPPOE_Session = ETH_PPPOE_SESSION; /********************************************************************** *%FUNCTION: etherType *%ARGUMENTS: * packet -- a received PPPoE packet *%RETURNS: * ethernet packet type (see /usr/include/net/ethertypes.h) *%DESCRIPTION: * Checks the ethernet packet header to determine its type. * We should only be receveing DISCOVERY and SESSION types if the BPF * is set up correctly. Logs an error if an unexpected type is received. * Note that the ethernet type names come from "pppoe.h" and the packet * packet structure names use the LINUX dialect to maintain consistency * with the rest of this file. See the BSD section of "pppoe.h" for * translations of the data structure names. ***********************************************************************/ UINT16_t etherType(PPPoEPacket *packet) { UINT16_t type = (UINT16_t) ntohs(packet->ethHdr.h_proto); if (type != Eth_PPPOE_Discovery && type != Eth_PPPOE_Session) { syslog(LOG_ERR, "Invalid ether type 0x%x", type); } return type; } #ifdef USE_BPF /********************************************************************** *%FUNCTION: getHWaddr *%ARGUMENTS: * ifname -- name of interface * hwaddr -- buffer for ehthernet address *%RETURNS: * Nothing *%DESCRIPTION: * Locates the Ethernet hardware address for an interface. ***********************************************************************/ void getHWaddr(int sock, char const *ifname, unsigned char *hwaddr) { char inbuf[8192]; const struct sockaddr_dl *sdl; struct ifconf ifc; struct ifreq ifreq, *ifr; int i; int found = 0; ifc.ifc_len = sizeof(inbuf); ifc.ifc_buf = inbuf; if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { fatalSys("SIOCGIFCONF"); } ifr = ifc.ifc_req; ifreq.ifr_name[0] = '\0'; for (i = 0; i < ifc.ifc_len; ) { ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i); i += sizeof(ifr->ifr_name) + (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) ? ifr->ifr_addr.sa_len : sizeof(struct sockaddr)); if (ifr->ifr_addr.sa_family == AF_LINK) { sdl = (const struct sockaddr_dl *) &ifr->ifr_addr; if ((sdl->sdl_type == IFT_ETHER) && (sdl->sdl_alen == ETH_ALEN) && !strncmp(ifname, ifr->ifr_name, sizeof(ifr->ifr_name))) { if (found) { char buffer[256]; sprintf(buffer, "interface %.16s has more than one ethernet address", ifname); rp_fatal(buffer); } else { found = 1; memcpy(hwaddr, LLADDR(sdl), ETH_ALEN); } } } } if (!found) { char buffer[256]; sprintf(buffer, "interface %.16s has no ethernet address", ifname); rp_fatal(buffer); } } /********************************************************************** *%FUNCTION: initFilter *%ARGUMENTS: * fd -- file descriptor of BSD device * type -- Ethernet frame type (0 for watch mode) * hwaddr -- buffer with ehthernet address *%RETURNS: * Nothing *%DESCRIPTION: * Initializes the packet filter rules. ***********************************************************************/ void initFilter(int fd, UINT16_t type, unsigned char *hwaddr) { /* Packet Filter Instructions: * Note that the ethernet type names come from "pppoe.h" and are * used here to maintain consistency with the rest of this file. */ static struct bpf_insn bpfRun[] = { /* run PPPoE */ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), /* ethernet type */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_PPPOE_SESSION, 5, 0), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETH_PPPOE_DISCOVERY, 0, 9), BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 0), /* first word of dest. addr */ #define PPPOE_BCAST_CMPW 4 /* offset of word compare */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 2), BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 4), /* next 1/2 word of dest. */ #define PPPOE_BCAST_CMPH 6 /* offset of 1/2 word compare */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 4, 0), BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 0), /* first word of dest. addr */ #define PPPOE_FILTER_CMPW 8 /* offset of word compare */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 3), BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 4), /* next 1/2 word of dest. */ #define PPPOE_FILTER_CMPH 10 /* offset of 1/rd compare */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 1), BPF_STMT(BPF_RET+BPF_K, (u_int) -1), /* keep packet */ BPF_STMT(BPF_RET+BPF_K, 0), /* drop packet */ }; /* Fix the potentially varying parts */ bpfRun[1].code = (u_short) BPF_JMP+BPF_JEQ+BPF_K; bpfRun[1].jt = 5; bpfRun[1].jf = 0; bpfRun[1].k = Eth_PPPOE_Session; bpfRun[2].code = (u_short) BPF_JMP+BPF_JEQ+BPF_K; bpfRun[2].jt = 0; bpfRun[2].jf = 9; bpfRun[2].k = Eth_PPPOE_Discovery; { struct bpf_insn bpfInsn[sizeof(bpfRun) / sizeof(bpfRun[0])]; struct bpf_program bpfProgram; memcpy(bpfInsn, bpfRun, sizeof(bpfRun)); bpfInsn[PPPOE_BCAST_CMPW].k = ((0xff << 24) | (0xff << 16) | (0xff << 8) | 0xff); bpfInsn[PPPOE_BCAST_CMPH].k = ((0xff << 8) | 0xff); bpfInsn[PPPOE_FILTER_CMPW].k = ((hwaddr[0] << 24) | (hwaddr[1] << 16) | (hwaddr[2] << 8) | hwaddr[3]); bpfInsn[PPPOE_FILTER_CMPH].k = ((hwaddr[4] << 8) | hwaddr[5]); bpfProgram.bf_len = (sizeof(bpfInsn) / sizeof(bpfInsn[0])); bpfProgram.bf_insns = &bpfInsn[0]; /* Apply the filter */ if (ioctl(fd, BIOCSETF, &bpfProgram) < 0) { fatalSys("ioctl(BIOCSETF)"); } } } /********************************************************************** *%FUNCTION: openInterface *%ARGUMENTS: * ifname -- name of interface * type -- Ethernet frame type (0 for any frame type) * hwaddr -- if non-NULL, set to the hardware address *%RETURNS: * A file descriptor for talking with the Ethernet card. Exits on error. * Note that the Linux version of this routine returns a socket instead. *%DESCRIPTION: * Opens a BPF on an interface for all PPPoE traffic (discovery and * session). If 'type' is 0, uses promiscuous mode to watch any PPPoE * traffic on this network. ***********************************************************************/ int openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr) { static int fd = -1; char bpfName[32]; u_int optval; struct bpf_version bpf_ver; struct ifreq ifr; int sock; int i; /* BSD only opens one socket for both Discovery and Session packets */ if (fd >= 0) { return fd; } /* Find a free BPF device */ for (i = 0; i < 256; i++) { sprintf(bpfName, "/dev/bpf%d", i); if (((fd = open(bpfName, O_RDWR, 0)) >= 0) || (errno != EBUSY)) { break; } } if (fd < 0) { switch (errno) { case EACCES: /* permission denied */ { char buffer[256]; sprintf(buffer, "Cannot open %.32s -- pppoe must be run as root.", bpfName); rp_fatal(buffer); } break; case EBUSY: case ENOENT: /* no such file */ if (i == 0) { rp_fatal("No /dev/bpf* devices (check your kernel configuration for BPF support)"); } else { rp_fatal("All /dev/bpf* devices are in use"); } break; } fatalSys(bpfName); } if ((sock = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) { fatalSys("socket"); } /* Check that the interface is up */ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { fatalSys("ioctl(SIOCGIFFLAGS)"); } if ((ifr.ifr_flags & IFF_UP) == 0) { char buffer[256]; sprintf(buffer, "Interface %.16s is not up", ifname); rp_fatal(buffer); } /* Fill in hardware address and initialize the packet filter rules */ if (hwaddr == NULL) { rp_fatal("openInterface: no hwaddr arg."); } getHWaddr(sock, ifname, hwaddr); initFilter(fd, type, hwaddr); /* Sanity check on MTU -- apparently does not work on OpenBSD */ #if !defined(__OpenBSD__) strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) { fatalSys("ioctl(SIOCGIFMTU)"); } if (ifr.ifr_mtu < ETH_DATA_LEN) { char buffer[256]; sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d. You may have serious connection problems.", ifname, ifr.ifr_mtu, ETH_DATA_LEN); printErr(buffer); } #endif /* done with the socket */ if (close(sock) < 0) { fatalSys("close"); } /* Check the BPF version number */ if (ioctl(fd, BIOCVERSION, &bpf_ver) < 0) { fatalSys("ioctl(BIOCVERSION)"); } if ((bpf_ver.bv_major != BPF_MAJOR_VERSION) || (bpf_ver.bv_minor < BPF_MINOR_VERSION)) { char buffer[256]; sprintf(buffer, "Unsupported BPF version: %d.%d (kernel: %d.%d)", BPF_MAJOR_VERSION, BPF_MINOR_VERSION, bpf_ver.bv_major, bpf_ver.bv_minor); rp_fatal(buffer); } /* allocate a receive packet buffer */ if (ioctl(fd, BIOCGBLEN, &bpfLength) < 0) { fatalSys("ioctl(BIOCGBLEN)"); } if (!(bpfBuffer = (unsigned char *) malloc(bpfLength))) { rp_fatal("malloc"); } /* reads should return as soon as there is a packet available */ optval = 1; if (ioctl(fd, BIOCIMMEDIATE, &optval) < 0) { fatalSys("ioctl(BIOCIMMEDIATE)"); } /* Bind the interface to the filter */ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(fd, BIOCSETIF, &ifr) < 0) { char buffer[256]; sprintf(buffer, "ioctl(BIOCSETIF) can't select interface %.16s", ifname); rp_fatal(buffer); } syslog(LOG_INFO, "Interface=%.16s HWaddr=%02X:%02X:%02X:%02X:%02X:%02X Device=%.32s Buffer size=%d", ifname, hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5], bpfName, bpfLength); return fd; } #endif /* USE_BPF */ #ifdef USE_LINUX_PACKET /********************************************************************** *%FUNCTION: openInterface *%ARGUMENTS: * ifname -- name of interface * type -- Ethernet frame type * hwaddr -- if non-NULL, set to the hardware address * mtu -- if non-NULL, set to the MTU *%RETURNS: * A raw socket for talking to the Ethernet card. Exits on error. *%DESCRIPTION: * Opens a raw Ethernet socket ***********************************************************************/ int openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr, UINT16_t *mtu) { int optval=1; int fd; struct ifreq ifr; int domain, stype; #ifdef HAVE_STRUCT_SOCKADDR_LL struct sockaddr_ll sa; #else struct sockaddr sa; #endif memset(&sa, 0, sizeof(sa)); #ifdef HAVE_STRUCT_SOCKADDR_LL domain = PF_PACKET; stype = SOCK_RAW; #else domain = PF_INET; stype = SOCK_PACKET; #endif if ((fd = socket(domain, stype, htons(type))) < 0) { /* Give a more helpful message for the common error case */ if (errno == EPERM) { rp_fatal("Cannot create raw socket -- pppoe must be run as root."); } fatalSys("socket"); } if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0) { fatalSys("setsockopt"); } /* Fill in hardware address */ if (hwaddr) { strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { fatalSys("ioctl(SIOCGIFHWADDR)"); } memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); #ifdef ARPHRD_ETHER if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { char buffer[256]; sprintf(buffer, "Interface %.16s is not Ethernet", ifname); rp_fatal(buffer); } #endif if (NOT_UNICAST(hwaddr)) { char buffer[256]; sprintf(buffer, "Interface %.16s has broadcast/multicast MAC address??", ifname); rp_fatal(buffer); } } /* Sanity check on MTU */ strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) { fatalSys("ioctl(SIOCGIFMTU)"); } if (ifr.ifr_mtu < ETH_DATA_LEN) { char buffer[256]; sprintf(buffer, "Interface %.16s has MTU of %d -- should be %d. You may have serious connection problems.", ifname, ifr.ifr_mtu, ETH_DATA_LEN); printErr(buffer); } if (mtu) *mtu = ifr.ifr_mtu; #ifdef HAVE_STRUCT_SOCKADDR_LL /* Get interface index */ sa.sll_family = AF_PACKET; sa.sll_protocol = htons(type); strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) { fatalSys("ioctl(SIOCFIGINDEX): Could not get interface index"); } sa.sll_ifindex = ifr.ifr_ifindex; #else strcpy(sa.sa_data, ifname); #endif /* We're only interested in packets on specified interface */ if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { fatalSys("bind"); } return fd; } #endif /* USE_LINUX */ /*********************************************************************** *%FUNCTION: sendPacket *%ARGUMENTS: * sock -- socket to send to * pkt -- the packet to transmit * size -- size of packet (in bytes) *%RETURNS: * 0 on success; -1 on failure *%DESCRIPTION: * Transmits a packet ***********************************************************************/ int sendPacket(PPPoEConnection *conn, int sock, PPPoEPacket *pkt, int size) { #if defined(USE_BPF) if (write(sock, pkt, size) < 0) { sysErr("write (sendPacket)"); return -1; } #elif defined(HAVE_STRUCT_SOCKADDR_LL) if (send(sock, pkt, size, 0) < 0 && (errno != ENOBUFS)) { sysErr("send (sendPacket)"); return -1; } #else #ifdef USE_DLPI #define ABS(x) ((x) < 0 ? -(x) : (x)) u_char addr[MAXDLADDR]; u_char phys[MAXDLADDR]; u_char sap[MAXDLADDR]; u_char xmitbuf[MAXDLBUF]; int data_size; short tmp_sap; tmp_sap = htons(pkt->ethHdr.h_proto); data_size = size - sizeof(struct ethhdr); memcpy((char *)phys, (char *)pkt->ethHdr.h_dest, ETHERADDRL); memcpy((char *)sap, (char *)&tmp_sap, sizeof(ushort_t)); memcpy((char *)xmitbuf, (char *)pkt + sizeof(struct ethhdr), data_size); if (dl_saplen > 0) { /* order is sap+phys */ (void) memcpy((char*)addr, (char*)&sap, dl_abssaplen); (void) memcpy((char*)addr+dl_abssaplen, (char*)phys, ETHERADDRL); } else { /* order is phys+sap */ (void) memcpy((char*)addr, (char*)phys, ETHERADDRL); (void) memcpy((char*)addr+ETHERADDRL, (char*)&sap, dl_abssaplen); } #ifdef DL_DEBUG printf("%02x:%02x:%02x:%02x:%02x:%02x %02x:%02x\n", addr[0],addr[1],addr[2],addr[3],addr[4],addr[5], addr[6],addr[7]); #endif dlunitdatareq(sock, addr, dl_addrlen, 0, 0, xmitbuf, data_size); #else struct sockaddr sa; if (!conn) { rp_fatal("relay and server not supported on Linux 2.0 kernels"); } strcpy(sa.sa_data, conn->ifName); if (sendto(sock, pkt, size, 0, &sa, sizeof(sa)) < 0) { sysErr("sendto (sendPacket)"); return -1; } #endif #endif return 0; } #ifdef USE_BPF /*********************************************************************** *%FUNCTION: clearPacketHeader *%ARGUMENTS: * pkt -- packet that needs its head clearing *%RETURNS: * nothing *%DESCRIPTION: * Clears a PPPoE packet header after a truncated packet has been * received. Insures that the packet will fail any integrity tests * and will be discarded by upper level routines. Also resets the * bpfSize and bpfOffset variables to force a new read on the next * call to receivePacket(). ***********************************************************************/ void clearPacketHeader(PPPoEPacket *pkt) { bpfSize = bpfOffset = 0; memset(pkt, 0, HDR_SIZE); } #endif /*********************************************************************** *%FUNCTION: receivePacket *%ARGUMENTS: * sock -- socket to read from * pkt -- place to store the received packet * size -- set to size of packet in bytes *%RETURNS: * >= 0 if all OK; < 0 if error *%DESCRIPTION: * Receives a packet ***********************************************************************/ int receivePacket(int sock, PPPoEPacket *pkt, int *size) { #ifdef USE_BPF struct bpf_hdr hdr; int seglen, copylen; if (bpfSize <= 0) { bpfOffset = 0; if ((bpfSize = read(sock, bpfBuffer, bpfLength)) < 0) { sysErr("read (receivePacket)"); return -1; } } if (bpfSize < sizeof(hdr)) { syslog(LOG_ERR, "Truncated bpf packet header: len=%d", bpfSize); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } memcpy(&hdr, bpfBuffer + bpfOffset, sizeof(hdr)); if (hdr.bh_caplen != hdr.bh_datalen) { syslog(LOG_ERR, "Truncated bpf packet: caplen=%d, datalen=%d", hdr.bh_caplen, hdr.bh_datalen); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } seglen = hdr.bh_hdrlen + hdr.bh_caplen; if (seglen > bpfSize) { syslog(LOG_ERR, "Truncated bpf packet: seglen=%d, bpfSize=%d", seglen, bpfSize); clearPacketHeader(pkt); /* resets bpfSize and bpfOffset */ return 0; } seglen = BPF_WORDALIGN(seglen); *size = copylen = ((hdr.bh_caplen < sizeof(PPPoEPacket)) ? hdr.bh_caplen : sizeof(PPPoEPacket)); memcpy(pkt, bpfBuffer + bpfOffset + hdr.bh_hdrlen, copylen); if (seglen >= bpfSize) { bpfSize = bpfOffset = 0; } else { bpfSize -= seglen; bpfOffset += seglen; } #else #ifdef USE_DLPI struct strbuf data; int flags = 0; int retval; data.buf = (char *) pkt; data.maxlen = MAXDLBUF; data.len = 0; if ((retval = getmsg(sock, NULL, &data, &flags)) < 0) { sysErr("read (receivePacket)"); return -1; } *size = data.len; #else if ((*size = recv(sock, pkt, sizeof(PPPoEPacket), 0)) < 0) { sysErr("recv (receivePacket)"); return -1; } #endif #endif return 0; } #ifdef USE_DLPI /********************************************************************** *%FUNCTION: openInterface *%ARGUMENTS: * ifname -- name of interface * type -- Ethernet frame type * hwaddr -- if non-NULL, set to the hardware address *%RETURNS: * A raw socket for talking to the Ethernet card. Exits on error. *%DESCRIPTION: * Opens a raw Ethernet socket ***********************************************************************/ int openInterface(char const *ifname, UINT16_t type, unsigned char *hwaddr) { int fd; long buf[MAXDLBUF]; union DL_primitives *dlp; char base_dev[PATH_MAX]; int ppa; if(strlen(ifname) > PATH_MAX) { rp_fatal("socket: Interface name too long"); } if (strlen(ifname) < 2) { rp_fatal("socket: Interface name too short"); } ppa = atoi(&ifname[strlen(ifname)-1]); strlcpy(base_dev, ifname, PATH_MAX); /* rearranged order of DLPI code - delphys 20010803 */ dlp = (union DL_primitives*) buf; if ( (fd = open(base_dev, O_RDWR)) < 0) { /* Give a more helpful message for the common error case */ if (errno == EPERM) { rp_fatal("Cannot create raw socket -- pppoe must be run as root."); } /* Common error is to omit /dev/ */ if (errno == ENOENT) { char ifname[512]; snprintf(ifname, sizeof(ifname), "/dev/%s", base_dev); if ((fd = open(ifname, O_RDWR)) < 0) { if (errno == EPERM) { rp_fatal("Cannot create raw socket -- pppoe must be run as root."); } } } } if (fd < 0) { fatalSys("socket"); } /* rearranged order of DLPI code - delphys 20010803 */ dlattachreq(fd, ppa); dlokack(fd, (char *)buf); dlbindreq(fd, type, 0, DL_CLDLS, 0, 0); dlbindack(fd, (char *)buf); dlinforeq(fd); dlinfoack(fd, (char *)buf); dl_abssaplen = ABS(dlp->info_ack.dl_sap_length); dl_saplen = dlp->info_ack.dl_sap_length; if (ETHERADDRL != (dlp->info_ack.dl_addr_length - dl_abssaplen)) fatalSys("invalid destination physical address length"); dl_addrlen = dl_abssaplen + ETHERADDRL; /* ethernet address retrieved as part of DL_INFO_ACK - delphys 20010803 */ memcpy(hwaddr, (u_char*)((char*)(dlp) + (int)(dlp->info_ack.dl_addr_offset)), ETHERADDRL); if ( strioctl(fd, DLIOCRAW, -1, 0, NULL) < 0 ) { fatalSys("DLIOCRAW"); } if (ioctl(fd, I_FLUSH, FLUSHR) < 0) fatalSys("I_FLUSH"); return fd; } /* cloned from dlcommon.c */ static void dlpromisconreq(int fd, u_long level) { dl_promiscon_req_t promiscon_req; struct strbuf ctl; int flags; promiscon_req.dl_primitive = DL_PROMISCON_REQ; promiscon_req.dl_level = level; ctl.maxlen = 0; ctl.len = sizeof (promiscon_req); ctl.buf = (char *) &promiscon_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlpromiscon: putmsg"); } void dlinforeq(int fd) { dl_info_req_t info_req; struct strbuf ctl; int flags; info_req.dl_primitive = DL_INFO_REQ; ctl.maxlen = 0; ctl.len = sizeof (info_req); ctl.buf = (char *) &info_req; flags = RS_HIPRI; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlinforeq: putmsg"); } void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen) { long buf[MAXDLBUF]; union DL_primitives *dlp; struct strbuf data, ctl; dlp = (union DL_primitives*) buf; dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; dlp->unitdata_req.dl_dest_addr_length = addrlen; dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); dlp->unitdata_req.dl_priority.dl_min = minpri; dlp->unitdata_req.dl_priority.dl_max = maxpri; (void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen); ctl.maxlen = 0; ctl.len = sizeof (dl_unitdata_req_t) + addrlen; ctl.buf = (char *) buf; data.maxlen = 0; data.len = datalen; data.buf = (char *) datap; if (putmsg(fd, &ctl, &data, 0) < 0) fatalSys("dlunitdatareq: putmsg"); } void dlinfoack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_INFO_ACK, dlp); if (ctl.len < sizeof (dl_info_ack_t)) { char buffer[256]; sprintf(buffer, "dlinfoack: response ctl.len too short: %d", ctl.len); rp_fatal(buffer); } if (flags != RS_HIPRI) rp_fatal("dlinfoack: DL_INFO_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_info_ack_t)) { char buffer[256]; sprintf(buffer, "dlinfoack: short response ctl.len: %d", ctl.len); rp_fatal(buffer); } } void dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest) { dl_bind_req_t bind_req; struct strbuf ctl; int flags; bind_req.dl_primitive = DL_BIND_REQ; bind_req.dl_sap = sap; bind_req.dl_max_conind = max_conind; bind_req.dl_service_mode = service_mode; bind_req.dl_conn_mgmt = conn_mgmt; bind_req.dl_xidtest_flg = xidtest; ctl.maxlen = 0; ctl.len = sizeof (bind_req); ctl.buf = (char *) &bind_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlbindreq: putmsg"); } void dlattachreq(int fd, u_long ppa) { dl_attach_req_t attach_req; struct strbuf ctl; int flags; attach_req.dl_primitive = DL_ATTACH_REQ; attach_req.dl_ppa = ppa; ctl.maxlen = 0; ctl.len = sizeof (attach_req); ctl.buf = (char *) &attach_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) fatalSys("dlattachreq: putmsg"); } void dlokack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_OK_ACK, dlp); if (ctl.len < sizeof (dl_ok_ack_t)) { char buffer[256]; sprintf(buffer, "dlokack: response ctl.len too short: %d", ctl.len); rp_fatal(buffer); } if (flags != RS_HIPRI) rp_fatal("dlokack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_ok_ack_t)) { char buffer[256]; sprintf(buffer, "dlokack: short response ctl.len: %d", ctl.len); rp_fatal(buffer); } } void dlbindack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_BIND_ACK, dlp); if (flags != RS_HIPRI) rp_fatal("dlbindack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_bind_ack_t)) { char buffer[256]; sprintf(buffer, "dlbindack: short response ctl.len: %d", ctl.len); rp_fatal(buffer); } } int strioctl(int fd, int cmd, int timout, int len, char *dp) { struct strioctl sioc; int rc; sioc.ic_cmd = cmd; sioc.ic_timout = timout; sioc.ic_len = len; sioc.ic_dp = dp; rc = ioctl(fd, I_STR, &sioc); if (rc < 0) return (rc); else return (sioc.ic_len); } void strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller) { int rc; static char errmsg[80]; /* * Start timer. */ (void) signal(SIGALRM, sigalrm); if (alarm(MAXWAIT) < 0) { (void) sprintf(errmsg, "%s: alarm", caller); fatalSys(errmsg); } /* * Set flags argument and issue getmsg(). */ *flagsp = 0; if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) { (void) sprintf(errmsg, "%s: getmsg", caller); fatalSys(errmsg); } /* * Stop timer. */ if (alarm(0) < 0) { (void) sprintf(errmsg, "%s: alarm", caller); fatalSys(errmsg); } /* * Check for MOREDATA and/or MORECTL. */ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) { char buffer[256]; sprintf(buffer, "%s: MORECTL|MOREDATA", caller); rp_fatal(buffer); } if (rc & MORECTL) { char buffer[256]; sprintf(buffer, "%s: MORECTL", caller); rp_fatal(buffer); } if (rc & MOREDATA) { char buffer[256]; sprintf(buffer, "%s: MOREDATA", caller); rp_fatal(buffer); } /* * Check for at least sizeof (long) control data portion. */ if (ctlp->len < sizeof (long)) { char buffer[256]; sprintf(buffer, "getmsg: control portion length < sizeof (long): %d", ctlp->len); rp_fatal(buffer); } } void sigalrm(int sig) { (void) rp_fatal("sigalrm: TIMEOUT"); } void expecting(int prim, union DL_primitives *dlp) { if (dlp->dl_primitive != (u_long)prim) { char buffer[256]; sprintf(buffer, "expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive)); rp_fatal(buffer); exit(1); } } static char * dlprim(u_long prim) { static char primbuf[80]; switch ((int)prim) { CASERET(DL_INFO_REQ); CASERET(DL_INFO_ACK); CASERET(DL_ATTACH_REQ); CASERET(DL_DETACH_REQ); CASERET(DL_BIND_REQ); CASERET(DL_BIND_ACK); CASERET(DL_UNBIND_REQ); CASERET(DL_OK_ACK); CASERET(DL_ERROR_ACK); CASERET(DL_SUBS_BIND_REQ); CASERET(DL_SUBS_BIND_ACK); CASERET(DL_UNITDATA_REQ); CASERET(DL_UNITDATA_IND); CASERET(DL_UDERROR_IND); CASERET(DL_UDQOS_REQ); CASERET(DL_CONNECT_REQ); CASERET(DL_CONNECT_IND); CASERET(DL_CONNECT_RES); CASERET(DL_CONNECT_CON); CASERET(DL_TOKEN_REQ); CASERET(DL_TOKEN_ACK); CASERET(DL_DISCONNECT_REQ); CASERET(DL_DISCONNECT_IND); CASERET(DL_RESET_REQ); CASERET(DL_RESET_IND); CASERET(DL_RESET_RES); CASERET(DL_RESET_CON); default: (void) sprintf(primbuf, "unknown primitive 0x%lx", prim); return (primbuf); } } #endif /* USE_DLPI */ rp-pppoe-3.15/src/ppp.c0000644000175000017500000002210014045237010013037 0ustar dfsdfs/*********************************************************************** * * ppp.c * * Implementation of user-space PPPoE redirector for Linux. * * Functions for talking to PPP daemon * * Copyright (C) 2000-2012 by Roaring Penguin Software Inc. * Copyright (C) 2018-2021 Dianne Skoll * * This program may be distributed according to the terms of the GNU * General Public License, version 2 or (at your option) any later version. * * LIC: GPL * ***********************************************************************/ #include "pppoe.h" #ifdef HAVE_SYSLOG_H #include #endif #include #include #include #ifdef HAVE_SYS_UIO_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_N_HDLC #ifndef N_HDLC #include #endif #endif static int PPPState; static int PPPPacketSize; static unsigned char PPPXorValue; static UINT16_t const fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; /********************************************************************** *%FUNCTION: syncReadFromPPP *%ARGUMENTS: * conn -- PPPoEConnection structure * packet -- buffer in which to place PPPoE packet *%RETURNS: * Nothing *%DESCRIPTION: * Reads from a synchronous PPP device and builds and transmits a PPPoE * packet ***********************************************************************/ void syncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet) { int r; #ifndef HAVE_N_HDLC struct iovec vec[2]; unsigned char dummy[2]; vec[0].iov_base = (void *) dummy; vec[0].iov_len = 2; vec[1].iov_base = (void *) packet->payload; vec[1].iov_len = ETH_JUMBO_LEN - PPPOE_OVERHEAD; /* Use scatter-read to throw away the PPP frame address bytes */ r = readv(0, vec, 2); #else /* Bloody hell... readv doesn't work with N_HDLC line discipline... GRR! */ unsigned char buf[ETH_JUMBO_LEN - PPPOE_OVERHEAD + 2]; r = read(0, buf, ETH_JUMBO_LEN - PPPOE_OVERHEAD + 2); if (r >= 2) { memcpy(packet->payload, buf+2, r-2); } #endif if (r < 0) { /* Catch the Linux "select" bug */ if (errno == EAGAIN) { rp_fatal("Linux select bug hit! This message is harmless, but please ask the Linux kernel developers to fix it."); } fatalSys("read (syncReadFromPPP)"); } if (r == 0) { syslog(LOG_INFO, "end-of-file in syncReadFromPPP"); sendPADT(conn, "RP-PPPoE: EOF in syncReadFromPPP"); exit(0); } if (r < 2) { rp_fatal("too few characters read from PPP (syncReadFromPPP)"); } sendSessionPacket(conn, packet, r-2); } /********************************************************************** *%FUNCTION: initPPP *%ARGUMENTS: * None *%RETURNS: * Nothing *%DESCRIPTION: * Initializes the PPP state machine ***********************************************************************/ void initPPP(void) { PPPState = STATE_WAITFOR_FRAME_ADDR; PPPPacketSize = 0; PPPXorValue = 0; } /********************************************************************** *%FUNCTION: asyncReadFromPPP *%ARGUMENTS: * conn -- PPPoEConnection structure * packet -- buffer in which to place PPPoE packet *%RETURNS: * Nothing *%DESCRIPTION: * Reads from an async PPP device and builds a PPPoE packet to transmit ***********************************************************************/ void asyncReadFromPPP(PPPoEConnection *conn, PPPoEPacket *packet) { unsigned char buf[READ_CHUNK]; unsigned char *ptr = buf; unsigned char c; int r; r = read(0, buf, READ_CHUNK); if (r < 0) { fatalSys("read (asyncReadFromPPP)"); } if (r == 0) { syslog(LOG_INFO, "end-of-file in asyncReadFromPPP"); sendPADT(conn, "RP-PPPoE: EOF in asyncReadFromPPP"); exit(0); } while(r) { if (PPPState == STATE_WAITFOR_FRAME_ADDR) { while(r) { --r; if (*ptr++ == FRAME_ADDR) { PPPState = STATE_DROP_PROTO; break; } } } /* Still waiting... */ if (PPPState == STATE_WAITFOR_FRAME_ADDR) return; while(r && PPPState == STATE_DROP_PROTO) { --r; if (*ptr++ == (FRAME_CTRL ^ FRAME_ENC)) { PPPState = STATE_BUILDING_PACKET; } } if (PPPState == STATE_DROP_PROTO) return; /* Start building frame */ while(r && PPPState == STATE_BUILDING_PACKET) { --r; c = *ptr++; switch(c) { case FRAME_ESC: PPPXorValue = FRAME_ENC; break; case FRAME_FLAG: if (PPPPacketSize < 2) { rp_fatal("Packet too short from PPP (asyncReadFromPPP)"); } sendSessionPacket(conn, packet, PPPPacketSize-2); PPPPacketSize = 0; PPPXorValue = 0; PPPState = STATE_WAITFOR_FRAME_ADDR; break; default: if (PPPPacketSize >= ETH_JUMBO_LEN - 4) { syslog(LOG_ERR, "Packet too big! Check MTU on PPP interface"); PPPPacketSize = 0; PPPXorValue = 0; PPPState = STATE_WAITFOR_FRAME_ADDR; } else { packet->payload[PPPPacketSize++] = c ^ PPPXorValue; PPPXorValue = 0; } } } } } /********************************************************************** *%FUNCTION: decodeFromPPP *%ARGUMENTS: * conn -- PPPoEConnection structure * packet -- buffer in which to place PPPoE packet *%RETURNS: * Nothing *%DESCRIPTION: * Reads from an async PPP device and builds a PPPoE packet to transmit ***********************************************************************/ void decodeFromPPP(PPPoEConnection *conn, PPPoEPacket *packet, unsigned char *buf, int r) { unsigned char *ptr = buf; unsigned char c; while(r) { if (PPPState == STATE_WAITFOR_FRAME_ADDR) { while(r) { --r; if (*ptr++ == FRAME_ADDR) { PPPState = STATE_DROP_PROTO; break; } } } /* Still waiting... */ if (PPPState == STATE_WAITFOR_FRAME_ADDR) return; while(r && PPPState == STATE_DROP_PROTO) { --r; if (*ptr++ == (FRAME_CTRL ^ FRAME_ENC)) { PPPState = STATE_BUILDING_PACKET; } } if (PPPState == STATE_DROP_PROTO) return; /* Start building frame */ while(r && PPPState == STATE_BUILDING_PACKET) { --r; c = *ptr++; switch(c) { case FRAME_ESC: PPPXorValue = FRAME_ENC; break; case FRAME_FLAG: if (PPPPacketSize < 2) { rp_fatal("Packet too short from PPP (asyncReadFromPPP)"); } sendSessionPacket(conn, packet, PPPPacketSize-2); PPPPacketSize = 0; PPPXorValue = 0; PPPState = STATE_WAITFOR_FRAME_ADDR; break; default: if (PPPPacketSize >= ETH_JUMBO_LEN - 4) { syslog(LOG_ERR, "Packet too big! Check MTU on PPP interface"); PPPPacketSize = 0; PPPXorValue = 0; PPPState = STATE_WAITFOR_FRAME_ADDR; } else { packet->payload[PPPPacketSize++] = c ^ PPPXorValue; PPPXorValue = 0; } } } } } /********************************************************************** *%FUNCTION: pppFCS16 *%ARGUMENTS: * fcs -- current fcs * cp -- a buffer's worth of data * len -- length of buffer "cp" *%RETURNS: * A new FCS *%DESCRIPTION: * Updates the PPP FCS. ***********************************************************************/ UINT16_t pppFCS16(UINT16_t fcs, unsigned char * cp, int len) { while (len--) fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff]; return (fcs); } rp-pppoe-3.15/src/config.h.in0000644000175000017500000000727614045237010014140 0ustar dfsdfs/* config.h.in. Generated automatically from configure.in by autoheader. */ /* LIC: GPL */ /* Define to empty if the keyword does not work. */ #undef const /* Define if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define to `int' if doesn't define. */ #undef pid_t /* Define as the return type of signal handlers (int or void). */ #undef RETSIGTYPE /* Define if the setvbuf function takes the buffering type as its second argument and the buffer pointer as the third, as on System V before release 3. */ #undef SETVBUF_REVERSED /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define if your declares struct tm. */ #undef TM_IN_SYS_TIME #undef HAVE_STRUCT_SOCKADDR_LL /* The number of bytes in a unsigned int. */ #undef SIZEOF_UNSIGNED_INT /* The number of bytes in a unsigned long. */ #undef SIZEOF_UNSIGNED_LONG /* The number of bytes in a unsigned short. */ #undef SIZEOF_UNSIGNED_SHORT /* Define if you have the select function. */ #undef HAVE_SELECT /* Define if you have the socket function. */ #undef HAVE_SOCKET /* Define if you have the strerror function. */ #undef HAVE_STRERROR /* Define if you have the strtol function. */ #undef HAVE_STRTOL /* Define if you have the strlcpy function. */ #undef HAVE_STRLCPY /* Define if you have the header file. */ #undef HAVE_ASM_TYPES_H /* Define if you have the header file. */ #undef HAVE_FCNTL_H /* Define if you have the header file. */ #undef HAVE_GETOPT_H /* Define if you have the header file. */ #undef HAVE_LINUX_IF_ETHER_H /* Define if you have kernel-mode PPPoE in Linux file. */ #undef HAVE_LINUX_KERNEL_PPPOE /* Define if you have the header file. */ #undef HAVE_LINUX_IF_PACKET_H /* Define if you have the header file. */ #undef HAVE_LINUX_IF_PPPOX_H /* Define if you have the header file. */ #undef HAVE_NET_BPF_H /* Define if you have the header file. */ #undef HAVE_NET_IF_ARP_H /* Define if you have the header file. */ #undef HAVE_NET_ETHERNET_H /* Define if you have the header file. */ #undef HAVE_NET_IF_H /* Define if you have the header file. */ #undef HAVE_LINUX_IF_H /* Define if you have the header file. */ #undef HAVE_NET_IF_DL_H /* Define if you have the header file. */ #undef HAVE_NET_IF_ETHER_H /* Define if you have the header file. */ #undef HAVE_NET_IF_TYPES_H /* Define if you have the header file. */ #undef HAVE_NETINET_IF_ETHER_H /* Define if you have the header file. */ #undef HAVE_NETPACKET_PACKET_H /* Define if you have the header file. */ #undef HAVE_SYS_DLPI_H /* Define if you have the header file. */ #undef HAVE_SYS_IOCTL_H /* Define if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define if you have the header file. */ #undef HAVE_SYS_UIO_H /* Define if you have the header file. */ #undef HAVE_SYSLOG_H /* Define if you have the header file. */ #undef HAVE_UNISTD_H /* Define if you have the N_HDLC line discipline in pty.h */ #undef HAVE_N_HDLC /* Define to include debugging code */ #undef DEBUGGING_ENABLED /* Solaris moans if we don't do this... */ #ifdef __sun #define __EXTENSIONS__ 1 #endif rp-pppoe-3.15/man/0000755000175000017500000000000014045237010012065 5ustar dfsdfsrp-pppoe-3.15/man/pppoe-relay.80000644000175000017500000001035214045237010014414 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-RELAY 8 "26 January 2001" .\"" .UC 4 .SH NAME pppoe-relay \- user-space PPPoE relay agent. .SH SYNOPSIS .B pppoe-relay \fR[\fIoptions\fR] .SH DESCRIPTION \fBpppoe-relay\fR is a user-space relay agent for PPPoE (Point-to-Point Protocol over Ethernet) for Linux. \fBpppoe-relay\fR works in concert with the \fBpppoe\fR client and \fBpppoe-server\fR server. See the OPERATION section later in this manual for details on how \fBpppoe-relay\fR works. .SH OPTIONS .TP .B \-S \fIinterface\fR Adds the Ethernet interface \fIinterface\fR to the list of interfaces managed by \fBpppoe-relay\fR. Only PPPoE servers may be connected to this interface. .TP .B \-C \fIinterface\fR Adds the Ethernet interface \fIinterface\fR to the list of interfaces managed by \fBpppoe-relay\fR. Only PPPoE clients may be connected to this interface. .TP .B \-B \fIinterface\fR Adds the Ethernet interface \fIinterface\fR to the list of interfaces managed by \fBpppoe-relay\fR. Both PPPoE clients and servers may be connected to this interface. .TP .B \-n \fInum\fR Allows at most \fInum\fR concurrent PPPoE sessions. If not specified, the default is 5000. \fInum\fR can range from 1 to 65534. .TP .B \-i \fItimeout\fR Specifies the session idle timeout. If both peers in a session are idle for more than \fItimeout\fR seconds, the session is terminated. If \fItimeout\fR is specified as zero, sessions will never be terminated because of idleness. Note that the idle-session expiry routine is never run more frequently than every 30 seconds, so the timeout is approximate. The default value for \fItimeout\fR is 600 seconds (10 minutes.) .TP .B \-F The \fB\-F\fR option causes \fBpppoe-relay\fR \fInot\fR to fork into the background; instead, it remains in the foreground. .TP .B \-h The \fB\-h\fR option prints a brief usage message and exits. .SH OPERATION \fBpppoe-relay\fR listens for incoming PPPoE PADI frames on all interfaces specified with \fB-B\fR or \fB-C\fR options. When a PADI frame appears, \fBpppoe-relay\fR adds a Relay-Session-ID tag and broadcasts the PADI on all interfaces specified with \fB-B\fR or \fB-S\fR options (except the interface on which the frame arrived.) Any PADO frames received are relayed back to the client which sent the PADI (assuming they contain valid Relay-Session-ID tags.) Likewise, PADR frames from clients are relayed back to the matching access concentrator. When a PADS frame is received, \fBpppoe-relay\fR enters the two peers' MAC addresses and session-ID's into a hash table. (The session-ID seen by the access concentrator may be different from that seen by the client; \fBpppoe-relay\fR must renumber sessions to avoid the possibility of duplicate session-ID's.) Whenever either peer sends a session frame, \fBpppoe-relay\fR looks up the session entry in the hash table and relays the frame to the correct peer. When a PADT frame is received, \fBpppoe-relay\fR relays it to the peer and deletes the session entry from its hash table. If a client and server crash (or frames are lost), PADT frames may never be sent, and \fBpppoe-relay\fR's hash table can fill up with stale sessions. Therefore, a session-cleaning routine runs periodically, and removes old sessions from the hash table. A session is considered "old" if no traffic has been seen within \fItimeout\fR seconds. When a session is deleted because of a timeout, a PADT frame is sent to each peer to make certain that they are aware the session has been killed. .SH EXAMPLE INVOCATIONS .nf pppoe-relay -C eth0 -S eth1 .fi The example above relays frames between PPPoE clients on the eth0 network and PPPoE servers on the eth1 network. .nf pppoe-relay -B eth0 -B eth1 .fi This example is a transparent relay -- frames are relayed between any mix of clients and servers on the eth0 and eth1 networks. .nf pppoe-relay -S eth0 -C eth1 -C eth2 -C eth3 .fi This example relays frames between servers on the eth0 network and clients on the eth1, eth2 and eth3 networks. .SH AUTHORS \fBpppoe-relay\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe-start(8), pppoe-stop(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe(8), pppoe-setup(8), pppoe-status(8), pppoe-sniff(8), pppoe-server(8) rp-pppoe-3.15/man/pppoe-server.80000644000175000017500000001555314045237010014616 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-SERVER 8 "21 June 2008" .\"" .UC 4 .SH NAME pppoe-server \- user-space PPPoE server .SH SYNOPSIS .B pppoe-server \fR[\fIoptions\fR] .SH DESCRIPTION \fBpppoe-server\fR is a user-space server for PPPoE (Point-to-Point Protocol over Ethernet) for Linux and other UNIX systems. \fBpppoe-server\fR works in concert with the \fBpppoe\fR client to respond to PPPoE discovery packets and set up PPPoE sessions. .SH OPTIONS .TP .B \-F The \fB\-F\fR option causes \fBpppoe-server\fR not to fork and become a daemon. The default is to fork and become a daemon. .TP .B \-I \fIinterface\fR The \fB\-I\fR option specifies the Ethernet interface to use. Under Linux, it is typically \fIeth0\fR or \fIeth1\fR. The interface should be "up" before you start \fBpppoe-server\fR, but need not have an IP address. You can supply multiple \fB\-I\fR options if you want the server to respond on more than one interface. .TP .B \-X \fIpidfile\fR This option causes \fBpppoe-server\fR to write its process ID to \fIpidfile\fR. Additionally, it keeps the file locked so that only a single process may be started for a given \fIpidfile\fR. .TP .B \-q \fI/path/to/pppd\fR Specifies the full path to the \fBpppd\fR program. The default is determined at compile time. One use of this option is to supply a wrapper program that modifies the arguments passed to pppd. This lets you do things not directly supported by the server (for example, specify IPv6 addresses.) .TP .B \-Q \fI/path/to/pppoe\fR Specifies the full path to the \fBpppoe\fR program. The default is determined at compile time. This option is only relevant if you are \fInot\fR using kernel-mode PPPoE. .TP .B \-T \fItimeout\fR This option is passed directly to \fBpppoe\fR; see \fBpppoe\fR(8) for details. If you are using kernel-mode PPPoE, this option has \fIno effect\fR. .TP .B \-C \fIac_name\fR Specifies which name to report as the access concentrator name. If not supplied, the host name is used. .TP .B \-S \fIname\fR Offer a service named \fIname\fR. Multiple \fB\-S\fR options may be specified; each one causes the named service to be advertised in a Service-Name tag in the PADO frame. The first \fB\-S\fR option specifies the default service, and is used if the PPPoE client requests a Service-Name of length zero. .TP .B \-m \fIMSS\fR This option is passed directly to \fBpppoe\fR; see \fBpppoe\fR(8) for details. If you are using kernel-mode PPPoE, this option has \fIno effect\fR. .TP .B \-x \fIn\fR Limit the number of sessions per peer MAC address to \fIn\fR. If a given MAC address attempts to create more than \fIn\fR sessions, then its PADI and PADR packets are ignored. If you set \fIn\fR to 0 (the default), then no limit is imposed on the number of sessions per peer MAC address. .TP .B \-s This option is passed directly to \fBpppoe\fR; see \fBpppoe\fR(8) for details. In addition, it causes \fBpppd\fR to be invoked with the \fIsync\fR option. .TP .B \-L \fIip\fR Sets the local IP address. This is passed to spawned \fBpppd\fR processes. If not specified, the default is 10.0.0.1. .TP .B \-R \fIip\fR Sets the starting remote IP address. As sessions are established, IP addresses are assigned starting from \fIip\fR. \fBpppoe-server\fR automatically keeps track of the pool of addresses and passes a valid remote IP address to \fBpppd\fR. If not specified, a starting address of 10.67.15.1 is used. .TP .B \-N \fInum\fR Allows at most \fInum\fR concurrent PPPoE sessions. If not specified, the default is 64. .TP .B \-M \fIstring\fR Sends \fIstring\fR in a MOTM tag in a PADM packet right after sending the PADS to a client. .TP .B \-H \fIurl\fR Sends \fIurl\fR in a HURL tag in a PADM packet right after sending the PADS to a client. Note that \fIurl\fR must start with either \fBhttp://\fR or \fBhttps://\fR. .TP .B \-O \fIfname\fR This option causes \fBpppoe-server\fR to tell \fBpppd\fR to use the option file \fIfname\fR instead of the default \fI/etc/ppp/pppoe-server-options\fR. .TP .B \-p \fIfname\fR Reads the specified file \fIfname\fR which is a text file consisting of one IP address per line. These IP addresses will be assigned to clients. The number of sessions allowed will equal the number of addresses found in the file. The \fB\-p\fR option overrides both \fB\-R\fR and \fB\-N\fR. In addition to containing IP addresses, the pool file can contain lines of the form: .nf a.b.c.d-e .fi which includes all IP addresses from a.b.c.d to a.b.c.e. For example, the line: .nf 1.2.3.4-7 .fi is equivalent to: .nf 1.2.3.4 1.2.3.5 1.2.3.6 1.2.3.7 .fi .TP .B \-r Tells the PPPoE server to randomly permute session numbers. Instead of handing out sessions in order, the session numbers are assigned in an unpredictable order. .TP .B \-u Tells the server to invoke \fBpppd\fR with the \fIunit\fR option. Note that this option only works for \fBpppd\fR version 2.4.0 or newer. .TP .B \-o \fIoffset\fR Instead of numbering PPPoE sessions starting at 1, they will be numbered starting at \fIoffset\fR+1. This allows you to run multiple servers on a given machine; just make sure that their session numbers do not overlap. .TP .B \-f disc:sess The \fB\-f\fR option sets the Ethernet frame types for PPPoE discovery and session frames. The types are specified as hexadecimal numbers separated by a colon. Standard PPPoE uses frame types 8863:8864. \fIYou should not use this option\fR unless you are absolutely sure the peer you are dealing with uses non-standard frame types. .TP .B \-k The \fB\-k\fR option tells the server to use kernel-mode PPPoE on Linux. This option is available only on Linux kernels 2.4.0 and later, and only if the server was built with kernel-mode support. .TP .B \-i The \fB\-i\fR option tells the server to completely ignore PADI frames if there are no free session slots. .TP .B \-h The \fB\-h\fR option prints a brief usage message and exits. .SH OPERATION \fBpppoe-server\fR listens for incoming PPPoE discovery packets. When a session is established, it spawns a \fBpppd\fR process. The following options are passed to \fBpppd\fR: .nf nodetach noaccomp nobsdcom nodeflate nopcomp novj novjccomp default-asyncmap .fi In addition, the local and remote IP address are set based on the \fB\-L\fR and \fB\-R\fR options. The \fBpty\fR option is supplied along with a \fBpppoe\fR command to initiate the PPPoE session. Finally, additional \fBpppd\fR options can be placed in the file \fB/etc/ppp/pppoe-server-options\fR (which must exist, even if it is just empty!) Note that \fBpppoe-server\fR is meant mainly for testing PPPoE clients. It is \fInot\fR a high-performance server meant for production use. .SH AUTHORS \fBpppoe-server\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe-start(8), pppoe-stop(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe(8), pppoe-setup(8), pppoe-status(8), pppoe-sniff(8), pppoe-relay(8) rp-pppoe-3.15/man/pppoe-setup.80000644000175000017500000000130414045237010014435 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-SETUP 8 "21 February 2000" .UC 4 .SH NAME pppoe-setup \- Shell script to configure RP-PPPoE client .SH SYNOPSIS .B pppoe-setup .SH DESCRIPTION \fBpppoe-setup\fR is a shell script which prompts you for various pieces of information and sets up an /etc/ppp/pppoe.conf configuration script for the \fBpppoe-start\fR, \fBpppoe-stop\fR and \fBpppoe-connect\fR scripts. .SH AUTHOR \fBpppoe-setup\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe(8), pppoe-start(8), pppoe-stop(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe-status(8), pppoe-sniff(8), pppoe-relay(8), pppoe-server(8) rp-pppoe-3.15/man/pppoe-start.80000644000175000017500000000155614045237010014443 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-START 8 "21 February 2000" .UC 4 .SH NAME pppoe-start \- Shell script to bring up a PPPoE link .SH SYNOPSIS .B pppoe-start \fR[\fIconfig_file\fR] .P .B pppoe-start \fR\fIinterface user\fR [\fIconfig_file\fR] .SH DESCRIPTION \fBpppoe-start\fR is a shell script which starts the RP-PPPoE user-space PPPoE client. If you omit \fIconfig_file\fR, the default file \fB/etc/ppp/pppoe.conf\fR is used. If you supply \fIinterface\fR and \fIuser\fR, then they override the Ethernet interface and user-name settings in the configuration file. .SH AUTHOR \fBpppoe-start\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe(8), pppoe-stop(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe-setup(8), pppoe-status(8), pppoe-sniff(8), pppoe-relay(8), pppoe-server(8) rp-pppoe-3.15/man/pppoe-stop.80000644000175000017500000000124014045237010014261 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-STOP 8 "21 February 2000" .UC 4 .SH NAME pppoe-stop \- Shell script to shut down a PPPoE link .SH SYNOPSIS .B pppoe-stop \fR[\fIconfig_file\fR] .SH DESCRIPTION \fBpppoe-stop\fR is a shell script which stops the RP-PPPoE user-space PPPoE client. If you omit \fIconfig_file\fR, the default file \fB/etc/ppp/pppoe.conf\fR is used. .SH AUTHOR \fBpppoe-stop\fR was written by Dianne Skoll The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe(8), pppoe-start(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe-setup(8), pppoe-status(8), pppoe-sniff(8), pppoe-relay(8), pppoe-server(8) rp-pppoe-3.15/man/pppoe.conf.50000644000175000017500000001306014045237010014222 0ustar dfsdfs.\" LIC: GPL .TH PPPOE.CONF 5 "21 February 2000" .UC 4 .SH NAME pppoe.conf \- Configuration file used by \fBpppoe-start\fR(8), \fBpppoe-stop\fR(8), \fBpppoe-status(8)\fR and \fBpppoe-connect\fR(8). .SH DESCRIPTION \fB/etc/ppp/pppoe.conf\fR is a shell script which contains configuration information for RP-PPPoE scripts. Note that \fBpppoe.conf\fR is used only by the various pppoe-* shell scripts, not by \fBpppoe\fR itself. \fBpppoe.conf\fR consists of a sequence of shell variable assignments. The variables and their meanings are: .TP .B ETH The Ethernet interface connected to the DSL modem (for example, eth0). .TP .B USER The PPPoE user-id (for example, b1xxnxnx@sympatico.ca). .TP .B SERVICENAME If this is not blank, then it is passed with the \fB\-S\fR option to \fBpppoe\fR. It specifies a service name to ask for. Usually, you should leave it blank. .TP .B ACNAME If this is not blank, then it is passed with the \fB\-C\fR option to \fBpppoe\fR. It specifies the name of the access concentrator to connect to. Usually, you should leave it blank. .TP .B DEMAND If set to a number, the link is activated on demand and brought down after after \fBDEMAND\fR seconds. If set to \fBno\fR, the link is kept up all the time rather than being activated on demand. .TP .B DNSTYPE One of \fBNOCHANGE\fR, \fBSPECIFY\fR or \fBSERVER\fR. If set to NOCHANGE, \fBpppoe-connect\fR will not adjust the DNS setup in any way. If set to SPECIFY, it will re-write /etc/resolv.conf with the values of DNS1 and DNS2. If set to \fBSERVER\fR, it will supply the \fIusepeerdns\fR option to \fBpppd\fR, and make a symlink from /etc/resolv.conf to /etc/ppp/resolv.conf. .TP .B DNS1, DNS2 IP addresses of DNS servers if you use DNSTYPE=SPECIFY. .TP .B NONROOT If the line \fBNONROOT=OK\fR (exactly like that; no whitespace or comments) appears in the configuration file, then \fBpppoe-wrapper\fR will allow non-root users to bring the conneciton up or down. The wrapper is installed only if you installed the rp-pppoe-gui package. .TP .B USEPEERDNS If set to "yes", then \fBpppoe-connect\fR will supply the \fIusepeerdns\fR option to \fBpppd\fR, which causes it to obtain DNS server addresses from the peer and create a new \fB/etc/resolv.conf\fR file. Otherwise, \fBpppoe-connect\fR will not supply this option, and \fBpppd\fR will not modify \fB/etc/resolv.conf\fR. .TP .B CONNECT_POLL How often (in seconds) \fBpppoe-start\fR should check to see if a new PPP interface has come up. If this is set to 0, the \fBpppoe-start\fR simply initiates the PPP session, but does not wait to see if it comes up successfully. .TP .B CONNECT_TIMEOUT How long (in seconds) \fBpppoe-start\fR should wait for a new PPP interface to come up before concluding that \fBpppoe-connect\fR has failed and killing the session. .TP .B PING A character which is echoed every \fBCONNECT_POLL\fR seconds while \fBpppoe-start\fR is waiting for the PPP interface to come up. .TP .B FORCEPING A character which is echoed every \fBCONNECT_POLL\fR seconds while \fBpppoe-start\fR is waiting for the PPP interface to come up. Similar to \fBPING\fR, but the character is echoed even if \fBpppoe-start\fR's standard output is not a tty. .TP .B PIDFILE A file in which to write the process-ID of the pppoe-connect process (for example, \fB/var/run/pppoe.pid\fR). Two additional files ($PIDFILE.pppd and $PIDFILE.pppoe) hold the process-ID's of the \fBpppd\fR and \fBpppoe\fR processes, respectively. .TP .B SYNCHRONOUS An indication of whether or not to use synchronous PPP (\fByes\fR or \fBno\fR). Synchronous PPP is safe on Linux machines with the n_hdlc line discipline. (If you have a file called "n_hdlc.o" in your modules directory, you have the line discipline.) It is \fInot recommended\fR on other machines or on Linux machines without the n_hdlc line discipline due to some known and unsolveable race conditions in a user-mode client. .TP .B CLAMPMSS The value at which to "clamp" the advertised MSS for TCP sessions. The default of 1412 should be fine. .TP .B LCP_INTERVAL How often (in seconds) \fBpppd\fR sends out LCP echo-request packets. .TP .B LCP_FAILURE How many unanswered LCP echo-requests must occur before \fBpppd\fR concludes the link is dead. .TP .B PPPOE_TIMEOUT If this many seconds elapse without any activity seen by \fBpppoe\fR, then \fBpppoe\fR exits. .TP .B FIREWALL One of NONE, STANDALONE or MASQUERADE. If NONE, then \fBpppoe-connect\fR does not add any firewall rules. If STANDALONE, then it clears existing firewall rules and sets up basic rules for a standalone machine. If MASQUERADE, then it clears existing firewall rules and sets up basic rules for an Internet gateway. If you run services on your machine, these simple firewall scripts are inadequate; you'll have to make your own firewall rules and set FIREWALL to NONE. .TP .B PPPOE_EXTRA Any extra arguments to pass to \fBpppoe\fR .TP .B PPPD_EXTRA Any extra arguments to pass to \fBpppd\fR .TP .B LINUX_PLUGIN If non-blank, the full path of the Linux kernel-mode PPPoE plugin (typically \fB/etc/ppp/plugins/rp-pppoe.so\fR.) This forces \fBpppoe-connect\fR to use kernel-mode PPPoE on Linux 2.4.x systems. This code is experimental and unsupported. Use of the plugin causes \fBpppoe-connect\fR to ignore CLAMPMSS, PPPOE_EXTRA, SYNCHRONOUS and PPPOE_TIMEOUT. .P By using different configuration files with different PIDFILE settings, you can manage multiple PPPoE connections. Just specify the configuration file as an argument to \fBpppoe-start\fR and \fBpppoe-stop\fR. .SH SEE ALSO pppoe(8), pppoe-connect(8), pppoe-start(8), pppoe-stop(8), pppd(8), pppoe-setup(8), pppoe-wrapper(8) rp-pppoe-3.15/man/pppoe-connect.80000644000175000017500000000441714045237010014736 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-CONNECT 8 "21 February 2000" .UC 4 .SH NAME pppoe-connect \- Shell script to manage a PPPoE link .SH SYNOPSIS .B pppoe-connect \fR[\fIconfig_file\fR] .P .B pppoe-connect \fR\fIinterface user\fR [\fIconfig_file\fR] .SH DESCRIPTION \fBpppoe-connect\fR is a shell script which manages a PPPoE connection using the Roaring Penguin user-space PPPoE client. If you omit \fIconfig_file\fR, the default file \fB/etc/ppp/pppoe.conf\fR is used. If you supply \fIinterface\fR and \fIuser\fR, then they override the Ethernet interface and user-name settings in the configuration file. .P Note that normally, you should \fInot\fR invoke \fBpppoe-connect\fR directly. Instead, use \fBpppoe-start\fR to bring up the PPPoE connection. .P \fBpppoe-connect\fR first reads a configuration file. It then brings up a PPPoE connection. If the connection ever drops, a message is logged to syslog, and \fBpppoe-connect\fR re-establishes the connection. In addition, each time the connection is dropped or cannot be established, \fBpppoe-connect\fR executes the script \fB/etc/ppp/pppoe-lost\fR if it exists and is executable. .P The shell script \fBpppoe-stop\fR causes \fBpppoe-connect\fR to break out of its loop, bring the connection down, and exit. .SH TECHNICAL DETAILS \fBpppoe-connect\fR uses the following shell variables from the configuration file: .TP .B ETH The Ethernet interface connected to the DSL modem (for example, eth0). .TP .B USER The PPPoE user-id (for example, b1xxnxnx@sympatico.ca). .TP .B PIDFILE A file in which to write the process-ID of the pppoe-connect process (for example, \fB/var/run/pppoe.pid\fR). Two additional files ($PIDFILE.pppd and $PIDFILE.pppoe) hold the process-ID's of the \fBpppd\fR and \fBpppoe\fR processes, respectively. .P By using different configuration files with different PIDFILE settings, you can manage multiple PPPoE connections. Just specify the configuration file as an argument to \fBpppoe-start\fR and \fBpppoe-stop\fR. .SH AUTHOR \fBpppoe-connect\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe(8), pppoe-start(8), pppoe-stop(8), pppd(8), pppoe.conf(5), pppoe-setup(8), pppoe-status(8), pppoe-sniff(8), pppoe-server(8), pppoe-relay(8) rp-pppoe-3.15/man/pppoe.80000644000175000017500000002267214045237010013312 0ustar dfsdfs.\" LIC: GPL .TH PPPOE 8 "5 October 2015" .UC 4 .SH NAME pppoe \- user-space PPPoE client. .SH SYNOPSIS .B pppd pty 'pppoe \fR[\fIpppoe_options\fR]\fB' \fR[\fIpppd_options\fR] .P .B pppoe -A \fR[\fIpppoe_options\fR] .SH DESCRIPTION \fBpppoe\fR is a user-space client for PPPoE (Point-to-Point Protocol over Ethernet) for Linux and other UNIX systems. \fBpppoe\fR works in concert with the \fBpppd\fR PPP daemon to provide a PPP connection over Ethernet, as is used by many DSL service providers. .SH OPTIONS .TP .B \-I \fIinterface\fR The \fB\-I\fR option specifies the Ethernet interface to use. Under Linux, it is typically \fIeth0\fR or \fIeth1\fR. The interface should be "up" before you start \fBpppoe\fR, but should \fInot\fR be configured to have an IP address. .TP .B \-T \fItimeout\fR The \fB\-T\fR option causes \fBpppoe\fR to exit if no session traffic is detected for \fItimeout\fR seconds. I recommend that you use this option as an extra safety measure, but if you do, you should make sure that PPP generates enough traffic so the timeout will normally not be triggered. The best way to do this is to use the \fIlcp-echo-interval\fR option to \fBpppd\fR. You should set the PPPoE timeout to be about four times the LCP echo interval. .TP .B \-D \fIfile_name\fR The \fB\-D\fR option causes every packet to be dumped to the specified \fIfile_name\fR. This is intended for debugging only; it produces huge amounts of output and greatly reduces performance. .TP .B \-V The \fB\-V\fR option causes \fBpppoe\fR to print its version number and exit. .TP .B \-A The \fB\-A\fR option causes \fBpppoe\fR to send a PADI packet and then print the names of access concentrators in each PADO packet it receives. Do not use this option in conjunction with \fBpppd\fR; the \fB\-A\fR option is meant to be used interactively to give interesting information about the access concentrator. .TP .B \-S \fIservice_name\fR Specifies the desired service name. \fBpppoe\fR will only initiate sessions with access concentrators which can provide the specified service. In most cases, you should \fInot\fR specify this option. Use it only if you know that there are multiple access concentrators or know that you need a specific service name. .TP .B \-C \fIac_name\fR Specifies the desired access concentrator name. \fBpppoe\fR will only initiate sessions with the specified access concentrator. In most cases, you should \fInot\fR specify this option. Use it only if you know that there are multiple access concentrators. If both the \fB\-S\fR and \fB\-C\fR options are specified, they must \fIboth\fR match for \fBpppoe\fR to initiate a session. .TP .B \-U Causes \fBpppoe\fR to use the Host-Uniq tag in its discovery packets. This lets you run multiple \fBpppoe\fR daemons without having their discovery packets interfere with one another. You must supply this option to \fIall\fR \fBpppoe\fR daemons if you intend to run multiple daemons simultaneously. The specific Host-Uniq value used is the hexadecimal representation of the \fBpppoe\fR process's PID. .TP .B \-W value Causes \fBpppoe\fR to use the Host-Uniq tag in its discovery packets, and furthermore to set the value of Host-Uniq to \fIvalue\fR. Use with caution. Note that \fB\-W\fR and \fB\-U\fR are mutually-incompatible. .TP .B \-s Causes \fBpppoe\fR to use \fIsynchronous\fR PPP encapsulation. If you use this option, then you \fImust\fR use the \fBsync\fR option with \fBpppd\fR. You are encouraged to use this option if it works, because it greatly reduces the CPU overhead of \fBpppoe\fR. However, it MAY be unreliable on slow machines -- there is a race condition between pppd writing data and pppoe reading it. For this reason, the default setting is asynchronous. If you encounter bugs or crashes with Synchronous PPP, turn it off -- don't e-mail me for support! .TP .B \-m \fIMSS\fR Causes \fBpppoe\fR to \fIclamp\fR the TCP maximum segment size at the specified value. Because of PPPoE overhead, the maximum segment size for PPPoE is smaller than for normal Ethernet encapsulation. This could cause problems for machines on a LAN behind a gateway using PPPoE. If you have a LAN behind a gateway, and the gateway connects to the Internet using PPPoE, you are strongly recommended to use a \fB\-m 1412\fR option. This avoids having to set the MTU on all the hosts on the LAN. .TP .B \-p \fIfile\fR Causes \fBpppoe\fR to write its process-ID to the specified file. This can be used to locate and kill \fBpppoe\fR processes. .TP .B \-e \fIsess:mac\fR Causes \fBpppoe\fR to skip the discovery phase and move directly to the session phase. The session is given by \fIsess\fR and the MAC address of the peer by \fImac\fR. This mode is \fInot\fR meant for normal use; it is designed only for \fBpppoe-server\fR(8). .TP .B \-n Causes \fBpppoe\fR not to open a discovery socket. This mode is \fInot\fR meant for normal use; it is designed only for \fBpppoe-server\fR(8). .TP .B \-k Causes \fBpppoe\fR to terminate an existing session by sending a PADT frame, and then exit. You must use the \fB\-e\fR option in conjunction with this option to specify the session to kill. This may be useful for killing sessions when a buggy peer does not realize the session has ended. .TP .B \-d Causes \fBpppoe\fR to perform discovery and then exit, after printing session information to standard output. The session information is printed in exactly the format expected by the \fB\-e\fR option. This option lets you initiate a PPPoE discovery, perform some other work, and then start the actual PPP session. \fIBe careful\fR; if you use this option in a loop, you can create many sessions, which may annoy your peer. .TP .B \-f disc:sess The \fB\-f\fR option sets the Ethernet frame types for PPPoE discovery and session frames. The types are specified as hexadecimal numbers separated by a colon. Standard PPPoE uses frame types 8863:8864. \fIYou should not use this option\fR unless you are absolutely sure the peer you are dealing with uses non-standard frame types. If your ISP uses non-standard frame types, complain! .TP .B \-h The \fB\-h\fR option causes \fBpppoe\fR to print usage information and exit. .SH PPPOE BACKGROUND PPPoE (Point-to-Point Protocol over Ethernet) is described in RFC 2516 and is a protocol which allows the session abstraction to be maintained over bridged Ethernet networks. PPPoE works by encapsulating PPP frames in Ethernet frames. The protocol has two distinct stages: The \fIdiscovery\fR and the \fIsession\fR stage. In the discovery stage, the host broadcasts a special PADI (PPPoE Active Discovery Initiation) frame to discover any \fIaccess concentrators\fR. The access concentrators (typically, only one access concentrator) reply with PADO (PPPoE Active Discovery Offer) packets, announcing their presence and the services they offer. The host picks one of the access concentrators and transmits a PADR (PPPoE Active Discovery Request) packet, asking for a session. The access concentrator replies with a PADS (PPPoE Active Discovery Session-Confirmation) packet. The protocol then moves to the session stage. In the session stage, the host and access concentrator exchange PPP frames embedded in Ethernet frames. The normal Ethernet MTU is 1500 bytes, but the PPPoE overhead plus two bytes of overhead for the encapsulated PPP frame mean that the MTU of the PPP interface is at most 1492 bytes. This causes \fIall kinds of problems\fR if you are using a Linux machine as a firewall and interfaces behind the firewall have an MTU greater than 1492. In fact, to be safe, I recommend setting the MTU of machines behind the firewall to 1412, to allow for worst-case TCP and IP options in their respective headers. Normally, PPP uses the Link Control Protocol (LCP) to shut down a PPP link. However, the PPPoE specification allows the link to be shut down with a special PADT (PPPoE Active Discovery Terminate) packet. This client recognizes this packet and will correctly terminate if a terminate request is received for the PPP session. .SH DESIGN GOALS My design goals for this PPPoE client were as follows, in descending order of importance: .TP .B o It must work. .TP .B o It must be a user-space program and not a kernel patch. .TP .B o The code must be easy to read and maintain. .TP .B o It must be fully compliant with RFC 2516, the proposed PPPoE standard. .TP .B o It must never hang up forever -- if the connection is broken, it must detect this and exit, allowing a wrapper script to restart the connection. .TP .B o It must be fairly efficient. .P I believe I have achieved all of these goals, but (of course) am open to suggestions, patches and ideas. See my home page, https://dianne.skoll.ca/projects/rp-pppoe/, for contact information. .SH NOTES For best results, you must give \fBpppd\fR an mtu option of 1492. I have observed problems with excessively-large frames unless I set this option. Also, if \fBpppoe\fR is running on a firewall machine, all machines behind the firewall should have MTU's of 1412. If you have problems, check your system logs. \fBpppoe\fR logs interesting things to syslog. You may have to turn on logging of \fIdebug\fR-level messages for complete diagnosis. .SH AUTHORS \fBpppoe\fR was written by Dianne Skoll , with much inspiration from an earlier version by Luke Stras. The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe-start(8), pppoe-stop(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe-setup(8), pppoe-status(8), pppoe-sniff(8), pppoe-server(8), pppoe-relay(8) rp-pppoe-3.15/man/pppoe-sniff.80000644000175000017500000000451314045237010014407 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-SNIFF 8 "3 July 2000" .\"" .UC 4 .SH NAME pppoe-sniff \- examine network for non-standard PPPoE frames .SH SYNOPSIS .B pppoe-sniff \fR[\fIoptions\fR] .SH DESCRIPTION \fBpppoe-sniff\fR listens for likely-looking PPPoE PADR and session frames and deduces extra options required for \fBpppoe(8)\fR to work. Some DSL providers seem to use non-standard frame types for PPPoE frames, and/or require a certain value in the Service-Name field. It is often easier to sniff those values from a machine which can successfully connect rather than try to pry them out of the DSL provider. To use \fBpppoe-sniff\fR, you need two computers, a DSL modem and an Ethernet hub (\fInot\fR an Ethernet switch.) If the DSL modem normally connects directly to your computer's Ethernet card, connect it to the "uplink" port on the Ethernet hub. Plug two computers into normal ports on the hub. On one computer, run whatever software the DSL provider gave you on whatever operating system the DSL provider supports. On the other computer, run Linux and log in as root. On the Linux machine, put the Ethernet interface into promiscuous mode and start \fBpppoe-sniff\fR. If the ethernet interface is \fIeth0\fR, for example, type these commands: .nf ip link set eth0 promisc on pppoe-sniff -I eth0 .fi On the other machine, start your DSL connection as usual. After a short time, \fBpppoe-sniff\fR should print recommendations for the value of \fBPPPOE_EXTRA\fR. Set this value in \fB/etc/ppp/pppoe.conf\fR. After \fBpppoe-sniff\fR finishes (or you stop it if it seems hung), remember to turn off promiscuous mode: .nf ip link set eth0 promisc on .fi .SH OPTIONS .TP .B \-I \fIinterface\fR The \fB\-I\fR option specifies the Ethernet interface to use. Under Linux, it is typically \fIeth0\fR or \fIeth1\fR. The interface should be "up" and in promiscuous mode before you start \fBpppoe-sniff\fR. .TP .B \-V The \fB\-V\fR option causes \fBpppoe-sniff\fR to print its version number and exit. .SH BUGS \fBpppoe-sniff\fR only works on Linux. .SH AUTHORS \fBpppoe-sniff\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe-start(8), pppoe-stop(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe(8), pppoe-setup(8), pppoe-status(8), pppoe-server(8), pppoe-relay(8) rp-pppoe-3.15/man/pppoe-status.80000644000175000017500000000134214045237010014622 0ustar dfsdfs.\" LIC: GPL .TH PPPOE-STATUS 8 "16 March 2000" .UC 4 .SH NAME pppoe-status \- Shell script to report on status of PPPoE link .SH SYNOPSIS .B pppoe-status \fR[\fIconfig_file\fR] .SH DESCRIPTION \fBpppoe-status\fR is a shell script which checks the status of the PPPoE link established by the Roaring Penguin user-space PPPoE client. If you omit \fIconfig_file\fR, the default file \fB/etc/ppp/pppoe.conf\fR is used. .SH AUTHOR \fBpppoe-status\fR was written by Dianne Skoll . The \fBpppoe\fR home page is \fIhttps://dianne.skoll.ca/projects/rp-pppoe/\fR. .SH SEE ALSO pppoe(8), pppoe-start(8), pppoe-connect(8), pppd(8), pppoe.conf(5), pppoe-setup(8), pppoe-stop(8), pppoe-sniff(8), pppoe-relay(8), pppoe-server(8) rp-pppoe-3.15/go-gui0000755000175000017500000000367414045237007012447 0ustar dfsdfs#!/bin/sh # LIC: GPL #*********************************************************************** # # go-gui # # Quick-start shell script to set up PPPoE and GUI wrapper # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018-2021 Dianne Skoll # # $Id$ #*********************************************************************** # GUI only works on Linux if test "`uname`" != "Linux" ; then echo "Sorry, the GUI only works on Linux." exit 1 fi # Figure out directory of script MYDIR=`dirname $0` cd $MYDIR/src echo "Running ./configure..." ./configure if [ "$?" != 0 ] ; then echo "Oops! It looks like ./configure failed." exit 1 fi echo "Running make..." make if [ "$?" != 0 ] ; then echo "Oops! It looks like make failed." exit 1 fi echo "Running make install..." make install if [ "$?" != 0 ] ; then echo "Oops! It looks like make install failed." exit 1 fi echo "Building GUI wrapper..." cd ../gui make if [ "$?" != 0 ] ; then echo "Oops! It looks like make failed." exit 1 fi echo "Installing GUI..." make install if [ "$?" != 0 ] ; then echo "Oops! It looks like make install failed." exit 1 fi # Install entry in KDE menu if test -n "$KDEDIR" ; then echo "Installing KDE menu entry Internet : TkPPPoE..." mkdir -p "$KDEDIR/share/applnk/Internet" cat < "$KDEDIR/share/applnk/Internet/tkpppoe.kdelnk" # KDE Config File [KDE Desktop Entry] Name=TkPPPoE Comment=Start/Stop PPPoE connections Exec=tkpppoe Terminal=0 Type=Application EOF fi # Install entry in GNOME menus GNOMEDIR=`gnome-config --datadir 2>/dev/null` if test -n "$GNOMEDIR" ; then echo "Installing GNOME menu entry Internet : TkPPPoE..." mkdir -p "$GNOMEDIR/gnome/apps/Internet" cat < "$GNOMEDIR/gnome/apps/Internet/tkpppoe.desktop" [Desktop Entry] Name=TkPPPoE Comment=Start/Stop PPPoE connections Exec=tkpppoe Terminal=0 Type=Application EOF fi echo "Running GUI configuration tool..." tkpppoe & exit 0 rp-pppoe-3.15/SERVPOET0000644000175000017500000000105014045237007012506 0ustar dfsdfs# LIC: GPL ServPoET -------- ServPoET is a commercial version of the PPPoE server. While everything you received in this package is licensed under the GNU General Public License, ServPoET is not free software and is licensed under a traditional commercial license. ServPoET features RADIUS support, support for different realms, real-time server status reporting and a friendly curses-based GUI for administration. For information on ServPoET: Contact Fine Point Technologies, Inc. (http://www.finepoint.com/) -- Dianne Skoll rp-pppoe-3.15/configs/0000755000175000017500000000000014045237010012742 5ustar dfsdfsrp-pppoe-3.15/configs/pppoe-server-options0000644000175000017500000000015014045237010017001 0ustar dfsdfs# PPP options for the PPPoE server # LIC: GPL require-pap login lcp-echo-interval 10 lcp-echo-failure 2 rp-pppoe-3.15/configs/pap-secrets0000644000175000017500000000042614045237007015123 0ustar dfsdfs# LIC: GPL # Edit this file and place it in /etc/ppp/pap-secrets #User #Server #Password #IP bxxxxx@sympatico.ca * my_password * # Replace bxxxxx@sympatico.ca with your Sympatico user-ID # Replace my_password with your Sympatico password # For Magma, use xxyyzz@magma.ca rp-pppoe-3.15/configs/pppoe.conf0000644000175000017500000001072314045237010014737 0ustar dfsdfs#*********************************************************************** # # pppoe.conf # # Configuration file for rp-pppoe. Edit as appropriate and install in # /etc/ppp/pppoe.conf # # NOTE: This file is used by the pppoe-start, pppoe-stop, pppoe-connect and # pppoe-status shell scripts. It is *not* used in any way by the # "pppoe" executable. # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018-2021 Dianne Skoll # # This file may be distributed under the terms of the GNU General # Public License. # # LIC: GPL # $Id$ #*********************************************************************** # When you configure a variable, DO NOT leave spaces around the "=" sign. # Ethernet card connected to DSL modem ETH=eth1 # PPPoE user name. You may have to supply "@provider.com" Sympatico # users in Canada do need to include "@sympatico.ca" # Sympatico uses PAP authentication. Make sure /etc/ppp/pap-secrets # contains the right username/password combination. # For Magma, use xxyyzz@magma.ca USER=bxxxnxnx@sympatico.ca # Bring link up on demand? Default is to leave link up all the time. # If you want the link to come up on demand, set DEMAND to a number indicating # the idle time after which the link is brought down. DEMAND=no #DEMAND=300 # DNS type: SERVER=obtain from server; SPECIFY=use DNS1 and DNS2; # NOCHANGE=do not adjust. DNSTYPE=SERVER # Obtain DNS server addresses from the peer (recent versions of pppd only) # In old config files, this used to be called USEPEERDNS. Changed to # PEERDNS for better Red Hat compatibility PEERDNS=yes DNS1= DNS2= # Make the PPPoE connection your default route. Set to # DEFAULTROUTE=no if you don't want this. DEFAULTROUTE=yes ### ONLY TOUCH THE FOLLOWING SETTINGS IF YOU'RE AN EXPERT # How long pppoe-start waits for a new PPP interface to appear before # concluding something went wrong. If you use 0, then pppoe-start # exits immediately with a successful status and does not wait for the # link to come up. Time is in seconds. # # WARNING WARNING WARNING: # # If you are using rp-pppoe on a physically-inaccessible host, set # CONNECT_TIMEOUT to 0. This makes SURE that the machine keeps trying # to connect forever after pppoe-start is called. Otherwise, it will # give out after CONNECT_TIMEOUT seconds and will not attempt to # connect again, making it impossible to reach. CONNECT_TIMEOUT=30 # How often in seconds pppoe-start polls to check if link is up CONNECT_POLL=2 # Specific desired AC Name ACNAME= # Specific desired service name SERVICENAME= # Character to echo at each poll. Use PING="" if you don't want # anything echoed PING="." # File where the pppoe-connect script writes its process-ID. # Three files are actually used: # $PIDFILE contains PID of pppoe-connect script # $PIDFILE.pppoe contains PID of pppoe process # $PIDFILE.pppd contains PID of pppd process CF_BASE=`basename $CONFIG` PIDFILE="/var/run/$CF_BASE-pppoe.pid" # Do you want to use synchronous PPP? "yes" or "no". "yes" is much # easier on CPU usage, but may not work for you. It is safer to use # "no", but you may want to experiment with "yes". "yes" is generally # safe on Linux machines with the n_hdlc line discipline; unsafe on others. SYNCHRONOUS=no # Do you want to clamp the MSS? Here's how to decide: # - If you have only a SINGLE computer connected to the DSL modem, choose # "no". # - If you have a computer acting as a gateway for a LAN, choose "1412". # The setting of 1412 is safe for either setup, but uses slightly more # CPU power. CLAMPMSS=1412 #CLAMPMSS=no # LCP echo interval and failure count. LCP_INTERVAL=20 LCP_FAILURE=3 # PPPOE_TIMEOUT should be about 4*LCP_INTERVAL PPPOE_TIMEOUT=80 # Firewalling: One of NONE, STANDALONE or MASQUERADE FIREWALL=NONE # Linux kernel-mode plugin for pppd. If you want to try the kernel-mode # plugin, use LINUX_PLUGIN=/etc/ppp/plugins/rp-pppoe.so LINUX_PLUGIN= # Any extra arguments to pass to pppoe. Normally, use a blank string # like this: PPPOE_EXTRA="" # Rumour has it that "Citizen's Communications" with a 3Com # HomeConnect DSL Modem DualLink requires these extra options: # PPPOE_EXTRA="-f 3c12:3c13 -S ISP" # Any extra arguments to pass to pppd. Normally, use a blank string # like this: PPPD_EXTRA="" ########## DON'T CHANGE BELOW UNLESS YOU KNOW WHAT YOU ARE DOING # If you wish to COMPLETELY overrride the pppd invocation: # Example: # OVERRIDE_PPPD_COMMAND="pppd call dsl" # If you want pppoe-connect to exit when connection drops: # RETRY_ON_FAILURE=no rp-pppoe-3.15/configs/firewall-masq0000644000175000017500000000434414045237007015444 0ustar dfsdfs#!/bin/sh # # firewall-masq This script sets up firewall rules for a machine # acting as a masquerading gateway # # Copyright (C) 2000 Roaring Penguin Software Inc. This software may # be distributed under the terms of the GNU General Public License, version # 2 or any later version. # LIC: GPL # Interface to Internet EXTIF=ppp+ # NAT-Tables are different, so we can use ACCEPT everywhere (?) iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t nat -P POSTROUTING ACCEPT # Flush the NAT-Table iptables -t nat -F iptables -t filter -P INPUT DROP iptables -t filter -F # Allow incoming SSH #iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 22 -j ACCEPT # Log & Deny the rest of the privileged ports iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 0:1023 -j LOG iptables -t filter -A INPUT -i $EXTIF -p udp --dport 0:1023 -j LOG iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 0:1023 -j DROP iptables -t filter -A INPUT -i $EXTIF -p udp --dport 0:1023 -j DROP # Log & Deny NFS iptables -t filter -A INPUT -i $EXTIF -p udp --dport 2049 -j LOG iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 2049 -j LOG iptables -t filter -A INPUT -i $EXTIF -p udp --dport 2049 -j DROP iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 2049 -j DROP # Log & Deny X11 iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 6000:6063 -j LOG iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 6000:6063 -j DROP # Log & Deny XFS iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 7100 -j LOG iptables -t filter -A INPUT -i $EXTIF -p tcp --dport 7100 -j DROP # Deny TCP connection attempts iptables -t filter -A INPUT -i $EXTIF -p tcp --syn -j LOG iptables -t filter -A INPUT -i $EXTIF -p tcp --syn -j DROP # Deny ICMP echo-requests iptables -t filter -A INPUT -i $EXTIF -p icmp --icmp-type echo-request -j DROP # Do masquerading iptables -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE # Enable forwarding echo 1 > /proc/sys/net/ipv4/ip_forward # no IP spoofing if [ -e /proc/sys/net/ipv4/conf/all/rp_filter ] ; then for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $i done fi # Disable Source Routed Packets for i in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $i done rp-pppoe-3.15/configs/firewall-standalone0000644000175000017500000000172214045237007016630 0ustar dfsdfs#!/bin/sh # # firewall-standalone This script sets up firewall rules for a standalone # machine # # Copyright (C) 2005 Roaring Penguin Software Inc. This software may # be distributed under the terms of the GNU General Public License, version # 2 or any later version. # LIC: GPL # Interface to Internet EXTIF=ppp+ iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD DROP iptables -F FORWARD iptables -F INPUT iptables -F OUTPUT # Deny TCP and UDP packets to privileged ports iptables -A INPUT -p udp -i $EXTIF --dport 0:1023 -j LOG iptables -A INPUT -p tcp -i $EXTIF --dport 0:1023 -j LOG iptables -A INPUT -p udp -i $EXTIF --dport 0:1023 -j DROP iptables -A INPUT -p tcp -i $EXTIF --dport 0:1023 -j DROP # Deny TCP connection attempts iptables -A INPUT -i $EXTIF -p tcp --syn -j LOG iptables -A INPUT -i $EXTIF -p tcp --syn -j DROP # Deny ICMP echo-requests iptables -A INPUT -i $EXTIF -p icmp --icmp-type echo-request -j DROP rp-pppoe-3.15/scripts/0000755000175000017500000000000014045237010013001 5ustar dfsdfsrp-pppoe-3.15/scripts/pppoe-stop.in0000755000175000017500000000432214045237010015443 0ustar dfsdfs#!/bin/sh # @configure_input@ #*********************************************************************** # # pppoe-stop # # Shell script to bring down a PPPoE connection # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018 Dianne Skoll # # $Id$ # # This file may be distributed under the terms of the GNU General # Public License. # # LIC: GPL # # Usage: pppoe-stop [config_file] # If config_file is omitted, defaults to /etc/ppp/pppoe.conf # #*********************************************************************** # Set to "C" locale so we can parse messages from commands LANG=C export LANG ME="`basename $0`" LOGGER="/usr/bin/logger -t $ME" CONFIG="$1" if [ "$CONFIG" = "" ] ; then CONFIG=/etc/ppp/pppoe.conf fi if [ ! -f "$CONFIG" -o ! -r "$CONFIG" ] ; then echo "$ME: Cannot read configuration file '$CONFIG'" >& 2 exit 1 fi export CONFIG . $CONFIG PPPOE_PIDFILE="$PIDFILE.pppoe" PPPD_PIDFILE="$PIDFILE.pppd" STARTPID="$PIDFILE.start" # Backward config file compatibility if test "$DEMAND" = "" ; then DEMAND=no fi # Ignore SIGTERM trap "" 15 # Check for pidfile if [ -r "$PIDFILE" ] ; then PID=`cat $PIDFILE` # Check if still running kill -0 $PID > /dev/null 2>&1 if [ $? != 0 ] ; then echo "$ME: The pppoe-connect script (PID $PID) appears to have died" >& 2 fi # Kill pppd, which should in turn kill pppoe if [ -r "$PPPD_PIDFILE" ] ; then PPPD_PID=`cat "$PPPD_PIDFILE"` $LOGGER -p daemon.notice "Killing pppd" echo "Killing pppd ($PPPD_PID)" kill $PPPD_PID > /dev/null 2>&1 || exit 1 fi # Kill pppoe-start PIDS=`cat $STARTPID` kill -0 $PIDS > /dev/null 2>&1 if [ $? = 0 ] ; then $LOGGER -p daemon.notice "Killing pppoe-connect" kill $PIDS > /dev/null 2>&1 fi # Kill pppoe-connect $LOGGER -p daemon.notice "Killing pppoe-connect" echo "Killing pppoe-connect ($PID)" kill -9 $PID > /dev/null 2>&1 # Kill pppd again, in case it's still hanging around if [ -r "$PPPD_PIDFILE" ] ; then PPPD_PID=`cat "$PPPD_PIDFILE"` kill -9 $PPPD_PID > /dev/null 2>&1 || exit 1 fi rm -f "$PIDFILE" "$PPPD_PIDFILE" "$PPPOE_PIDFILE" "$STARTPID" else echo "$ME: No PPPoE connection appears to be running" >&2 exit 1 fi exit 0 rp-pppoe-3.15/scripts/pppoe-init.in0000755000175000017500000000227014045237010015421 0ustar dfsdfs#!/bin/sh # # pppoe This script starts or stops a PPPoE connection # # chkconfig: 2345 99 01 # description: Connects to PPPoE provider # # LIC: GPL # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018 Dianne Skoll # This software may be distributed under the terms of the GNU General # Public License, version 2 or any later version. # Source function library if it exists test -r /etc/rc.d/init.d/functions && . /etc/rc.d/init.d/functions # From AUTOCONF prefix=@prefix@ exec_prefix=@exec_prefix@ # Paths to programs START=@sbindir@/pppoe-start STOP=@sbindir@/pppoe-stop STATUS=@sbindir@/pppoe-status case "$1" in start) echo -n "Bringing up PPPoE link" $START if [ $? = 0 ] ; then touch /var/lock/subsys/pppoe echo_success else echo_failure fi echo "" ;; stop) echo -n "Shutting down PPPoE link" $STOP > /dev/null 2>&1 if [ $? = 0 ] ; then rm -f /var/lock/subsys/pppoe echo_success else echo_failure fi echo "" ;; restart) $0 stop $0 start ;; status) $STATUS ;; *) echo "Usage: pppoe {start|stop|restart|status}" exit 1 esac exit 0 rp-pppoe-3.15/scripts/pppoe-status0000755000175000017500000000413514045237010015376 0ustar dfsdfs#!/bin/sh #*********************************************************************** # # pppoe-status # # Shell script to report on status of PPPoE connection # # Copyright (C) 2000-2001 Roaring Penguin Software Inc. # Copyright (C) 2018 Dianne Skoll # # $Id$ # # This file may be distributed under the terms of the GNU General # Public License. # # LIC: GPL # # Usage: pppoe-status [config_file] # If config_file is omitted, defaults to /etc/ppp/pppoe.conf # #*********************************************************************** # Defaults CONFIG=/etc/ppp/pppoe.conf PATH=/bin:/usr/bin:/sbin:/usr/sbin:$PATH IP=`which ip` case "$#" in 1) CONFIG="$1" ;; esac if [ ! -f "$CONFIG" -o ! -r "$CONFIG" ] ; then echo "$0: Cannot read configuration file '$CONFIG'" >& 2 exit 1 fi . $CONFIG PPPOE_PIDFILE="$PIDFILE.pppoe" PPPD_PIDFILE="$PIDFILE.pppd" if [ "$DEMAND" != "no" ] ; then echo "Note: You have enabled demand-connection; pppoe-status may be inaccurate." fi # If no PPPOE_PIDFILE, connection is down, unless we're using the Linux plugin if [ "$LINUX_PLUGIN" = "" ] ; then if [ ! -r "$PPPOE_PIDFILE" ] ; then echo "pppoe-status: Link is down (can't read pppoe PID file $PPPOE_PIDFILE)" exit 1 fi fi # If no PPPD_PIDFILE, something fishy! if [ ! -r "$PPPD_PIDFILE" ] ; then echo "pppoe-status: Link is down (can't read pppd PID file $PPPD_PIDFILE)" exit 1 fi PPPD_PID=`cat "$PPPD_PIDFILE"` # Sigh. Some versions of pppd put PID files in /var/run; others put them # in /etc/ppp. Since it's too messy to figure out what pppd does, we # try both locations. for i in /etc/ppp/ppp*.pid /var/run/ppp*.pid ; do if [ -r $i ] ; then PID=`cat $i` if [ "$PID" = "$PPPD_PID" ] ; then IF=`basename $i .pid` $IP route | grep "dev ${IF}" > /dev/null if [ "$?" != "0" ] ; then echo "pppoe-status: Link is attached to $IF, but $IF is down" exit 1 fi echo "pppoe-status: Link is up and running on interface $IF" $IP link show $IF exit 0 fi fi done echo "pppoe-status: Link is down -- could not find interface corresponding to" echo "pppd pid $PPPD_PID" exit 1 rp-pppoe-3.15/scripts/pppoe-setup.in0000755000175000017500000002244114045237010015620 0ustar dfsdfs#!/bin/sh #*********************************************************************** # # pppoe-setup # # All-purpose slicing/dicing shell script to configure rp-pppoe. # # LIC: GPL # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018 Dianne Skoll # #*********************************************************************** # From AUTOCONF prefix=@prefix@ exec_prefix=@exec_prefix@ # Paths to programs IFCONFIG=/sbin/ifconfig IP=@IP@ PPPD=@PPPD@ PPPOE=@sbindir@/pppoe LOGGER="/usr/bin/logger -t `basename $0`" # Set to "C" locale so we can parse messages from commands LANG=C export LANG CONFIG=/etc/ppp/pppoe.conf # Protect created files umask 077 copy() { cp $1 $2 if [ "$?" != 0 ] ; then echo "*** Error copying $1 to $2" echo "*** Quitting." exit 1 fi } echo "Welcome to the RP-PPPoE client setup. First, I will run" echo "some checks on your system to make sure the PPPoE client is installed" echo "properly..." echo "" # Must be root if [ "`@ID@ -u`" != 0 ] ; then echo "$0: Sorry, you must be root to run this script" exit 1 fi # Prototype config file must exist if [ ! -r "$CONFIG" ] ; then echo "Oh, dear, I don't see the file '$CONFIG' anywhere. Please" echo "re-install the PPPoE client." exit 1 fi # Must have pppd if [ ! -x $PPPD ] ; then echo "Oops, I can't execute the program '$PPPD'. You" echo "must install the PPP software suite, version 2.3.10 or later." exit 1 fi export CONFIG . $CONFIG if [ "$DEMAND" = "" ] ; then DEMAND=no fi # pppoe must exist if [ ! -x "$PPPOE" ] ; then echo "Oh, dear, I can't execute the program '$PPPOE'. Please" echo "re-install the rp-pppoe client." exit 1 fi echo "Looks good! Now, please enter some information:" while [ true ] ; do echo "" echo "USER NAME" echo "" printf "%s" ">>> Enter your PPPoE user name (default $USER): " read U if [ "$U" = "" ] ; then U="$USER" fi # Under Linux, "fix" the default interface if eth1 is not available if test `uname -s` = "Linux" ; then $IP link show $ETH > /dev/null 2>&1 || ETH=eth0 else $IFCONFIG $ETH > /dev/null 2>&1 || ETH=eth0 fi echo "" echo "INTERFACE" echo "" echo ">>> Enter the Ethernet interface connected to the DSL modem" echo "For Solaris, this is likely to be something like /dev/hme0." echo "For Linux, it will be ethn, where 'n' is a number." printf "%s" "(default $ETH): " read E if [ "$E" = "" ] ; then E="$ETH" fi echo "" echo "Do you want the link to come up on demand, or stay up continuously?" echo "If you want it to come up on demand, enter the idle time in seconds" echo "after which the link should be dropped. If you want the link to" echo "stay up permanently, enter 'no' (two letters, lower-case.)" echo "NOTE: Demand-activated links do not interact well with dynamic IP" echo "addresses. You may have some problems with demand-activated links." printf "%s" ">>> Enter the demand value (default $DEMAND): " read D if [ "$D" = "" ] ; then D=$DEMAND fi echo "" echo "DNS" echo "" echo "Please enter the IP address of your ISP's primary DNS server." echo "If your ISP claims that 'the server will provide DNS addresses'," echo "enter 'server' (all lower-case) here." echo "If you just press enter, I will assume you know what you are" echo "doing and not modify your DNS setup." printf "%s" ">>> Enter the DNS information here: " read DNS1 if [ "$DNS1" != "" ] ; then if [ "$DNS1" != "server" ] ; then echo "Please enter the IP address of your ISP's secondary DNS server." echo "If you just press enter, I will assume there is only one DNS server." printf "%s" ">>> Enter the secondary DNS server address here: " read DNS2 fi fi while [ true ] ; do echo "" echo "PASSWORD" echo "" stty -echo printf "%s" ">>> Please enter your PPPoE password: " read PWD1 echo "" printf "%s" ">>> Please re-enter your PPPoE password: " read PWD2 echo "" stty echo if [ "$PWD1" = "$PWD2" ] ; then break fi printf "%s" ">>> Sorry, the passwords do not match. Try again? (y/n)" read ANS case "$ANS" in N|No|NO|Non|n|no|non) echo "OK, quitting. Bye." exit 1 esac done # Firewalling echo "" echo "FIREWALLING" echo "" if test `uname -s` != "Linux" ; then echo "Sorry, firewalling is only supported under Linux. Consult" echo "your operating system manuals for details on setting up" echo "packet filters for your system." FIREWALL=NONE else echo "Please choose the firewall rules to use. Note that these rules are" echo "very basic. You are strongly encouraged to use a more sophisticated" echo "firewall setup; however, these will provide basic security. If you" echo "are running any servers on your machine, you must choose 'NONE' and" echo "set up firewalling yourself. Otherwise, the firewall rules will deny" echo "access to all standard servers like Web, e-mail, ftp, etc. If you" echo "are using SSH, the rules will block outgoing SSH connections which" echo "allocate a privileged source port." echo "" while [ true ] ; do echo "The firewall choices are:" echo "0 - NONE: This script will not set any firewall rules. You are responsible" echo " for ensuring the security of your machine. You are STRONGLY" echo " recommended to use some kind of firewall rules." echo "1 - STANDALONE: Appropriate for a basic stand-alone web-surfing workstation" echo "2 - MASQUERADE: Appropriate for a machine acting as an Internet gateway" echo " for a LAN" printf "%s" ">>> Choose a type of firewall (0-2): " read a if [ "$a" = 0 -o "$a" = 1 -o "$a" = 2 ] ; then break fi echo "Please enter a number from 0 to 2" done case "$a" in 0) FIREWALL=NONE ;; 1) FIREWALL=STANDALONE ;; 2) FIREWALL=MASQUERADE ;; esac fi echo "" echo "** Summary of what you entered **" echo "" echo "Ethernet Interface: $E" echo "User name: $U" if [ "$D" = "no" ] ; then echo "Activate-on-demand: No" else echo "Activate-on-demand: Yes; idle timeout = $D seconds" fi if [ "$DNS1" != "" ] ; then if [ "$DNS1" = "server" ] ; then echo "DNS addresses: Supplied by ISP's server" else echo "Primary DNS: $DNS1" if [ "$DNS2" != "" ] ; then echo "Secondary DNS: $DNS2" fi fi else echo "DNS: Do not adjust" fi echo "Firewalling: $FIREWALL" echo "" while [ true ] ; do printf "%s" '>>> Accept these settings and adjust configuration files (y/n)? ' read ANS case "ANS" in Y|y|yes|Yes|oui|Oui) ANS=y ;; N|n|no|No|non|Non) ANS=n ;; esac if [ "$ANS" = "y" -o "$ANS" = "n" ] ; then break fi done if [ "$ANS" = "y" ] ; then break fi done # Adjust configuration files. First to $CONFIG echo "Adjusting $CONFIG" copy $CONFIG $CONFIG-bak if [ "$DNS1" = "server" ] ; then DNSTYPE=SERVER DNS1="" PEERDNS=yes else PEERDNS=no if [ "$DNS1" = "" ] ; then DNSTYPE=NOCHANGE else DNSTYPE=SPECIFY fi fi # Where is pppd likely to put its pid? if [ -d /var/run ] ; then VARRUN=/var/run else VARRUN=/etc/ppp fi # Some #$(*& ISP's use a slash in the user name... sed -e "s&^USER=.*&USER='$U'&" \ -e "s&^ETH=.*Ð='$E'&" \ -e "s&^PIDFILE=.*&PIDFILE=\"$VARRUN/\$CF_BASE-pppoe.pid\"&" \ -e "s/^FIREWALL=.*/FIREWALL=$FIREWALL/" \ -e "s/^DEMAND=.*/DEMAND=$D/" \ -e "s/^DNSTYPE=.*/DNSTYPE=$DNSTYPE/" \ -e "s/^DNS1=.*/DNS1=$DNS1/" \ -e "s/^DNS2=.*/DNS2=$DNS2/" \ -e "s/^PEERDNS=.*/PEERDNS=$PEERDNS/" \ < $CONFIG-bak > $CONFIG if [ $? != 0 ] ; then echo "** Error modifying $CONFIG" echo "** Quitting" exit 1 fi if [ "$DNS1" != "" ] ; then if [ "$DNS1" != "server" ] ; then echo "Adjusting /etc/resolv.conf" if [ -r /etc/resolv.conf ] ; then grep -s "MADE-BY-RP-PPPOE" /etc/resolv.conf > /dev/null 2>&1 if [ "$?" != 0 ] ; then echo " (But first backing it up to /etc/resolv.conf-bak)" copy /etc/resolv.conf /etc/resolv.conf-bak fi fi echo "# MADE-BY-RP-PPPOE" > /etc/resolv.conf echo "nameserver $DNS1" >> /etc/resolv.conf if [ "$DNS2" != "" ] ; then echo "nameserver $DNS2" >> /etc/resolv.conf fi fi fi echo "Adjusting /etc/ppp/pap-secrets and /etc/ppp/chap-secrets" if [ -r /etc/ppp/pap-secrets ] ; then echo " (But first backing it up to /etc/ppp/pap-secrets-bak)" copy /etc/ppp/pap-secrets /etc/ppp/pap-secrets-bak else cp /dev/null /etc/ppp/pap-secrets-bak fi if [ -r /etc/ppp/chap-secrets ] ; then echo " (But first backing it up to /etc/ppp/chap-secrets-bak)" copy /etc/ppp/chap-secrets /etc/ppp/chap-secrets-bak else cp /dev/null /etc/ppp/chap-secrets-bak fi egrep -v "^$U|^\"$U\"" /etc/ppp/pap-secrets-bak > /etc/ppp/pap-secrets echo "\"$U\" * \"$PWD1\"" >> /etc/ppp/pap-secrets egrep -v "^$U|^\"$U\"" /etc/ppp/chap-secrets-bak > /etc/ppp/chap-secrets echo "\"$U\" * \"$PWD1\"" >> /etc/ppp/chap-secrets echo "" echo "" echo "" echo "Congratulations, it should be all set up!" echo "" echo "Type 'pppoe-start' to bring up your PPPoE link and 'pppoe-stop' to bring" echo "it down. Type 'pppoe-status' to see the link status." exit 0 rp-pppoe-3.15/scripts/pppoe-init-suse.in0000755000175000017500000000300114045237010016367 0ustar dfsdfs#!/bin/sh # # pppoe This script starts or stops a PPPoE connection # # chkconfig: 2345 99 01 # description: Connects to PPPoE provider # # LIC: GPL # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018 Dianne Skoll # This software may be distributed under the terms of the GNU General # Public License, version 2 or any later version. # Modifed to work with SuSE 6.4 linux by Gary Cameron. # # Source function library. #. /etc/rc.d/init.d/functions # For red hat? . /etc/rc.config # For SuSE, enables setting from /etc/rc.config #Tweak this restart_time=120 # From AUTOCONF prefix=@prefix@ exec_prefix=@exec_prefix@ # Paths to programs START=@sbindir@/pppoe-start STOP=@sbindir@/pppoe-stop STATUS=@sbindir@/pppoe-status test "$PPPoE_START" = "yes" || exit 0 # The echo return value for success (defined in /etc/rc.config). return=$rc_done case "$1" in start) echo -n "Bringing up PPPoE link" $START > /dev/null 2>&1 || return=$rc_failed echo -e "$return" ;; stop) echo -n "Shutting down PPPoE link" $STOP > /dev/null 2>&1 || return=$rc_failed echo -e "$return" ;; restart) $0 stop echo "Waiting" $restart_time "seconds for the host to reset itself" sleep $restart_time #Note: Need time for host to reset itself $0 start ;; status) $STATUS ;; *) echo "Usage: pppoe {start|stop|restart|status}" exit 1 esac exit 0 rp-pppoe-3.15/scripts/pppoe-start.in0000755000175000017500000001137414045237010015620 0ustar dfsdfs#!/bin/sh # @configure_input@ #*********************************************************************** # # pppoe-start # # Shell script to bring up a PPPoE connection # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018 Dianne Skoll # # $Id$ # # This file may be distributed under the terms of the GNU General # Public License. # # LIC: GPL # # Usage: pppoe-start [config_file] # pppoe-start interface user [config_file] # Second form overrides USER and ETH from config file. # If config_file is omitted, defaults to /etc/ppp/pppoe.conf # #*********************************************************************** # From AUTOCONF prefix=@prefix@ exec_prefix=@exec_prefix@ # Paths to programs CONNECT=@sbindir@/pppoe-connect IP=@IP@ # Set to "C" locale so we can parse messages from commands LANG=C export LANG # Defaults CONFIG=/etc/ppp/pppoe.conf USER="" ETH="" ME=`basename $0` # Must be root if [ "`@ID@ -u`" != 0 ] ; then echo "$ME: You must be root to run this script" >& 2 exit 1 fi # Debugging if [ "$DEBUG" = "1" ] ; then echo "*** Running in debug mode... please be patient..." DEBUG="/tmp/pppoe-debug-$$" mkdir "$DEBUG" if [ "$?" != 0 ] ; then echo "Could not create directory $DEBUG... exiting" exit 1 fi DEBUG="$DEBUG/pppoe-debug.txt" # Initial debug output { echo "---------------------------------------------" echo "* The following section contains information about your system" date echo "Output of uname -a" uname -a echo "---------------------------------------------" echo "* The following section contains information about your network" echo "* interfaces. The one you chose for PPPoE should contain the words:" echo "* 'UP' and 'RUNNING'. If it does not, you probably have an Ethernet" echo "* driver problem." echo "Output of ip link show" $IP link show echo "---------------------------------------------" if [ "`uname -s`" = "Linux" ] ; then echo "* The following section contains information about kernel modules." echo "Output of lsmod" lsmod echo "---------------------------------------------" fi echo "* The following section lists your routing table." echo "* If you have an entry which starts with '0.0.0.0', you probably" echo "* have defined a default route and gateway, and pppd will" echo "* not create a default route using your ISP. Try getting" echo "* rid of this route." echo "Output of ip route" $IP route echo "---------------------------------------------" echo "Contents of /etc/resolv.conf" echo "* The following section lists DNS setup." echo "* If you can browse by IP address, but not name, suspect" echo "* a DNS problem." cat /etc/resolv.conf echo "---------------------------------------------" echo "* The following section lists /etc/ppp/options." echo "* You should have NOTHING in that file." echo "Contents of /etc/ppp/options" cat /etc/ppp/options 2>/dev/null echo "---------------------------------------------" } > "$DEBUG" else DEBUG="" fi # Sort out command-line arguments case "$#" in 1) CONFIG="$1" ;; 3) CONFIG="$3" ;; esac if [ ! -f "$CONFIG" -o ! -r "$CONFIG" ] ; then echo "$ME: Cannot read configuration file '$CONFIG'" >& 2 exit 1 fi export CONFIG . "$CONFIG" # Check for command-line overriding of ETH and USER case "$#" in 2|3) ETH="$1" USER="$2" ;; esac # Check for pidfile if [ -r "$PIDFILE" ] ; then PID=`cat "$PIDFILE"` # Check if still running kill -0 $PID > /dev/null 2>&1 if [ $? = 0 ] ; then echo "$ME: There already seems to be a PPPoE connection up (PID $PID)" >& 2 exit 1 fi # Delete bogus PIDFILE rm -f "$PIDFILE" "$PIDFILE.pppd" "$PIDFILE.pppoe" "$PIDFILE.start" fi echo $$ > $PIDFILE.start # Start the connection in the background unless we're debugging if [ "$DEBUG" != "" ] ; then $CONNECT "$@" exit 0 fi $CONNECT "$@" > /dev/null 2>&1 & CONNECT_PID=$! if [ "$CONNECT_TIMEOUT" = "" -o "$CONNECT_TIMEOUT" = 0 ] ; then exit 0 fi # Don't monitor connection if dial-on-demand if [ "$DEMAND" != "" -a "$DEMAND" != "no" ] ; then exit 0 fi # Monitor connection TIME=0 while [ true ] ; do @sbindir@/pppoe-status "$CONFIG" > /dev/null 2>&1 # Looks like the interface came up if [ $? = 0 ] ; then # Print newline if standard input is a TTY tty -s && echo " Connected!" exit 0 fi if test -n "$FORCEPING" ; then printf "%s" "$FORCEPING" else tty -s && printf "%s" "$PING" fi sleep $CONNECT_POLL TIME=`expr $TIME + $CONNECT_POLL` if [ $TIME -gt $CONNECT_TIMEOUT ] ; then break fi done echo "TIMED OUT" >& 2 # Timed out! Kill the pppoe-connect process and quit kill $CONNECT_PID > /dev/null 2>&1 # Clean up PIDFILE(s) rm -f "$PIDFILE" "$PIDFILE.pppd" "$PIDFILE.pppoe" "$PIDFILE.start" exit 1 rp-pppoe-3.15/scripts/pppoe-connect.in0000755000175000017500000002140414045237010016107 0ustar dfsdfs#!/bin/sh # @configure_input@ #*********************************************************************** # # pppoe-connect # # Shell script to connect to a PPPoE provider # # Copyright (C) 2000 Roaring Penguin Software Inc. # # $Id$ # # This file may be distributed under the terms of the GNU General # Public License. # # LIC: GPL # # Usage: pppoe-connect [config_file] # pppoe-connect interface user [config_file] # Second form overrides USER and ETH from config file. # If config_file is omitted, defaults to /etc//ppp/pppoe.conf # #*********************************************************************** # From AUTOCONF prefix=@prefix@ exec_prefix=@exec_prefix@ localstatedir=/var # Paths to programs IP=@IP@ IFCONFIG=/sbin/ifconfig PPPD=@PPPD@ SETSID=@SETSID@ PPPOE=@sbindir@/pppoe LOGGER="/usr/bin/logger -t `basename $0`" # Set to "C" locale so we can parse messages from commands LANG=C export LANG # Must be root if test "`@ID@ -u`" != 0 ; then echo "$0: You must be root to run this script" >& 2 exit 1 fi if test "$SETSID" != "" -a ! -x "$SETSID"; then SETSID="" fi CONFIG=/etc//ppp/pppoe.conf USER="" ETH="" # Sort out command-line arguments case "$#" in 1) CONFIG="$1" ;; 3) CONFIG="$3" ;; esac if test ! -f "$CONFIG" -o ! -r "$CONFIG" ; then echo "$0: Cannot read configuration file '$CONFIG'" >& 2 exit 1 fi export CONFIG . $CONFIG PPPOE_PIDFILE="$PIDFILE.pppoe" PPPD_PIDFILE="$PIDFILE.pppd" # Check for command-line overriding of ETH and USER case "$#" in 2|3) ETH="$1" USER="$2" ;; esac # Check that config file is sane if test "$USER" = "" ; then echo "$0: Check '$CONFIG' -- no setting for USER" >& 2 exit 1 fi if test "$ETH" = "" ; then echo "$0: Check '$CONFIG' -- no setting for ETH" >& 2 exit 1 fi PPPD_PID=0 # Catch common error if test "$DEBUG" = "1" ; then echo "*** If you want to use DEBUG, invoke pppoe-start, not pppoe-connect." exit 1 fi if test "$DEBUG" != "" ; then if test "$LINUX_PLUGIN" != "" ; then echo "Cannot use DEBUG mode and LINUX_PLUGIN at the same time." echo "Kernel-mode PPPoE is experimental and unsupported." exit 1 fi echo "* The following section identifies your Ethernet interface" >> $DEBUG echo "* and user name. Some ISP's need 'username'; others" >> $DEBUG echo "* need 'username@isp.com'. Try both" >> $DEBUG echo "ETH=$ETH; USER=$USER" >> $DEBUG echo "---------------------------------------------" >> $DEBUG fi # MTU of Ethernet card attached to modem MUST be 1500. This apparently # fails on some *BSD's, so we'll only do it under Linux if test `uname -s` = Linux ; then $IP link set $ETH up mtu 1500 # For 2.4 kernels. Will fail on 2.2.x, but who cares? modprobe ppp_generic > /dev/null 2>&1 modprobe ppp_async > /dev/null 2>&1 modprobe ppp_synctty > /dev/null 2>&1 if test -n "$LINUX_PLUGIN" ; then modprobe pppox > /dev/null 2>&1 modprobe pppoe > /dev/null 2>&1 fi else $IFCONFIG $ETH up fi if test "$SYNCHRONOUS" = "yes" ; then PPPOE_SYNC=-s PPPD_SYNC=sync # Increase the chances of it working on Linux... if test `uname -s` = Linux ; then modprobe n_hdlc > /dev/null 2>&1 fi else PPPOE_SYNC="" PPPD_SYNC="" fi if test -n "$ACNAME" ; then ACNAME="-C $ACNAME" fi if test -n "$SERVICENAME" ; then SERVICENAMEOPT="-S $SERVICENAME" else SERVICENAMEOPT="" fi if test "$CLAMPMSS" = "no" ; then CLAMPMSS="" else CLAMPMSS="-m $CLAMPMSS" fi # If DNSTYPE is SERVER, we must use "usepeerdns" option to pppd. if test "$DNSTYPE" = "SERVER" ; then PEERDNS=yes USEPEERDNS=yes fi if test "$PEERDNS" = "yes" ; then PEERDNS="usepeerdns" else PEERDNS="" fi # Backward config file compatibility -- PEERDNS used to be USEPEERDNS if test "$USEPEERDNS" = "yes" ; then PEERDNS="usepeerdns" fi if test "$USEPEERDNS" = "no" ; then PEERDNS="" fi # Backward config file compatibility if test "$DEMAND" = "" ; then DEMAND=no fi if test "$DEMAND" = "no" ; then DEMAND="" else DEMAND="demand persist idle $DEMAND 10.112.112.112:10.112.112.113 ipcp-accept-remote ipcp-accept-local connect true noipdefault ktune" fi case "$FIREWALL" in STANDALONE) . /etc/ppp/firewall-standalone ;; MASQUERADE) . /etc/ppp/firewall-masq ;; esac # If we're using kernel-mode PPPoE on Linux... if test "$LINUX_PLUGIN" != "" ; then PLUGIN_OPTS="plugin $LINUX_PLUGIN nic-$ETH" if test -n "$SERVICENAME" ; then PLUGIN_OPTS="$PLUGIN_OPTS rp_pppoe_service $SERVICENAME" fi modprobe pppoe > /dev/null 2>&1 fi if test "$DEFAULTROUTE" != "no" ; then DEFAULTROUTE="defaultroute" else DEFAULTROUTE="" fi if test -n "$UNIT" ; then DOUNIT="unit $UNIT" else DOUNIT="" fi if test "$MTU" = "" ; then MTU=1492 fi if test "$MRU" = "" ; then MRU=1492 fi # Standard PPP options we always use PPP_STD_OPTIONS="$PLUGIN_OPTS $DOUNIT noipdefault noauth default-asyncmap $DEFAULTROUTE hide-password nodetach $PEERDNS mtu $MTU mru $MRU noaccomp nodeflate nopcomp novj novjccomp user $USER lcp-echo-interval $LCP_INTERVAL lcp-echo-failure $LCP_FAILURE $PPPD_EXTRA" # Jigger DNS if required... if test "$DNSTYPE" = "SERVER" ; then # Sorry, dude... rm -f /etc/resolv.conf ln -s /etc/ppp/resolv.conf /etc/resolv.conf elif test "$DNSTYPE" = "SPECIFY" ; then # Sorry, dude... rm -f /etc/resolv.conf echo "nameserver $DNS1" > /etc/resolv.conf if test -n "$DNS2" ; then echo "nameserver $DNS2" >> /etc/resolv.conf fi fi # PPPoE invocation PPPOE_CMD="$PPPOE -p $PPPOE_PIDFILE -I $ETH -T $PPPOE_TIMEOUT -U $PPPOE_SYNC $CLAMPMSS $ACNAME $SERVICENAMEOPT $PPPOE_EXTRA" if test "$DEBUG" != "" ; then if test "$DEMAND" != "" ; then echo "(Turning off DEMAND for debugging purposes)" DEMAND="" fi echo "* The following section shows the pppd command we will invoke" >> $DEBUG echo "pppd invocation" >> $DEBUG echo "$SETSID $PPPD pty '$PPPOE_CMD' $PPP_STD_OPTIONS $PPPD_SYNC debug" >> $DEBUG echo "---------------------------------------------" >> $DEBUG $SETSID $PPPD pty "$PPPOE_CMD -D $DEBUG-0" \ $PPP_STD_OPTIONS \ $PPPD_SYNC \ debug >> $DEBUG 2>&1 echo "---------------------------------------------" >> $DEBUG echo "* The following section is an extract from your log." >> $DEBUG echo "* Look for error messages from pppd, such as" >> $DEBUG echo "* a lack of kernel support for PPP, authentication failure" >> $DEBUG echo "* etc." >> $DEBUG if test -f "/var/log/messages" ; then echo "Extract from /var/log/messages" >> $DEBUG grep 'ppp' /var/log/messages | tail -150 >> $DEBUG elif test -f "/var/adm/messages"; then echo "Extract from /var/adm/messages" >> $DEBUG grep 'ppp' /var/adm/messages | tail -150 >> $DEBUG else echo "Can't find messages file (looked for /var/{log,adm}/messages" >> $DEBUG fi date >> $DEBUG echo "---------------------------------------------" >> $DEBUG echo "* The following section is a dump of the packets" >> $DEBUG echo "* sent and received by rp-pppoe. If you don't see" >> $DEBUG echo "* any output, it's an Ethernet driver problem. If you only" >> $DEBUG echo "* see three PADI packets and nothing else, check your cables" >> $DEBUG echo "* and modem. Make sure the modem lights flash when you try" >> $DEBUG echo "* to connect. Check that your Ethernet card is in" >> $DEBUG echo "* half-duplex, 10Mb/s mode. If all else fails," >> $DEBUG echo "* try using pppoe-sniff." >> $DEBUG echo "rp-pppoe debugging dump" >> $DEBUG cat $DEBUG-0 >> $DEBUG rm -f $DEBUG-0 for i in 1 2 3 4 5 6 7 8 9 10 ; do echo "" echo "" echo "" done echo "*** Finished debugging run. Please review the file" echo "*** '$DEBUG' and try to" echo "*** figure out what is going on." echo "***" echo "*** Unfortunately, we can NO LONGER accept debugging" echo "*** output for analysis. Please do not send this to" echo "*** Roaring Penguin; it is too time-consuming for" echo "*** us to deal with all the analyses we have been sent." exit 0 fi echo $$ > $PIDFILE while [ true ] ; do if test "$OVERRIDE_PPPD_COMMAND" != "" ; then $SETSID $OVERRIDE_PPPD_COMMAND & echo "$!" > $PPPD_PIDFILE elif test "$LINUX_PLUGIN" != "" ; then $SETSID $PPPD $PPP_STD_OPTIONS $DEMAND & echo "$!" > $PPPD_PIDFILE else $SETSID $PPPD pty "$PPPOE_CMD" \ $PPP_STD_OPTIONS \ $DEMAND \ $PPPD_SYNC & echo "$!" > $PPPD_PIDFILE fi wait if test "$RETRY_ON_FAILURE" = "no" ; then exit fi # Run /etc/ppp/pppoe-lost if it exists test -x /etc/ppp/pppoe-lost && /etc/ppp/pppoe-lost # Re-establish the connection $LOGGER -p daemon.notice \ "PPPoE connection lost; attempting re-connection." # Wait a bit in case a problem causes tons of log messages :-) sleep 5 done rp-pppoe-3.15/go0000755000175000017500000000155714045237007011663 0ustar dfsdfs#!/bin/sh # LIC: GPL #*********************************************************************** # # go # # Quick-start shell script to set up PPPoE # # Copyright (C) 2000 Roaring Penguin Software Inc. # Copyright (C) 2018 Dianne Skoll # # $Id$ #*********************************************************************** # Figure out directory of script MYDIR=`dirname $0` cd $MYDIR/src echo "Running ./configure..." ./configure if [ "$?" != 0 ] ; then echo "Oops! It looks like ./configure failed." exit 1 fi echo "Running make..." make if [ "$?" != 0 ] ; then echo "Oops! It looks like make failed." exit 1 fi echo "Running make install..." make install if [ "$?" != 0 ] ; then echo "Oops! It looks like make install failed." exit 1 fi for i in a a a a a a a a a a a a a a a a a a a a a a a a a a a a ; do echo "" done sh ../scripts/pppoe-setup