pax_global_header00006660000000000000000000000064135371206710014517gustar00rootroot0000000000000052 comment=67d68af5212a6b02f1999d241419c9c27c72eb08 ap51-flash-2019.0.1/000077500000000000000000000000001353712067100136125ustar00rootroot00000000000000ap51-flash-2019.0.1/.gitattributes000066400000000000000000000003301353712067100165010ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann * text=auto *.c text diff=cpp *.h text diff=cpp *.rst text *.py text diff=python *.rst text Makefile text ap51-flash-2019.0.1/.github/000077500000000000000000000000001353712067100151525ustar00rootroot00000000000000ap51-flash-2019.0.1/.github/pull_request_template000066400000000000000000000006371353712067100215220ustar00rootroot00000000000000Thanks for your contribution to ap51-flash! * Prefer small & digestible over long "all in one" patches. * Add a "Signed-off-by: Your Name " line to the patch message to make the ownership of the patch clear. * use "ap51-flash: " as prefix in your commit message's subject * make sure that you have updated docs/ to reflect your changes Please remove this message before posting the pull request. ap51-flash-2019.0.1/.github/pull_request_template.license000066400000000000000000000002741353712067100231400ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2009-2019, Marek Lindner # SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann ap51-flash-2019.0.1/.gitignore000066400000000000000000000003001353712067100155730ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann *.d *.o /ap51-flash /ap51-flash.exe /ap51-flash-osx /ap51-flash-res /docs/_build/ ap51-flash-2019.0.1/.travis.yml000066400000000000000000000056731353712067100157360ustar00rootroot00000000000000# SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann sudo: required dist: xenial language: cpp compiler: - gcc - clang addons: apt: packages: - libpcap-dev - binutils - libc-bin env: matrix: - CPPFLAGS="" - CPPFLAGS="-DDEBUG" - CPPFLAGS="-DCLEAR_SCREEN" - CPPFLAGS="-DCLEAR_SCREEN -DDEBUG" before_script: - dd if=/dev/urandom of=test.img count=10000 bs=1024 script: - make clean V=s && make CC="${CC}" V=s - make clean V=s && make CC="${CC}" EMBED_CI="test.img" V=s matrix: include: # windows cross-compiler - os: linux env: - MXE_CPU=i686 - PATH="/usr/lib/mxe/usr/bin/:$PATH" addons: apt: sources: - sourceline: 'deb http://pkg.mxe.cc/repos/apt/ xenial main' key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xC6BF758A33A3A276' packages: - mxe-i686-w64-mingw32.static-gcc - mxe-i686-w64-mingw32.static-winpcap before_script: - dd if=/dev/urandom of=test.img count=10000 bs=1024 script: - make clean V=s && make V=s CROSS="${MXE_CPU}-w64-mingw32.static-" ap51-flash.exe - make clean V=s && CPPFLAGS="-DCLEAR_SCREEN" make V=s CROSS="${MXE_CPU}-w64-mingw32.static-" ap51-flash.exe - make clean V=s && CPPFLAGS="-DCLEAR_SCREEN -DDEBUG" make V=s CROSS="${MXE_CPU}-w64-mingw32.static-" ap51-flash.exe - make clean V=s && CPPFLAGS="-DDEBUG" make V=s CROSS="${MXE_CPU}-w64-mingw32.static-" ap51-flash.exe - make clean V=s && make V=s CROSS="${MXE_CPU}-w64-mingw32.static-" EMBED_CI="test.img" ap51-flash.exe - make clean V=s && CFLAGS="-flto -O2" make V=s CROSS="${MXE_CPU}-w64-mingw32.static-" ap51-flash.exe && mv ap51-flash.exe ap51-flash-i686.exe # musl static cross build - os: linux env: - CPPFLAGS="-Ikernel-headers/x86/include/" - CFLAGS="-static -m64 -flto -O2" - LDFLAGS="-Wl,-m -Wl,elf_x86_64" addons: apt: packages: - git - musl-tools before_script: - git clone https://github.com/sabotage-linux/kernel-headers -b v3.12.6-5 kernel-headers script: - make clean V=s && make V=s CC=musl-gcc && mv ap51-flash ap51-flash-x86_64-linux # osx native build - os: osx before_script: - dd if=/dev/urandom of=test.img count=10000 bs=1024 script: - make clean V=s && make V=s ap51-flash-osx - make clean V=s && CPPFLAGS="-DDEBUG" make V=s ap51-flash-osx - make clean V=s && make V=s EMBED_CI="test.img" ap51-flash-osx - make clean V=s && CFLAGS="-flto -O2" make V=s ap51-flash-osx # reuse test - os: linux language: minimal services: - docker env: - REUSE_TEST=1 before_install: - docker pull fsfe/reuse:latest - docker run --name reuse -v ${TRAVIS_BUILD_DIR}:/repo fsfe/reuse /bin/sh -c "cd /repo; reuse lint" script: - true ap51-flash-2019.0.1/CHANGELOG.rst000066400000000000000000000023061353712067100156340ustar00rootroot00000000000000.. SPDX-License-Identifier: CC0-1.0 .. SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann 2019.0.1 (2019-09-14) ===================== * Fix support for flashing of embedded images 2019.0 (2019-08-30) =================== * improved Zyxel firmware detection * introduced optional MAC address filtering * added support for: - Plasma Cloud PA300 - Plasma Cloud PA1200 - Plasma Cloud PA2200 2018.0 (2018-06-19) =================== * added support for: - Alfa Network AP121F - Dlink DIR-300 - Engenius EOC-1650 - Engenius EOC-2610 - Engenius EOC-2610p - Engenius 3660 - FON La Fonera (2100) - Open Mesh A40 - Open Mesh A42 - Open Mesh A60 - Open Mesh A62 - Open Mesh D200 - Open Mesh G200 - Open Mesh MR500 - Open Mesh MR600 (v1, v2) - Open Mesh MR900 (v1, v2) - Open Mesh MR1750 (v1, v2) - Open Mesh OM1P - Open Mesh OM2P (v1, v2, v4) - Open Mesh OM2P-HS (v1, v2, v3, v4) - Open Mesh OM2P-LC - Open Mesh OM5P - Open Mesh OM5P-AN - Open Mesh OM5P-AC (v1, v2) - Ubiquiti Bullet2 & HP - Ubiquiti NanoStation2 - Ubiquiti NanoStation5 - Ubiquiti Pico2 & HP - Ubiquiti RouterStation - UniAppliance Colibrì (!UniData) - Zyxel NBG6817 ap51-flash-2019.0.1/LICENSES/000077500000000000000000000000001353712067100150175ustar00rootroot00000000000000ap51-flash-2019.0.1/LICENSES/CC0-1.0.txt000066400000000000000000000154041353712067100164250ustar00rootroot00000000000000Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. ap51-flash-2019.0.1/LICENSES/GPL-3.0-or-later.txt000066400000000000000000001032461353712067100202310ustar00rootroot00000000000000GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ap51-flash-2019.0.1/Makefile000066400000000000000000000072001353712067100152510ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2009-2019, Marek Lindner # enable debug output # CPPFLAGS += -DDEBUG # clear screen after each subsequent flash # CPPFLAGS += -DCLEAR_SCREEN # define $EMBED_IMG=/path/to/image to have your image included # into the binary where $EMBED_IMG is one of the following: # * EMBED_CI # * EMBED_CE # * EMBED_UBNT # * EMBED_UBOOT # * EMBED_ZYXEL BINARY_NAME = ap51-flash OBJ += commandline.o OBJ += flash.o OBJ += fwcfg.o OBJ += proto.o OBJ += router_images.o OBJ += router_redboot.o OBJ += router_tftp_client.o OBJ += router_tftp_server.o OBJ += router_netconsole.o OBJ += router_types.o OBJ += socket.o AP51_RC = ap51-flash-res BINARY_TARGET_NAMES += $(BINARY_NAME) BINARY_TARGET_NAMES += $(BINARY_NAME).exe BINARY_TARGET_NAMES += $(BINARY_NAME)-osx # ap51-flash flags and options CFLAGS += -Wall -W -std=gnu99 -fno-strict-aliasing $(EXTRA_CFLAGS) -MD -MP CPPFLAGS += -D_GNU_SOURCE LDLIBS += # disable verbose output ifneq ($(findstring $(MAKEFLAGS),s),s) ifndef V Q_CC = @echo ' ' CC $@; Q_LD = @echo ' ' LD $@; Q_SILENT = @ export Q_CC export Q_LD export Q_SILENT endif endif CC = $(CROSS)gcc RM ?= rm -f STRIP = $(CROSS)strip OBJCOPY = $(CROSS)objcopy WINDRES = $(CROSS)windres COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c LINK.o = $(Q_LD)$(CC) $(CFLAGS) $(LDFLAGS) $(TARGET_ARCH) ifeq ($(MAKECMDGOALS),) PLATFORM = LINUX else ifeq ($(MAKECMDGOALS),$(BINARY_NAME)) PLATFORM = LINUX else ifeq ($(MAKECMDGOALS),$(BINARY_NAME).exe) PLATFORM = WIN32 else ifeq ($(MAKECMDGOALS),$(BINARY_NAME)-osx) PLATFORM = OSX endif ifneq ($(PLATFORM),) CPPFLAGS += -D$(PLATFORM) endif ifeq ($(PLATFORM),LINUX) BINARY_SUFFIX = else ifeq ($(PLATFORM),WIN32) BINARY_SUFFIX = .exe CPPFLAGS += -D_CONSOLE -D_MBCS -D__USE_MINGW_ANSI_STDIO=1 ifeq ($(origin PKG_CONFIG), undefined) PKG_CONFIG = $(CROSS)pkg-config ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) $(error $(PKG_CONFIG) not found) endif endif ifeq ($(origin WINPCAP_CFLAGS) $(origin WINPCAP_LDLIBS), undefined undefined) WINPCAP_NAME ?= winpcap ifeq ($(shell $(PKG_CONFIG) --modversion $(WINPCAP_NAME) 2>/dev/null),) $(error No $(WINPCAP_NAME) development libraries found!) endif WINPCAP_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(WINPCAP_NAME)) WINPCAP_LDLIBS += $(shell $(PKG_CONFIG) --libs $(WINPCAP_NAME)) endif CFLAGS += $(WINPCAP_CFLAGS) LDLIBS += $(WINPCAP_LDLIBS) else ifeq ($(PLATFORM),OSX) BINARY_SUFFIX = -osx LDLIBS += -lpcap endif EMBEDDED_IMAGES += $(EMBED_CI) EMBEDDED_IMAGES += $(EMBED_CE) EMBEDDED_IMAGES += $(EMBED_UBNT) EMBEDDED_IMAGES += $(EMBED_UBOOT) EMBEDDED_IMAGES += $(EMBED_ZYXEL) Makefile: embed_image.mk include embed_image.mk $(eval $(call embed_image,CI,ci)) $(eval $(call embed_image,CE,ce)) $(eval $(call embed_image,UBNT,ubnt)) $(eval $(call embed_image,UBOOT,uboot)) $(eval $(call embed_image,ZYXEL,zyxel)) # try to generate revision REVISION= $(shell \ if [ -d .git ]; then \ echo $$(git describe --always --dirty --match "v*" |sed 's/^v//' 2> /dev/null || echo "[unknown]"); \ fi) ifneq ($(REVISION),) CPPFLAGS += -DSOURCE_VERSION=\"$(REVISION)\" endif # standard build rules .SUFFIXES: .o .c .c.o: $(COMPILE.c) -o $@ $< all: $(BINARY_NAME)$(BINARY_SUFFIX) $(BINARY_TARGET_NAMES): $(OBJ) $(LINK.o) $^ $(LDLIBS) -o $@ $(STRIP) $@ $(OBJ): Makefile $(AP51_RC).o: $(AP51_RC) $(Q_CC)$(WINDRES) -i $(AP51_RC) -I. -o $@ clean: $(RM) *.o *.d *~ $(BINARY_TARGET_NAMES) $(AP51_RC) # load dependencies DEP = $(OBJ:.o=.d) -include $(DEP) .PHONY: all clean .DELETE_ON_ERROR: .DEFAULT_GOAL := all ap51-flash-2019.0.1/README.rst000066400000000000000000000020071353712067100153000ustar00rootroot00000000000000.. SPDX-License-Identifier: CC0-1.0 .. SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann ========== ap51-flash ========== .. image:: https://img.shields.io/coverity/scan/14627.svg :target: https://scan.coverity.com/projects/ap51-flash-ap51-flash .. image:: https://img.shields.io/readthedocs/ap51-flash.svg :target: https://ap51-flash.readthedocs.io/ .. image:: https://img.shields.io/travis/ap51-flash/ap51-flash/master.svg :target: https://travis-ci.org/ap51-flash/ap51-flash firmware flasher for ethernet connected routers and access points ap51-flash is a tool to simplify the automatic firmware deployment for a multitude of home routers and wireless access points. ap51-flash can identify target device(s), select the correct firmware image and perform the required communication to carry out the installation procedure. It works without the need for a local TFTP server or manual, target device specific network configuration. See https://ap51-flash.readthedocs.io/ for more information. ap51-flash-2019.0.1/ap51-flash-res.h000066400000000000000000000005341353712067100164150ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_RES_H__ #define __AP51_FLASH_RES_H__ #define IDR_CI_IMG 101 #define IDR_CE_IMG 102 #define IDR_UBNT_IMG 103 #define IDR_UBOOT_IMG 104 #define IDR_ZYXEL_IMG 105 #endif /* __AP51_FLASH_RES_H__ */ ap51-flash-2019.0.1/ap51-flash.h000066400000000000000000000005211353712067100156220ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_AP51_FLASH_H__ #define __AP51_FLASH_AP51_FLASH_H__ #define DESC_MAX_LENGTH 30 #define FILE_NAME_MAX_LENGTH 33 #define FLASH_PAGE_SIZE 0x10000 #endif /* __AP51_FLASH_AP51_FLASH_H__ */ ap51-flash-2019.0.1/commandline.c000066400000000000000000000057361353712067100162570ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #include "commandline.h" #include #include #include #include #include "flash.h" #include "router_images.h" #include "router_types.h" #include "socket.h" #ifndef SOURCE_VERSION #define SOURCE_VERSION "2019.0.1" #endif static void usage(const char *prgname) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "%s interface image\t\t\tflash router with given image\n", prgname); fprintf(stderr, "%s [-m ...] interface image\tflash router at given MAC address(es)\n", prgname); fprintf(stderr, "%s -h\t\t\t\t\tshow usage/help\n", prgname); fprintf(stderr, "%s -v\t\t\t\t\tprints version information\n", prgname); fprintf(stderr, "\nOne or multiple images of the following type can be specified:\n"); router_images_print_desc(); fprintf(stderr, "\nThe interface has to be one of the devices that are part of the supported device list which follows.\nYou can either specify its name or the interface number.\n"); socket_print_all_ifaces(); } int main(int argc, char* argv[]) { bool print_help = false; bool print_version = false; int c; char *iface = NULL; int ret = -1; bool load_embedded = true; const char *progname = "ap51-flash"; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {"mac", required_argument, 0, 'm'}, {} }; while ((c = getopt_long(argc, argv, "hvm:", long_options, NULL)) != -1) { switch (c) { case 'h': print_help = true; ret = 0; break; case 'v': print_version = true; ret = 0; break; case 'm': if (mac_whitelist_add(optarg) == 0) break; /* fall-through */ case '?': print_help = true; break; } } progname = argv[0]; if (print_help) { usage(progname); goto out; } if (print_version) { #if defined(EMBEDDED_DESC) printf("ap51-flash (%s) [embedded: %s]\n", SOURCE_VERSION, EMBEDDED_DESC); #else printf("ap51-flash (%s)\n", SOURCE_VERSION); #endif goto out; } argc -= optind; argv += optind; if (argc < 1) { fprintf(stderr, "Error - no interface specified\n"); usage(progname); goto out; } if (strlen(argv[0]) < 3) iface = socket_find_iface_by_index(argv[0]); if (!iface) iface = argv[0]; argc -= 1; argv += 1; router_images_init(); while (argc > 0) { ret = router_images_verify_path(argv[0]); if (ret < 0) goto out; argc -= 1; argv += 1; load_embedded = false; } if (load_embedded) { router_images_init_embedded(); } else { #if defined(EMBED_UBOOT) || defined(EMBED_UBNT) || defined(EMBED_CI) || defined(EMBED_CE) || defined(EMBED_ZYXEL) printf("Embedded image disabled\n"); #endif } #if defined(DEBUG) printf("Listening on interface: %s\n", iface); #endif if (!router_images_available()) { fprintf(stderr, "Error - no images specified\n"); usage(progname); goto out; } ret = flash_start(iface); out: return ret; } ap51-flash-2019.0.1/commandline.h000066400000000000000000000004331353712067100162510ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_COMMANDLINE_H__ #define __AP51_FLASH_COMMANDLINE_H__ int main(int argc, char* argv[]); #endif /* __AP51_FLASH_COMMANDLINE_H__ */ ap51-flash-2019.0.1/compat.h000066400000000000000000000076641353712067100152630ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_COMPAT_H__ #define __AP51_FLASH_COMPAT_H__ #if defined(LINUX) #include #include #include #include #include #include #include #include #include #include #include #include #define O_BINARY 0 #define USE_PCAP 0 #elif defined(OSX) #include #include #include #include #include #include #include #define O_BINARY 0 #define USE_PCAP 1 #define ETH_ALEN 6 #define ETH_HLEN 14 #define ETH_DATA_LEN 1500 #elif defined(WIN32) #define USE_PCAP 1 #include #include #define ntohs(x) __swab16(x) #define htons(x) __swab16(x) #define htonl(x) __swab32(x) #define ntohl(x) __swab32(x) #define ETH_ALEN 6 #define ETH_HLEN 14 #define ETH_DATA_LEN 1500 struct ether_header { uint8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ uint8_t ether_shost[ETH_ALEN]; /* source ether addr */ uint16_t ether_type; /* packet type ID field */ } __attribute__((packed)); struct arphdr { uint16_t ar_hrd; /* format of hardware address */ uint16_t ar_pro; /* format of protocol address */ uint8_t ar_hln; /* length of hardware address */ uint8_t ar_pln; /* length of protocol address */ uint16_t ar_op; /* ARP opcode (command) */ } __attribute__((packed)); struct ether_arp { struct arphdr ea_hdr; /* fixed-size header */ uint8_t arp_sha[ETH_ALEN]; /* sender hardware address */ uint8_t arp_spa[4]; /* sender protocol address */ uint8_t arp_tha[ETH_ALEN]; /* target hardware address */ uint8_t arp_tpa[4]; /* target protocol address */ } __attribute__((packed)); #endif #ifndef IPPORT_TFTP #define IPPORT_TFTP 69 #endif #ifndef IPPORT_ICMP #define IPPORT_ICMP 1 #endif #if USE_PCAP #define ETH_P_IP 0x0800 #define ETH_P_ARP 0x0806 #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 #define IPPORT_TFTP 69 #define ARPOP_REQUEST 1 #define ARPOP_REPLY 2 #define __swab16(x) ((uint16_t)( \ (((uint16_t)(x) & (uint16_t)0x00ffU) << 8) | \ (((uint16_t)(x) & (uint16_t)0xff00U) >> 8))) #define __swab32(x) ((uint32_t)( \ (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24))) #define iphdr iphdr_linux #define udphdr udphdr_linux #define tcphdr tcphdr_linux #define icmphdr icmphdr_linux struct iphdr_linux { uint8_t ihl:4; uint8_t version:4; uint8_t tos; uint16_t tot_len; uint16_t id; uint16_t frag_off; uint8_t ttl; uint8_t protocol; uint16_t check; uint32_t saddr; uint32_t daddr; }; struct udphdr_linux { uint16_t source; uint16_t dest; uint16_t len; uint16_t check; }; struct tcphdr_linux { uint16_t source; uint16_t dest; uint32_t seq; uint32_t ack_seq; uint16_t res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; uint16_t window; uint16_t check; uint16_t urg_ptr; }; struct icmphdr_linux { uint8_t type; /* message type */ uint8_t code; /* type sub-code */ uint16_t checksum; union { struct { uint16_t id; uint16_t sequence; } echo; /* echo datagram */ uint32_t gateway; /* gateway address */ struct { uint16_t __unused; uint16_t mtu; } frag; /* path mtu discovery */ } un; }; #endif #endif /* __AP51_FLASH_COMPAT_H__ */ ap51-flash-2019.0.1/contrib/000077500000000000000000000000001353712067100152525ustar00rootroot00000000000000ap51-flash-2019.0.1/contrib/iwyu/000077500000000000000000000000001353712067100162475ustar00rootroot00000000000000ap51-flash-2019.0.1/contrib/iwyu/compat_map.iwyu000066400000000000000000000036711353712067100213150ustar00rootroot00000000000000[ { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, { include: [ "", "private", "\"compat.h\"", "public" ] }, ] ap51-flash-2019.0.1/contrib/iwyu/compat_map.iwyu.license000066400000000000000000000001501353712067100227230ustar00rootroot00000000000000SPDX-License-Identifier: CC0-1.0 SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann ap51-flash-2019.0.1/docs/000077500000000000000000000000001353712067100145425ustar00rootroot00000000000000ap51-flash-2019.0.1/docs/Makefile000066400000000000000000000006071353712067100162050ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann SPHINXOPTS = SPHINXBUILD = sphinx-build SOURCEDIR = . BUILDDIR = _build help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile ap51-flash-2019.0.1/docs/conf.py000066400000000000000000000115051353712067100160430ustar00rootroot00000000000000# -*- coding: utf-8 -*- # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann # Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Project information ----------------------------------------------------- project = u'ap51-flash' copyright = u'2017-2019, ap51-flash Team' author = u'ap51-flash Team' # The short X.Y version version = u'2019.0.1' # The full version, including alpha/beta/rc tags release = u'2019.0.1' # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # The default sidebars (for documents that don't match any pattern) are # defined by theme itself. Builtin themes are using these templates by # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', # 'searchbox.html']``. # # html_sidebars = {} # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'ap51-flashdoc' # -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'ap51-flash.tex', u'ap51-flash Documentation', u'ap51-flash Team', 'manual'), ] # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'ap51-flash', u'ap51-flash Documentation', [author], 1) ] # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'ap51-flash', u'ap51-flash Documentation', author, 'ap51-flash', 'One line description of project.', 'Miscellaneous'), ] # -- Options for Epub output ------------------------------------------------- # Bibliographic Dublin Core info. epub_title = project # The unique identifier of the text. This can be a ISBN number # or the project homepage. # # epub_identifier = '' # A unique identification for the text. # # epub_uid = '' # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] ap51-flash-2019.0.1/docs/flash-station/000077500000000000000000000000001353712067100173165ustar00rootroot00000000000000ap51-flash-2019.0.1/docs/flash-station/.config000066400000000000000000001305021353712067100205650ustar00rootroot00000000000000# # Automatically generated make config: don't edit # OpenWrt version: Kamikaze (r18405) # Sat Dec 26 02:22:30 2009 # # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing CONFIG_HAVE_DOT_CONFIG=y # CONFIG_TARGET_ppc40x is not set # CONFIG_TARGET_ppc44x is not set CONFIG_TARGET_atheros=y # CONFIG_TARGET_ar71xx is not set # CONFIG_TARGET_at91 is not set # CONFIG_TARGET_avr32 is not set # CONFIG_TARGET_brcm63xx is not set # CONFIG_TARGET_brcm47xx is not set # CONFIG_TARGET_brcm_2_4 is not set # CONFIG_TARGET_sibyte is not set # CONFIG_TARGET_octeon is not set # CONFIG_TARGET_cobalt is not set # CONFIG_TARGET_gemini is not set # CONFIG_TARGET_etrax is not set # CONFIG_TARGET_coldfire is not set # CONFIG_TARGET_mpc52xx is not set # CONFIG_TARGET_mpc83xx is not set # CONFIG_TARGET_goldfish is not set # CONFIG_TARGET_amazon is not set # CONFIG_TARGET_ifxmips is not set # CONFIG_TARGET_adm5120 is not set # CONFIG_TARGET_iop32x is not set # CONFIG_TARGET_ixp4xx is not set # CONFIG_TARGET_kirkwood is not set # CONFIG_TARGET_orion is not set # CONFIG_TARGET_pxa is not set # CONFIG_TARGET_rb532 is not set # CONFIG_TARGET_olpc is not set # CONFIG_TARGET_pxcab is not set # CONFIG_TARGET_rdc is not set # CONFIG_TARGET_au1000 is not set # CONFIG_TARGET_ramips is not set # CONFIG_TARGET_s3c24xx is not set # CONFIG_TARGET_ps3 is not set # CONFIG_TARGET_ar7 is not set # CONFIG_TARGET_ubicom32 is not set # CONFIG_TARGET_uml is not set # CONFIG_TARGET_x86 is not set # CONFIG_TARGET_cobalt_Default is not set # CONFIG_TARGET_au1000_au1500_Atheros is not set # CONFIG_TARGET_au1000_au1500_InternetBox is not set # CONFIG_TARGET_au1000_au1500_MeshCube is not set # CONFIG_TARGET_au1000_au1550_DBAu1550 is not set # CONFIG_TARGET_olpc_Default is not set # CONFIG_TARGET_brcm_2_4_Broadcom is not set # CONFIG_TARGET_brcm_2_4_BroadcomMimo is not set # CONFIG_TARGET_brcm_2_4_None is not set # CONFIG_TARGET_brcm_2_4_USBGeneric is not set # CONFIG_TARGET_brcm_2_4_WL500G is not set # CONFIG_TARGET_brcm_2_4_WL500GD is not set # CONFIG_TARGET_brcm_2_4_WL500GP is not set # CONFIG_TARGET_brcm_2_4_WL700GE is not set # CONFIG_TARGET_brcm_2_4_WLHDD is not set # CONFIG_TARGET_brcm_2_4_WRT54G3G is not set # CONFIG_TARGET_iop32x_Default is not set # CONFIG_TARGET_mpc83xx_Default is not set # CONFIG_TARGET_ubicom32_Default is not set # CONFIG_TARGET_s3c24xx_openmoko-gta02-minimal is not set # CONFIG_TARGET_s3c24xx_openmoko-gta02-full is not set # CONFIG_TARGET_etrax_default is not set # CONFIG_TARGET_etrax_vhdl_no_fb is not set # CONFIG_TARGET_gemini_Default is not set # CONFIG_TARGET_kirkwood_Default is not set # CONFIG_TARGET_rdc_amit_Default is not set # CONFIG_TARGET_rdc_ar525w_Default is not set # CONFIG_TARGET_rdc_r8610_Default is not set # CONFIG_TARGET_rdc_dir_450_Default is not set # CONFIG_TARGET_avr32_Default is not set # CONFIG_TARGET_ifxmips_None is not set # CONFIG_TARGET_ifxmips_Atheros is not set # CONFIG_TARGET_ifxmips_Ralink is not set CONFIG_TARGET_atheros_Default=y # CONFIG_TARGET_coldfire_Default is not set # CONFIG_TARGET_adm5120_router_le_Generic is not set # CONFIG_TARGET_adm5120_router_le_CAS630 is not set # CONFIG_TARGET_adm5120_router_le_CAS630W is not set # CONFIG_TARGET_adm5120_router_le_CAS670 is not set # CONFIG_TARGET_adm5120_router_le_CAS670W is not set # CONFIG_TARGET_adm5120_router_le_CAS700 is not set # CONFIG_TARGET_adm5120_router_le_CAS700W is not set # CONFIG_TARGET_adm5120_router_le_CAS771 is not set # CONFIG_TARGET_adm5120_router_le_CAS771W is not set # CONFIG_TARGET_adm5120_router_le_CAS790 is not set # CONFIG_TARGET_adm5120_router_le_CAS861 is not set # CONFIG_TARGET_adm5120_router_le_CAS861W is not set # CONFIG_TARGET_adm5120_router_le_NFS101U is not set # CONFIG_TARGET_adm5120_router_le_NFS101WU is not set # CONFIG_TARGET_adm5120_router_le_NP27G is not set # CONFIG_TARGET_adm5120_router_le_NP28G is not set # CONFIG_TARGET_adm5120_router_le_WP54 is not set # CONFIG_TARGET_adm5120_router_le_BR6104K is not set # CONFIG_TARGET_adm5120_router_le_BR6104KP is not set # CONFIG_TARGET_adm5120_router_le_BR6104WG is not set # CONFIG_TARGET_adm5120_router_le_BR6114WG is not set # CONFIG_TARGET_adm5120_router_le_EASY5120RT is not set # CONFIG_TARGET_adm5120_router_le_EASY5120PATA is not set # CONFIG_TARGET_adm5120_router_le_PMUGW is not set # CONFIG_TARGET_adm5120_router_le_5GXI is not set # CONFIG_TARGET_adm5120_router_le_RouterBoard is not set # CONFIG_TARGET_adm5120_router_be_Generic is not set # CONFIG_TARGET_adm5120_router_be_P334WT is not set # CONFIG_TARGET_adm5120_router_be_P335WT is not set # CONFIG_TARGET_pxa_Default is not set # CONFIG_TARGET_x86_generic_Generic is not set # CONFIG_TARGET_x86_generic_Alix is not set # CONFIG_TARGET_x86_generic_Soekris45xx is not set # CONFIG_TARGET_x86_generic_Soekris48xx is not set # CONFIG_TARGET_x86_generic_Wrap is not set # CONFIG_TARGET_x86_olpc_Default is not set # CONFIG_TARGET_ar71xx_Default is not set # CONFIG_TARGET_ar71xx_Madwifi is not set # CONFIG_TARGET_ar71xx_A02RBW300N is not set # CONFIG_TARGET_ar71xx_WP543 is not set # CONFIG_TARGET_ar71xx_DIR615C1 is not set # CONFIG_TARGET_ar71xx_WRT160NL is not set # CONFIG_TARGET_ar71xx_WRT400N is not set # CONFIG_TARGET_ar71xx_MZKW04NU is not set # CONFIG_TARGET_ar71xx_MZKW300NH is not set # CONFIG_TARGET_ar71xx_TLWR741NDV1 is not set # CONFIG_TARGET_ar71xx_TLWR841NDV3 is not set # CONFIG_TARGET_ar71xx_TLWR941NDV2 is not set # CONFIG_TARGET_ar71xx_TEW632BRP is not set # CONFIG_TARGET_ar71xx_TEW652BRP is not set # CONFIG_TARGET_ar71xx_UBNTRS is not set # CONFIG_TARGET_ar71xx_UBNTRSPRO is not set # CONFIG_TARGET_ar71xx_UBNT is not set # CONFIG_TARGET_goldfish_Default is not set # CONFIG_TARGET_octeon_generic is not set # CONFIG_TARGET_octeon_mototech is not set # CONFIG_TARGET_octeon_simulator is not set # CONFIG_TARGET_ar7_Annex-A is not set # CONFIG_TARGET_ar7_Annex-B is not set # CONFIG_TARGET_ar7_Texas is not set # CONFIG_TARGET_ar7_None is not set # CONFIG_TARGET_pxcab_Default is not set # CONFIG_TARGET_ppc44x_Default is not set # CONFIG_TARGET_uml_Default is not set # CONFIG_TARGET_at91_Default is not set # CONFIG_TARGET_mpc52xx_Default is not set # CONFIG_TARGET_brcm47xx_Broadcom-b43 is not set # CONFIG_TARGET_brcm47xx_Atheros is not set # CONFIG_TARGET_brcm47xx_Atheros-ath5k is not set # CONFIG_TARGET_brcm47xx_None is not set # CONFIG_TARGET_brcm47xx_WGT634U is not set # CONFIG_TARGET_brcm47xx_WL500GPv1 is not set # CONFIG_TARGET_brcm47xx_WRT350Nv1 is not set # CONFIG_TARGET_brcm47xx_WRTSL54GS is not set # CONFIG_TARGET_brcm63xx_Broadcom is not set # CONFIG_TARGET_brcm63xx_Atheros is not set # CONFIG_TARGET_brcm63xx_Ralink is not set # CONFIG_TARGET_brcm63xx_NoWiFi is not set # CONFIG_TARGET_brcm63xx_GW6X00 is not set # CONFIG_TARGET_ppc40x_Default is not set # CONFIG_TARGET_ixp4xx_generic_Default is not set # CONFIG_TARGET_ixp4xx_generic_Atheros-ath5k is not set # CONFIG_TARGET_ixp4xx_generic_NSLU2 is not set # CONFIG_TARGET_ixp4xx_generic_NAS100d is not set # CONFIG_TARGET_ixp4xx_generic_DSMG600RevA is not set # CONFIG_TARGET_ixp4xx_generic_USR8200 is not set # CONFIG_TARGET_ixp4xx_harddisk_FSG3 is not set # CONFIG_TARGET_amazon_Default is not set # CONFIG_TARGET_rb532_Default is not set # CONFIG_TARGET_ps3_petitboot_Default is not set # CONFIG_TARGET_orion_generic_Default is not set # CONFIG_TARGET_orion_harddisk_Default is not set # CONFIG_TARGET_ramips_rt288x_Default is not set # CONFIG_TARGET_ramips_rt305x_Default is not set # CONFIG_TARGET_sibyte_Default is not set CONFIG_TARGET_BOARD="atheros" CONFIG_DEFAULT_TARGET_OPTIMIZATION="-Os -pipe -mips32 -mtune=mips32 -funit-at-a-time" CONFIG_LINUX_2_6_30=y CONFIG_DEFAULT_base-files=y CONFIG_DEFAULT_busybox=y CONFIG_DEFAULT_dnsmasq=y CONFIG_DEFAULT_dropbear=y CONFIG_DEFAULT_firewall=y CONFIG_DEFAULT_gpioctl=y CONFIG_DEFAULT_hostapd-mini=y CONFIG_DEFAULT_hotplug2=y CONFIG_DEFAULT_iptables=y CONFIG_DEFAULT_kmod-ipt-nathelper=y CONFIG_DEFAULT_kmod-madwifi=y CONFIG_DEFAULT_libc=y CONFIG_DEFAULT_libgcc=y CONFIG_DEFAULT_mtd=y CONFIG_DEFAULT_opkg=y CONFIG_DEFAULT_ppp=y CONFIG_DEFAULT_ppp-mod-pppoe=y CONFIG_DEFAULT_swconfig=y CONFIG_DEFAULT_uci=y CONFIG_DEFAULT_ucitrigger=y CONFIG_DEFAULT_udevtrigger=y CONFIG_LINUX_2_6=y CONFIG_GPIO_SUPPORT=y CONFIG_PCI_SUPPORT=y CONFIG_BIG_ENDIAN=y CONFIG_USES_SQUASHFS=y CONFIG_USES_JFFS2=y CONFIG_mips=y CONFIG_ARCH="mips" # # Target Images # # CONFIG_TARGET_ROOTFS_INITRAMFS is not set # CONFIG_TARGET_ROOTFS_JFFS2 is not set CONFIG_TARGET_ROOTFS_SQUASHFS=y # CONFIG_TARGET_ROOTFS_TGZ is not set # CONFIG_TARGET_ROOTFS_CPIOGZ is not set # CONFIG_TARGET_ROOTFS_EXT2FS is not set # # Image Options # CONFIG_OLPC_BOOTSCRIPT_ROOTPART="/dev/sda2" CONFIG_X86_GRUB_ROOTPART="/dev/sda2" CONFIG_X86_GRUB_BOOTOPTS="" # # Global build settings # # CONFIG_ALL is not set # # General build options # # CONFIG_CLEAN_IPKG is not set # CONFIG_LARGEFILE is not set CONFIG_SHADOW_PASSWORDS=y # CONFIG_NO_STRIP is not set # CONFIG_USE_STRIP is not set CONFIG_USE_SSTRIP=y # CONFIG_USE_MKLIBS is not set # CONFIG_STRIP_KERNEL_EXPORTS is not set # # Package build options # # CONFIG_DEBUG is not set # CONFIG_DEBUG_DIR is not set # CONFIG_IPV6 is not set # # Kernel build options # # CONFIG_KERNEL_KALLSYMS is not set # CONFIG_KERNEL_PROFILING is not set # CONFIG_KERNEL_DEBUG_FS is not set # CONFIG_DEVEL is not set # CONFIG_BROKEN is not set CONFIG_DOWNLOAD_FOLDER="" CONFIG_AUTOREBUILD=y CONFIG_BUILD_SUFFIX="" CONFIG_TARGET_ROOTFS_DIR="" # CONFIG_CCACHE is not set CONFIG_EXTERNAL_KERNEL_TREE="" CONFIG_KERNEL_GIT_CLONE_URI="" CONFIG_KERNEL_GIT_LOCAL_REPOSITORY="" CONFIG_TARGET_OPTIMIZATION="-Os -pipe -mips32 -mtune=mips32 -funit-at-a-time" CONFIG_SOFT_FLOAT=y # CONFIG_EXTRA_TARGET_ARCH is not set CONFIG_EXTRA_BINUTILS_CONFIG_OPTIONS="" CONFIG_BINUTILS_VERSION="2.19.1" CONFIG_GCC_VERSION_4_3_3_CS=y CONFIG_EXTRA_GCC_CONFIG_OPTIONS="" # CONFIG_SSP_SUPPORT is not set CONFIG_INSTALL_LIBSTDCPP=y # CONFIG_INSTALL_LIBGCJ is not set CONFIG_USE_UCLIBC=y # CONFIG_GDB is not set # CONFIG_INSIGHT is not set CONFIG_GCC_VERSION="4.3.3+cs" CONFIG_GCC_VERSION_4=y CONFIG_GCC_VERSION_4_3=y CONFIG_UCLIBC_VERSION="0.9.30.1" CONFIG_LIBC="uClibc" CONFIG_LIBC_VERSION="0.9.30.1" CONFIG_TARGET_SUFFIX="uclibc" # CONFIG_IB is not set # CONFIG_SDK is not set # CONFIG_UCI_PRECONFIG is not set CONFIG_UCI_PRECONFIG_network_lan_dns="" CONFIG_UCI_PRECONFIG_network_lan_proto="static" CONFIG_UCI_PRECONFIG_network_lan_gateway="" CONFIG_UCI_PRECONFIG_network_lan_netmask="255.255.255.0" CONFIG_UCI_PRECONFIG_network_lan_ipaddr="192.168.1.1" # # Base system # CONFIG_PACKAGE_base-files=y # CONFIG_PACKAGE_br2684ctl is not set CONFIG_PACKAGE_bridge=y CONFIG_PACKAGE_busybox=y # # Configuration # # CONFIG_BUSYBOX_CONFIG_FEATURE_DEVFS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_2_4_MODULES is not set CONFIG_BUSYBOX_CONFIG_FEATURE_2_6_MODULES=y # CONFIG_BUSYBOX_CONFIG_NOMMU is not set # CONFIG_CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH is not set # CONFIG_BUSYBOX_CONFIG_HUSH is not set CONFIG_BUSYBOX_CONFIG_HAVE_DOT_CONFIG=y # # Busybox Settings # # # General Configuration # # CONFIG_BUSYBOX_CONFIG_DESKTOP is not set # CONFIG_BUSYBOX_CONFIG_EXTRA_COMPAT is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_ASSUME_UNICODE is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set CONFIG_BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y # CONFIG_BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set CONFIG_BUSYBOX_CONFIG_SHOW_USAGE=y CONFIG_BUSYBOX_CONFIG_FEATURE_VERBOSE_USAGE=y CONFIG_BUSYBOX_CONFIG_FEATURE_COMPRESS_USAGE=y # CONFIG_BUSYBOX_CONFIG_FEATURE_INSTALLER is not set # CONFIG_BUSYBOX_CONFIG_LOCALE_SUPPORT is not set CONFIG_BUSYBOX_CONFIG_GETOPT_LONG=y CONFIG_BUSYBOX_CONFIG_FEATURE_DEVPTS=y # CONFIG_BUSYBOX_CONFIG_FEATURE_CLEAN_UP is not set CONFIG_BUSYBOX_CONFIG_FEATURE_PIDFILE=y CONFIG_BUSYBOX_CONFIG_FEATURE_SUID=y # CONFIG_BUSYBOX_CONFIG_FEATURE_SUID_CONFIG is not set # CONFIG_BUSYBOX_CONFIG_SELINUX is not set CONFIG_BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS=y CONFIG_BUSYBOX_CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG=y CONFIG_BUSYBOX_CONFIG_FEATURE_HAVE_RPC=y # # Build Options # # CONFIG_BUSYBOX_CONFIG_STATIC is not set # CONFIG_BUSYBOX_CONFIG_PIE is not set CONFIG_BUSYBOX_CONFIG_LFS=y CONFIG_BUSYBOX_CONFIG_CROSS_COMPILER_PREFIX="" CONFIG_BUSYBOX_CONFIG_EXTRA_CFLAGS="" # # Debugging Options # # CONFIG_BUSYBOX_CONFIG_DEBUG is not set # CONFIG_BUSYBOX_CONFIG_WERROR is not set CONFIG_BUSYBOX_CONFIG_NO_DEBUG_LIB=y # CONFIG_BUSYBOX_CONFIG_DMALLOC is not set # CONFIG_BUSYBOX_CONFIG_EFENCE is not set CONFIG_BUSYBOX_CONFIG_INCLUDE_SUSv2=y # # Installation Options # # CONFIG_BUSYBOX_CONFIG_INSTALL_NO_USR is not set CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_SYMLINKS=y # CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_HARDLINKS is not set # CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set # CONFIG_BUSYBOX_CONFIG_INSTALL_APPLET_DONT is not set CONFIG_BUSYBOX_CONFIG_PREFIX="./_install" # # Busybox Library Tuning # CONFIG_BUSYBOX_CONFIG_PASSWORD_MINLEN=6 CONFIG_BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED=2 CONFIG_BUSYBOX_CONFIG_FEATURE_FAST_TOP=y # CONFIG_BUSYBOX_CONFIG_FEATURE_ETC_NETWORKS is not set CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING=y CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_MAX_LEN=512 # CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_VI is not set CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_HISTORY=256 # CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_SAVEHISTORY is not set CONFIG_BUSYBOX_CONFIG_FEATURE_TAB_COMPLETION=y # CONFIG_BUSYBOX_CONFIG_FEATURE_USERNAME_COMPLETION is not set CONFIG_BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT=y # CONFIG_BUSYBOX_CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set CONFIG_BUSYBOX_CONFIG_FEATURE_COPYBUF_KB=4 # CONFIG_BUSYBOX_CONFIG_MONOTONIC_SYSCALL is not set CONFIG_BUSYBOX_CONFIG_IOCTL_HEX2STR_ERROR=y # CONFIG_BUSYBOX_CONFIG_FEATURE_HWIB is not set # # Applets # # # Archival Utilities # # CONFIG_BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2 is not set CONFIG_BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ=y # CONFIG_BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z is not set # CONFIG_BUSYBOX_CONFIG_AR is not set # CONFIG_BUSYBOX_CONFIG_BUNZIP2 is not set # CONFIG_BUSYBOX_CONFIG_BZIP2 is not set # CONFIG_BUSYBOX_CONFIG_CPIO is not set # CONFIG_BUSYBOX_CONFIG_DPKG is not set # CONFIG_BUSYBOX_CONFIG_DPKG_DEB is not set # CONFIG_BUSYBOX_CONFIG_GUNZIP is not set CONFIG_BUSYBOX_CONFIG_GZIP=y # CONFIG_BUSYBOX_CONFIG_RPM2CPIO is not set # CONFIG_BUSYBOX_CONFIG_RPM is not set CONFIG_BUSYBOX_CONFIG_TAR=y CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_CREATE=y # CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_AUTODETECT is not set CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_FROM=y # CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y # CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_TAR_UNAME_GNAME is not set # CONFIG_BUSYBOX_CONFIG_UNCOMPRESS is not set # CONFIG_BUSYBOX_CONFIG_UNLZMA is not set # CONFIG_BUSYBOX_CONFIG_UNZIP is not set # # Coreutils # CONFIG_BUSYBOX_CONFIG_BASENAME=y # CONFIG_BUSYBOX_CONFIG_CAL is not set CONFIG_BUSYBOX_CONFIG_CAT=y # CONFIG_BUSYBOX_CONFIG_CATV is not set CONFIG_BUSYBOX_CONFIG_CHGRP=y CONFIG_BUSYBOX_CONFIG_CHMOD=y CONFIG_BUSYBOX_CONFIG_CHOWN=y CONFIG_BUSYBOX_CONFIG_CHROOT=y # CONFIG_BUSYBOX_CONFIG_CKSUM is not set # CONFIG_BUSYBOX_CONFIG_COMM is not set CONFIG_BUSYBOX_CONFIG_CP=y CONFIG_BUSYBOX_CONFIG_CUT=y CONFIG_BUSYBOX_CONFIG_DATE=y CONFIG_BUSYBOX_CONFIG_FEATURE_DATE_ISOFMT=y CONFIG_BUSYBOX_CONFIG_DD=y CONFIG_BUSYBOX_CONFIG_FEATURE_DD_SIGNAL_HANDLING=y # CONFIG_BUSYBOX_CONFIG_FEATURE_DD_IBS_OBS is not set CONFIG_BUSYBOX_CONFIG_DF=y # CONFIG_BUSYBOX_CONFIG_FEATURE_DF_FANCY is not set CONFIG_BUSYBOX_CONFIG_DIRNAME=y # CONFIG_BUSYBOX_CONFIG_DOS2UNIX is not set CONFIG_BUSYBOX_CONFIG_DU=y CONFIG_BUSYBOX_CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y CONFIG_BUSYBOX_CONFIG_ECHO=y CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_ECHO=y CONFIG_BUSYBOX_CONFIG_ENV=y # CONFIG_BUSYBOX_CONFIG_FEATURE_ENV_LONG_OPTIONS is not set # CONFIG_BUSYBOX_CONFIG_EXPAND is not set CONFIG_BUSYBOX_CONFIG_EXPR=y # CONFIG_BUSYBOX_CONFIG_EXPR_MATH_SUPPORT_64 is not set CONFIG_BUSYBOX_CONFIG_FALSE=y # CONFIG_BUSYBOX_CONFIG_FOLD is not set CONFIG_BUSYBOX_CONFIG_HEAD=y CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_HEAD=y CONFIG_BUSYBOX_CONFIG_HOSTID=y CONFIG_BUSYBOX_CONFIG_ID=y # CONFIG_BUSYBOX_CONFIG_INSTALL is not set CONFIG_BUSYBOX_CONFIG_LENGTH=y CONFIG_BUSYBOX_CONFIG_LN=y # CONFIG_BUSYBOX_CONFIG_LOGNAME is not set CONFIG_BUSYBOX_CONFIG_LS=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_FILETYPES=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_FOLLOWLINKS=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_RECURSIVE=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_SORTFILES=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_TIMESTAMPS=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_USERNAME=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_COLOR=y CONFIG_BUSYBOX_CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y CONFIG_BUSYBOX_CONFIG_MD5SUM=y CONFIG_BUSYBOX_CONFIG_MKDIR=y # CONFIG_BUSYBOX_CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set CONFIG_BUSYBOX_CONFIG_MKFIFO=y CONFIG_BUSYBOX_CONFIG_MKNOD=y CONFIG_BUSYBOX_CONFIG_MV=y # CONFIG_BUSYBOX_CONFIG_FEATURE_MV_LONG_OPTIONS is not set CONFIG_BUSYBOX_CONFIG_NICE=y CONFIG_BUSYBOX_CONFIG_NOHUP=y # CONFIG_BUSYBOX_CONFIG_OD is not set # CONFIG_BUSYBOX_CONFIG_PRINTENV is not set CONFIG_BUSYBOX_CONFIG_PRINTF=y CONFIG_BUSYBOX_CONFIG_PWD=y # CONFIG_BUSYBOX_CONFIG_READLINK is not set # CONFIG_BUSYBOX_CONFIG_REALPATH is not set CONFIG_BUSYBOX_CONFIG_RM=y CONFIG_BUSYBOX_CONFIG_RMDIR=y # CONFIG_BUSYBOX_CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set CONFIG_BUSYBOX_CONFIG_SEQ=y # CONFIG_BUSYBOX_CONFIG_SHA1SUM is not set # CONFIG_BUSYBOX_CONFIG_SHA256SUM is not set # CONFIG_BUSYBOX_CONFIG_SHA512SUM is not set CONFIG_BUSYBOX_CONFIG_SLEEP=y CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_SLEEP=y # CONFIG_BUSYBOX_CONFIG_FEATURE_FLOAT_SLEEP is not set CONFIG_BUSYBOX_CONFIG_SORT=y # CONFIG_BUSYBOX_CONFIG_FEATURE_SORT_BIG is not set # CONFIG_BUSYBOX_CONFIG_SPLIT is not set # CONFIG_BUSYBOX_CONFIG_STAT is not set # CONFIG_BUSYBOX_CONFIG_STTY is not set # CONFIG_BUSYBOX_CONFIG_SUM is not set CONFIG_BUSYBOX_CONFIG_SYNC=y # CONFIG_BUSYBOX_CONFIG_TAC is not set CONFIG_BUSYBOX_CONFIG_TAIL=y CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_TAIL=y CONFIG_BUSYBOX_CONFIG_TEE=y CONFIG_BUSYBOX_CONFIG_FEATURE_TEE_USE_BLOCK_IO=y CONFIG_BUSYBOX_CONFIG_TEST=y # CONFIG_BUSYBOX_CONFIG_FEATURE_TEST_64 is not set CONFIG_BUSYBOX_CONFIG_TOUCH=y CONFIG_BUSYBOX_CONFIG_TR=y # CONFIG_BUSYBOX_CONFIG_FEATURE_TR_CLASSES is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_TR_EQUIV is not set CONFIG_BUSYBOX_CONFIG_TRUE=y # CONFIG_BUSYBOX_CONFIG_TTY is not set CONFIG_BUSYBOX_CONFIG_UNAME=y # CONFIG_BUSYBOX_CONFIG_UNEXPAND is not set CONFIG_BUSYBOX_CONFIG_UNIQ=y CONFIG_BUSYBOX_CONFIG_USLEEP=y # CONFIG_BUSYBOX_CONFIG_UUDECODE is not set # CONFIG_BUSYBOX_CONFIG_UUENCODE is not set CONFIG_BUSYBOX_CONFIG_WC=y # CONFIG_BUSYBOX_CONFIG_FEATURE_WC_LARGE is not set # CONFIG_BUSYBOX_CONFIG_WHO is not set # CONFIG_BUSYBOX_CONFIG_WHOAMI is not set CONFIG_BUSYBOX_CONFIG_YES=y # # Common options for cp and mv # CONFIG_BUSYBOX_CONFIG_FEATURE_PRESERVE_HARDLINKS=y # # Common options for ls, more and telnet # CONFIG_BUSYBOX_CONFIG_FEATURE_AUTOWIDTH=y # # Common options for df, du, ls # CONFIG_BUSYBOX_CONFIG_FEATURE_HUMAN_READABLE=y # # Common options for md5sum, sha1sum # CONFIG_BUSYBOX_CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y # # Console Utilities # # CONFIG_BUSYBOX_CONFIG_CHVT is not set CONFIG_BUSYBOX_CONFIG_CLEAR=y # CONFIG_BUSYBOX_CONFIG_DEALLOCVT is not set # CONFIG_BUSYBOX_CONFIG_DUMPKMAP is not set # CONFIG_BUSYBOX_CONFIG_KBD_MODE is not set # CONFIG_BUSYBOX_CONFIG_LOADFONT is not set # CONFIG_BUSYBOX_CONFIG_LOADKMAP is not set # CONFIG_BUSYBOX_CONFIG_OPENVT is not set CONFIG_BUSYBOX_CONFIG_RESET=y # CONFIG_BUSYBOX_CONFIG_RESIZE is not set # CONFIG_BUSYBOX_CONFIG_SETCONSOLE is not set # CONFIG_BUSYBOX_CONFIG_SETFONT is not set # CONFIG_BUSYBOX_CONFIG_SETKEYCODES is not set # CONFIG_BUSYBOX_CONFIG_SETLOGCONS is not set # CONFIG_BUSYBOX_CONFIG_SHOWKEY is not set # # Debian Utilities # CONFIG_BUSYBOX_CONFIG_MKTEMP=y # CONFIG_BUSYBOX_CONFIG_PIPE_PROGRESS is not set # CONFIG_BUSYBOX_CONFIG_RUN_PARTS is not set CONFIG_BUSYBOX_CONFIG_START_STOP_DAEMON=y # CONFIG_BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set CONFIG_BUSYBOX_CONFIG_WHICH=y # # Editors # CONFIG_BUSYBOX_CONFIG_AWK=y CONFIG_BUSYBOX_CONFIG_FEATURE_AWK_LIBM=y # CONFIG_BUSYBOX_CONFIG_CMP is not set # CONFIG_BUSYBOX_CONFIG_DIFF is not set # CONFIG_BUSYBOX_CONFIG_ED is not set # CONFIG_BUSYBOX_CONFIG_PATCH is not set CONFIG_BUSYBOX_CONFIG_SED=y CONFIG_BUSYBOX_CONFIG_VI=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_MAX_LEN=1024 CONFIG_BUSYBOX_CONFIG_FEATURE_VI_8BIT=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_COLON=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_YANKMARK=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SEARCH=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_USE_SIGNALS=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_DOT_CMD=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_READONLY=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SETOPTS=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_SET=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_WIN_RESIZE=y CONFIG_BUSYBOX_CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y CONFIG_BUSYBOX_CONFIG_FEATURE_ALLOW_EXEC=y # # Finding Utilities # CONFIG_BUSYBOX_CONFIG_FIND=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PRINT0=y # CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MTIME is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MMIN is not set CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PERM=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_TYPE=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_XDEV=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_MAXDEPTH=y # CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_NEWER is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_INUM is not set CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_EXEC=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_USER=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_GROUP=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_NOT=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_DEPTH=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PAREN=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_SIZE=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PRUNE=y # CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_DELETE is not set CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_PATH=y CONFIG_BUSYBOX_CONFIG_FEATURE_FIND_REGEX=y CONFIG_BUSYBOX_CONFIG_GREP=y CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_EGREP_ALIAS=y CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_FGREP_ALIAS=y CONFIG_BUSYBOX_CONFIG_FEATURE_GREP_CONTEXT=y CONFIG_BUSYBOX_CONFIG_XARGS=y CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y CONFIG_BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y # # Init Utilities # CONFIG_BUSYBOX_CONFIG_INIT=y CONFIG_BUSYBOX_CONFIG_FEATURE_USE_INITTAB=y # CONFIG_BUSYBOX_CONFIG_FEATURE_KILL_REMOVED is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_SCTTY is not set CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_SYSLOG=y # CONFIG_BUSYBOX_CONFIG_FEATURE_EXTRA_QUIET is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_INIT_COREDUMPS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_INITRD is not set CONFIG_BUSYBOX_CONFIG_HALT=y CONFIG_BUSYBOX_CONFIG_MESG=y # # Login/Password Management Utilities # # CONFIG_BUSYBOX_CONFIG_FEATURE_SHADOWPASSWDS is not set # CONFIG_BUSYBOX_CONFIG_USE_BB_PWD_GRP is not set # CONFIG_BUSYBOX_CONFIG_USE_BB_CRYPT is not set # CONFIG_BUSYBOX_CONFIG_ADDGROUP is not set # CONFIG_BUSYBOX_CONFIG_DELGROUP is not set # CONFIG_BUSYBOX_CONFIG_ADDUSER is not set # CONFIG_BUSYBOX_CONFIG_DELUSER is not set # CONFIG_BUSYBOX_CONFIG_GETTY is not set # CONFIG_BUSYBOX_CONFIG_LOGIN is not set CONFIG_BUSYBOX_CONFIG_PASSWD=y CONFIG_BUSYBOX_CONFIG_FEATURE_PASSWD_WEAK_CHECK=y # CONFIG_BUSYBOX_CONFIG_CRYPTPW is not set # CONFIG_BUSYBOX_CONFIG_CHPASSWD is not set # CONFIG_BUSYBOX_CONFIG_SU is not set # CONFIG_BUSYBOX_CONFIG_SULOGIN is not set # CONFIG_BUSYBOX_CONFIG_VLOCK is not set # # Linux Ext2 FS Progs # # CONFIG_BUSYBOX_CONFIG_CHATTR is not set # CONFIG_BUSYBOX_CONFIG_FSCK is not set # CONFIG_BUSYBOX_CONFIG_LSATTR is not set # # Linux Module Utilities # # CONFIG_BUSYBOX_CONFIG_MODPROBE_SMALL is not set CONFIG_BUSYBOX_CONFIG_INSMOD=y CONFIG_BUSYBOX_CONFIG_RMMOD=y CONFIG_BUSYBOX_CONFIG_LSMOD=y CONFIG_BUSYBOX_CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y # CONFIG_BUSYBOX_CONFIG_MODPROBE is not set # CONFIG_BUSYBOX_CONFIG_DEPMOD is not set # # Options common to multiple modutils # CONFIG_BUSYBOX_CONFIG_FEATURE_CHECK_TAINTED_MODULE=y CONFIG_BUSYBOX_CONFIG_DEFAULT_MODULES_DIR="/lib/modules" # # Linux System Utilities # # CONFIG_BUSYBOX_CONFIG_ACPID is not set # CONFIG_BUSYBOX_CONFIG_BLKID is not set CONFIG_BUSYBOX_CONFIG_DMESG=y CONFIG_BUSYBOX_CONFIG_FEATURE_DMESG_PRETTY=y # CONFIG_BUSYBOX_CONFIG_FBSET is not set # CONFIG_BUSYBOX_CONFIG_FDFLUSH is not set # CONFIG_BUSYBOX_CONFIG_FDFORMAT is not set # CONFIG_BUSYBOX_CONFIG_FDISK is not set CONFIG_BUSYBOX_CONFIG_FDISK_SUPPORT_LARGE_DISKS=y # CONFIG_BUSYBOX_CONFIG_FINDFS is not set # CONFIG_BUSYBOX_CONFIG_FREERAMDISK is not set # CONFIG_BUSYBOX_CONFIG_FSCK_MINIX is not set # CONFIG_BUSYBOX_CONFIG_MKFS_MINIX is not set # CONFIG_BUSYBOX_CONFIG_MKFS_VFAT is not set # CONFIG_BUSYBOX_CONFIG_GETOPT is not set CONFIG_BUSYBOX_CONFIG_HEXDUMP=y # CONFIG_BUSYBOX_CONFIG_FEATURE_HEXDUMP_REVERSE is not set # CONFIG_BUSYBOX_CONFIG_HD is not set CONFIG_BUSYBOX_CONFIG_HWCLOCK=y # CONFIG_BUSYBOX_CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set # CONFIG_BUSYBOX_CONFIG_IPCRM is not set # CONFIG_BUSYBOX_CONFIG_IPCS is not set # CONFIG_BUSYBOX_CONFIG_LOSETUP is not set # CONFIG_BUSYBOX_CONFIG_MDEV is not set # CONFIG_BUSYBOX_CONFIG_MKSWAP is not set # CONFIG_BUSYBOX_CONFIG_MORE is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_USE_TERMIOS is not set # CONFIG_BUSYBOX_CONFIG_VOLUMEID is not set CONFIG_BUSYBOX_CONFIG_MOUNT=y # CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FAKE is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_VERBOSE is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_HELPERS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_LABEL is not set CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_NFS=y # CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_CIFS is not set CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FLAGS=y CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_FSTAB=y CONFIG_BUSYBOX_CONFIG_PIVOT_ROOT=y CONFIG_BUSYBOX_CONFIG_RDATE=y # CONFIG_BUSYBOX_CONFIG_RDEV is not set # CONFIG_BUSYBOX_CONFIG_READPROFILE is not set # CONFIG_BUSYBOX_CONFIG_RTCWAKE is not set # CONFIG_BUSYBOX_CONFIG_SCRIPT is not set # CONFIG_BUSYBOX_CONFIG_SETARCH is not set # CONFIG_BUSYBOX_CONFIG_SWAPONOFF is not set CONFIG_BUSYBOX_CONFIG_SWITCH_ROOT=y CONFIG_BUSYBOX_CONFIG_UMOUNT=y CONFIG_BUSYBOX_CONFIG_FEATURE_UMOUNT_ALL=y # # Common options for mount/umount # CONFIG_BUSYBOX_CONFIG_FEATURE_MOUNT_LOOP=y # CONFIG_BUSYBOX_CONFIG_FEATURE_MTAB_SUPPORT is not set # # Miscellaneous Utilities # # CONFIG_BUSYBOX_CONFIG_ADJTIMEX is not set # CONFIG_BUSYBOX_CONFIG_BBCONFIG is not set # CONFIG_BUSYBOX_CONFIG_CHAT is not set # CONFIG_BUSYBOX_CONFIG_CHRT is not set # CONFIG_BUSYBOX_CONFIG_CROND is not set # CONFIG_BUSYBOX_CONFIG_CRONTAB is not set # CONFIG_BUSYBOX_CONFIG_DC is not set # CONFIG_BUSYBOX_CONFIG_DEVFSD is not set # CONFIG_BUSYBOX_CONFIG_DEVMEM is not set # CONFIG_BUSYBOX_CONFIG_EJECT is not set # CONFIG_BUSYBOX_CONFIG_FBSPLASH is not set # CONFIG_BUSYBOX_CONFIG_FLASH_ERASEALL is not set # CONFIG_BUSYBOX_CONFIG_IONICE is not set # CONFIG_BUSYBOX_CONFIG_INOTIFYD is not set # CONFIG_BUSYBOX_CONFIG_LAST is not set CONFIG_BUSYBOX_CONFIG_LESS=y CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_MAXLINES=9999999 # CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_BRACKETS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_FLAGS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_MARKS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_REGEXP is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_WINCH is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_LESS_DASHCMD is not set # CONFIG_BUSYBOX_CONFIG_HDPARM is not set CONFIG_BUSYBOX_CONFIG_LOCK=y # CONFIG_BUSYBOX_CONFIG_MAKEDEVS is not set # CONFIG_BUSYBOX_CONFIG_MAN is not set # CONFIG_BUSYBOX_CONFIG_MICROCOM is not set # CONFIG_BUSYBOX_CONFIG_MOUNTPOINT is not set # CONFIG_BUSYBOX_CONFIG_MT is not set # CONFIG_BUSYBOX_CONFIG_RAIDAUTORUN is not set # CONFIG_BUSYBOX_CONFIG_READAHEAD is not set # CONFIG_BUSYBOX_CONFIG_RUNLEVEL is not set # CONFIG_BUSYBOX_CONFIG_RX is not set # CONFIG_BUSYBOX_CONFIG_SETSID is not set CONFIG_BUSYBOX_CONFIG_STRINGS=y # CONFIG_BUSYBOX_CONFIG_TASKSET is not set CONFIG_BUSYBOX_CONFIG_TIME=y # CONFIG_BUSYBOX_CONFIG_TIMEOUT is not set # CONFIG_BUSYBOX_CONFIG_TTYSIZE is not set # CONFIG_BUSYBOX_CONFIG_WATCHDOG is not set # # Networking Utilities # CONFIG_BUSYBOX_CONFIG_FEATURE_IPV6=y # CONFIG_BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set CONFIG_BUSYBOX_CONFIG_VERBOSE_RESOLUTION_ERRORS=y # CONFIG_BUSYBOX_CONFIG_ARP is not set # CONFIG_BUSYBOX_CONFIG_ARPING is not set CONFIG_BUSYBOX_CONFIG_BRCTL=y CONFIG_BUSYBOX_CONFIG_FEATURE_BRCTL_FANCY=y CONFIG_BUSYBOX_CONFIG_FEATURE_BRCTL_SHOW=y # CONFIG_BUSYBOX_CONFIG_DNSD is not set # CONFIG_BUSYBOX_CONFIG_ETHER_WAKE is not set # CONFIG_BUSYBOX_CONFIG_FAKEIDENTD is not set # CONFIG_BUSYBOX_CONFIG_FTPD is not set # CONFIG_BUSYBOX_CONFIG_FTPGET is not set # CONFIG_BUSYBOX_CONFIG_FTPPUT is not set # CONFIG_BUSYBOX_CONFIG_HOSTNAME is not set # CONFIG_BUSYBOX_CONFIG_HTTPD is not set CONFIG_BUSYBOX_CONFIG_IFCONFIG=y CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_STATUS=y # CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_SLIP is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_HW=y CONFIG_BUSYBOX_CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y # CONFIG_BUSYBOX_CONFIG_IFENSLAVE is not set # CONFIG_BUSYBOX_CONFIG_IFUPDOWN is not set # CONFIG_BUSYBOX_CONFIG_INETD is not set # CONFIG_BUSYBOX_CONFIG_IP is not set # CONFIG_BUSYBOX_CONFIG_IPCALC is not set # CONFIG_BUSYBOX_CONFIG_NAMEIF is not set CONFIG_BUSYBOX_CONFIG_NC=y CONFIG_BUSYBOX_CONFIG_NETMSG=y # CONFIG_BUSYBOX_CONFIG_NC_SERVER is not set # CONFIG_BUSYBOX_CONFIG_NC_EXTRA is not set CONFIG_BUSYBOX_CONFIG_NETSTAT=y CONFIG_BUSYBOX_CONFIG_FEATURE_NETSTAT_WIDE=y CONFIG_BUSYBOX_CONFIG_FEATURE_NETSTAT_PRG=y CONFIG_BUSYBOX_CONFIG_NSLOOKUP=y CONFIG_BUSYBOX_CONFIG_PING=y # CONFIG_BUSYBOX_CONFIG_PING6 is not set CONFIG_BUSYBOX_CONFIG_FEATURE_FANCY_PING=y # CONFIG_BUSYBOX_CONFIG_PSCAN is not set CONFIG_BUSYBOX_CONFIG_ROUTE=y # CONFIG_BUSYBOX_CONFIG_SLATTACH is not set # CONFIG_BUSYBOX_CONFIG_TELNET is not set CONFIG_BUSYBOX_CONFIG_TELNETD=y CONFIG_BUSYBOX_CONFIG_FEATURE_TELNETD_STANDALONE=y # CONFIG_BUSYBOX_CONFIG_TFTP is not set # CONFIG_BUSYBOX_CONFIG_TFTPD is not set CONFIG_BUSYBOX_CONFIG_TRACEROUTE=y CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_VERBOSE=y # CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set # CONFIG_BUSYBOX_CONFIG_APP_UDHCPD is not set CONFIG_BUSYBOX_CONFIG_APP_UDHCPC=y # CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCPC_ARPING is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCP_PORT is not set # CONFIG_BUSYBOX_CONFIG_UDHCP_DEBUG is not set CONFIG_BUSYBOX_CONFIG_FEATURE_UDHCP_RFC3397=y CONFIG_BUSYBOX_CONFIG_UDHCPC_DEFAULT_SCRIPT="/usr/share/udhcpc/default.script" CONFIG_BUSYBOX_CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=80 CONFIG_BUSYBOX_CONFIG_VCONFIG=y # CONFIG_BUSYBOX_CONFIG_WGET is not set # CONFIG_BUSYBOX_CONFIG_ZCIP is not set # CONFIG_BUSYBOX_CONFIG_TCPSVD is not set # CONFIG_BUSYBOX_CONFIG_TUNCTL is not set # CONFIG_BUSYBOX_CONFIG_UDPSVD is not set # # Print Utilities # # CONFIG_BUSYBOX_CONFIG_LPD is not set # CONFIG_BUSYBOX_CONFIG_LPR is not set # CONFIG_BUSYBOX_CONFIG_LPQ is not set # # Mail Utilities # # CONFIG_BUSYBOX_CONFIG_MAKEMIME is not set # CONFIG_BUSYBOX_CONFIG_POPMAILDIR is not set # CONFIG_BUSYBOX_CONFIG_REFORMIME is not set # CONFIG_BUSYBOX_CONFIG_SENDMAIL is not set # # Process Utilities # CONFIG_BUSYBOX_CONFIG_FREE=y # CONFIG_BUSYBOX_CONFIG_FUSER is not set CONFIG_BUSYBOX_CONFIG_KILL=y CONFIG_BUSYBOX_CONFIG_KILLALL=y CONFIG_BUSYBOX_CONFIG_KILLALL5=y # CONFIG_BUSYBOX_CONFIG_NMETER is not set CONFIG_BUSYBOX_CONFIG_PGREP=y CONFIG_BUSYBOX_CONFIG_PIDOF=y # CONFIG_BUSYBOX_CONFIG_FEATURE_PIDOF_SINGLE is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_PIDOF_OMIT is not set CONFIG_BUSYBOX_CONFIG_PKILL=y CONFIG_BUSYBOX_CONFIG_PS=y # CONFIG_BUSYBOX_CONFIG_FEATURE_PS_WIDE is not set # CONFIG_BUSYBOX_CONFIG_RENICE is not set # CONFIG_BUSYBOX_CONFIG_BB_SYSCTL is not set CONFIG_BUSYBOX_CONFIG_TOP=y CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y # CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_SMP_CPU is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_DECIMALS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_TOP_SMP_PROCESS is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_TOPMEM is not set CONFIG_BUSYBOX_CONFIG_UPTIME=y # CONFIG_BUSYBOX_CONFIG_WATCH is not set # # Runit Utilities # # CONFIG_BUSYBOX_CONFIG_RUNSV is not set # CONFIG_BUSYBOX_CONFIG_RUNSVDIR is not set # CONFIG_BUSYBOX_CONFIG_SV is not set # CONFIG_BUSYBOX_CONFIG_SVLOGD is not set # CONFIG_BUSYBOX_CONFIG_CHPST is not set # CONFIG_BUSYBOX_CONFIG_SETUIDGID is not set # CONFIG_BUSYBOX_CONFIG_ENVUIDGID is not set # CONFIG_BUSYBOX_CONFIG_ENVDIR is not set # CONFIG_BUSYBOX_CONFIG_SOFTLIMIT is not set # # Shells # CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_ASH=y # CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_MSH is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_SH_IS_NONE is not set CONFIG_BUSYBOX_CONFIG_ASH=y # # Ash Shell Options # CONFIG_BUSYBOX_CONFIG_ASH_BASH_COMPAT=y CONFIG_BUSYBOX_CONFIG_ASH_JOB_CONTROL=y # CONFIG_BUSYBOX_CONFIG_ASH_READ_NCHARS is not set CONFIG_BUSYBOX_CONFIG_ASH_READ_TIMEOUT=y CONFIG_BUSYBOX_CONFIG_ASH_ALIAS=y CONFIG_BUSYBOX_CONFIG_ASH_GETOPTS=y CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_ECHO=y CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_PRINTF=y CONFIG_BUSYBOX_CONFIG_ASH_BUILTIN_TEST=y CONFIG_BUSYBOX_CONFIG_ASH_CMDCMD=y # CONFIG_BUSYBOX_CONFIG_ASH_MAIL is not set # CONFIG_BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set # CONFIG_BUSYBOX_CONFIG_ASH_RANDOM_SUPPORT is not set CONFIG_BUSYBOX_CONFIG_ASH_EXPAND_PRMT=y # CONFIG_BUSYBOX_CONFIG_LASH is not set # CONFIG_BUSYBOX_CONFIG_MSH is not set # # Bourne Shell Options # CONFIG_BUSYBOX_CONFIG_SH_MATH_SUPPORT=y CONFIG_BUSYBOX_CONFIG_SH_MATH_SUPPORT_64=y # CONFIG_BUSYBOX_CONFIG_FEATURE_SH_EXTRA_QUIET is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_SH_STANDALONE is not set # CONFIG_BUSYBOX_CONFIG_FEATURE_SH_NOFORK is not set # CONFIG_BUSYBOX_CONFIG_CTTYHACK is not set # # System Logging Utilities # # CONFIG_BUSYBOX_CONFIG_SYSLOGD is not set # CONFIG_BUSYBOX_CONFIG_KLOGD is not set # CONFIG_BUSYBOX_CONFIG_LOGGER is not set # CONFIG_PACKAGE_dnsmasq is not set # CONFIG_PACKAGE_dropbear is not set # CONFIG_PACKAGE_ead is not set CONFIG_PACKAGE_hotplug2=y # CONFIG_PACKAGE_iptables is not set CONFIG_PACKAGE_libc=y CONFIG_PACKAGE_libgcc=y # CONFIG_PACKAGE_libpthread is not set # CONFIG_PACKAGE_librt is not set # CONFIG_PACKAGE_libstdcpp is not set # CONFIG_PACKAGE_mtd is not set CONFIG_PACKAGE_opkg=y CONFIG_PACKAGE_swconfig=y CONFIG_PACKAGE_uci=y # CONFIG_PACKAGE_ucitrigger is not set # CONFIG_PACKAGE_udev is not set CONFIG_PACKAGE_udevtrigger=y # CONFIG_PACKAGE_wireless-tools is not set # # Libraries # # # Filesystem # # CONFIG_PACKAGE_libblkid is not set # CONFIG_PACKAGE_libext2fs is not set # CONFIG_PACKAGE_libfuse is not set # CONFIG_PACKAGE_libuuid is not set # # SSL # # CONFIG_PACKAGE_libopenssl is not set # CONFIG_PACKAGE_libdaemon is not set # CONFIG_PACKAGE_libiptc is not set # CONFIG_PACKAGE_libiw is not set # CONFIG_PACKAGE_libltdl is not set # CONFIG_PACKAGE_liblua is not set # CONFIG_PACKAGE_liblzo is not set # CONFIG_PACKAGE_libncurses is not set # CONFIG_PACKAGE_libnl is not set CONFIG_PACKAGE_libnl-tiny=y CONFIG_PACKAGE_libpcap=y # CONFIG_PACKAGE_libpopt is not set # CONFIG_PACKAGE_libreadline is not set CONFIG_PACKAGE_libuci=y # CONFIG_PACKAGE_libuci-lua is not set # CONFIG_PACKAGE_libxtables is not set # CONFIG_PACKAGE_linux-atm is not set # CONFIG_PACKAGE_zlib is not set # # Network # # # VPN # # CONFIG_PACKAGE_tinc is not set # CONFIG_PACKAGE_arptables is not set # CONFIG_PACKAGE_crda is not set # CONFIG_PACKAGE_ebtables is not set # CONFIG_PACKAGE_ebtables-utils is not set # CONFIG_PACKAGE_genl is not set # CONFIG_PACKAGE_hostapd is not set # CONFIG_PACKAGE_hostapd-mini is not set # CONFIG_PACKAGE_ifenslave is not set # CONFIG_PACKAGE_ifplugd is not set CONFIG_PACKAGE_ip=y # CONFIG_PACKAGE_iw is not set # CONFIG_PACKAGE_mini-snmpd is not set # CONFIG_PACKAGE_ppp is not set # CONFIG_PACKAGE_pptp is not set # CONFIG_PACKAGE_tc is not set # CONFIG_PACKAGE_tcpdump is not set # CONFIG_PACKAGE_tkx is not set # CONFIG_PACKAGE_wpa-supplicant is not set # CONFIG_PACKAGE_wprobe-export is not set # CONFIG_PACKAGE_wprobe-util is not set # # IPv6 # # CONFIG_PACKAGE_ip6tables is not set # CONFIG_PACKAGE_radvd is not set # # Kernel modules # # # Block Devices # # CONFIG_PACKAGE_kmod-aoe is not set # CONFIG_PACKAGE_kmod-ata-core is not set # CONFIG_PACKAGE_kmod-ide-aec62xx is not set # CONFIG_PACKAGE_kmod-ide-core is not set # CONFIG_PACKAGE_kmod-ide-it821x is not set # CONFIG_PACKAGE_kmod-ide-pdc202xx is not set # CONFIG_PACKAGE_kmod-loop is not set # CONFIG_PACKAGE_kmod-nbd is not set # CONFIG_PACKAGE_kmod-scsi-core is not set # CONFIG_PACKAGE_kmod-scsi-generic is not set # # Cryptographic API modules # # CONFIG_PACKAGE_kmod-crypto-aes is not set # CONFIG_PACKAGE_kmod-crypto-arc4 is not set # CONFIG_PACKAGE_kmod-crypto-authenc is not set # CONFIG_PACKAGE_kmod-crypto-core is not set # CONFIG_PACKAGE_kmod-crypto-des is not set # CONFIG_PACKAGE_kmod-crypto-hmac is not set # CONFIG_PACKAGE_kmod-crypto-hw-geode is not set # CONFIG_PACKAGE_kmod-crypto-hw-hifn-795x is not set # CONFIG_PACKAGE_kmod-crypto-hw-padlock is not set # CONFIG_PACKAGE_kmod-crypto-md5 is not set # CONFIG_PACKAGE_kmod-crypto-michael-mic is not set # CONFIG_PACKAGE_kmod-crypto-misc is not set # CONFIG_PACKAGE_kmod-crypto-null is not set # CONFIG_PACKAGE_kmod-crypto-ocf is not set # CONFIG_PACKAGE_kmod-crypto-sha1 is not set # CONFIG_PACKAGE_kmod-crypto-test is not set # # Filesystems # # CONFIG_PACKAGE_kmod-fs-autofs4 is not set # CONFIG_PACKAGE_kmod-fs-btrfs is not set # CONFIG_PACKAGE_kmod-fs-cifs is not set CONFIG_PACKAGE_kmod-fs-exportfs=y # CONFIG_PACKAGE_kmod-fs-ext2 is not set # CONFIG_PACKAGE_kmod-fs-ext3 is not set # CONFIG_PACKAGE_kmod-fs-ext4 is not set # CONFIG_PACKAGE_kmod-fs-hfs is not set # CONFIG_PACKAGE_kmod-fs-hfsplus is not set # CONFIG_PACKAGE_kmod-fs-isofs is not set # CONFIG_PACKAGE_kmod-fs-mbcache is not set # CONFIG_PACKAGE_kmod-fs-minix is not set # CONFIG_PACKAGE_kmod-fs-msdos is not set CONFIG_PACKAGE_kmod-fs-nfs=y CONFIG_PACKAGE_kmod-fs-nfs-common=y # CONFIG_PACKAGE_kmod-fs-nfsd is not set # CONFIG_PACKAGE_kmod-fs-ntfs is not set # CONFIG_PACKAGE_kmod-fs-reiserfs is not set # CONFIG_PACKAGE_kmod-fs-udf is not set # CONFIG_PACKAGE_kmod-fs-vfat is not set # CONFIG_PACKAGE_kmod-fs-xfs is not set # CONFIG_PACKAGE_kmod-fuse is not set # CONFIG_PACKAGE_kmod-nls-base is not set # CONFIG_PACKAGE_kmod-nls-cp1250 is not set # CONFIG_PACKAGE_kmod-nls-cp1251 is not set # CONFIG_PACKAGE_kmod-nls-cp437 is not set # CONFIG_PACKAGE_kmod-nls-cp775 is not set # CONFIG_PACKAGE_kmod-nls-cp850 is not set # CONFIG_PACKAGE_kmod-nls-cp852 is not set # CONFIG_PACKAGE_kmod-nls-iso8859-1 is not set # CONFIG_PACKAGE_kmod-nls-iso8859-13 is not set # CONFIG_PACKAGE_kmod-nls-iso8859-15 is not set # CONFIG_PACKAGE_kmod-nls-iso8859-2 is not set # CONFIG_PACKAGE_kmod-nls-koi8r is not set # CONFIG_PACKAGE_kmod-nls-utf8 is not set # # FireWire support # # CONFIG_PACKAGE_kmod-ieee1394 is not set # # Hardware Monitoring Support # # CONFIG_PACKAGE_kmod-hwmon-core is not set # # I2C support # # CONFIG_PACKAGE_kmod-i2c-core is not set # CONFIG_PACKAGE_kmod-i2c-gpio-custom is not set # # Netfilter Extensions # # CONFIG_PACKAGE_kmod-arptables is not set # CONFIG_PACKAGE_kmod-ebtables is not set # CONFIG_PACKAGE_kmod-ip6tables is not set # CONFIG_PACKAGE_kmod-ipt-core is not set # CONFIG_PACKAGE_kmod-nf-conntrack-netlink is not set # CONFIG_PACKAGE_kmod-nfnetlink is not set # CONFIG_PACKAGE_kmod-nfnetlink-log is not set # CONFIG_PACKAGE_kmod-nfnetlink-queue is not set # # Network Devices # # CONFIG_PACKAGE_kmod-e1000 is not set # CONFIG_PACKAGE_kmod-hfcmulti is not set CONFIG_PACKAGE_kmod-libphy=y # CONFIG_PACKAGE_kmod-siit is not set # CONFIG_PACKAGE_kmod-tg3 is not set # # Network Support # # CONFIG_PACKAGE_kmod-atm is not set # CONFIG_PACKAGE_kmod-batman-adv-kernelland is not set # CONFIG_PACKAGE_kmod-bonding is not set # CONFIG_PACKAGE_kmod-capi is not set # CONFIG_PACKAGE_kmod-gre is not set # CONFIG_PACKAGE_kmod-ip6-tunnel is not set # CONFIG_PACKAGE_kmod-ipip is not set # CONFIG_PACKAGE_kmod-ipsec is not set # CONFIG_PACKAGE_kmod-iptunnel4 is not set # CONFIG_PACKAGE_kmod-iptunnel6 is not set # CONFIG_PACKAGE_kmod-ipv6 is not set # CONFIG_PACKAGE_kmod-isdn4linux is not set # CONFIG_PACKAGE_kmod-misdn is not set # CONFIG_PACKAGE_kmod-mp-alg is not set # CONFIG_PACKAGE_kmod-ppp is not set # CONFIG_PACKAGE_kmod-pktgen is not set # CONFIG_PACKAGE_kmod-sched is not set # CONFIG_PACKAGE_kmod-sit is not set # CONFIG_PACKAGE_kmod-tun is not set # CONFIG_PACKAGE_kmod-wprobe is not set # # OCF Configuration # # # Other modules # # CONFIG_PACKAGE_kmod-button-hotplug is not set # CONFIG_PACKAGE_kmod-crc-ccitt is not set # CONFIG_PACKAGE_kmod-crc-itu-t is not set # CONFIG_PACKAGE_kmod-crc16 is not set # CONFIG_PACKAGE_kmod-crc7 is not set # CONFIG_PACKAGE_kmod-eeprom-93cx6 is not set # CONFIG_PACKAGE_kmod-gpio-dev is not set # CONFIG_PACKAGE_kmod-hid is not set # CONFIG_PACKAGE_kmod-input-core is not set # CONFIG_PACKAGE_kmod-input-evdev is not set # CONFIG_PACKAGE_kmod-input-gpio-buttons is not set # CONFIG_PACKAGE_kmod-input-gpio-keys is not set # CONFIG_PACKAGE_kmod-input-joydev is not set # CONFIG_PACKAGE_kmod-input-polldev is not set # CONFIG_PACKAGE_kmod-leds-gpio is not set # CONFIG_PACKAGE_kmod-ledtrig-morse is not set # CONFIG_PACKAGE_kmod-ledtrig-netdev is not set # CONFIG_PACKAGE_kmod-mmc is not set # CONFIG_PACKAGE_kmod-mmc-over-gpio is not set # CONFIG_PACKAGE_kmod-pcspkr is not set # CONFIG_PACKAGE_kmod-softdog is not set # CONFIG_PACKAGE_kmod-ssb is not set # CONFIG_PACKAGE_kmod-textsearch is not set # CONFIG_PACKAGE_kmod-wrt55agv2-spidevs is not set # # SPI Support # # CONFIG_PACKAGE_kmod-mmc-spi is not set # CONFIG_PACKAGE_kmod-spi-bitbang is not set # CONFIG_PACKAGE_kmod-spi-dev is not set # CONFIG_PACKAGE_kmod-spi-gpio is not set # CONFIG_PACKAGE_kmod-spi-gpio-old is not set # CONFIG_PACKAGE_kmod-spi-ks8995 is not set # # Sound Support # # CONFIG_PACKAGE_kmod-sound-core is not set # # USB Support # # # Video Support # # CONFIG_PACKAGE_kmod-video-core is not set # # W1 support # # CONFIG_PACKAGE_kmod-w1 is not set # # Wireless Drivers # # CONFIG_PACKAGE_kmod-ath is not set # CONFIG_PACKAGE_kmod-ath5k is not set # CONFIG_PACKAGE_kmod-ath9k is not set # CONFIG_PACKAGE_kmod-b43 is not set # CONFIG_PACKAGE_kmod-b43legacy is not set # CONFIG_PACKAGE_kmod-hostap is not set # CONFIG_PACKAGE_kmod-lib80211 is not set # CONFIG_PACKAGE_kmod-mac80211 is not set # CONFIG_PACKAGE_kmod-mac80211-hwsim is not set # CONFIG_PACKAGE_kmod-madwifi is not set # CONFIG_PACKAGE_kmod-net-airo is not set # CONFIG_PACKAGE_kmod-net-hermes is not set # CONFIG_PACKAGE_kmod-net-hermes-pci is not set # CONFIG_PACKAGE_kmod-net-hermes-plx is not set # CONFIG_PACKAGE_kmod-net-ipw2100 is not set # CONFIG_PACKAGE_kmod-net-ipw2200 is not set # CONFIG_PACKAGE_kmod-net-libipw is not set # CONFIG_PACKAGE_kmod-net-prism54 is not set # CONFIG_PACKAGE_kmod-p54-common is not set # CONFIG_PACKAGE_kmod-p54-pci is not set # CONFIG_PACKAGE_kmod-rt2400-pci is not set # CONFIG_PACKAGE_kmod-rt2500-pci is not set # CONFIG_PACKAGE_kmod-rt2800-pci is not set # CONFIG_PACKAGE_kmod-rt2x00-lib is not set # CONFIG_PACKAGE_kmod-rt2x00-pci is not set # CONFIG_PACKAGE_kmod-rt61-pci is not set # CONFIG_PACKAGE_kmod-rtl8180 is not set # # Boot Loaders # # # Utilities # # # Filesystem # # CONFIG_PACKAGE_e2fsprogs is not set # CONFIG_PACKAGE_fuse-utils is not set # # disc # # CONFIG_PACKAGE_cfdisk is not set # CONFIG_PACKAGE_fdisk is not set # CONFIG_PACKAGE_swap-utils is not set CONFIG_PACKAGE_ap51-flash=y # CONFIG_PACKAGE_dropbearconvert is not set # CONFIG_PACKAGE_fconfig is not set # CONFIG_PACKAGE_flock is not set # CONFIG_PACKAGE_gdb is not set # CONFIG_PACKAGE_gdbserver is not set CONFIG_PACKAGE_gpioctl=y # CONFIG_PACKAGE_hwclock is not set # CONFIG_PACKAGE_kexec-tools is not set CONFIG_KEXEC_TOOLS_TARGET_NAME="mips" # CONFIG_PACKAGE_ldconfig is not set # CONFIG_PACKAGE_ldd is not set # CONFIG_PACKAGE_losetup is not set # CONFIG_PACKAGE_mount-utils is not set # CONFIG_PACKAGE_ocf-crypto-headers is not set # CONFIG_PACKAGE_openssl-util is not set # CONFIG_PACKAGE_robocfg is not set # CONFIG_PACKAGE_spidev-test is not set # # Development # # CONFIG_PACKAGE_binutils is not set # CONFIG_PACKAGE_objdump is not set # # Emulators # # # Languages # # # Lua # # CONFIG_PACKAGE_lua is not set # CONFIG_PACKAGE_luac is not set ap51-flash-2019.0.1/docs/flash-station/Makefile000066400000000000000000000022651353712067100207630ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing include $(TOPDIR)/rules.mk PKG_NAME:=ap51-flash PKG_REV:=93 PKG_VERSION:=r$(PKG_REV) PKG_RELEASE:=1 PKG_SOURCE_PROTO:=svn PKG_SOURCE_VERSION:=$(PKG_REV) PKG_SOURCE_SUBDIR:=ap51-flash-$(PKG_VERSION) PKG_SOURCE_URL:=http://dev.open-mesh.com/downloads/svn/ap51-flash/trunk PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk define Package/ap51-flash SECTION:=utils CATEGORY:=Utilities DEPENDS:=+libpcap TITLE:=A tool for flashing (nearly) all ap51/ap61 based routers URL:=http://dev.open-mesh.com endef define Package/ap51-flash/install $(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d $(1)/usr/sbin $(INSTALL_BIN) $(PKG_BUILD_DIR)/ap51-flash $(1)/usr/sbin/ $(INSTALL_BIN) ./files/ap51-flash.init $(1)/etc/init.d/ap51-flash $(INSTALL_DATA) ./files/ap51-flash.conf $(1)/etc/config/ap51-flash endef # install -m0755 -d $(1)/usr/sbin # install -m0755 $(PKG_BUILD_DIR)/ap51-flash $(1)/usr/sbin/ # install -m0755 $(PKG_BUILD_DIR)/src/ifplugd $(1)/usr/sbin/ $(eval $(call BuildPackage,ap51-flash)) ap51-flash-2019.0.1/docs/flash-station/ap51-flash.conf000066400000000000000000000005151353712067100220270ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing #config flash # option ifname eth0.1 # option rootfs /tmp/images/openwrt-atheros-root.squashfs # option kernel /tmp/images/openwrt-atheros-vmlinux.lzma ## option ubnt /tmp/images/openwrt-atheros-ubnt5-squashfs.bin ap51-flash-2019.0.1/docs/flash-station/ap51-flash.init000066400000000000000000000026731353712067100220540ustar00rootroot00000000000000#!/bin/sh /etc/rc.common # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing START=20 NAME=ap51-flash start_daemon() { local cfg="$1" config_get ifname "$cfg" ifname config_get rootfs "$cfg" rootfs config_get kernel "$cfg" kernel config_get ubntimg "$cfg" ubntimg if [ -n "$ifname" -a -n "$rootfs" -a -n "$kernel" ]; then [ -n "`ls /var/run/$NAME-$ifname.pid 2> /dev/null`" ] && { echo "Can't start more than one ap51-flash for interface $ifname!" return 0 } start-stop-daemon -S -b -m -p /var/run/$NAME-$ifname.pid -n $NAME -x /usr/sbin/$NAME -- $ifname $rootfs $kernel elif [ -n "$ifname" -a -n "$ubntimg" ]; then [ -n "`ls /var/run/$NAME-$ifname-ubnt.pid 2> /dev/null`" ] && { echo "Can't start more than one ap51-flash (ubnt) for interface $ifname!" return 0 } start-stop-daemon -S -b -m -p /var/run/$NAME-$ifname-ubnt.pid -n $NAME -x /usr/sbin/$NAME -- $ifname $ubntimg fi } start() { config_load ap51-flash config_foreach start_daemon flash } stop() { # Terminating all ap51-flash processes echo "WARNING: Going to teminate all ap51-flash processes! (hope you made sure that they're not flashing right now)" echo "OR you can stop this with Ctrl+c within 10 seconds" sleep 10 local pidfile for pidfile in `ls /var/run/${NAME}-*.pid 2> /dev/null`; do start-stop-daemon -K -s TERM -p "${pidfile}" -n "${NAME}" >/dev/null rm -f "${pidfile}" done } ap51-flash-2019.0.1/docs/flash-station/fstab000066400000000000000000000007321353712067100203420ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing config mount option target /home option device /dev/sda1 option fstype ext3 option options rw,sync option enabled 0 config swap option device /dev/sda2 option enabled 0 config mount option target /tmp/images option device 192.168.1.2:/srv/nfs/images option fstype nfs option options rsize=32768,wsize=32768,hard,udp,nolock option enabled 1 ap51-flash-2019.0.1/docs/flash-station/index.rst000066400000000000000000000021551353712067100211620ustar00rootroot00000000000000.. SPDX-License-Identifier: GPL-3.0-or-later .. SPDX-FileCopyrightText: 2013, Linus Lüssing ============================== ap51-flash station for OpenWRT ============================== OpenWRT-package =============== * :download:`Makefile` * files/:download:`ap51-flash.conf` * files/:download:`ap51-flash.init` Example configuration of a Dlink DIR-300 as a ap51-flash station ================================================================ * minimal :download:`.config`-file (kicking out a lot of the standard applications and modules to save as much RAM as possible and adding nfs-support for remote images) * /etc/config/:download:`network` (configuring ports 1-4 as seperate VLANS for flashing other devices and the WAN-port as the adminstration port) * /etc/:download:`fstab` (for mounting nfs-shares at boot time) Example image (using the same config as stated above): * http://x-realis.dyndns.org/Freifunk/firmware/ap51-flash-station/ 2-port-vlan without host learning (hub-mode, for debugging ap51-flash) * /etc/config/:download:`network2` * /etc/init.d/:download:`switch-2-hub` ap51-flash-2019.0.1/docs/flash-station/network000066400000000000000000000023501353712067100207320ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing config 'interface' 'loopback' option 'ifname' 'lo' option 'proto' 'static' option 'ipaddr' '127.0.0.1' option 'netmask' '255.0.0.0' config 'interface' 'WAN' option 'ifname' 'eth0.5' option 'proto' 'static' option 'ipaddr' '192.168.1.1' option 'netmask' '255.255.255.0' config 'interface' 'LAN1' option 'ifname' 'eth0.4' option 'proto' 'none' config 'interface' 'LAN2' option 'ifname' 'eth0.3' option 'proto' 'none' config 'interface' 'LAN3' option 'ifname' 'eth0.2' option 'proto' 'none' config 'interface' 'LAN4' option 'ifname' 'eth0.1' option 'proto' 'none' config 'switch' 'eth0' option 'reset' '1' option 'enable_vlan' '1' config 'switch_vlan' 'eth0_1' option 'device' 'eth0' option 'vlan' '1' option 'ports' '0 5t' config 'switch_vlan' 'eth0_2' option 'device' 'eth0' option 'vlan' '2' option 'ports' '1 5t' config 'switch_vlan' 'eth0_3' option 'device' 'eth0' option 'vlan' '3' option 'ports' '2 5t' config 'switch_vlan' 'eth0_4' option 'device' 'eth0' option 'vlan' '4' option 'ports' '3 5t' config 'switch_vlan' 'eth0_5' option 'device' 'eth0' option 'vlan' '5' option 'ports' '4 5t' ap51-flash-2019.0.1/docs/flash-station/network2000066400000000000000000000020751353712067100210200ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing config 'interface' 'loopback' option 'ifname' 'lo' option 'proto' 'static' option 'ipaddr' '127.0.0.1' option 'netmask' '255.0.0.0' config 'interface' 'WAN' option 'ifname' 'eth0.4' option 'proto' 'static' option 'ipaddr' '192.168.1.1' option 'netmask' '255.255.255.0' config 'interface' 'LAN1' option 'ifname' 'eth0.3' option 'proto' 'none' config 'interface' 'LAN2' option 'ifname' 'eth0.2' option 'proto' 'none' config 'interface' 'LAN3' option 'ifname' 'eth0.1' option 'proto' 'none' config 'switch' 'eth0' option 'reset' '1' option 'enable_vlan' '1' config 'switch_vlan' 'eth0_1' option 'device' 'eth0' option 'vlan' '1' option 'ports' '0 1 5t' config 'switch_vlan' 'eth0_2' option 'device' 'eth0' option 'vlan' '2' option 'ports' '2 5t' config 'switch_vlan' 'eth0_3' option 'device' 'eth0' option 'vlan' '3' option 'ports' '3 5t' config 'switch_vlan' 'eth0_4' option 'device' 'eth0' option 'vlan' '4' option 'ports' '4 5t' ap51-flash-2019.0.1/docs/flash-station/switch-2-hub000066400000000000000000000007321353712067100214570ustar00rootroot00000000000000#!/bin/sh /etc/rc.common # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2013, Linus Lüssing START=45 start() { swconfig dev eth0 set phy 30 swconfig dev eth0 set reg 16 if [ "`swconfig dev eth0 get val`" = "7967" ]; then swconfig dev eth0 set val 31 fi } stop() { swconfig dev eth0 set phy 30 swconfig dev eth0 set reg 16 if [ "`swconfig dev eth0 get val`" = "31" ]; then swconfig dev eth0 set val 7967 fi } ap51-flash-2019.0.1/docs/index.rst000066400000000000000000000005241353712067100164040ustar00rootroot00000000000000.. SPDX-License-Identifier: GPL-3.0-or-later .. SPDX-FileCopyrightText: 2009-2019, Marek Lindner .. SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann ========== ap51-flash ========== .. toctree:: :maxdepth: 2 :caption: Contents: supported-devices/index flash-station/index ap51-flash-2019.0.1/docs/supported-devices/000077500000000000000000000000001353712067100202075ustar00rootroot00000000000000ap51-flash-2019.0.1/docs/supported-devices/index.rst000066400000000000000000000032411353712067100220500ustar00rootroot00000000000000.. SPDX-License-Identifier: GPL-3.0-or-later .. SPDX-FileCopyrightText: 2013, Saverio Proto .. SPDX-FileCopyrightText: 2013-2019, Marek Lindner .. SPDX-FileCopyrightText: 2018, Antonio Quartulli .. SPDX-FileCopyrightText: 2017-2019, Sven Eckelmann ================= Supported devices ================= In general you can flash all devices which use the redboot bootloader that has the reflashing function enabled. ap51-flash will automatically detect redboot when you turn on the device. If your device is not in the "known to work" list which follows you still can try it and inform us about the result. ap51-flash also supports plain tftp flashing without redboot. This method is quite common amongst a variety of devices. Tested ====== * Alfa Network - AP121F * Dlink - DIR-300 (after installing a reflash-enabled redboot) * Engenius - EOC-1650 - EOC-2610 - EOC-2610p - 3660 * FON - La Fonera (2100) * Open Mesh - A40 - A42 - A60 - A62 - D200 - G200 - MR500 - MR600 (v1, v2) - MR900 (v1, v2) - MR1750 (v1, v2) - OM1P - OM2P (v1, v2, v4) - OM2P-HS (v1, v2, v3, v4) - OM2P-LC - OM5P - OM5P-AN - OM5P-AC (v1, v2) * Plasma Cloud - PA300 - PA1200 - PA2200 * Ubiquiti - Bullet2 & HP - NanoStation2 - NanoStation5 - Pico2 & HP - RouterStation * UniAppliance - Colibrì (!UniData) * Zyxel - NBG6817 Other Devices ============= There are many different devices out there which differ slighty in their way of doing things. Even if your device does not work out of the box it might require only small changes to support it. ap51-flash-2019.0.1/embed_image.mk000066400000000000000000000027171353712067100163700ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2009-2019, Marek Lindner # SPDX-FileCopyrightText: 2015-2019, Sven Eckelmann $(AP51_RC):: Makefile $(Q_SILENT)echo '#include "ap51-flash-res.h"' > $(AP51_RC) ifneq ($(filter-out ,$(EMBEDDED_IMAGES)),) ifeq ($(PLATFORM),WIN32) OBJ += $(AP51_RC).o endif ifeq ($(PLATFORM),LINUX) ifeq ($(OBJCP_OUT),) ifeq ($(shell getconf LONG_BIT),64) OBJCP_OUT = elf64-x86-64 else OBJCP_OUT = elf32-i386 endif endif endif ifneq ($(DESC),) CPPFLAGS += -DEMBEDDED_DESC=\"$(DESC)\" endif endif # automatically generate embedding images via: # $(call embed_image,TYPE_UPPER,TYPE_LOWER)) define embed_image ifneq ($(EMBED_$(1)),) EMBED_$(1)_SYM = _binary_$(shell echo $(EMBED_$(1)) | sed 's@[-/.]@_@g') CPPFLAGS += -DEMBED_$(1) ifeq ($(PLATFORM),LINUX) OBJ += img_$(2).o img_$(2).o: $(EMBED_$(1)) $(Q_CC)$(OBJCOPY) -B i386 -I binary $(EMBED_$(1)) -O $(OBJCP_OUT) \ --redefine-sym $$(EMBED_$(1)_SYM)_start=_binary_img_$(2)_start \ --redefine-sym $$(EMBED_$(1)_SYM)_end=_binary_img_$(2)_end \ --redefine-sym $$(EMBED_$(1)_SYM)_size=_binary_img_$(2)_size img_$(2).o else ifeq ($(PLATFORM),WIN32) $(AP51_RC):: $(EMBED_$(1)) $(Q_SILENT)[ -z "$(EMBED_$(1))" ] || echo 'IDR_$(1)_IMG RCDATA DISCARDABLE "$(EMBED_$(1))"' >> $(AP51_RC) else ifeq ($(PLATFORM),OSX) LDFLAGS += -sectcreate __DATA _binary_img_$(2) $(EMBED_$(1)) endif endif endef # embed_image ap51-flash-2019.0.1/flash.c000066400000000000000000000115541353712067100150610ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #include "flash.h" #include #include #include #include #include "compat.h" #include "list.h" #include "proto.h" #include "router_tftp_client.h" #include "router_types.h" #include "socket.h" static int running = 1; static struct list *node_list; static uint8_t our_mac[] = {0x00, 0xba, 0xbe, 0xca, 0xff, 0x00}; #if defined(CLEAR_SCREEN) int num_nodes_flashed = 0; #endif #define PACKET_BUFF_LEN 2000 #define READ_SLEEP_SEC 0 #define READ_SLEEP_USEC 250000 static int node_list_init(void) { node_list = NULL; return 0; } struct node *node_list_get(const uint8_t *mac_addr) { struct list *list; struct node *node = NULL, *node_tmp; slist_for_each (list, node_list) { node_tmp = (struct node *)list->data; if (memcmp(node_tmp->his_mac_addr, mac_addr, ETH_ALEN) != 0) continue; node = node_tmp; break; } if (node) goto out; node = malloc(sizeof(struct node) + router_types_priv_size); if (!node) goto out; list = malloc(sizeof(struct list)); if (!list) goto free_node; memset(list, 0, sizeof(struct list)); memset(node, 0, sizeof(struct node) + router_types_priv_size); memcpy(node->his_mac_addr, mac_addr, ETH_ALEN); node->image_state.fd = -1; list->data = node; list->next = NULL; list_prepend(&node_list, list); goto out; free_node: free(node); node = NULL; out: return node; } static void _node_list_free(struct list *list) { struct node *node = (struct node *)list->data; free(node); free(list); } static void node_list_free(void) { struct list *list, *list_tmp; slist_for_each_safe (list, list_tmp, node_list) _node_list_free(list); node_list = NULL; } static void node_list_maintain(void) { struct list *list, *list_tmp; struct node *node; int ret; slist_for_each_safe (list, list_tmp, node_list) { node = (struct node *)list->data; switch (node->status) { case NODE_STATUS_UNKNOWN: case NODE_STATUS_RESET_SENT: case NODE_STATUS_DETECTING: /* ignored */ break; case NODE_STATUS_DETECTED: switch (node->flash_mode) { case FLASH_MODE_TFTP_SERVER: tftp_init_upload(node); break; case FLASH_MODE_REDBOOT: telnet_handle_connection(node); break; case FLASH_MODE_TFTP_CLIENT: case FLASH_MODE_NETCONSOLE: /* ignored; handled in handle_udp_packet */ break; case FLASH_MODE_UKNOWN: fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: Error, flash mode unknown.\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5]); break; } break; case NODE_STATUS_FLASHING: /* if (node->flash_mode == FLASH_MODE_REDBOOT) telnet_keep_alive(node); */ break; case NODE_STATUS_FINISHED: if (node->flash_mode != FLASH_MODE_TFTP_CLIENT) break; ret = tftp_client_flash_completed(node); if (ret == 0) break; fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: flash complete. Device ready to unplug.\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); node->status = NODE_STATUS_REBOOTED; #if defined(CLEAR_SCREEN) num_nodes_flashed++; #endif break; case NODE_STATUS_REBOOTED: case NODE_STATUS_NO_FLASH: /* check timeout and call _node_list_free(list); */ break; } } } void our_mac_set(struct node *node) { memcpy(node->our_mac_addr, our_mac, ETH_ALEN); /* TODO: 256 addresses might not be sufficient */ our_mac[5]++; } static void sig_handler(int signal) { switch (signal) { case SIGINT: case SIGTERM: running = 0; break; } } int flash_start(const char *iface) { char *packet_buff_align; char *packet_buff; int ret, sleep_sec, sleep_usec; ret = socket_open(iface); if (ret < 0) goto out; ret = node_list_init(); if (ret < 0) goto sock_close; packet_buff_align = malloc(PACKET_BUFF_LEN + NET_IP_ALIGN); if (!packet_buff_align) goto list_free; packet_buff = &packet_buff_align[NET_IP_ALIGN]; ret = proto_init(); if (ret < 0) goto pack_free; ret = router_types_init(); if (ret < 0) goto proto_free; signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); sleep_sec = READ_SLEEP_SEC; sleep_usec = READ_SLEEP_USEC; while (running) { ret = socket_read(packet_buff, PACKET_BUFF_LEN, &sleep_sec, &sleep_usec); if (ret == 0) { router_types_detect_pre(our_mac); node_list_maintain(); } if (ret <= 0) goto reset_sleep; handle_eth_packet(packet_buff, ret); continue; reset_sleep: sleep_sec = READ_SLEEP_SEC; sleep_usec = READ_SLEEP_USEC; } ret = 0; proto_free: proto_free(); pack_free: free(packet_buff_align); list_free: node_list_free(); sock_close: socket_close(iface); out: return ret; } ap51-flash-2019.0.1/flash.h000066400000000000000000000021651353712067100150640ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_FLASH_H__ #define __AP51_FLASH_FLASH_H__ #include #include "proto.h" enum flash_mode { FLASH_MODE_UKNOWN, FLASH_MODE_REDBOOT, FLASH_MODE_TFTP_SERVER, FLASH_MODE_TFTP_CLIENT, FLASH_MODE_NETCONSOLE, }; enum node_status { NODE_STATUS_UNKNOWN, NODE_STATUS_DETECTING, NODE_STATUS_DETECTED, NODE_STATUS_FLASHING, NODE_STATUS_FINISHED, NODE_STATUS_RESET_SENT, NODE_STATUS_REBOOTED, NODE_STATUS_NO_FLASH, }; struct node { uint8_t his_mac_addr[6]; uint8_t our_mac_addr[6]; uint32_t his_ip_addr; uint32_t our_ip_addr; enum node_status status; enum flash_mode flash_mode; struct router_type *router_type; struct image_state image_state; struct tcp_state tcp_state; void *router_priv; /* priv declarations are added at runtime */ }; #if defined(CLEAR_SCREEN) extern int num_nodes_flashed; #endif struct node *node_list_get(const uint8_t *mac_addr); void our_mac_set(struct node *node); int flash_start(const char *iface); #endif /* __AP51_FLASH_FLASH_H__ */ ap51-flash-2019.0.1/fwcfg.c000066400000000000000000000065501353712067100150600ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2015-2019, Sven Eckelmann */ #include "fwcfg.h" #include #include #include #include #include #include #include #include #include #include "compat.h" #include "router_images.h" static void rtrim(char *s) { size_t len = strlen(s); char *t = &s[len]; while (t-- && t >= s) { if (!isspace(*t)) break; *t = '\0'; } } static unsigned int fwcfg_parse_sizes(struct router_image *router_image, char *content) { char *line, *str_start, *saveptr; size_t line_len; char *value, *type, *tv_delim; unsigned int size = 0; const char *section = NULL; struct file_info *file_info; /* parse */ for (str_start = content; ; str_start = NULL) { line = strtok_r(str_start, "\n", &saveptr); if (!line) break; if (strlen(line) == 0) continue; if (!section && line[0] != '[') { fprintf(stderr, "Found line before section: %s\n", line); return 0; } if (line[0] == '[') { /* section */ rtrim(line); line_len = strlen(line); if (line[line_len - 1] != ']') { fprintf(stderr, "Found section line without delimiter: %s\n", line); return 0; } line[line_len - 1] = '\0'; section = &line[1]; } else { /* type value pair */ type = line; tv_delim = strchr(line, '='); if (!tv_delim) { fprintf(stderr, "Found type=value line without '=': %s\n", line); return 0; } tv_delim[0] = '\0'; value = &tv_delim[1]; if (strcmp("filename", type) != 0) continue; file_info = router_image_get_file_info(router_image, value); if (!file_info) { fprintf(stderr, "Failed to find file %s referenced in fwupgrade.cfg\n", value); return 0; } size += file_info->file_size; } } return size; } unsigned int fwupgrade_cfg_read_sizes(struct router_image *router_image, const struct file_info *file_info) { int fd = -1; int size = 0; int read_len; char *dst = NULL; uint8_t *file_data; off_t reto; /* * WARNING only call when calle first verified that image size is * correct and offset/size of files don't violate the size */ read_len = file_info->file_size; dst = malloc(read_len + 1); if (!dst) { fprintf(stderr, "Error - allocate memory for '%s': %s\n", file_info->file_name, strerror(errno)); goto out; } if (router_image->path) { fd = open(router_image->path, O_RDONLY | O_BINARY); if (fd < 0) { fprintf(stderr, "Error - can't open image file '%s': %s\n", router_image->path, strerror(errno)); goto out; } if (read_len > 0) { reto = lseek(fd, file_info->file_offset, SEEK_SET); if (reto == (off_t) -1) { fprintf(stderr, "Error - seeking in file '%s': %s\n", router_image->path, strerror(errno)); goto out; } if (read_len != read(fd, dst, read_len)) { fprintf(stderr, "Error - reading from file '%s': %s\n", router_image->path, strerror(errno)); goto out; } } } else if (router_image->embedded_img) { file_data = (uint8_t *)router_image->embedded_img; file_data += file_info->file_offset; if (read_len > 0) memcpy(dst, file_data, read_len); } dst[read_len] = '\0'; size = fwcfg_parse_sizes(router_image, dst); out: if (fd >= 0) close(fd); free(dst); return size; } ap51-flash-2019.0.1/fwcfg.h000066400000000000000000000005771353712067100150700ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2015-2019, Sven Eckelmann */ #ifndef __AP51_FLASH_FWCFG_H__ #define __AP51_FLASH_FWCFG_H__ struct file_info; struct router_image; unsigned int fwupgrade_cfg_read_sizes(struct router_image *router_image, const struct file_info *file_info); #endif /* __AP51_FLASH_FWCFG_H__ */ ap51-flash-2019.0.1/list.h000066400000000000000000000012721353712067100147400ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_LIST_H__ #define __AP51_FLASH_LIST_H__ struct list { struct list *next; void *data; }; #define slist_for_each(node, head) \ for (node = (head); (node); node = node->next) #define slist_for_each_safe(node, safe, head) \ for (node = (head); \ (node) && (((safe) = node->next) || 1); \ node = safe) static inline void list_prepend(struct list **list, struct list *list_item) { if (!(*list)) { *list = list_item; return; } list_item->next = (*list)->next; (*list)->next = list_item; } #endif /* __AP51_FLASH_LIST_H__ */ ap51-flash-2019.0.1/man/000077500000000000000000000000001353712067100143655ustar00rootroot00000000000000ap51-flash-2019.0.1/man/ap51-flash.8000066400000000000000000000056061353712067100163260ustar00rootroot00000000000000.\" SPDX-License-Identifier: GPL-3.0-or-later .\" SPDX-FileCopyrightText: 2019, Sven Eckelmann .TH "AP51-FLASH" "8" "August 29, 2019" .\" Please adjust this date whenever revising the manpage. .\" -------------------------------------------------------------------------- .\" Process this file with .\" groff -man man/ap51-flash.8 -Tutf8 .\" Retrieve format warnings with .\" LC_ALL=en_US.UTF-8 MANROFFSEQ='' MANWIDTH=80 man --warnings -E UTF-8 -l -Tutf8 -Z man/ap51-flash.8 >/dev/null .\" -------------------------------------------------------------------------- .SH NAME ap51\-flash \- firmware flasher for ethernet connected routers and access points .SH SYNOPSIS .na .B ap51\-flash [ .B \-vh ] [ .B \-m .I mac ] [ .I interface .I image .I ... ] .br .ad .SH DESCRIPTION \fBap51\-flash\fP listens on traffic of a network \fIinterface\fP, detects remote devices and checks the traffic for known identification markers. These markers are send out automatically by supported devices during the initial boot process of the embedded boot loader. .PP On success, it will search the list of provided \fIimage\fPs for a matching firmware. A device specific communication procedure is initiated to begin the flashing process. The firmware data is extracted from the selected \fIimage\fP and transferred to the device in TFTP server or client mode. .PP \fBap51\-flash\fP will run in foreground and continue using the \fIinterface\fP until it is interrupted by an SIGINT signal (typically generated by control-C) or SIGTERM signal (for example generated by the .BR kill(1) command). .PP The \fIinterface\fP doesn't require a valid layer 3 network configuration but has to be set in the UP state (using the .BR ip\-link(8) command). \fBap51\-flash\fP requires enough privileges to capture and inject raw ethernet packets on the selected \fIinterface\fP. These are often only accessible to the root user. .PP While \fBap51\-flash\fP doesn't require a target device specific network configuration or TFTP client/server on the same machine, it is recommended to disable any other TFTP client or server on the system running \fBap51\-flash\fP to avoid interferences by a different TFTP program. .SH OPTIONS Listed below are the command line options for \fBap51\-flash\fP: .TP \fB\-m\fP \fImac\fP, \fB\--mac\fP \fImac\fP Adds \fImac\fP address to the whitelist filter. Only these addresses will be tried to be flashed when one or more addresses are supplied. The option has to be supplied multiple times to add multiple addresses to the whitelist filter. If not specified, all detected devices will be flashed. .TP .BR \-v ", " \-\-version print ap51\-flash version and exit .TP .BR \-h ", " \-\-help print ap51\-flash help and exit .SH AUTHOR ap51-flash was written by Marek Lindner and others. This manual page was written by Sven Eckelmann . It is licensed under the terms of the GNU GPL (version 3 or later). ap51-flash-2019.0.1/proto.c000066400000000000000000000633521353712067100151320ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #include "proto.h" #include #include #include #include #include "ap51-flash.h" #include "compat.h" #include "flash.h" #include "router_images.h" #include "router_redboot.h" #include "router_tftp_client.h" #include "router_netconsole.h" #include "router_types.h" #include "socket.h" #define TFTP_SRC_PORT 13337 #define REDBOOT_TELNET_SPORT 13337 #define REDBOOT_TELNET_DPORT 9000 #define TFTP_PAYLOAD_SIZE 512 enum tcp_packet_type { TCP_SYN, TCP_ACK, TCP_DATA, }; #define PACKET_BUFF_LEN 2000 #define ARP_LEN (sizeof(struct ether_header) + sizeof(struct ether_arp)) #define MAX_TCP_PAYLOAD (ETH_DATA_LEN - ETH_HLEN - sizeof(struct iphdr) - \ sizeof(struct tcphdr)) static char *out_packet_buff; static char *out_packet_buff_align; static struct ether_header *out_ethhdr; static struct ether_arp *out_arphdr; static struct iphdr *out_iphdr; static struct udphdr *out_udphdr; static char *out_tftp_data; static struct icmphdr *out_icmphdr; static unsigned short chksum(unsigned short sum, const unsigned char *data, unsigned short len) { unsigned short t; const unsigned char *dataptr, *last_byte; dataptr = data; last_byte = data + len - 1; while (dataptr < last_byte) { t = (dataptr[0] << 8) + dataptr[1]; sum += t; if(sum < t) sum++; dataptr += 2; } if (dataptr == last_byte) { t = (dataptr[0] << 8) + 0; sum += t; if(sum < t) sum++; } return sum; } static void arp_init(const uint8_t *src_mac, const uint8_t *dst_mac, unsigned int src_ip, unsigned int dst_ip, unsigned short arp_type) { memcpy(out_ethhdr->ether_shost, src_mac, ETH_ALEN); memcpy(out_ethhdr->ether_dhost, dst_mac, ETH_ALEN); out_ethhdr->ether_type = htons(ETH_P_ARP); out_arphdr->ea_hdr.ar_hrd = htons(0x0001); /* ethernet */ out_arphdr->ea_hdr.ar_pro = htons(ETH_P_IP); /* IPv4 */ out_arphdr->ea_hdr.ar_hln = ETH_ALEN; out_arphdr->ea_hdr.ar_pln = 4; /* IPv4 addr len */ out_arphdr->ea_hdr.ar_op = htons(arp_type); memcpy(out_arphdr->arp_sha, src_mac, ETH_ALEN); store_ip_addr(out_arphdr->arp_spa, src_ip); store_ip_addr(out_arphdr->arp_tpa, dst_ip); } int arp_req_send(const uint8_t *src_mac, const uint8_t *dst_mac, unsigned int src_ip, unsigned int dst_ip) { arp_init(src_mac, dst_mac, src_ip, dst_ip, ARPOP_REQUEST); return socket_write(out_packet_buff, ARP_LEN); } static int arp_rep_send(const uint8_t *src_mac, const uint8_t *dst_mac, unsigned int src_ip, unsigned int dst_ip) { arp_init(src_mac, dst_mac, src_ip, dst_ip, ARPOP_REPLY); /* fprintf(stderr, "arp_rep_send() to: %02x:%02x:%02x:%02x:%02x:%02x from %02x:%02x:%02x:%02x:%02x:%02x\n", dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5], src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5]);*/ return socket_write(out_packet_buff, ARP_LEN); } static void tftp_packet_init(struct node *node, unsigned short src_port, unsigned short dst_port) { memcpy(out_ethhdr->ether_shost, node->our_mac_addr, ETH_ALEN); memcpy(out_ethhdr->ether_dhost, node->his_mac_addr, ETH_ALEN); out_ethhdr->ether_type = htons(ETH_P_IP); out_iphdr->version = 4; out_iphdr->ihl = 5; out_iphdr->tos = 0; out_iphdr->id = 0; out_iphdr->frag_off = 0; out_iphdr->ttl = 50; out_iphdr->protocol = IPPROTO_UDP; out_iphdr->saddr = node->our_ip_addr; out_iphdr->daddr = node->his_ip_addr; out_udphdr->source = src_port; out_udphdr->dest = dst_port; } static int tftp_packet_send_data(struct node *node, unsigned short src_port, unsigned short dst_port, int tftp_data_len) { unsigned short sum; tftp_packet_init(node, src_port, dst_port); out_udphdr->len = htons(8 + tftp_data_len); /* UDP checksum */ out_udphdr->check = 0; sum = ntohs(out_udphdr->len) + out_iphdr->protocol; sum = chksum(sum, (void *)&out_iphdr->saddr, 2 * sizeof(out_iphdr->saddr)); sum = chksum(sum, (void *)out_udphdr, ntohs(out_udphdr->len)); out_udphdr->check = ~(htons(sum)); out_iphdr->tot_len = htons(20 + 8 + tftp_data_len); out_iphdr->check = 0; out_iphdr->check = ~(htons(chksum(0, (void *)out_iphdr, sizeof(struct iphdr)))); return socket_write(out_packet_buff, ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr) + tftp_data_len); } int tftp_init_upload(struct node *node) { int data_len; /* TFTP write request */ *((unsigned short *)out_tftp_data) = htons(2); data_len = 2; data_len += sprintf(out_tftp_data + data_len, "\"%s\"", "flash_update"); data_len += sprintf(out_tftp_data + data_len + 1, "%s", "octet"); data_len += 2; /* sprintf does not count \0 */ return tftp_packet_send_data(node, htons(TFTP_SRC_PORT), htons(IPPORT_TFTP), data_len); } int netconsole_init_upload(struct node *node) { int data_len; /* TFTP start command and reset (for subsequential reboot) */ data_len = sprintf(out_tftp_data, "run fw_upg; reset\n"); return tftp_packet_send_data(node, htons(IPPORT_NETCONSOLE), htons(IPPORT_NETCONSOLE), data_len); } static void handle_arp_packet(const char *packet_buff, int packet_buff_len, struct node *node) { struct ether_arp *arphdr; int ret; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) return; arphdr = (struct ether_arp *)packet_buff; switch (ntohs(arphdr->ea_hdr.ar_op)) { case ARPOP_REQUEST: case ARPOP_REPLY: #if defined(DEBUG) fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: received ARP %s, device status: %d, sender hw addr: %02x:%02x:%02x:%02x:%02x:%02x, target hw addr: %02x:%02x:%02x:%02x:%02x:%02x\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], ntohs(arphdr->ea_hdr.ar_op) == ARPOP_REQUEST ? "request" : "reply", node->status, arphdr->arp_sha[0], arphdr->arp_sha[1], arphdr->arp_sha[2], arphdr->arp_sha[3], arphdr->arp_sha[4], arphdr->arp_sha[5], arphdr->arp_tha[0], arphdr->arp_tha[1], arphdr->arp_tha[2], arphdr->arp_tha[3], arphdr->arp_tha[4], arphdr->arp_tha[5]); #endif break; default: fprintf(stderr, "ARP, unknown op code: %i, status: %d\n", ntohs(arphdr->ea_hdr.ar_op), node->status); return; } switch (node->status) { case NODE_STATUS_UNKNOWN: node->status = NODE_STATUS_DETECTING; /* fall through */ case NODE_STATUS_DETECTING: ret = router_types_detect_main(node, packet_buff, packet_buff_len); if (ret != 1) break; node->status = NODE_STATUS_DETECTED; /* fall through */ case NODE_STATUS_DETECTED: case NODE_STATUS_FLASHING: if (ntohs(arphdr->ea_hdr.ar_op) != ARPOP_REQUEST) break; arp_rep_send(node->our_mac_addr, arphdr->arp_sha, load_ip_addr(arphdr->arp_tpa), load_ip_addr(arphdr->arp_spa)); break; case NODE_STATUS_RESET_SENT: case NODE_STATUS_FINISHED: if (node->flash_mode != FLASH_MODE_NETCONSOLE) { fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: flash complete. Device ready to unplug.\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); node->status = NODE_STATUS_REBOOTED; #if defined(CLEAR_SCREEN) num_nodes_flashed++; #endif } break; case NODE_STATUS_REBOOTED: case NODE_STATUS_NO_FLASH: break; } } static void handle_udp_packet(const char *packet_buff, int packet_buff_len, struct node *node) { struct udphdr *udphdr; struct file_info *file_info; unsigned short opcode, block; const char *file_name; int ret, data_len; static const char fwupgradecfg[] = "fwupgrade.cfg"; if (!len_check(packet_buff_len, sizeof(struct udphdr), "UDP")) return; udphdr = (struct udphdr *)packet_buff; switch (node->flash_mode) { case FLASH_MODE_NETCONSOLE: if (udphdr->dest == htons(IPPORT_NETCONSOLE)) { size_t len = sizeof(*udphdr); handle_netconsole_packet(packet_buff + len, packet_buff_len - len, node); return; } /* fall through */ case FLASH_MODE_REDBOOT: case FLASH_MODE_TFTP_CLIENT: if (udphdr->dest != htons(IPPORT_TFTP)) return; break; case FLASH_MODE_TFTP_SERVER: if (udphdr->source != htons(IPPORT_TFTP)) return; break; default: return; } opcode = ntohs(*(unsigned short *)(packet_buff + sizeof(struct udphdr))); block = ntohs(*(unsigned short *)(packet_buff + sizeof(struct udphdr) + 2)); /* fprintf(stderr, "tftp opcode=%d, block=%d, len=%i\n", opcode, block, htons(rcv_udphdr->len) - sizeof(struct udphdr)); */ switch (opcode) { /* TFTP read request */ case 1: file_name = packet_buff + sizeof(struct udphdr) + 2; switch (node->flash_mode) { case FLASH_MODE_UKNOWN: /* ignore */ break; case FLASH_MODE_TFTP_SERVER: /* ignored; handled in node_list_maintain */ break; case FLASH_MODE_REDBOOT: case FLASH_MODE_TFTP_CLIENT: case FLASH_MODE_NETCONSOLE: file_info = router_image_get_file(node->router_type, file_name); if (!file_info) { fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: tftp client asks for '%s' - file not found ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, file_name); goto out; } if (node->image_state.fd <= 0) { ret = router_images_open_path(node); if (ret < 0) goto out; node->status = NODE_STATUS_FLASHING; } fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: tftp client asks for '%s', serving %s portion of: %s (%i blocks) ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, file_name,file_info->file_name, node->router_type->image->path ? node->router_type->image->path : "embedded image", ((file_info->file_fsize + TFTP_PAYLOAD_SIZE - 1) / TFTP_PAYLOAD_SIZE)); node->image_state.file_size = file_info->file_size; node->image_state.flash_size = file_info->file_fsize; node->image_state.offset = file_info->file_offset; break; } block = 0; node->image_state.bytes_sent = 0; node->image_state.last_packet_size = 0; if (strncmp(file_name, fwupgradecfg, strlen(fwupgradecfg)) == 0) node->image_state.count_globally = 0; else node->image_state.count_globally = 1; /* fall through - start sending data */ /* TFTP ack */ case 4: if (block == 0) { if (node->flash_mode == FLASH_MODE_TFTP_SERVER) { ret = router_images_open_path(node); if (ret < 0) return; node->status = NODE_STATUS_FLASHING; node->image_state.file_size = node->router_type->image->file_size; node->image_state.flash_size = ((node->router_type->image->file_size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE; node->image_state.offset = 0; fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: connection to tftp server established - uploading %i blocks ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, ((node->image_state.flash_size + TFTP_PAYLOAD_SIZE - 1) / TFTP_PAYLOAD_SIZE)); } node->image_state.block_acked = 0; node->image_state.block_sent = 0; } else if (block != node->image_state.block_sent) { if (block < node->image_state.block_sent) fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: tftp repeat block %d, last received ack: %d\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, block + 1, node->image_state.block_acked); else fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: tftp acks unsent block %d (last sent block: %d)\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, block, node->image_state.block_sent); block = node->image_state.block_acked; node->image_state.bytes_sent -= node->image_state.last_packet_size; } else { /* nothing more to send */ if (node->image_state.last_packet_size != TFTP_PAYLOAD_SIZE) { /* don't count this file as payload? */ if (!node->image_state.count_globally) goto out; node->image_state.total_bytes_sent += node->image_state.bytes_sent; if (node->image_state.total_bytes_sent >= router_image_get_size(node->router_type)) { switch (node->flash_mode) { case FLASH_MODE_TFTP_SERVER: case FLASH_MODE_TFTP_CLIENT: case FLASH_MODE_NETCONSOLE: fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: image successfully transmitted - writing image to flash ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); router_images_close_path(node); if (node->flash_mode == FLASH_MODE_TFTP_CLIENT) tftp_client_flash_time_set(node); node->status = NODE_STATUS_FINISHED; break; case FLASH_MODE_REDBOOT: /* ignored; handled in REDBOOT_STATE_EXECY */ break; case FLASH_MODE_UKNOWN: /* ignore */ break; } } goto out; } node->image_state.block_acked = block; } block++; /* TFTP DATA packet */ *((unsigned short *)out_tftp_data) = htons(3); *((unsigned short *)(out_tftp_data + 2)) = htons(block); data_len = router_images_read_data(out_tftp_data + 4, node); if (data_len < 0) break; data_len += 4; /* opcode size */ ret = tftp_packet_send_data(node, udphdr->dest, udphdr->source, data_len); if (ret < 0) return; node->image_state.last_packet_size = data_len - 4; /* opcode size */ node->image_state.bytes_sent += node->image_state.last_packet_size; node->image_state.block_sent = block; /* printf("tftp data out: tftp_sent=%lu, remaining_size=%lu, data_len=%i, block=%d\n", tftp_sent, tftp_xfer_size - tftp_sent, tftp_data_len - 4, block); */ break; /* TFTP error */ case 5: if ((block == 2) && (htons(udphdr->len) - sizeof(struct udphdr) > 4)) fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: received TFTP error: %s\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, (packet_buff + sizeof(struct udphdr) + 4)); else fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: received TFTP error code: %d\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, block); break; default: fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: unexpected TFTP opcode: %d\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, opcode); break; } out: return; } static void tcp_init_state(struct node *node) { struct ether_header *ethhdr; struct iphdr *iphdr; struct tcphdr *tcphdr; node->tcp_state.packet_buff = malloc(PACKET_BUFF_LEN); if (!node->tcp_state.packet_buff) goto out; memset(node->tcp_state.packet_buff, 0, PACKET_BUFF_LEN); ethhdr = (struct ether_header *)node->tcp_state.packet_buff; memcpy(ethhdr->ether_shost, node->our_mac_addr, ETH_ALEN); memcpy(ethhdr->ether_dhost, node->his_mac_addr, ETH_ALEN); ethhdr->ether_type = htons(ETH_P_IP); iphdr = (struct iphdr *)(node->tcp_state.packet_buff + ETH_HLEN); iphdr->version = 4; iphdr->ihl = 5; iphdr->tos = 0; iphdr->id = 0; iphdr->frag_off = 0; iphdr->ttl = 50; iphdr->protocol = IPPROTO_TCP; iphdr->saddr = node->our_ip_addr; iphdr->daddr = node->his_ip_addr; tcphdr = (struct tcphdr *)(node->tcp_state.packet_buff + ETH_HLEN + sizeof(struct iphdr)); tcphdr->source = htons(REDBOOT_TELNET_SPORT); tcphdr->dest = htons(REDBOOT_TELNET_DPORT); out: return; } static int tcp_send(struct node *node, int tcp_data_len, enum tcp_packet_type flags) { struct iphdr *iphdr; struct tcphdr *tcphdr; unsigned short sum; unsigned int mss_option = htonl(0x02040000 | MAX_TCP_PAYLOAD); iphdr = (struct iphdr *)(node->tcp_state.packet_buff + ETH_HLEN); tcphdr = (struct tcphdr *)(node->tcp_state.packet_buff + ETH_HLEN + sizeof(struct iphdr)); /* tcp header */ tcphdr->seq = htonl(node->tcp_state.my_seq); tcphdr->ack_seq = htonl(node->tcp_state.my_ack_seq); tcphdr->window = htons(MAX_TCP_PAYLOAD); tcphdr->doff = 5; /* always set PUSH flag if sending data */ if (tcp_data_len > 0) tcphdr->psh = 1; else tcphdr->psh = 0; switch (flags) { case TCP_SYN: tcphdr->syn = 1; tcphdr->ack = 0; /* send MSS option */ tcp_data_len += 4; memcpy((unsigned char *)(tcphdr + 1), &mss_option, sizeof(mss_option)); tcphdr->doff++; break; case TCP_ACK: case TCP_DATA: tcphdr->syn = 0; tcphdr->ack = 1; break; } /* TCP checksum */ tcphdr->check = 0; if (flags == TCP_SYN) sum = (tcphdr->doff * 4) + iphdr->protocol; else sum = (tcphdr->doff * 4) + tcp_data_len + iphdr->protocol; sum = chksum(sum, (void *)&iphdr->saddr, 2 * sizeof(iphdr->saddr)); sum = chksum(sum, (void *)tcphdr, sizeof(struct tcphdr) + tcp_data_len); tcphdr->check = ~(htons(sum)); iphdr->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + tcp_data_len); iphdr->check = 0; iphdr->check = ~(htons(chksum(0, (void *)iphdr, sizeof(struct iphdr)))); return socket_write(node->tcp_state.packet_buff, ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr) + tcp_data_len); } static int tcp_send_syn(struct node *node) { return tcp_send(node, 0, TCP_SYN); } static int tcp_send_ack(struct node *node) { return tcp_send(node, 0, TCP_ACK); } static int tcp_send_data(struct node *node, int tcp_data_len) { return tcp_send(node, tcp_data_len, TCP_DATA); } static int tcp_resend_data(struct node *node) { char *packet_buff; packet_buff = node->tcp_state.packet_buff + ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr); return tcp_send(node, (int)strlen(packet_buff), TCP_DATA); } void telnet_handle_connection(struct node *node) { if (!node->tcp_state.packet_buff) tcp_init_state(node); if (!node->tcp_state.packet_buff) goto out; /* keep sending SYN packets until we get a reply */ switch (node->tcp_state.status) { case TCP_STATUS_SYN_SENT: tcp_send_syn(node); break; case TCP_STATUS_ESTABLISHED: case TCP_STATUS_TELNET_READY: /* TODO: check timer if we need to resend */ break; } out: return; } int telnet_send_cmd(struct node *node, const char *cmd) { char *packet_buff; size_t buflen = PACKET_BUFF_LEN; packet_buff = node->tcp_state.packet_buff + ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr); buflen -= ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr); strncpy(packet_buff, cmd, buflen); packet_buff[buflen - 1] = '\0'; return tcp_send_data(node, (int)strlen(cmd)); } static void handle_tcp_packet(char *packet_buff, int packet_buff_len, struct node *node) { struct tcphdr *tcphdr; unsigned int data_len; char *buff; if (!len_check(packet_buff_len, sizeof(struct tcphdr), "TCP")) goto out; tcphdr = (struct tcphdr *)packet_buff; /* not telnet */ if (tcphdr->source != htons(REDBOOT_TELNET_DPORT)) goto out; if (tcphdr->dest != htons(REDBOOT_TELNET_SPORT)) goto out; if (tcphdr->ack != 1) goto out; data_len = packet_buff_len - (tcphdr->doff * 4); switch (node->tcp_state.status) { case TCP_STATUS_SYN_SENT: if (tcphdr->syn != 1) goto out; node->tcp_state.status = TCP_STATUS_ESTABLISHED; node->tcp_state.my_ack_seq = ntohl(tcphdr->seq) + 1; node->tcp_state.my_seq = ntohl(tcphdr->ack_seq); tcp_send_ack(node); break; case TCP_STATUS_ESTABLISHED: if (tcphdr->syn != 0) goto out; packet_buff[packet_buff_len - 1] = '\0'; buff = (char *)(tcphdr + 1); node->tcp_state.status = TCP_STATUS_TELNET_READY; node->tcp_state.my_ack_seq += data_len; /* send CTRL + C */ buff = node->tcp_state.packet_buff + ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr); buff[0] = 0x03; tcp_send_data(node, 1); break; case TCP_STATUS_TELNET_READY: if (tcphdr->syn != 0) goto out; /* check for retransmission */ if ((tcphdr->seq == node->tcp_state.his_seq) && (tcphdr->ack_seq == node->tcp_state.his_ack_seq) && (data_len == node->tcp_state.his_last_len)) { /* printf("retransmission received: seq = %u, ack_seq: %u, len: %u\n", ntohl(tcphdr->seq), ntohl(tcphdr->ack_seq), data_len); */ tcp_resend_data(node); goto out; } node->tcp_state.his_seq = tcphdr->seq; node->tcp_state.his_ack_seq = tcphdr->ack_seq; node->tcp_state.his_last_len = data_len; if (node->tcp_state.his_last_len == 0) { /* TODO probably should do something useful with the ACK */ /* printf("received simple ACK (no text)\n"); */ goto out; } node->tcp_state.my_ack_seq += data_len; if (ntohl(tcphdr->ack_seq) > node->tcp_state.my_seq) node->tcp_state.my_seq = ntohl(tcphdr->ack_seq); packet_buff[packet_buff_len] = '\0'; redboot_main(node, (char *)(tcphdr + 1)); break; default: return; } out: return; } static void handle_icmp_packet(char *packet_buff, int packet_buff_len, struct node *node) { struct icmphdr *icmphdr; size_t len; if (!len_check(packet_buff_len, sizeof(struct icmphdr), "ICMP")) goto out; icmphdr = (struct icmphdr *)packet_buff; /* not echo request */ if (icmphdr->type != 8) goto out; if (icmphdr->code != 0) goto out; len = 0; memcpy(out_ethhdr->ether_dhost, node->his_mac_addr, ETH_ALEN); memcpy(out_ethhdr->ether_shost, node->our_mac_addr, ETH_ALEN); out_ethhdr->ether_type = htons(ETH_P_IP); len += sizeof(*out_ethhdr); out_iphdr->version = 4; out_iphdr->ihl = 5; out_iphdr->tos = 0; out_iphdr->id = 0; out_iphdr->frag_off = 0; out_iphdr->ttl = 50; out_iphdr->protocol = IPPROTO_ICMP; out_iphdr->saddr = node->our_ip_addr; out_iphdr->daddr = node->his_ip_addr; out_iphdr->tot_len = htons(sizeof(*out_iphdr) + sizeof(*out_icmphdr)); out_iphdr->check = 0; out_iphdr->check = ~(htons(chksum(0, (void *)out_iphdr, sizeof(*out_iphdr)))); len += sizeof(*out_iphdr); out_icmphdr->type = 0; out_icmphdr->code = 0; out_icmphdr->un.echo.id = icmphdr->un.echo.id; out_icmphdr->un.echo.sequence = icmphdr->un.echo.sequence; out_icmphdr->checksum = 0; out_icmphdr->checksum = ~(htons(chksum(0, (void *)out_icmphdr, sizeof(*out_icmphdr)))); len += sizeof(*out_icmphdr); socket_write(out_packet_buff, len); out: return; } static void handle_ip_packet(char *packet_buff, int packet_buff_len, struct node *node) { struct iphdr *iphdr; size_t iphdr_len; int length; if (!len_check(packet_buff_len, sizeof(struct iphdr), "IPv4")) return; iphdr = (struct iphdr *)packet_buff; if (iphdr->ihl < 5) return; iphdr_len = iphdr->ihl * 4; if (!len_check(packet_buff_len, iphdr_len, "IPv4 full")) return; switch (node->status) { case NODE_STATUS_DETECTED: case NODE_STATUS_FLASHING: case NODE_STATUS_RESET_SENT: break; case NODE_STATUS_FINISHED: /* in netconsole mode a 'reset' command is still required to * reboot the router */ if (node->flash_mode == FLASH_MODE_NETCONSOLE) break; case NODE_STATUS_UNKNOWN: case NODE_STATUS_DETECTING: case NODE_STATUS_NO_FLASH: default: return; } if (iphdr->saddr != node->his_ip_addr) return; if (iphdr->daddr != node->our_ip_addr) return; length = ntohs(iphdr->tot_len); if (length > packet_buff_len) length = packet_buff_len; if (length < (int)iphdr_len) return; switch (iphdr->protocol) { case IPPROTO_UDP: handle_udp_packet(packet_buff + iphdr_len, length - iphdr_len, node); break; case IPPROTO_TCP: if (node->flash_mode != FLASH_MODE_REDBOOT) break; handle_tcp_packet(packet_buff + iphdr_len, length - iphdr_len, node); break; case IPPROTO_ICMP: handle_icmp_packet(packet_buff + iphdr_len, length - iphdr_len, node); break; } return; } void handle_eth_packet(char *packet_buff, int packet_buff_len) { struct ether_header *eth_hdr; struct node *node; uint8_t bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; if (!len_check(packet_buff_len, ETH_HLEN, "ethernet")) return; eth_hdr = (struct ether_header *)packet_buff; if (memcmp(eth_hdr->ether_shost, bcast_addr, ETH_ALEN) == 0) return; switch (ntohs(eth_hdr->ether_type)) { case ETH_P_ARP: node = node_list_get(eth_hdr->ether_shost); if (!node) return; handle_arp_packet(packet_buff + ETH_HLEN, packet_buff_len - ETH_HLEN, node); break; case ETH_P_IP: if (memcmp(eth_hdr->ether_dhost, bcast_addr, ETH_ALEN) == 0) return; node = node_list_get(eth_hdr->ether_shost); if (!node) return; handle_ip_packet(packet_buff + ETH_HLEN, packet_buff_len - ETH_HLEN, node); break; default: /* silently drop packet */ break; } } int proto_init(void) { int ret = -1; out_packet_buff_align = malloc(PACKET_BUFF_LEN + NET_IP_ALIGN); if (!out_packet_buff_align) goto out; out_packet_buff = &out_packet_buff_align[NET_IP_ALIGN]; out_ethhdr = (struct ether_header *)out_packet_buff; out_arphdr = (struct ether_arp *)(out_packet_buff + ETH_HLEN); out_iphdr = (struct iphdr *)(out_packet_buff + ETH_HLEN); out_udphdr = (struct udphdr *)(out_packet_buff + ETH_HLEN + sizeof(struct iphdr)); out_tftp_data = (void *)(out_packet_buff + ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr)); out_icmphdr = (struct icmphdr *)(out_packet_buff + ETH_HLEN + sizeof(struct iphdr)); ret = 0; out: return ret; } void proto_free(void) { free(out_packet_buff_align); } ap51-flash-2019.0.1/proto.h000066400000000000000000000036441353712067100151350ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_PROTO_H__ #define __AP51_FLASH_PROTO_H__ #include #include #include struct node; #define NET_IP_ALIGN 2 enum tcp_status { TCP_STATUS_SYN_SENT, TCP_STATUS_ESTABLISHED, TCP_STATUS_TELNET_READY, }; struct tcp_state { char *packet_buff; enum tcp_status status; unsigned int his_seq; unsigned int his_ack_seq; unsigned int his_last_len; unsigned int my_seq; unsigned int my_ack_seq; }; struct image_state { int fd; unsigned int bytes_sent; unsigned int file_size; unsigned int total_bytes_sent; unsigned int flash_size; unsigned int offset; unsigned short last_packet_size; unsigned short block_acked; unsigned short block_sent; /* flags */ unsigned char count_globally:1; }; int arp_req_send(const uint8_t *src_mac, const uint8_t *dst_mac, unsigned int src_ip, unsigned int dst_ip); int tftp_init_upload(struct node *node); int netconsole_init_upload(struct node *node); void telnet_handle_connection(struct node *node); int telnet_send_cmd(struct node *node, const char *cmd); void handle_eth_packet(char *packet_buff, int packet_buff_len); int proto_init(void); void proto_free(void); static inline void store_ip_addr(void *dst, uint32_t ip) { memcpy(dst, &ip, sizeof(ip)); } static inline uint32_t load_ip_addr(void *src) { uint32_t ip; memcpy(&ip, src, sizeof(ip)); return ip; } #if defined(DEBUG) static inline int len_check(int buff_len, int req_len, char *desc) #else static inline int len_check(int buff_len, int req_len, char (*desc)__attribute__((unused))) #endif { if (buff_len >= req_len) return 1; #if defined(DEBUG) fprintf(stderr, "Warning - dropping received %s packet as it is smaller than expected: %i (required: %i)\n", desc, buff_len, req_len); #endif return 0; } #endif /* __AP51_FLASH_PROTO_H__ */ ap51-flash-2019.0.1/router_images.c000066400000000000000000000554251353712067100166360ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner * SPDX-FileCopyrightText: 2014-2019, Sven Eckelmann */ #include "router_images.h" #include #include #include #include #include #include #include #include #include #include #include "ap51-flash.h" #include "ap51-flash-res.h" #include "compat.h" #include "flash.h" #include "fwcfg.h" #include "list.h" #include "proto.h" #include "router_types.h" static const char fwupgradecfg[] = "fwupgrade.cfg"; static const char fwupgradecfgsig[] = "fwupgrade.cfg.sig"; #define TFTP_PAYLOAD_SIZE 512 #if defined(EMBED_UBOOT) && defined(LINUX) extern unsigned long _binary_img_uboot_start; extern unsigned long _binary_img_uboot_end; extern unsigned long _binary_img_uboot_size; #endif #if defined(EMBED_UBNT) && defined(LINUX) extern unsigned long _binary_img_ubnt_start; extern unsigned long _binary_img_ubnt_end; extern unsigned long _binary_img_ubnt_size; #endif #if defined(EMBED_CI) && defined(LINUX) extern unsigned long _binary_img_ci_start; extern unsigned long _binary_img_ci_end; extern unsigned long _binary_img_ci_size; #endif #if defined(EMBED_CE) && defined(LINUX) extern unsigned long _binary_img_ce_start; extern unsigned long _binary_img_ce_end; extern unsigned long _binary_img_ce_size; #endif #if defined(EMBED_ZYXEL) && defined(LINUX) extern unsigned long _binary_img_zyxel_start; extern unsigned long _binary_img_zyxel_end; extern unsigned long _binary_img_zyxel_size; #endif struct router_info *router_image_router_get(struct router_image *router_image, const char *router_desc) { struct list *list; struct router_info *router_info = NULL, *router_info_tmp; slist_for_each (list, router_image->router_list) { router_info_tmp = (struct router_info *)list->data; if (strcasecmp(router_info_tmp->router_name, router_desc) != 0) continue; router_info = router_info_tmp; break; } return router_info; } static struct router_info *router_image_router_add(struct router_image *router_image, const char *router_desc) { struct list *list; struct router_info *router_info; router_info = router_image_router_get(router_image, router_desc); if (router_info) goto out; router_info = malloc(sizeof(struct router_info)); if (!router_info) goto out; list = malloc(sizeof(struct list)); if (!list) goto free_router; memset(list, 0, sizeof(struct list)); memset(router_info, 0, sizeof(struct router_info)); strncpy(router_info->router_name, router_desc, sizeof(router_info->router_name)); router_info->router_name[sizeof(router_info->router_name) - 1] = '\0'; router_info->file_size = 0; list->data = router_info; list->next = NULL; list_prepend(&router_image->router_list, list); goto out; free_router: free(router_info); router_info = NULL; out: return router_info; } static struct file_info *_router_image_get_file(struct list *file_list, const char *file_name) { struct list *list; struct file_info *file_info = NULL, *file_info_tmp; slist_for_each (list, file_list) { file_info_tmp = (struct file_info *)list->data; if (strcasecmp(file_info_tmp->file_name, file_name) != 0) continue; file_info = file_info_tmp; break; } return file_info; } struct file_info *router_image_get_file(struct router_type *router_type, const char *file_name) { struct file_info *file_info = NULL; char file_name_buff[FILE_NAME_MAX_LENGTH]; if (strcmp(file_name, fwupgradecfg) == 0) { snprintf(file_name_buff, FILE_NAME_MAX_LENGTH - 1, "%s-%s", file_name, router_type->image_desc ? router_type->image_desc : router_type->desc); file_info = _router_image_get_file(router_type->image->file_list, file_name_buff); } if (strcmp(file_name, fwupgradecfgsig) == 0) { snprintf(file_name_buff, FILE_NAME_MAX_LENGTH - 1, "%s-%s.sig", fwupgradecfg, router_type->image_desc ? router_type->image_desc : router_type->desc); file_info = _router_image_get_file(router_type->image->file_list, file_name_buff); } if (!file_info) file_info = _router_image_get_file(router_type->image->file_list, file_name); return file_info; } static struct file_info *_router_image_add_file(struct router_image *router_image, const char *file_name) { struct list *list; struct file_info *file_info; file_info = _router_image_get_file(router_image->file_list, file_name); if (file_info) goto out; file_info = malloc(sizeof(struct file_info)); if (!file_info) goto out; list = malloc(sizeof(struct list)); if (!list) goto free_node; memset(list, 0, sizeof(struct list)); memset(file_info, 0, sizeof(struct file_info)); strncpy(file_info->file_name, file_name, sizeof(file_info->file_name)); file_info->file_name[sizeof(file_info->file_name) - 1] = '\0'; list->data = file_info; list->next = NULL; list_prepend(&router_image->file_list, list); goto out; free_node: free(file_info); file_info = NULL; out: return file_info; } static int router_image_add_file(struct router_image *router_image, const char *file_name, int file_size, int file_fsize, int file_offset) { struct file_info *file_info; file_info = _router_image_add_file(router_image, file_name); if (!file_info) return 1; file_info->file_size = file_size; file_info->file_fsize = file_fsize; file_info->file_offset = file_offset; return 0; } unsigned int router_image_get_size(struct router_type *router_type) { const char *router_desc; const struct router_info *router_info; if (router_type->image_desc) router_desc = router_type->image_desc; else router_desc = router_type->desc; router_info = router_image_router_get(router_type->image, router_desc); if (router_info && router_info->file_size) return router_info->file_size; return router_type->image->file_size; } struct file_info *router_image_get_file_info(struct router_image *router_image, const char *file_name) { struct file_info *file_info; file_info = _router_image_get_file(router_image->file_list, file_name); if (!file_info) return NULL; return file_info; } static void router_image_set_size(struct router_image *router_image, const char *router_desc, unsigned int size) { struct list *list; struct router_info *router_info_tmp; slist_for_each (list, router_image->router_list) { router_info_tmp = (struct router_info *)list->data; if (router_desc && strcasecmp(router_info_tmp->router_name, router_desc) != 0) continue; if (!router_desc && router_info_tmp->file_size) continue; router_info_tmp->file_size = size; } } static int uboot_verify(struct router_image *router_image, const char *buff, unsigned int buff_len, int size) { int ret; if (buff_len < 4) return 0; /* uboot magic header */ if ((buff[0] != 0x27) || (buff[1] != 0x05) || (buff[2] != 0x19) || (buff[3] != 0x56)) return 0; ret = router_image_add_file(router_image, "mr500.bin", size, size, 0); if (ret) return 0; ret = router_image_add_file(router_image, "firmware.bin", size, size, 0); if (ret) return 0; router_image->file_size = size; return 1; } static int ubnt_verify(struct router_image *router_image, const char *buff, unsigned int buff_len, int size) { if (buff_len < 4) return 0; /* ubnt magic header */ if ((strncmp(buff, "UBNT", 4) != 0) && (strncmp(buff, "OPEN", 4) != 0)) return 0; router_image->file_size = size; return 1; } static int ci_verify(struct router_image *router_image, const char *buff, unsigned int buff_len, int size) { unsigned int kernel_size, rootfs_size; int ret; if (buff_len < 64) return 0; /* combined image magic header */ if ((buff[0] != 'C') || (buff[1] != 'I')) return 0; sscanf(buff, "CI%08x%08x", &kernel_size, &rootfs_size); if ((!kernel_size) || (!rootfs_size)) return 0; ret = router_image_add_file(router_image, "kernel", kernel_size, ((kernel_size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE, 64 * 1024); if (ret) return 0; ret = router_image_add_file(router_image, "rootfs", rootfs_size, ((rootfs_size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE, (64 * 1024) + kernel_size); if (ret) return 0; router_image->file_size = size - (64 * 1024); return 1; } static int strendswith(const char *str, const char *end) { size_t end_len = strlen(end); size_t str_len = strlen(str); if (end_len > str_len) return 0; if (strcmp(&str[str_len - end_len], end) == 0) return 1; return 0; } static void ce_calculate_router_file_size(struct router_image *router_image) { struct list *file_list = router_image->file_list; struct list *list; struct file_info *file_info_tmp; const char *router_desc; const char *file_name; unsigned int size; slist_for_each (list, file_list) { file_info_tmp = (struct file_info *)list->data; file_name = file_info_tmp->file_name; if (strncmp(file_name, fwupgradecfg, strlen(fwupgradecfg)) != 0) continue; if (strendswith(file_name, ".sig")) continue; router_desc = NULL; if (file_name[strlen(fwupgradecfg)] == '-') router_desc = &file_name[strlen(fwupgradecfg) + 1]; size = fwupgrade_cfg_read_sizes(router_image, file_info_tmp); if (!size) continue; router_image_set_size(router_image, router_desc, size); } } static int ce_verify(struct router_image *router_image, const char *buff, unsigned int buff_len, int size) { char name_buff[33], *name_ptr, md5_buff[33]; unsigned int num_files, hdr_offset, file_offset, file_size = 0; unsigned image_size = 0; unsigned int ce_version = 0, hdr_offset_sec; int ret; file_offset = 64 * 1024; if (buff_len < 100) return 0; /* ext combined image magic header */ if ((buff[0] != 'C') || (buff[1] != 'E')) return 0; /* the old format does not have a version field */ if (isxdigit(buff[2]) && isxdigit(buff[3])) { ret = sscanf(buff, "CE%02x", &ce_version); if (ret != 1) return 0; } switch (ce_version) { case 0: ret = sscanf(buff, "CE%10s%02x", name_buff, &num_files); if (ret != 2) return 0; hdr_offset = 14; hdr_offset_sec = 28; break; case 1: ret = sscanf(buff, "CE%*02x%32s%02x", name_buff, &num_files); if (ret != 2) return 0; hdr_offset = 38; hdr_offset_sec = 72; break; default: /* unsupported version */ return 0; } name_ptr = strtok(name_buff, ","); while (name_ptr) { router_image_router_add(router_image, name_ptr); name_ptr = strtok(NULL, ","); } while (num_files > 0) { if (hdr_offset + hdr_offset_sec > buff_len) { fprintf(stderr, "Error - buffer too small to parse CE header\n"); return 0; } switch (ce_version) { case 0: ret = sscanf(buff + hdr_offset, "%20s%08x", name_buff, &file_size); if (ret != 2) return 0; break; case 1: ret = sscanf(buff + hdr_offset, "%32s%08x%32s", name_buff, &file_size, md5_buff); if (ret != 3) return 0; break; } ret = router_image_add_file(router_image, name_buff, file_size, file_size, file_offset); if (ret) return 0; file_offset += file_size; hdr_offset += hdr_offset_sec; num_files--; if (strncmp(name_buff, fwupgradecfg, strlen(fwupgradecfg)) == 0) { if (strlen(fwupgradecfg) + 1 < strlen(name_buff) && !strendswith(name_buff, ".sig")) router_image_router_add(router_image, &name_buff[strlen(fwupgradecfg) + 1]); /*** * Don't add fwupgrade.cfg* files to the file size in * order to detect the end-of-flash correctly. */ continue; } image_size += file_size; } if (image_size > (unsigned)size) { fprintf(stderr, "Error - bogus CE image: claimed size bigger than actual size\n"); return 0; } router_image->file_size = image_size; /* calculate size of files referenced by fwupgrade.cfg of each router */ ce_calculate_router_file_size(router_image); return 1; } static int zyxel_verify(struct router_image *router_image, const char *buff, unsigned int buff_len, int size) { /* zyxel header: * 4 bytes: checksum of the rootfs image * 4 bytes: length of the contained rootfs image file (big endian) * 32 bytes: Firmware Version string (NUL terminated, 0xff padded) * 4 bytes: checksum over the header partition (big endian - see below) * 64 bytes: Model (e.g. "NBG6617", NUL termiated, 0xff padded) * 4 bytes: checksum of the kernel partition * 4 bytes: length of the contained kernel image file (big endian) * rest: 0xff padding (To erase block size) */ struct zyxel_header { uint32_t rootfs_chksum; uint32_t rootfs_size; char firmware_version[32]; uint32_t header_chksum; char model[64]; uint32_t kernel_chksum; uint32_t kernel_size; }; struct zyxel_header *zyxel_header; unsigned kernel_size, rootfs_size; unsigned zyxel_hdr_size = 64 * 1024; int ret; if (buff_len < sizeof(*zyxel_header)) return 0; zyxel_header = (struct zyxel_header *)buff; kernel_size = ntohl(zyxel_header->kernel_size); rootfs_size = ntohl(zyxel_header->rootfs_size); if ((unsigned)size != zyxel_hdr_size + kernel_size + rootfs_size) return 0; ret = router_image_add_file(router_image, "ras.bin", size, size, 0); if (ret) return 0; router_image->file_size = size; return 1; } static int router_image_init_embedded(struct router_image *router_image) { int ret = 0; #if defined(LINUX) || defined(OSX) router_image->embedded_img = router_image->embedded_img_pre_check; ret = router_image->image_verify(router_image, router_image->embedded_img_pre_check, (unsigned)router_image->embedded_file_size, (unsigned)router_image->embedded_file_size); if (ret != 1) router_image->embedded_img = NULL; #elif defined(WIN32) HGLOBAL hGlobal; HRSRC hRsrc; int size; char *buff; hRsrc = FindResource(NULL, MAKEINTRESOURCE(router_image->embedded_img_res), RT_RCDATA); if (hRsrc) { hGlobal = LoadResource(NULL, hRsrc); buff = LockResource(hGlobal); size = SizeofResource(NULL, hRsrc); router_image->embedded_img = buff; ret = router_image->image_verify(router_image, buff, size, size); if (ret != 1) router_image->embedded_img = NULL; } #endif return ret; } struct router_image img_uboot = { .type = IMAGE_TYPE_UBOOT, .desc = "uboot image", .image_verify = uboot_verify, }; struct router_image img_ubnt = { .type = IMAGE_TYPE_UBNT, .desc = "ubiquiti image", .image_verify = ubnt_verify, }; struct router_image img_ci = { .type = IMAGE_TYPE_CI, .desc = "combined image", .image_verify = ci_verify, }; struct router_image img_ce = { .type = IMAGE_TYPE_CE, .desc = "combined ext image", .image_verify = ce_verify, }; struct router_image img_zyxel = { .type = IMAGE_TYPE_ZYXEL, .desc = "Zyxel image", .image_verify = zyxel_verify, }; static struct router_image *router_images[] = { &img_uboot, &img_ubnt, &img_ci, &img_ce, &img_zyxel, NULL, }; void router_images_init(void) { struct router_image **router_image; for (router_image = router_images; *router_image; ++router_image) (*router_image)->file_list = NULL; } void router_images_init_embedded(void) { struct router_image **router_image; int ret; for (router_image = router_images; *router_image; ++router_image) { if ((*router_image)->path || (*router_image)->embedded_img) continue; if (!(*router_image)->image_verify) continue; switch ((*router_image)->type) { case IMAGE_TYPE_UNKNOWN: continue; case IMAGE_TYPE_UBOOT: #if defined(EMBED_UBOOT) #if defined(LINUX) (*router_image)->embedded_img_pre_check = (char *)&_binary_img_uboot_start; (*router_image)->embedded_file_size = (unsigned long)&_binary_img_uboot_size; #elif defined(OSX) (*router_image)->embedded_img_pre_check = getsectdata("__DATA", "_binary_img_uboot", &(*router_image)->embedded_file_size); if ((*router_image)->embedded_img_pre_check) (*router_image)->embedded_img_pre_check += _dyld_get_image_vmaddr_slide(0); #elif defined(WIN32) (*router_image)->embedded_img_res = IDR_UBOOT_IMG; #endif #endif break; case IMAGE_TYPE_UBNT: #if defined(EMBED_UBNT) #if defined(LINUX) (*router_image)->embedded_img_pre_check = (char *)&_binary_img_ubnt_start; (*router_image)->embedded_file_size = (unsigned long)&_binary_img_ubnt_size; #elif defined(OSX) (*router_image)->embedded_img_pre_check = getsectdata("__DATA", "_binary_img_ubnt", &(*router_image)->embedded_file_size); if ((*router_image)->embedded_img_pre_check) (*router_image)->embedded_img_pre_check += _dyld_get_image_vmaddr_slide(0); #elif defined(WIN32) (*router_image)->embedded_img_res = IDR_UBNT_IMG; #endif #endif break; case IMAGE_TYPE_CI: #if defined(EMBED_CI) #if defined(LINUX) (*router_image)->embedded_img_pre_check = (char *)&_binary_img_ci_start; (*router_image)->embedded_file_size = (unsigned long)&_binary_img_ci_size; #elif defined(OSX) (*router_image)->embedded_img_pre_check = getsectdata("__DATA", "_binary_img_ci", &(*router_image)->embedded_file_size); if ((*router_image)->embedded_img_pre_check) (*router_image)->embedded_img_pre_check += _dyld_get_image_vmaddr_slide(0); #elif defined(WIN32) (*router_image)->embedded_img_res = IDR_CI_IMG; #endif #endif break; case IMAGE_TYPE_CE: #if defined(EMBED_CE) #if defined(LINUX) (*router_image)->embedded_img_pre_check = (char *)&_binary_img_ce_start; (*router_image)->embedded_file_size = (unsigned long)&_binary_img_ce_size; #elif defined(OSX) (*router_image)->embedded_img_pre_check = getsectdata("__DATA", "_binary_img_ce", &(*router_image)->embedded_file_size); if ((*router_image)->embedded_img_pre_check) (*router_image)->embedded_img_pre_check += _dyld_get_image_vmaddr_slide(0); #elif defined(WIN32) (*router_image)->embedded_img_res = IDR_CE_IMG; #endif #endif break; case IMAGE_TYPE_ZYXEL: #if defined(EMBED_ZYXEL) #if defined(LINUX) (*router_image)->embedded_img_pre_check = (char *)&_binary_img_zyxel_start; (*router_image)->embedded_file_size = (unsigned long)&_binary_img_zyxel_size; #elif defined(OSX) (*router_image)->embedded_img_pre_check = getsectdata("__DATA", "_binary_img_zyxel", &(*router_image)->embedded_file_size); if ((*router_image)->embedded_img_pre_check) (*router_image)->embedded_img_pre_check += _dyld_get_image_vmaddr_slide(0); #elif defined(WIN32) (*router_image)->embedded_img_res = IDR_ZYXEL_IMG; #endif #endif break; } ret = router_image_init_embedded(*router_image); if (ret != 1) continue; #if defined(DEBUG) printf("init embedded image: %s found (%u bytes)\n", (*router_image)->desc, (*router_image)->file_size); #endif } } void router_images_print_desc(void) { struct router_image **router_image; for (router_image = router_images; *router_image; ++router_image) fprintf(stderr, " * %s\n", (*router_image)->desc); } int router_images_verify_path(const char *image_path) { struct router_image **router_image; char *file_buff = NULL, found_consumer = 0; unsigned int file_buff_size = 64 * 1024; // max CE hdr size int fd, file_size, ret = -1, len; file_buff = malloc(file_buff_size); if (!file_buff) goto out; fd = open(image_path, O_RDONLY | O_BINARY); if (fd < 0) { fprintf(stderr, "Error - can't open image file '%s': %s\n", image_path, strerror(errno)); goto out; } ret = (int)read(fd, file_buff, file_buff_size); if (ret < 0) { fprintf(stderr, "Error - can't read image file '%s': %s\n", image_path, strerror(errno)); goto close_fd; } len = ret; for (router_image = router_images; *router_image; ++router_image) { if ((*router_image)->path || (*router_image)->embedded_img) continue; if (!(*router_image)->image_verify) continue; file_size = (int)lseek(fd, 0, SEEK_END); if (file_size < 0) { fprintf(stderr, "Unable to retrieve file size of '%s': %s\n", image_path, strerror(errno)); continue; } (*router_image)->path = image_path; ret = (*router_image)->image_verify((*router_image), file_buff, len, file_size); if (ret != 1) { (*router_image)->path = NULL; continue; } found_consumer = 1; #if defined(DEBUG) printf("verify image path: %s: %s (%i bytes)\n", image_path, (*router_image)->desc, (*router_image)->file_size); #endif } if (!found_consumer) fprintf(stderr, "Unsupported image '%s': ignoring file\n", image_path); ret = 0; close_fd: close(fd); out: free(file_buff); return ret; } int router_images_open_path(struct node *node) { /* embedded image */ if ((!node->router_type->image->path) && (node->router_type->image->embedded_img) && (node->router_type->image->file_size > 0)) { node->image_state.fd = 1; goto out; } node->image_state.fd = open(node->router_type->image->path, O_RDONLY | O_BINARY); if (node->image_state.fd < 0) fprintf(stderr, "Error - can't open image file '%s': %s\n", node->router_type->image->path, strerror(errno)); out: return node->image_state.fd; } int router_images_read_data(char *dst, struct node *node) { int len = TFTP_PAYLOAD_SIZE, read_len; uint8_t *file_data; off_t reto; if (node->image_state.flash_size - node->image_state.bytes_sent < TFTP_PAYLOAD_SIZE) len = node->image_state.flash_size - node->image_state.bytes_sent; read_len = len; if (node->image_state.file_size < node->image_state.bytes_sent) read_len = 0; else if (node->image_state.file_size < node->image_state.bytes_sent + len) read_len = node->image_state.file_size - node->image_state.bytes_sent; if (node->router_type->image->path) { if (node->image_state.fd < 0) { #if defined(DEBUG) fprintf(stderr, "router_images_read_data(): image has file path but no open fd ??\n"); #endif goto err; } if (read_len > 0) { reto = lseek(node->image_state.fd, node->image_state.bytes_sent + node->image_state.offset, SEEK_SET); if (reto == (off_t) -1) { fprintf(stderr, "Error - seeking in file '%s': %s\n", node->router_type->image->path, strerror(errno)); return -1; } if (read_len != read(node->image_state.fd, dst, read_len)) { fprintf(stderr, "Error - reading from file '%s': %s\n", node->router_type->image->path, strerror(errno)); return -1; } } if (read_len != len) memset(dst + read_len, 0, len - read_len); return len; } else if (node->router_type->image->embedded_img) { file_data = (uint8_t *)node->router_type->image->embedded_img; file_data += node->image_state.bytes_sent; file_data += node->image_state.offset; if (read_len > 0) memcpy(dst, file_data, read_len); if (read_len != len) memset(dst + read_len, 0, len - read_len); return len; } err: return -1; } bool router_images_available(void) { struct router_image **router_image; for (router_image = router_images; *router_image; ++router_image) { if ((*router_image)->path || (*router_image)->embedded_img) return true; } return false; } void router_images_close_path(struct node *node) { if ((node->router_type->image->path) && (node->image_state.fd > 0)) close(node->image_state.fd); node->image_state.fd = -1; } ap51-flash-2019.0.1/router_images.h000066400000000000000000000041731353712067100166350ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_ROUTER_IMAGES_H__ #define __AP51_FLASH_ROUTER_IMAGES_H__ #include #include "ap51-flash.h" struct node; struct router_type; enum image_type { IMAGE_TYPE_UNKNOWN, IMAGE_TYPE_UBOOT, IMAGE_TYPE_UBNT, IMAGE_TYPE_CI, IMAGE_TYPE_CE, IMAGE_TYPE_ZYXEL, }; struct router_image { enum image_type type; char desc[DESC_MAX_LENGTH]; int (*image_verify)(struct router_image *router_image, const char *buff, unsigned int buff_len, int size); const char *path; char *embedded_img; #if defined(LINUX) char *embedded_img_pre_check; unsigned int embedded_file_size; #elif defined(OSX) char *embedded_img_pre_check; unsigned long embedded_file_size; #elif defined(WIN32) unsigned int embedded_img_res; #endif unsigned int file_size; struct list *file_list; struct list *router_list; }; struct router_info { char router_name[DESC_MAX_LENGTH]; unsigned int file_size; }; struct file_info { char file_name[FILE_NAME_MAX_LENGTH]; unsigned int file_offset; unsigned int file_size; unsigned int file_fsize; }; struct router_info *router_image_router_get(struct router_image *router_image, const char *router_desc); struct file_info *router_image_get_file(struct router_type *router_type, const char *file_name); void router_images_init(void); void router_images_init_embedded(void); bool router_images_available(void); void router_images_print_desc(void); int router_images_verify_path(const char *image_path); int router_images_open_path(struct node *node); int router_images_read_data(char *dst, struct node *node); void router_images_close_path(struct node *node); unsigned int router_image_get_size(struct router_type *router_type); struct file_info *router_image_get_file_info(struct router_image *router_image, const char *file_name); extern struct router_image img_uboot; extern struct router_image img_ubnt; extern struct router_image img_ci; extern struct router_image img_ce; extern struct router_image img_zyxel; #endif /* __AP51_FLASH_ROUTER_IMAGES_H__ */ ap51-flash-2019.0.1/router_netconsole.c000066400000000000000000000063741353712067100175410ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: Antonio Quartulli */ #include "router_netconsole.h" #include #include "compat.h" #include "flash.h" #include "proto.h" #include "router_images.h" #include "router_types.h" static const unsigned int ap121f_ip = 3232235777UL; /* 192.168.1.1 */ static const unsigned int my_ip = 3232235778UL; /* 192.168.1.2 */ static const uint8_t zero_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t ap121f_mac[] = { 0x00, 0x03, 0x7f, 0x09, 0x0b, 0xad }; enum netconsole_state { NETCONSOLE_STATE_WAITING, NETCONSOLE_STATE_STARTED, NETCONSOLE_STATE_DONE, NETCONSOLE_STATE_RESET, }; struct netconsole_priv { enum netconsole_state state; }; static int ap121f_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_spa) != htonl(ap121f_ip)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(my_ip)) goto out; if (memcmp(arphdr->arp_sha, ap121f_mac, ETH_ALEN)) goto out; if (memcmp(arphdr->arp_tha, zero_mac, ETH_ALEN)) goto out; ret = 1; out: return ret; } static void netconsole_detect_post(struct node *node, const char *packet_buff, int packet_buff_len) { struct netconsole_priv *priv = node->router_priv; struct ether_arp *arphdr; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; node->flash_mode = FLASH_MODE_NETCONSOLE; node->his_ip_addr = load_ip_addr(arphdr->arp_spa); node->our_ip_addr = load_ip_addr(arphdr->arp_tpa); priv->state = NETCONSOLE_STATE_WAITING; out: return; } const struct router_type ap121f = { .desc = "Alfa Network AP121F", .detect_main = ap121f_detect_main, .detect_post = netconsole_detect_post, .image = &img_uboot, .priv_size = sizeof(struct netconsole_priv), }; void handle_netconsole_packet(const char *packet_buff, int packet_buff_len, struct node *node) { struct netconsole_priv *priv = node->router_priv; #define PROMPT_STR "u-boot> " #define DONE_STR "DONE!" // fprintf(stderr, "received netconsole packet: '%s'\n", packet_buff); switch (priv->state) { case NETCONSOLE_STATE_WAITING: if (packet_buff_len < (int)strlen(PROMPT_STR)) return; if (strncmp(packet_buff, PROMPT_STR, strlen(PROMPT_STR)) != 0) return; netconsole_init_upload(node); priv->state = NETCONSOLE_STATE_STARTED; break; case NETCONSOLE_STATE_STARTED: /* check if we received the completion message */ if (packet_buff_len < (int)strlen(DONE_STR)) return; if (strncmp(packet_buff, DONE_STR, strlen(DONE_STR)) != 0) return; fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: flash complete. Rebooting\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); priv->state = NODE_STATUS_REBOOTED; #if defined(CLEAR_SCREEN) num_nodes_flashed++; #endif break; default: break; } } ap51-flash-2019.0.1/router_netconsole.h000066400000000000000000000006671353712067100175450ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: Antonio Quartulli */ #ifndef __AP51_FLASH_ROUTER_NETCONSOLE_H__ #define __AP51_FLASH_ROUTER_NETCONSOLE_H__ #define IPPORT_NETCONSOLE 6666 struct node; extern const struct router_type ap121f; void handle_netconsole_packet(const char *packet_buff, int packet_buff_len, struct node *node); #endif /* __AP51_FLASH_ROUTER_NETCONSOLE_H__ */ ap51-flash-2019.0.1/router_redboot.c000066400000000000000000000255221353712067100170220ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #include "router_redboot.h" #include #include #include #include #include #include "ap51-flash.h" #include "compat.h" #include "flash.h" #include "proto.h" #include "router_images.h" #include "router_types.h" enum redboot_state { REDBOOT_STATE_INIT, REDBOOT_STATE_VERSION, REDBOOT_STATE_IP_ADDR, REDBOOT_STATE_LD_KERNEL, REDBOOT_STATE_FL_KERNEL, REDBOOT_STATE_LD_ROOTFS, REDBOOT_STATE_FL_ROOTFS, REDBOOT_STATE_BSCRIPT, REDBOOT_STATE_BSCRIPTK, REDBOOT_STATE_EXEC, REDBOOT_STATE_EXECY, REDBOOT_STATE_RESET, REDBOOT_STATE_FINISHED, REDBOOT_STATE_FIS_INIT, REDBOOT_STATE_FIS_INITY, REDBOOT_STATE_FAILED, }; static const unsigned int ubnt_ip = 3232235796UL; /* 192.168.1.20 */ struct redboot_priv { int arp_count; enum redboot_state redboot_state; struct redboot_type *redboot_type; char *version_info; }; static int redboot_8mb_detect(struct node *node) { struct redboot_priv *redboot_priv = node->router_priv; unsigned long device_size = 0; char *flash_str; int num_blocks = 0, ret = 0; flash_str = strstr(redboot_priv->version_info, "FLASH:"); if (!flash_str) goto out; sscanf(flash_str, "FLASH: 0x%*08x - 0x%*08x, %d blocks of 0x%08lx bytes each", &num_blocks, &device_size); if ((!num_blocks) || (!device_size)) goto out; if (num_blocks * device_size != 0x800000) goto out; #if defined(DEBUG) fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: flash size of 8 MB was detected ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); #endif ret = 1; out: return ret; } #if defined(DEBUG) static int redboot_4mb_detect(struct node *node) #else static int redboot_4mb_detect(struct node (*node)__attribute__((unused))) #endif { /* default redboot type */ #if defined(DEBUG) fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: flash size of 4 MB was detected (default) ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); #endif return 1; } static const struct redboot_type redboot_8mb = { .flash_size = 0x7A0000, .freememlo = 0x80041000, /* %{FREEMEMLO} provokes errors on the meraki mini */ .flash_addr = 0xa8030000, .kernel_load_addr = 0x80041000, .detect = redboot_8mb_detect, }; static const struct redboot_type redboot_4mb = { .flash_size = 0x3A0000, .freememlo = 0, /* we can use %{FREEMEMLO} */ .flash_addr = 0xbfc30000, .kernel_load_addr = 0x80041000, .detect = redboot_4mb_detect, }; static const struct redboot_type *redboot_types[] = { &redboot_8mb, &redboot_4mb, NULL, }; static int redboot_type_detect(struct node *node) { struct redboot_priv *redboot_priv = node->router_priv; const struct redboot_type **redboot_type; int ret = 0; for (redboot_type = redboot_types; *redboot_type; ++redboot_type) { if (!(*redboot_type)->detect) continue; ret = (*redboot_type)->detect(node); if (ret != 1) continue; redboot_priv->redboot_type = (struct redboot_type *)(*redboot_type); break; } return ret; } void redboot_main(struct node *node, const char *telnet_msg) { struct redboot_priv *redboot_priv = node->router_priv; struct file_info *file_info; unsigned long req_flash_size; char buff[100]; switch (redboot_priv->redboot_state) { case REDBOOT_STATE_INIT: redboot_priv->redboot_state = REDBOOT_STATE_VERSION; telnet_send_cmd(node, "version\n"); break; case REDBOOT_STATE_VERSION: redboot_priv->version_info = malloc(strlen(telnet_msg) + 1); if (!redboot_priv->version_info) goto redboot_failure; strncpy(redboot_priv->version_info, telnet_msg, strlen(telnet_msg) + 1); redboot_priv->version_info[strlen(telnet_msg)] = '\0'; redboot_type_detect(node); req_flash_size = ((node->router_type->image->file_size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE; if (redboot_priv->redboot_type->flash_size < req_flash_size) { fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: image size '%s' of 0x%08lx exceeds router capacity: 0x%08lx\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc, node->router_type->image->path, req_flash_size, redboot_priv->redboot_type->flash_size); goto redboot_failure; } sprintf(buff, "ip_addr -l %d.%d.%d.%d/8 -h %d.%d.%d.%d\n", ((unsigned char *)&node->his_ip_addr)[0], ((unsigned char *)&node->his_ip_addr)[1], ((unsigned char *)&node->his_ip_addr)[2], ((unsigned char *)&node->his_ip_addr)[3], ((unsigned char *)&node->our_ip_addr)[0], ((unsigned char *)&node->our_ip_addr)[1], ((unsigned char *)&node->our_ip_addr)[2], ((unsigned char *)&node->our_ip_addr)[3]); printf("[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: setting IP address ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); telnet_send_cmd(node, buff); redboot_priv->redboot_state = REDBOOT_STATE_IP_ADDR; break; case REDBOOT_STATE_IP_ADDR: if (redboot_priv->redboot_type->freememlo) sprintf(buff, "load -r -b 0x%08lx -m tftp kernel\n", redboot_priv->redboot_type->freememlo); else sprintf(buff, "load -r -b %%{FREEMEMLO} -m tftp kernel\n"); telnet_send_cmd(node, buff); redboot_priv->redboot_state = REDBOOT_STATE_LD_KERNEL; break; case REDBOOT_STATE_LD_KERNEL: if ((unsigned int)node->image_state.bytes_sent < node->image_state.flash_size) { fprintf(stderr, "Error transferring kernel, send: %d, expected: %d\n", node->image_state.bytes_sent, node->image_state.flash_size); goto redboot_failure; } printf("[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: initializing partitions ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); telnet_send_cmd(node, "fis init\n"); redboot_priv->redboot_state = REDBOOT_STATE_FIS_INIT; break; case REDBOOT_STATE_FIS_INIT: telnet_send_cmd(node, "y\n"); redboot_priv->redboot_state = REDBOOT_STATE_FIS_INITY; break; case REDBOOT_STATE_FIS_INITY: sprintf(buff, "fis create -e 0x%08lx -r 0x%08lx vmlinux.bin.l7\n", redboot_priv->redboot_type->kernel_load_addr, redboot_priv->redboot_type->kernel_load_addr); printf("[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: flashing kernel ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); telnet_send_cmd(node, buff); redboot_priv->redboot_state = REDBOOT_STATE_FL_KERNEL; break; case REDBOOT_STATE_FL_KERNEL: if (redboot_priv->redboot_type->freememlo) sprintf(buff, "load -r -b 0x%08lx -m tftp rootfs\n", redboot_priv->redboot_type->freememlo); else sprintf(buff, "load -r -b %%{FREEMEMLO} -m tftp rootfs\n"); telnet_send_cmd(node, buff); redboot_priv->redboot_state = REDBOOT_STATE_LD_ROOTFS; break; case REDBOOT_STATE_LD_ROOTFS: file_info = router_image_get_file(node->router_type, "kernel"); if (!file_info) return; sprintf(buff, "fis create -f 0x%08lx -l 0x%08lx rootfs\n", redboot_priv->redboot_type->flash_addr + file_info->file_fsize, redboot_priv->redboot_type->flash_size - file_info->file_fsize); printf("[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: flashing rootfs ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); telnet_send_cmd(node, buff); redboot_priv->redboot_state = REDBOOT_STATE_FL_ROOTFS; break; case REDBOOT_STATE_FL_ROOTFS: printf("[%02x:%02x:%02x:%02x:%02x:%02x]: %s router: setting boot_script_data ...\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); telnet_send_cmd(node, "fconfig -d boot_script_data\n"); redboot_priv->redboot_state = REDBOOT_STATE_BSCRIPT; break; case REDBOOT_STATE_BSCRIPT: telnet_send_cmd(node, "fis load -l vmlinux.bin.l7\n"); redboot_priv->redboot_state = REDBOOT_STATE_BSCRIPTK; break; case REDBOOT_STATE_BSCRIPTK: telnet_send_cmd(node, "exec\n\n"); redboot_priv->redboot_state = REDBOOT_STATE_EXEC; break; case REDBOOT_STATE_EXEC: telnet_send_cmd(node, "y\n"); redboot_priv->redboot_state = REDBOOT_STATE_EXECY; break; case REDBOOT_STATE_EXECY: telnet_send_cmd(node, "reset\n"); redboot_priv->redboot_state = REDBOOT_STATE_FINISHED; node->status = NODE_STATUS_RESET_SENT; break; default: break; } return; redboot_failure: redboot_priv->redboot_state = REDBOOT_STATE_FAILED; // TODO: close telnet connection ? return; } static int redboot_detect_main(void *priv, const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; struct redboot_priv *redboot_priv = priv; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; /* we are waiting for gratuitous ARP requests */ if (load_ip_addr(arphdr->arp_spa) != load_ip_addr(arphdr->arp_tpa)) goto out; /** * use gratuitous ARP requests from ubnt devices with care * the ubnt pico can be in redboot or tftp server mode */ if (load_ip_addr(arphdr->arp_spa) == htonl(ubnt_ip)) { if (redboot_priv->arp_count < 5) { redboot_priv->arp_count++; goto out; } } /* printf("redboot_detect_main(): receiving packet: len: %i (arp: %i, arp_count: %i)\n", packet_buff_len, sizeof(struct ether_arp), redboot_priv->arp_count);*/ ret = 1; out: return ret; } static void redboot_detect_post(struct node *node, const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->arp_tpa[3] == 20) arphdr->arp_tpa[3] = 1; else arphdr->arp_tpa[3] = 20; node->flash_mode = FLASH_MODE_REDBOOT; node->his_ip_addr = load_ip_addr(arphdr->arp_spa); node->our_ip_addr = load_ip_addr(arphdr->arp_tpa); out: return; } const struct router_type redboot = { .desc = "redboot", .detect_pre = NULL, .detect_main = redboot_detect_main, .detect_post = redboot_detect_post, .image = &img_ci, .priv_size = sizeof(struct redboot_priv), }; ap51-flash-2019.0.1/router_redboot.h000066400000000000000000000010461353712067100170220ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_ROUTER_REDBOOT_H__ #define __AP51_FLASH_ROUTER_REDBOOT_H__ struct node; struct redboot_type { unsigned long flash_size; unsigned long freememlo; unsigned long flash_addr; unsigned long kernel_load_addr; int (*detect)(struct node *node); }; extern const struct router_type redboot; void redboot_main(struct node *node, const char *telnet_msg); #endif /* __AP51_FLASH_ROUTER_REDBOOT_H__ */ ap51-flash-2019.0.1/router_tftp_client.c000066400000000000000000000524721353712067100177030ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner * SPDX-FileCopyrightText: 2014-2019, Sven Eckelmann */ #include "router_tftp_client.h" #include #include #include #include #include "compat.h" #include "flash.h" #include "proto.h" #include "router_images.h" #include "router_types.h" static const unsigned int mr500_ip = 3232260872UL; /* 192.168.99.8 */ static const unsigned int om2p_ip = 3232261128UL; /* 192.168.100.8 */ static const unsigned int zyxel_ip = 3232235875UL; /* 192.168.1.99 */ struct mr500_priv { time_t start_flash; }; struct om2p_priv { time_t start_flash; }; static void tftp_client_detect_post(struct node *node, const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; node->flash_mode = FLASH_MODE_TFTP_CLIENT; node->his_ip_addr = load_ip_addr(arphdr->arp_spa); node->our_ip_addr = load_ip_addr(arphdr->arp_tpa); out: return; } void tftp_client_flash_time_set(struct node *node) { struct mr500_priv *mr500_priv; struct om2p_priv *om2p_priv; if (node->router_type == &mr500) { mr500_priv = node->router_priv; mr500_priv->start_flash = time(NULL); } else if ((node->router_type == &mr600) || (node->router_type == &mr900) || (node->router_type == &mr1750) || (node->router_type == &a40) || (node->router_type == &a42) || (node->router_type == &a60) || (node->router_type == &a62) || (node->router_type == &om2p) || (node->router_type == &om5p) || (node->router_type == &om5pac) || (node->router_type == &om5pan) || (node->router_type == &p60) || (node->router_type == &d200) || (node->router_type == &g200) || (node->router_type == &pa300) || (node->router_type == &pa1200) || (node->router_type == &pa2200) || (node->router_type == &zyxel)) { om2p_priv = node->router_priv; om2p_priv->start_flash = time(NULL); } } int tftp_client_flash_completed(struct node *node) { struct mr500_priv *mr500_priv; struct om2p_priv *om2p_priv; time_t time2flash; if (node->router_type == &mr500) { mr500_priv = node->router_priv; time2flash = mr500_priv->start_flash + 45 + (node->image_state.total_bytes_sent / 65536); } else if ((node->router_type == &mr600) || (node->router_type == &mr900) || (node->router_type == &mr1750) || (node->router_type == &a40) || (node->router_type == &a42) || (node->router_type == &a60) || (node->router_type == &a62) || (node->router_type == &om2p) || (node->router_type == &om5p) || (node->router_type == &om5pac) || (node->router_type == &om5pan) || (node->router_type == &p60) || (node->router_type == &d200) || (node->router_type == &g200) || (node->router_type == &pa300) || (node->router_type == &pa1200) || (node->router_type == &pa2200) || (node->router_type == &zyxel)) { om2p_priv = node->router_priv; time2flash = om2p_priv->start_flash + 10 + (node->image_state.total_bytes_sent / 65536); } else { return 0; } if (time(NULL) < time2flash) return 0; return 1; } static int mr500_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(mr500_ip)) goto out; ret = 1; out: return ret; } const struct router_type mr500 = { .desc = "MR500 router", .detect_pre = NULL, .detect_main = mr500_detect_main, .detect_post = tftp_client_detect_post, .image = &img_uboot, .priv_size = sizeof(struct mr500_priv), }; static int mr600_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'M') goto out; if (arphdr->arp_tha[1] != 'R') goto out; if (arphdr->arp_tha[2] != '6') goto out; if (arphdr->arp_tha[3] != '0') goto out; if (arphdr->arp_tha[4] != '0') goto out; ret = 1; out: return ret; } const struct router_type mr600 = { .desc = "MR600", .detect_pre = NULL, .detect_main = mr600_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int mr900_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'M') goto out; if (arphdr->arp_tha[1] != 'R') goto out; if (arphdr->arp_tha[2] != '9') goto out; if (arphdr->arp_tha[3] != '0') goto out; if (arphdr->arp_tha[4] != '0') goto out; ret = 1; out: return ret; } const struct router_type mr900 = { .desc = "MR900", .detect_pre = NULL, .detect_main = mr900_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int mr1750_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'M') goto out; if (arphdr->arp_tha[1] != 'R') goto out; if (arphdr->arp_tha[2] != '1') goto out; if (arphdr->arp_tha[3] != '7') goto out; if (arphdr->arp_tha[4] != '5') goto out; if (arphdr->arp_tha[5] != '0') goto out; ret = 1; out: return ret; } const struct router_type mr1750 = { .desc = "MR1750", .detect_pre = NULL, .detect_main = mr1750_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static bool om2p_orig_arp(const uint8_t arp_tha[ETH_ALEN]) { /* target mac address field has to be zero */ if (arp_tha[0] != '\0') return false; if (arp_tha[1] != '\0') return false; if (arp_tha[2] != '\0') return false; if (arp_tha[3] != '\0') return false; if (arp_tha[4] != '\0') return false; if (arp_tha[5] != '\0') return false; return true; } static bool om2p_v4_arp(const uint8_t arp_tha[ETH_ALEN]) { if (arp_tha[0] != 'O') return false; if (arp_tha[1] != 'M') return false; if (arp_tha[2] != '2') return false; if (arp_tha[3] != 'P') return false; if (arp_tha[4] != 'V') return false; if (arp_tha[5] != '4') return false; return true; } static int om2p_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (!om2p_orig_arp(arphdr->arp_tha) && !om2p_v4_arp(arphdr->arp_tha)) goto out; ret = 1; out: return ret; } const struct router_type om2p = { .desc = "OM2P", .detect_pre = NULL, .detect_main = om2p_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int a40_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'A') goto out; if (arphdr->arp_tha[1] != '4') goto out; if (arphdr->arp_tha[2] != '0') goto out; if (arphdr->arp_tha[3] != '\0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type a40 = { .desc = "A40", .detect_pre = NULL, .detect_main = a40_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .image_desc = "A60", .priv_size = sizeof(struct om2p_priv), }; static int a60_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'A') goto out; if (arphdr->arp_tha[1] != '6') goto out; if (arphdr->arp_tha[2] != '0') goto out; if (arphdr->arp_tha[3] != '\0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type a60 = { .desc = "A60", .detect_pre = NULL, .detect_main = a60_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int a42_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'A') goto out; if (arphdr->arp_tha[1] != '4') goto out; if (arphdr->arp_tha[2] != '2') goto out; if (arphdr->arp_tha[3] != '\0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type a42 = { .desc = "A42", .detect_pre = NULL, .detect_main = a42_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int a62_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'A') goto out; if (arphdr->arp_tha[1] != '6') goto out; if (arphdr->arp_tha[2] != '2') goto out; if (arphdr->arp_tha[3] != '\0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type a62 = { .desc = "A62", .detect_pre = NULL, .detect_main = a62_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int om5p_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'O') goto out; if (arphdr->arp_tha[1] != 'M') goto out; if (arphdr->arp_tha[2] != '5') goto out; if (arphdr->arp_tha[3] != 'P') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type om5p = { .desc = "OM5P", .detect_pre = NULL, .detect_main = om5p_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int om5pan_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'O') goto out; if (arphdr->arp_tha[1] != 'M') goto out; if (arphdr->arp_tha[2] != '5') goto out; if (arphdr->arp_tha[3] != 'P') goto out; if (arphdr->arp_tha[4] != 'A') goto out; if (arphdr->arp_tha[5] != 'N') goto out; ret = 1; out: return ret; } const struct router_type om5pan = { .desc = "OM5P-AN", .detect_pre = NULL, .detect_main = om5pan_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .image_desc = "OM5P", .priv_size = sizeof(struct om2p_priv), }; static int om5pac_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'O') goto out; if (arphdr->arp_tha[1] != 'M') goto out; if (arphdr->arp_tha[2] != '5') goto out; if (arphdr->arp_tha[3] != 'P') goto out; if (arphdr->arp_tha[4] != 'A') goto out; if (arphdr->arp_tha[5] != 'C') goto out; ret = 1; out: return ret; } const struct router_type om5pac = { .desc = "OM5P-AC", .detect_pre = NULL, .detect_main = om5pac_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .image_desc = "OM5PAC", .priv_size = sizeof(struct om2p_priv), }; static int p60_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'P') goto out; if (arphdr->arp_tha[1] != '6') goto out; if (arphdr->arp_tha[2] != '0') goto out; if (arphdr->arp_tha[3] != '\0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type p60 = { .desc = "P60", .detect_pre = NULL, .detect_main = p60_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .image_desc = "P60", .priv_size = sizeof(struct om2p_priv), }; static int d200_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'D') goto out; if (arphdr->arp_tha[1] != '2') goto out; if (arphdr->arp_tha[2] != '0') goto out; if (arphdr->arp_tha[3] != '0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type d200 = { .desc = "D200", .detect_pre = NULL, .detect_main = d200_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .image_desc = "D200", .priv_size = sizeof(struct om2p_priv), }; static int g200_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'G') goto out; if (arphdr->arp_tha[1] != '2') goto out; if (arphdr->arp_tha[2] != '0') goto out; if (arphdr->arp_tha[3] != '0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type g200 = { .desc = "G200", .detect_pre = NULL, .detect_main = g200_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .image_desc = "G200", .priv_size = sizeof(struct om2p_priv), }; static int pa300_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if (arphdr->arp_tha[0] != 'P') goto out; if (arphdr->arp_tha[1] != 'A') goto out; if (arphdr->arp_tha[2] != '3') goto out; if (arphdr->arp_tha[3] != '0') goto out; if (arphdr->arp_tha[4] != '0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type pa300 = { .desc = "PA300", .detect_pre = NULL, .detect_main = pa300_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int pa1200_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if ((arphdr->arp_tha[0] == 'R') && (arphdr->arp_tha[1] == 'K') && (arphdr->arp_tha[2] == '1') && (arphdr->arp_tha[3] == '2') && (arphdr->arp_tha[4] == '0') && (arphdr->arp_tha[5] == '0')) return 1; if ((arphdr->arp_tha[0] == 'P') && (arphdr->arp_tha[1] == 'A') && (arphdr->arp_tha[2] == '1') && (arphdr->arp_tha[3] == '2') && (arphdr->arp_tha[4] == '0') && (arphdr->arp_tha[5] == '0')) return 1; out: return ret; } const struct router_type pa1200 = { .desc = "PA1200", .detect_pre = NULL, .detect_main = pa1200_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int pa2200_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(om2p_ip)) goto out; if ((arphdr->arp_tha[0] == 'R') && (arphdr->arp_tha[1] == 'K') && (arphdr->arp_tha[2] == '2') && (arphdr->arp_tha[3] == '1') && (arphdr->arp_tha[4] == '0') && (arphdr->arp_tha[5] == '0')) return 1; if ((arphdr->arp_tha[0] == 'P') && (arphdr->arp_tha[1] == 'A') && (arphdr->arp_tha[2] == '2') && (arphdr->arp_tha[3] == '2') && (arphdr->arp_tha[4] == '0') && (arphdr->arp_tha[5] == '0')) return 1; out: return ret; } const struct router_type pa2200 = { .desc = "PA2200", .detect_pre = NULL, .detect_main = pa2200_detect_main, .detect_post = tftp_client_detect_post, .image = &img_ce, .priv_size = sizeof(struct om2p_priv), }; static int zyxel_detect_main(void (*priv)__attribute__((unused)), const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REQUEST)) goto out; if (*((unsigned int *)arphdr->arp_tpa) != htonl(zyxel_ip)) goto out; if (arphdr->arp_tha[0] != '\0') goto out; if (arphdr->arp_tha[1] != '\0') goto out; if (arphdr->arp_tha[2] != '\0') goto out; if (arphdr->arp_tha[3] != '\0') goto out; if (arphdr->arp_tha[4] != '\0') goto out; if (arphdr->arp_tha[5] != '\0') goto out; ret = 1; out: return ret; } const struct router_type zyxel = { .desc = "Zyxel", .detect_pre = NULL, .detect_main = zyxel_detect_main, .detect_post = tftp_client_detect_post, .image = &img_zyxel, .image_desc = "Zyxel", .priv_size = sizeof(struct om2p_priv), }; ap51-flash-2019.0.1/router_tftp_client.h000066400000000000000000000021641353712067100177010ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_ROUTER_TFTP_CLIENT_H__ #define __AP51_FLASH_ROUTER_TFTP_CLIENT_H__ struct node; extern const struct router_type a40; extern const struct router_type a42; extern const struct router_type a60; extern const struct router_type a62; extern const struct router_type d200; extern const struct router_type g200; extern const struct router_type mr1750; extern const struct router_type mr500; extern const struct router_type mr600; extern const struct router_type mr900; extern const struct router_type om2p; extern const struct router_type om5p; extern const struct router_type om5pac; extern const struct router_type om5pan; extern const struct router_type p60; extern const struct router_type pa300; extern const struct router_type pa1200; extern const struct router_type pa2200; extern const struct router_type zyxel; void tftp_client_flash_time_set(struct node *node); int tftp_client_flash_completed(struct node *node); #endif /* __AP51_FLASH_ROUTER_TFTP_CLIENT_H__ */ ap51-flash-2019.0.1/router_tftp_server.c000066400000000000000000000034511353712067100177240ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #include "router_tftp_server.h" #include #include "compat.h" #include "flash.h" #include "proto.h" #include "router_images.h" #include "router_types.h" static const unsigned int ubnt_ip = 3232235796UL; /* 192.168.1.20 */ static const unsigned int my_ip = 3232235801UL; /* 192.168.1.25 */ struct ubnt_priv { int arp_count; }; static void ubnt_detect_pre(const uint8_t *our_mac) { uint8_t bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; arp_req_send(our_mac, bcast_mac, htonl(my_ip), htonl(ubnt_ip)); } static int ubnt_detect_main(void *priv, const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; struct ubnt_priv *ubnt_priv = priv; int ret = 0; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; if (arphdr->ea_hdr.ar_op != htons(ARPOP_REPLY)) goto out; if (load_ip_addr(arphdr->arp_spa) != htonl(ubnt_ip)) goto out; if (ubnt_priv->arp_count < 20) { ubnt_priv->arp_count++; goto out; } ret = 1; out: return ret; } static void ubnt_detect_post(struct node *node, const char *packet_buff, int packet_buff_len) { struct ether_arp *arphdr; if (!len_check(packet_buff_len, sizeof(struct ether_arp), "ARP")) goto out; arphdr = (struct ether_arp *)packet_buff; node->flash_mode = FLASH_MODE_TFTP_SERVER; node->his_ip_addr = load_ip_addr(arphdr->arp_spa); node->our_ip_addr = load_ip_addr(arphdr->arp_tpa); out: return; } const struct router_type ubnt = { .desc = "ubiquiti", .detect_pre = ubnt_detect_pre, .detect_main = ubnt_detect_main, .detect_post = ubnt_detect_post, .image = &img_ubnt, .priv_size = sizeof(struct ubnt_priv), }; ap51-flash-2019.0.1/router_tftp_server.h000066400000000000000000000004641353712067100177320ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_ROUTER_TFTP_SERVER_H__ #define __AP51_FLASH_ROUTER_TFTP_SERVER_H__ extern const struct router_type ubnt; #endif /* __AP51_FLASH_ROUTER_TFTP_SERVER_H__ */ ap51-flash-2019.0.1/router_types.c000066400000000000000000000127211353712067100165250ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #include "router_types.h" #include #include #include #include "compat.h" #include "flash.h" #include "list.h" #include "router_images.h" #include "router_redboot.h" #include "router_tftp_client.h" #include "router_tftp_server.h" #include "router_netconsole.h" #if defined(CLEAR_SCREEN) #if defined(LINUX) || defined(WIN32) #include #endif #endif int router_types_priv_size = 0; static struct mac_whitelist_entry *mac_whitelist_head; static const struct router_type *router_types[] = { &a40, &a42, &a60, &a62, &d200, &g200, &mr1750, &mr500, &mr600, &mr900, &om2p, &om5p, &om5pac, &om5pan, &p60, &redboot, &ubnt, &zyxel, &ap121f, &pa300, &pa1200, &pa2200, NULL, }; static int read_mac(uint8_t mac[ETH_ALEN], const char *macstr) { int ret; ret = sscanf(macstr, "%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); if (ret != 6) ret = sscanf(macstr, "%02hhX-%02hhX-%02hhX-%02hhX-%02hhX-%02hhX", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); return (ret == 6); } int mac_whitelist_add(const char *macstr) { uint8_t mac[ETH_ALEN]; struct mac_whitelist_entry *new_entry; if (!read_mac(mac, macstr)) { fprintf(stderr, "Error - could not add MAC address to whitelist: %s\n", macstr); return -EINVAL; } new_entry = malloc(sizeof(*new_entry)); if (!new_entry) { fprintf(stderr, "Error - could not allocate memory for new MAC whitelist entry\n"); return -ENOMEM; } memcpy(new_entry->mac, mac, ETH_ALEN); new_entry->next = mac_whitelist_head; mac_whitelist_head = new_entry; return 0; } static bool mac_whitelist_find(const uint8_t *mac) { struct mac_whitelist_entry *current; slist_for_each (current, mac_whitelist_head) { if (memcmp(mac, current->mac, ETH_ALEN) == 0) return true; } return false; } int router_types_init(void) { int ret = -1; const struct router_type **router_type; for (router_type = router_types; *router_type; ++router_type) { if (!(*router_type)->image) { fprintf(stderr, "Error - can't have router definition without image attribute set: %s\n", (*router_type)->desc); goto out; } router_types_priv_size += (*router_type)->priv_size; } ret = 0; out: return ret; } void router_types_detect_pre(const uint8_t *our_mac) { const struct router_type **router_type; for (router_type = router_types; *router_type; ++router_type) { if (!(*router_type)->detect_pre) continue; (*router_type)->detect_pre(our_mac); } } int router_types_detect_main(struct node *node, const char *packet_buff, int packet_buff_len) { const struct router_type **router_type; struct router_info *router_info; void *priv = node + 1; int ret = 0; for (router_type = router_types; *router_type; ++router_type) { if (!(*router_type)->detect_main) goto next; ret = (*router_type)->detect_main(priv, packet_buff, packet_buff_len); if (ret != 1) goto next; /* we detected a router that we have no image for */ if ((*router_type)->image->file_size < 1) { fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: is of type '%s' that we have no image for\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], (*router_type)->desc); node->status = NODE_STATUS_NO_FLASH; ret = 0; break; } /* we detected a router whose MAC is not whitelisted */ if (mac_whitelist_head != NULL && !mac_whitelist_find(node->his_mac_addr)) { fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: is of type '%s' but MAC does not match MAC filter\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], (*router_type)->desc); node->status = NODE_STATUS_NO_FLASH; ret = 0; break; } if ((*router_type)->image->type == IMAGE_TYPE_CE) { router_info = router_image_router_get((*router_type)->image, (*router_type)->image_desc ? (char *)(*router_type)->image_desc : (char *)(*router_type)->desc); if (!router_info) { fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: is of type '%s' that we have no image for (ce)\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], (*router_type)->desc); node->status = NODE_STATUS_NO_FLASH; ret = 0; break; } } our_mac_set(node); node->router_type = (struct router_type *)(*router_type); node->router_priv = priv; #if defined(CLEAR_SCREEN) #if defined(LINUX) if (num_nodes_flashed > 0) ret = system("clear"); #elif defined(WIN32) if (num_nodes_flashed > 0) ret = system("cls"); #else #error CLEAR_SCREEN is not supported on your OS #endif /* keep gcc happy by retrieving the return value of the system() call */ ret = 1; #endif fprintf(stderr, "[%02x:%02x:%02x:%02x:%02x:%02x]: type '%s router' detected\n", node->his_mac_addr[0], node->his_mac_addr[1], node->his_mac_addr[2], node->his_mac_addr[3], node->his_mac_addr[4], node->his_mac_addr[5], node->router_type->desc); if (!(*router_type)->detect_post) break; (*router_type)->detect_post(node, packet_buff, packet_buff_len); break; next: priv = (char *)priv + (*router_type)->priv_size; } return ret; } ap51-flash-2019.0.1/router_types.h000066400000000000000000000026721353712067100165360ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_ROUTER_TYPES_H__ #define __AP51_FLASH_ROUTER_TYPES_H__ #include #include "ap51-flash.h" #include "compat.h" struct node; /** * each router type has to declare a router_type struct * and add a pointer to the router_types array * * detect_pre: called by the scheduler in regular intervals * can be used to send ARP requests * detect_main: called when an ARP packet is received * return 1 if the router has been detected * detect_post: called to let the router_type configure * the node#s settings (e.g. IP) */ struct router_type { char desc[DESC_MAX_LENGTH]; void (*detect_pre)(const uint8_t *our_mac); int (*detect_main)(void *priv, const char *packet_buff, int packet_buff_len); void (*detect_post)(struct node *node, const char *packet_buff, int packet_buff_len); struct router_image *image; char *image_desc; int priv_size; }; struct mac_whitelist_entry { uint8_t mac[ETH_ALEN]; struct mac_whitelist_entry *next; }; int router_types_init(void); void router_types_detect_pre(const uint8_t *our_mac); int router_types_detect_main(struct node *node, const char *packet_buff, int packet_buff_len); int mac_whitelist_add(const char *macstr); extern int router_types_priv_size; #endif /* __AP51_FLASH_ROUTER_TYPES_H__ */ ap51-flash-2019.0.1/socket.c000066400000000000000000000307371353712067100152600ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #include "socket.h" #include #include #include #include #include #include #include #include "compat.h" #ifdef USE_PCAP #include "list.h" #endif #if defined(LINUX) #define BUFF_LEN 8192 struct resp { struct nlmsghdr nh; unsigned char payload[BUFF_LEN]; }; static int raw_sock = -1; static int socket_get_all_ifaces(struct resp **resp, unsigned int *len) { struct { struct nlmsghdr nh; struct ifinfomsg ifinfomsg; } req; struct sockaddr_nl nl; struct nlmsgerr *nlme; struct nlmsghdr *nh; int ret = -1, sock; sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sock < 0) { fprintf(stderr, "Error - can't create netlink socket: %s\n", strerror(errno)); goto out; } memset(&nl, 0, sizeof(nl)); nl.nl_family = AF_NETLINK; ret = bind(sock, (struct sockaddr *)&nl, sizeof(nl)); if (ret < 0) { fprintf(stderr, "Error - can't bind netlink socket: %s\n", strerror(errno)); goto close_sock; } memset(&req, 0, sizeof(req)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.ifinfomsg)); req.nh.nlmsg_type = RTM_GETLINK; req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; req.ifinfomsg.ifi_family = AF_UNSPEC; ret = send(sock, &req, sizeof(req), 0); if (ret < 0) { fprintf(stderr, "Error - unable to send netlink request: %s\n", strerror(errno)); goto close_sock; } *resp = malloc(sizeof(struct nlmsghdr) + BUFF_LEN); if (!*resp) goto close_sock; ret = recv(sock, *resp, sizeof(struct nlmsghdr) + BUFF_LEN, 0); if (ret < 0) { fprintf(stderr, "Error - unable to receive netlink request: %s\n", strerror(errno)); goto free_resp; } *len = ret; nh = &(*resp)->nh; if (nh->nlmsg_type == NLMSG_ERROR) { nlme = NLMSG_DATA(nh); fprintf(stderr, "Error - netlink complained: %i\n", nlme->error); goto free_resp; } ret = 0; goto close_sock; free_resp: free(*resp); *resp = NULL; ret = -1; close_sock: close(sock); out: return ret; } #elif USE_PCAP pcap_t *pcap_fp = NULL; #endif char *socket_find_iface_by_index(const char *iface_number) { #if defined(LINUX) struct ifinfomsg *ifinfomsg; struct nlmsghdr *nh; struct rtattr *rta; struct resp *resp = NULL; unsigned int len = 0, if_count = 1; int ret, if_num; size_t attr_len; char *iface = NULL; if_num = strtol(iface_number, NULL, 10); if (if_num < 1) goto out; ret = socket_get_all_ifaces(&resp, &len); if (ret < 0) goto out; nh = &resp->nh; for (;NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh->nlmsg_type == NLMSG_DONE) break; if (nh->nlmsg_type != RTM_NEWLINK) continue; ifinfomsg = NLMSG_DATA(nh); rta = IFLA_RTA(ifinfomsg); attr_len = IFLA_PAYLOAD(nh); for (; RTA_OK(rta, attr_len); rta = RTA_NEXT(rta, attr_len)) { char *rta_data = RTA_DATA(rta); size_t rta_payload = RTA_PAYLOAD(rta); if (rta_payload <= 0) continue; rta_data[rta_payload - 1] = '\0'; if (rta->rta_type != IFLA_IFNAME) continue; if (strncmp(rta_data, "lo", rta_payload) == 0) continue; if (if_count == (unsigned int)if_num) { iface = strdup(rta_data); goto free_resp; } if_count++; } } free_resp: free(resp); out: return iface; #elif USE_PCAP pcap_if_t *alldevs = NULL, *dev; char errbuf[PCAP_ERRBUF_SIZE]; char *iface = NULL; long if_num; int ret, i; if_num = strtol(iface_number, NULL, 10); if (if_num < 1) goto out; ret = pcap_findalldevs(&alldevs, errbuf); if (ret < 0) goto out; i = 0; slist_for_each (dev, alldevs) { i++; if (if_num != i) continue; iface = strdup(dev->name); break; } if (alldevs) pcap_freealldevs(alldevs); out: return iface; #else #error socket_find_dev_by_index() is not supported on your OS return NULL; #endif } void socket_print_all_ifaces(void) { #if defined(LINUX) struct ifinfomsg *ifinfomsg; struct nlmsghdr *nh; struct rtattr *rta; struct resp *resp = NULL; unsigned int len = 0, if_count = 1; int ret; size_t attr_len; ret = socket_get_all_ifaces(&resp, &len); if (ret < 0) goto out; nh = &resp->nh; for (;NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) { if (nh->nlmsg_type == NLMSG_DONE) break; if (nh->nlmsg_type != RTM_NEWLINK) continue; ifinfomsg = NLMSG_DATA(nh); rta = IFLA_RTA(ifinfomsg); attr_len = IFLA_PAYLOAD(nh); for (; RTA_OK(rta, attr_len); rta = RTA_NEXT(rta, attr_len)) { char *rta_data = RTA_DATA(rta); size_t rta_payload = RTA_PAYLOAD(rta); if (rta_payload <= 0) continue; rta_data[rta_payload - 1] = '\0'; if (rta->rta_type != IFLA_IFNAME) continue; if (strncmp(rta_data, "lo", rta_payload) == 0) continue; fprintf(stderr, "%i: %s\n", if_count, rta_data); fprintf(stderr, "\t(No description available)\n"); if_count++; } } free(resp); out: return; #elif USE_PCAP pcap_if_t *alldevs = NULL, *dev; unsigned char *ptr, c; char errbuf[PCAP_ERRBUF_SIZE]; int ret, i; ret = pcap_findalldevs(&alldevs, errbuf); if (ret < 0) { fprintf(stderr, "Error - unable to retrieve interface list: %s\n", errbuf); goto out; } i = 0; slist_for_each (dev, alldevs) { i++; fprintf(stderr, "\n%i: %s\n", i, dev->name); if (!dev->description) { fprintf(stderr, "\t(No description available)\n"); continue; } ptr = (unsigned char *)dev->description; c = 0; fprintf(stderr, "\t(Description: "); while (' ' <= *ptr) { if (c != ' ' || c != *ptr) fprintf(stderr, "%c", *ptr); c = *ptr++; } fprintf(stderr, ")\n"); } if (alldevs) pcap_freealldevs(alldevs); out: return; #else #error socket_print_all_devices() is not supported on your OS #endif } int socket_open(const char *iface) { #if defined(LINUX) struct sockaddr_ll addr; struct ifreq req; int ret, sock_opts; if (strlen(iface) > IFNAMSIZ - 1) { fprintf(stderr, "Error - interface name too long: %s\n", iface); goto out; } raw_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (raw_sock < 0) { fprintf(stderr, "Error - can't create raw socket: %s\n", strerror(errno)); goto out; } memset(&req, 0, sizeof (struct ifreq)); strncpy(req.ifr_name, iface, IFNAMSIZ); req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; ret = ioctl(raw_sock, SIOCGIFFLAGS, &req); if (ret < 0) { if (errno == ENODEV) fprintf(stderr, "Error - interface does not exist: %s\n", iface); else fprintf(stderr, "Error - can't get interface flags (SIOCGIFFLAGS): %s\n", strerror(errno)); goto close_sock; } if (!(req.ifr_flags & (IFF_UP | IFF_RUNNING))) { fprintf(stderr, "Error - interface is not up & running: %s\n", iface); goto close_sock; } req.ifr_flags |= IFF_PROMISC; ret = ioctl(raw_sock, SIOCSIFFLAGS, &req); if (ret < 0) { fprintf(stderr, "Error - can't set interface flags (SIOCSIFFLAGS): %s\n", strerror(errno)); goto close_sock; } ret = ioctl(raw_sock, SIOCGIFINDEX, &req); if (ret < 0) { fprintf(stderr, "Error - can't get interface index (SIOCGIFINDEX): %s\n", strerror(errno)); goto close_sock; } addr.sll_family = AF_PACKET; addr.sll_protocol = htons(ETH_P_ALL); addr.sll_ifindex = req.ifr_ifindex; ret = bind(raw_sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_ll)); if (ret < 0) { fprintf(stderr, "Error - can't bind raw socket: %s\n", strerror(errno)); goto close_sock; } sock_opts = fcntl(raw_sock, F_GETFL, 0); if (sock_opts == -1) { fprintf(stderr, "Error - can't read socket flags: %s\n", strerror(errno)); goto close_sock; } ret = fcntl(raw_sock, F_SETFL, sock_opts | O_NONBLOCK); if (ret < 0) { fprintf(stderr, "Error - can't set socket flags: %s\n", strerror(errno)); goto close_sock; } return 0; close_sock: close(raw_sock); raw_sock = -1; out: return -1; #elif USE_PCAP char error[PCAP_ERRBUF_SIZE]; #if WIN32 pcap_fp = pcap_open_live(iface, 1500, 1, 250, error); if (!pcap_fp) { fprintf(stderr, "Error opening adapter: %s\n", error); return -1; } if (pcap_setmintocopy(pcap_fp, 1) < 0) { fprintf(stderr, "Error setting mintocopy: %s\n", error); return 1; } #else // For Mac OS X, and maybe others in the future, // we take the long way around and set individual options on pcap // in order to be able to set immediate mode before activating the pcap // handle. int ret; pcap_fp = pcap_create(iface, error); if (!pcap_fp) { fprintf(stderr, "Error opening adapter: %s\n", error); return -1; } ret = pcap_set_snaplen(pcap_fp, 1500); if (ret != 0) { fprintf(stderr, "Error setting pcap snaplen: %s\n", error); return -1; } ret = pcap_set_promisc(pcap_fp, 1); if (ret != 0) { fprintf(stderr, "Error setting pcap promiscuous mode: %s\n", error); return -1; } ret = pcap_set_timeout(pcap_fp, 250); if (ret != 0) { fprintf(stderr, "Error setting pcap timeout: %s\n", error); return -1; } ret = pcap_set_immediate_mode(pcap_fp, 1); if (ret != 0) { fprintf(stderr, "Error setting pcap immediate mode: %s\n", error); return -1; } ret = pcap_activate(pcap_fp); if (ret != 0) { fprintf(stderr, "Error activating pcap handle\n"); return -1; } #endif return 0; #else #error socket_open() is not supported on your OS return -1; #endif } #if defined(USE_PCAP) int socket_read(char *packet_buff, int packet_buff_len, int (*sleep_sec)__attribute__((unused)), int (*sleep_usec)__attribute__((unused))) #else int socket_read(char *packet_buff, int packet_buff_len, int *sleep_sec, int *sleep_usec) #endif { #if defined(LINUX) struct timeval tv; fd_set watched_fds; ssize_t read_len; int ret = -1; if (raw_sock < 0) { fprintf(stderr, "Error reading from network: raw socket not initialized yet\n"); goto out; } FD_ZERO(&watched_fds); FD_SET(raw_sock, &watched_fds); tv.tv_sec = *sleep_sec; tv.tv_usec = *sleep_usec; ret = select(raw_sock + 1, &watched_fds, NULL, NULL, &tv); *sleep_sec = tv.tv_sec; *sleep_usec = tv.tv_usec; if (ret < 0) { if (errno != EINTR) fprintf(stderr, "Error waiting for data from network: %s", strerror(errno)); } if (ret <= 0) goto out; read_len = read(raw_sock, packet_buff, packet_buff_len - 1); if (read_len < 0) { if ((errno != EWOULDBLOCK) && (errno != EINTR)) fprintf(stderr, "Error reading data from network: %s", strerror(errno)); } ret = (int)read_len; packet_buff[read_len] = '\0'; out: return ret; #elif USE_PCAP struct pcap_pkthdr hdr; const unsigned char *tmp_packet; int ret = -1; if (!pcap_fp) { fprintf(stderr, "Error reading from network: pcap socket not initialized yet\n"); goto out; } ret = 0; tmp_packet = pcap_next(pcap_fp, &hdr); if ((tmp_packet) && (hdr.len > 0)) { ret = hdr.len; if (ret > packet_buff_len) ret = packet_buff_len; memcpy(packet_buff, tmp_packet, ret); packet_buff[ret] = '\0'; } out: return ret; #else #error socket_read() is not supported on your OS return 0; #endif } int socket_write(const char *buff, int len) { #if defined(LINUX) int ret = -1; if (raw_sock < 0) { fprintf(stderr, "Error writing to network: raw socket not initialized yet\n"); goto out; } ret = write(raw_sock, buff, len); if (ret < 0) fprintf(stderr, "Error - can't write to raw socket: %s\n", strerror(errno)); out: return ret; #elif USE_PCAP int ret = -1; if (!pcap_fp) { fprintf(stderr, "Error writing to network: pcap socket not initialized yet\n"); goto out; } ret = pcap_sendpacket(pcap_fp, (unsigned char *)buff, len); if (ret < 0) fprintf(stderr, "Error - can't write to pcap socket\n"); out: return ret; #else #error socket_write() is not supported on your OS return 0; #endif } void socket_close(const char *iface) { #if defined(LINUX) struct ifreq req; int ret; if (raw_sock < 0) goto out; memset(&req, 0, sizeof (struct ifreq)); strncpy(req.ifr_name, iface, IFNAMSIZ); req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; ret = ioctl(raw_sock, SIOCGIFFLAGS, &req); if (ret < 0) { fprintf(stderr, "Error - can't get interface flags (SIOCGIFFLAGS): %s (%i)\n", strerror(errno), raw_sock); goto close_sock; } req.ifr_flags &= ~IFF_PROMISC; ret = ioctl(raw_sock, SIOCSIFFLAGS, &req); if (ret < 0) { fprintf(stderr, "Error - can't set interface flags (SIOCSIFFLAGS): %s\n", strerror(errno)); goto close_sock; } close_sock: close(raw_sock); raw_sock = -1; out: return; #elif USE_PCAP if (!pcap_fp) { fprintf(stderr, "Error closing adapter '%s': pcap socket not initialized yet\n", iface); goto out; } pcap_close(pcap_fp); out: return; #else #error socket_close() is not supported on your OS #endif } ap51-flash-2019.0.1/socket.h000066400000000000000000000010351353712067100152520ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: 2009-2019, Marek Lindner */ #ifndef __AP51_FLASH_SOCKET_H__ #define __AP51_FLASH_SOCKET_H__ void socket_print_all_ifaces(void); char *socket_find_iface_by_index(const char *iface_number); int socket_open(const char *iface); int socket_read(char *packet_buff, int packet_buff_len, int *sleep_sec, int *sleep_usec); int socket_write(const char *buff, int len); void socket_close(const char *iface); #endif /* __AP51_FLASH_SOCKET_H__ */