├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── Makefile.am ├── NEWS ├── README ├── bin ├── .gitignore └── Makefile.am ├── configure.ac ├── ext ├── openwrt │ ├── config │ │ └── freecwmp │ └── scripts │ │ ├── defaults │ │ ├── freecwmp.sh │ │ ├── functions │ │ ├── common │ │ ├── device_hosts │ │ ├── device_info │ │ ├── device_routing │ │ ├── device_users │ │ ├── lan_device │ │ ├── management_server │ │ ├── misc │ │ ├── wan_device │ │ └── x_freecwmp_org │ │ └── unused │ │ └── owsip_voice_service ├── soap_msg_templates │ ├── cwmp_inform_message.xml │ └── cwmp_response_message.xml └── tmp │ └── .gitignore └── src ├── b64.c ├── b64.h ├── config.c ├── config.h ├── cwmp.c ├── cwmp.h ├── external.c ├── external.h ├── freecwmp.c ├── freecwmp.h ├── http.c ├── http.h ├── messages.h ├── time.c ├── time.h ├── ubus.c ├── ubus.h ├── xml.c └── xml.h /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE! Don't add files that are generated in specific 3 | # subdirectories here. Add them in the ".gitignore" file 4 | # in that subdirectory instead. 5 | # 6 | # Normal rules 7 | # 8 | 9 | *.rej 10 | *.orig 11 | *.a 12 | *.o 13 | *.su 14 | *~ 15 | *.swp 16 | *.patch 17 | *.bin 18 | 19 | # 20 | # Generated files 21 | # 22 | 23 | /aclocal.m4 24 | /autom4te.cache/ 25 | /compile 26 | /configure 27 | /config.log 28 | /config.status 29 | /depcomp 30 | /INSTALL 31 | /install-sh 32 | /missing 33 | /Makefile 34 | /Makefile.in 35 | 36 | # stgit generated dirs 37 | patches-* 38 | .stgit-edit.txt 39 | 40 | # quilt's files 41 | patches 42 | series 43 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KanjiMonster/freecwmp/31f72890ae594bcd875bd8e1da03f2d0be676a4e/AUTHORS -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | state the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | freecwmp is GPLv2 licensed cwmp implementation 294 | Copyright (C) 2011-2012 Luka Perkov 295 | 296 | This program is free software: you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation, either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program. If not, see . 308 | 309 | freecwmp Copyright (C) 2011-2012 Luka Perkov 310 | This program comes with ABSOLUTELY NO WARRANTY. 311 | This is free software, and you are welcome to redistribute it 312 | under certain conditions. 313 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KanjiMonster/freecwmp/31f72890ae594bcd875bd8e1da03f2d0be676a4e/ChangeLog -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | MAINTAINERCLEANFILES = Makefile.in 2 | 3 | SUBDIRS = bin 4 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KanjiMonster/freecwmp/31f72890ae594bcd875bd8e1da03f2d0be676a4e/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | configure autotools 2 | =================== 3 | 4 | $ autoreconf -if 5 | 6 | clean it all up 7 | =============== 8 | 9 | $ make distclean 10 | 11 | or 12 | 13 | $ git clean -df 14 | 15 | development environment 16 | ======================= 17 | 18 | Make sure you have all the packages installed from packages-arch-tr069 git 19 | repository. 20 | 21 | $ ln -sf `pwd`/ext/openwrt/scripts/defaults /usr/share/freecwmp/defaults 22 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/common /usr/share/freecwmp/functions/common 23 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/device_info /usr/share/freecwmp/functions/device_info 24 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/lan_device /usr/share/freecwmp/functions/lan_device 25 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/management_server /usr/share/freecwmp/functions/management_server 26 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/voice_service /usr/share/freecwmp/functions/voice_service 27 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/wan_device /usr/share/freecwmp/functions/wan_device 28 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/x_freecwmp_org /usr/share/freecwmp/functions/x_freecwmp_org 29 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/device_users /usr/share/freecwmp/functions/device_users 30 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/device_hosts /usr/share/freecwmp/functions/device_hosts 31 | $ ln -sf `pwd`/ext/openwrt/scripts/functions/device_routing /usr/share/freecwmp/functions/device_routing 32 | 33 | run freecwmpd 34 | ============= 35 | 36 | $ export UCI_CONFIG_DIR="`pwd`/ext/openwrt/config/" 37 | $ export UBUS_SOCKET="/tmp/ubus.sock" 38 | $ ./bin/freecwmpd -f 39 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Generated files 3 | # 4 | 5 | /.deps/ 6 | /Makefile 7 | /Makefile.in 8 | 9 | # 10 | # Binary 11 | # 12 | 13 | /freecwmpd 14 | -------------------------------------------------------------------------------- /bin/Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = freecwmpd 2 | 3 | freecwmpd_SOURCES = \ 4 | ../src/b64.h \ 5 | ../src/b64.c \ 6 | ../src/config.h \ 7 | ../src/config.c \ 8 | ../src/cwmp.h \ 9 | ../src/cwmp.c \ 10 | ../src/external.h \ 11 | ../src/external.c \ 12 | ../src/freecwmp.h \ 13 | ../src/freecwmp.c \ 14 | ../src/http.h \ 15 | ../src/http.c \ 16 | ../src/time.h \ 17 | ../src/time.c \ 18 | ../src/ubus.h \ 19 | ../src/ubus.c \ 20 | ../src/xml.h \ 21 | ../src/xml.c 22 | 23 | freecwmpd_CFLAGS = \ 24 | $(AM_CFLAGS) \ 25 | $(LIBFREECWMP_CFLAGS) \ 26 | $(LIBUCI_CFLAGS) \ 27 | $(LIBUBOX_CFLAGS) \ 28 | $(LIBUBUS_CFLAGS) \ 29 | $(MICROXML_CFLAGS) \ 30 | $(LIBCURL_CFLAGS) \ 31 | $(LIBZSTREAM_CFLAGS) 32 | 33 | freecwmpd_LDFLAGS = \ 34 | $(AM_LDFLAGS) \ 35 | $(LIBFREECWMP_LDLAGS) \ 36 | $(LIBUCI_LDFLAGS) \ 37 | $(LIBUBOX_LDFLAGS) \ 38 | $(LIBUBUS_LDFLAGS) \ 39 | $(MICROXML_LDFLAGS) \ 40 | $(LIBCURL_LDFLAGS) \ 41 | $(LIBZSTREAM_CFLAGS) 42 | 43 | freecwmpd_LDADD = \ 44 | $(AM_LIBS) \ 45 | $(LIBFREECWMP_LIBS) \ 46 | $(LIBUCI_LIBS) \ 47 | $(LIBUBOX_LIBS) \ 48 | $(LIBUBUS_LIBS) \ 49 | $(MICROXML_LIBS) \ 50 | $(LIBCURL_LIBS) \ 51 | $(LIBZSTREAM_LIBS) 52 | 53 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([freecwmp], [0.1], [freecwmp@lukaperkov.net]) 2 | AM_INIT_AUTOMAKE 3 | AC_CONFIG_SRCDIR([src/freecwmp.c]) 4 | 5 | # additional options 6 | AC_ARG_ENABLE(acs, [AS_HELP_STRING([--enable-acs], 7 | [specify which ACS is going to be used; there are some optimizations available for HDM and Fusion ACS (default --enable-acs=multi]))],, 8 | [AC_DEFINE(ACS_MULTI)]) 9 | 10 | AS_IF([test "x$enable_acs" = "xhdm"], [AC_DEFINE(ACS_HDM)]) 11 | AS_IF([test "x$enable_acs" = "xfusion"], [AC_DEFINE(ACS_FUSION)]) 12 | AS_IF([test "x$enable_acs" = "xmulti"], [AC_DEFINE(ACS_MULTI)]) 13 | AS_IF([test "x$enable_acs" = "xyes"], [AC_DEFINE(ACS_MULTI)]) 14 | AS_IF([test "x$enable_acs" = "xno"], [AC_DEFINE(ACS_MULTI)]) 15 | 16 | AC_ARG_ENABLE(http, [AS_HELP_STRING([--enable-http], 17 | [specify which HTTP library is going to be used; one can choose from zstream and curl (default --enable-http=curl]))],,) 18 | 19 | AM_CONDITIONAL([HTTP_ZSTREAM], [test "x$enable_http" = "xzstream" ]) 20 | AM_CONDITIONAL([HTTP_CURL], [test "x$enable_http" = "xcurl" ]) 21 | 22 | AC_ARG_ENABLE(debug, [AS_HELP_STRING([--enable-debug], [enable debugging messages])], AC_DEFINE(DEBUG),) 23 | AC_ARG_ENABLE(devel, [AS_HELP_STRING([--enable-devel], [enable development messages])], AC_DEFINE(DEVEL),) 24 | AC_ARG_ENABLE(dummy_mode, [AS_HELP_STRING([--enable-dummy-mode], [enable development mode])], AC_DEFINE(DUMMY_MODE),) 25 | 26 | # checks for programs 27 | AC_PROG_CC 28 | AM_PROG_CC_C_O 29 | 30 | # checks for libraries 31 | AC_ARG_WITH([libfreecwmp-include-path], 32 | [AS_HELP_STRING([--with-libfreecwmp-include-path], 33 | [location of the libfreecwmp library headers])], 34 | [LIBFREECWMP_CFLAGS="-I$withval"]) 35 | AC_SUBST([LIBFREECWMP_CFLAGS]) 36 | 37 | AC_ARG_WITH([libfreecwmp-lib-path], 38 | [AS_HELP_STRING([--with-libfreecwmp-lib-path], [location of the libfreecwmp library])], [LIBFREECWMP_LDFLAGS="-L$withval"]) 39 | AC_SUBST([LIBFREECWMP_LDFLAGS]) 40 | 41 | LIBFREECWMP_LIBS='-lfreecwmp' 42 | AC_SUBST([LIBFREECWMP_LIBS]) 43 | 44 | AC_ARG_WITH([uci-include-path], 45 | [AS_HELP_STRING([--with-uci-include-path], 46 | [location of the uci library headers])], 47 | [LIBUCI_CFLAGS="-I$withval"]) 48 | AC_SUBST([LIBUCI_CFLAGS]) 49 | 50 | AC_ARG_WITH([uci-lib-path], 51 | [AS_HELP_STRING([--with-uci-lib-path], [location of the uci library])], [LIBUCI_LDFLAGS="-L$withval"]) 52 | AC_SUBST([LIBUCI_LDFLAGS]) 53 | 54 | LIBUCI_LIBS='-luci' 55 | AC_SUBST([LIBUCI_LIBS]) 56 | 57 | AC_ARG_WITH([libubox-include-path], 58 | [AS_HELP_STRING([--with-libubox-include-path], 59 | [location of the libubox library headers])], 60 | [LIBUBOX_CFLAGS="-I$withval"]) 61 | AC_SUBST([LIBUBOX_CFLAGS]) 62 | 63 | AC_ARG_WITH([libubox-lib-path], 64 | [AS_HELP_STRING([--with-libubox-lib-path], [location of the libubox library])], [LIBUBOX_LDFLAGS="-L$withval"]) 65 | AC_SUBST([LIBUBOX_LDFLAGS]) 66 | 67 | LIBUBOX_LIBS='-lubox' 68 | AC_SUBST([LIBUBOX_LIBS]) 69 | 70 | AC_ARG_WITH([libubus-include-path], 71 | [AS_HELP_STRING([--with-libubus-include-path], 72 | [location of the libubus library headers])], 73 | [LIBUBUS_CFLAGS="-I$withval"]) 74 | AC_SUBST([LIBUBUS_CFLAGS]) 75 | 76 | AC_ARG_WITH([libubus-lib-path], 77 | [AS_HELP_STRING([--with-libubus-lib-path], [location of the libubus library])], [LIBUBOX_LDFLAGS="-L$withval"]) 78 | AC_SUBST([LIBUBUS_LDFLAGS]) 79 | 80 | LIBUBUS_LIBS='-lubus' 81 | AC_SUBST([LIBUBUS_LIBS]) 82 | 83 | AM_COND_IF([HTTP_CURL], [ 84 | AC_DEFINE(HTTP_CURL) 85 | PKG_CHECK_MODULES(LIBCURL, [libcurl]) 86 | AC_SUBST(LIBCURL_CFLAGS) 87 | AC_SUBST(LIBCURL_LDFLAGS) 88 | AC_SUBST(LIBCURL_LIBS) 89 | ]) 90 | 91 | AM_COND_IF([HTTP_ZSTREAM], [ 92 | AC_DEFINE(HTTP_ZSTREAM) 93 | AC_ARG_WITH([zstream-include-path], 94 | [AS_HELP_STRING([--with-zstream-include-path], 95 | [location of the zstream library headers])], 96 | [LIBZSTREAM_CFLAGS="-I$withval"]) 97 | AC_SUBST([LIBZSTREAM_CFLAGS]) 98 | 99 | AC_ARG_WITH([zstream-lib-path], 100 | [AS_HELP_STRING([--with-zstream-lib-path], [location of the zstream library])], [LIBZSTREAM_LDFLAGS="-L$withval"]) 101 | 102 | LIBZSTREAM_LIBS='-lzstream' 103 | AC_SUBST([LIBZSTREAM_LIBS]) 104 | ]) 105 | 106 | PKG_CHECK_MODULES(MICROXML, [microxml]) 107 | AC_SUBST(MICROXML_CFLAGS) 108 | AC_SUBST(MICROXML_LDFLAGS) 109 | AC_SUBST(MICROXML_LIBS) 110 | 111 | # checks for header files 112 | AC_CHECK_HEADERS([stdlib.h string.h]) 113 | 114 | # checks for typedefs, structures, and compiler characteristics 115 | AC_TYPE_UINT8_T 116 | 117 | # Makefiles 118 | AC_CONFIG_FILES([ 119 | Makefile 120 | bin/Makefile 121 | ]) 122 | 123 | AC_OUTPUT 124 | -------------------------------------------------------------------------------- /ext/openwrt/config/freecwmp: -------------------------------------------------------------------------------- 1 | config local 2 | option interface eth0 3 | option port 7547 4 | option ubus_socket /var/run/ubus.sock 5 | list event bootstrap 6 | list event boot 7 | 8 | config acs 9 | option scheme http 10 | option username freecwmp 11 | option password freecwmp 12 | option hostname 192.168.1.1 13 | option port 7547 14 | option path / 15 | 16 | config device 17 | option manufacturer freecwmp 18 | option oui FFFFFF 19 | option product_class freecwmp 20 | option serial_number FFFFFF123456 21 | option hardware_version example_hw_version 22 | option software_version example_sw_version 23 | 24 | config scripts 25 | # load OpenWrt generic network functions 26 | list location /lib/functions/network.sh 27 | # load freecwmp common functions 28 | list location /usr/share/freecwmp/functions/common 29 | # freecwmp specific functions 30 | list location /usr/share/freecwmp/functions/device_info 31 | list get_value_function get_device_info 32 | list set_value_function set_device_info 33 | list get_value_function get_device_info_generic 34 | list set_value_function set_device_info_generic 35 | list location /usr/share/freecwmp/functions/lan_device 36 | list get_value_function get_lan_device 37 | list set_value_function set_lan_device 38 | list location /usr/share/freecwmp/functions/management_server 39 | list get_value_function get_management_server 40 | list set_value_function set_management_server 41 | list get_value_function get_management_server_generic 42 | list set_value_function set_management_server_generic 43 | list location /usr/share/freecwmp/functions/wan_device 44 | list get_value_function get_wan_device 45 | list set_value_function set_wan_device 46 | list location /usr/share/freecwmp/functions/misc 47 | list get_value_function get_misc 48 | list location /usr/share/freecwmp/functions/device_users 49 | list get_value_function get_device_users 50 | list set_value_function set_device_users 51 | list location /usr/share/freecwmp/functions/device_hosts 52 | list get_value_function get_device_hosts 53 | list location /usr/share/freecwmp/functions/device_routing 54 | list get_value_function get_device_routing 55 | 56 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/defaults: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2011-2012 Luka Perkov 3 | 4 | # set these to appropriate values and remove comment if you want to use them 5 | 6 | #default_management_server_acs_hostname="" 7 | #default_management_server_connection_request_url="" 8 | #default_wan_device_mng_interface_ip="" 9 | #default_wan_device_mng_interface_mac="" 10 | #default_device_hosts_dnsmasq_leases_file="" 11 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/freecwmp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2011-2012 Luka Perkov 3 | 4 | . /lib/functions.sh 5 | . /usr/share/shflags/shflags.sh 6 | . /usr/share/freecwmp/defaults 7 | 8 | # define a 'name' command-line string flag 9 | DEFINE_boolean 'newline' false 'do not output the trailing newline' 'n' 10 | DEFINE_boolean 'value' false 'output values only' 'v' 11 | DEFINE_boolean 'empty' false 'output empty parameters' 'e' 12 | DEFINE_boolean 'last' false 'output only last line ; for parameters that tend to have huge output' 'l' 13 | DEFINE_boolean 'debug' false 'give debug output' 'd' 14 | DEFINE_boolean 'dummy' false 'echo system commands' 'D' 15 | DEFINE_boolean 'force' false 'force getting values for certain parameters' 'f' 16 | DEFINE_string 'url' '' 'file to download [download only]' 'u' 17 | DEFINE_string 'size' '' 'size of file to download [download only]' 's' 18 | 19 | FLAGS_HELP=`cat << EOF 20 | USAGE: $0 [flags] command [parameter] [values] 21 | command: 22 | get [value|notification|tags|all] 23 | set [value|notification|tag] 24 | download 25 | factory_reset 26 | reboot 27 | EOF` 28 | 29 | FLAGS "$@" || exit 1 30 | eval set -- "${FLAGS_ARGV}" 31 | 32 | if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then 33 | exit 1 34 | fi 35 | 36 | if [ ${FLAGS_newline} -eq ${FLAGS_TRUE} ]; then 37 | ECHO_newline='-n' 38 | fi 39 | 40 | case "$1" in 41 | set) 42 | if [ "$2" = "notification" ]; then 43 | __arg1="$3" 44 | __arg2="$4" 45 | action="set_notification" 46 | elif [ "$2" = "tag" ]; then 47 | __arg1="$3" 48 | __arg2="$4" 49 | action="set_tag" 50 | elif [ "$2" = "value" ]; then 51 | __arg1="$3" 52 | __arg2="$4" 53 | action="set_value" 54 | else 55 | __arg1="$2" 56 | __arg2="$3" 57 | action="set_value" 58 | fi 59 | ;; 60 | get) 61 | if [ "$2" = "notification" ]; then 62 | __arg1="$3" 63 | action="get_notification" 64 | elif [ "$2" = "tags" ]; then 65 | __arg1="$3" 66 | action="get_tags" 67 | elif [ "$2" = "value" ]; then 68 | __arg1="$3" 69 | action="get_value" 70 | elif [ "$2" = "all" ]; then 71 | __arg1="$3" 72 | action="get_all" 73 | else 74 | __arg1="$2" 75 | action="get_value" 76 | fi 77 | ;; 78 | download) 79 | action="download" 80 | ;; 81 | factory_reset) 82 | action="factory_reset" 83 | ;; 84 | reboot) 85 | action="reboot" 86 | ;; 87 | esac 88 | 89 | if [ -z "$action" ]; then 90 | echo invalid action \'$1\' 91 | exit 1 92 | fi 93 | 94 | if [ ${FLAGS_debug} -eq ${FLAGS_TRUE} ]; then 95 | echo "[debug] started at \"`date`\"" 96 | fi 97 | 98 | load_script() { 99 | . $1 100 | } 101 | 102 | get_value_functions="" 103 | set_value_functions="" 104 | handle_scripts() { 105 | local section="$1" 106 | config_get prefix "$section" "prefix" 107 | config_list_foreach "$section" 'location' load_script 108 | config_get get_value_functions "$section" "get_value_function" 109 | config_get set_value_functions "$section" "set_value_function" 110 | } 111 | 112 | config_load freecwmp 113 | config_foreach handle_scripts "scripts" 114 | 115 | if [ "$action" = "get_value" -o "$action" = "get_all" ]; then 116 | if [ ${FLAGS_force} -eq ${FLAGS_FALSE} ]; then 117 | __tmp_arg="Device." 118 | # TODO: don't check only string length ; but this is only used 119 | # for getting correct prefix of CWMP parameter anyway 120 | if [ ${#__arg1} -lt ${#__tmp_arg} ]; then 121 | echo "CWMP parameters usualy begin with 'InternetGatewayDevice.' or 'Device.' " 122 | echo "if you want to force script execution with provided parameter use '-f' flag." 123 | exit -1 124 | fi 125 | fi 126 | for function_name in $get_value_functions 127 | do 128 | $function_name "$__arg1" 129 | done 130 | fi 131 | 132 | if [ "$action" = "set_value" ]; then 133 | for function_name in $set_value_functions 134 | do 135 | $function_name "$__arg1" "$__arg2" 136 | done 137 | fi 138 | 139 | if [ "$action" = "get_notification" -o "$action" = "get_all" ]; then 140 | freecwmp_get_parameter_notification "x_notification" "$__arg1" 141 | freecwmp_notification_output "$__arg1" "$x_notification" 142 | fi 143 | 144 | if [ "$action" = "set_notification" ]; then 145 | freecwmp_set_parameter_notification "$__arg1" "$__arg2" 146 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 147 | fi 148 | 149 | if [ "$action" = "get_tags" -o "$action" = "get_all" ]; then 150 | freecwmp_get_parameter_tags "x_tags" "$__arg1" 151 | freecwmp_tags_output "$__arg1" "$x_tags" 152 | fi 153 | 154 | if [ "$action" = "set_tag" ]; then 155 | freecwmp_set_parameter_tag "$__arg1" "$__arg2" 156 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 157 | fi 158 | 159 | if [ "$action" = "download" ]; then 160 | 161 | rm /tmp/freecwmp_download 2> /dev/null 162 | wget -O /tmp/freecwmp_download "${FLAGS_url}" > /dev/null 2>&1 163 | 164 | dl_size=`ls -l /tmp/freecwmp_download | awk '{ print $5 }'` 165 | if [ ! "$dl_size" -eq "${FLAGS_size}" ]; then 166 | rm /tmp/freecwmp_download 2> /dev/null 167 | exit 1 168 | fi 169 | fi 170 | 171 | if [ "$action" = "factory_reset" ]; then 172 | if [ ${FLAGS_dummy} -eq ${FLAGS_TRUE} ]; then 173 | echo "# factory_reset" 174 | else 175 | jffs2_mark_erase "rootfs_data" 176 | sync 177 | reboot 178 | fi 179 | fi 180 | 181 | if [ "$action" = "reboot" ]; then 182 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@local[0].event="boot" 183 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 184 | 185 | if [ ${FLAGS_dummy} -eq ${FLAGS_TRUE} ]; then 186 | echo "# reboot" 187 | else 188 | sync 189 | reboot 190 | fi 191 | fi 192 | 193 | if [ ${FLAGS_debug} -eq ${FLAGS_TRUE} ]; then 194 | echo "[debug] exited at \"`date`\"" 195 | fi 196 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/common: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2011-2012 Luka Perkov 3 | 4 | # TODO: merge this one somewhere in OpenWrt 5 | uci_remove_list_element() { 6 | local option="$1" 7 | local value="$2" 8 | local list="$(/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get $option)" 9 | local elem 10 | 11 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} delete $option 12 | for elem in $list; do 13 | if [ "$elem" != "$value" ]; then 14 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} add_list $option=$elem 15 | fi 16 | done 17 | } 18 | 19 | freecwmp_output() { 20 | local parameter="$1" 21 | local value="$2" 22 | local delimiter="$3" 23 | 24 | if [ "$delimiter" = "" ]; then 25 | delimiter=":" 26 | fi 27 | 28 | if [ -n "$value" -o ${FLAGS_empty} -eq ${FLAGS_TRUE} ]; then 29 | if [ ${FLAGS_value} -eq ${FLAGS_TRUE} ]; then 30 | echo $ECHO_newline $value 31 | else 32 | echo $ECHO_newline $parameter "$delimiter" $value 33 | fi 34 | fi 35 | } 36 | 37 | freecwmp_value_output() { 38 | freecwmp_output "$1" "$2" "V" 39 | } 40 | 41 | freecwmp_notification_output() { 42 | freecwmp_output "$1" "$2" "N" 43 | } 44 | 45 | freecwmp_tags_output() { 46 | freecwmp_output "$1" "$2" "T" 47 | } 48 | 49 | freecwmp_not_implemented() { 50 | freecwmp_output "$1" "NOT_IMPLEMENTED" 51 | } 52 | 53 | freecwmp_parse_formated_parameter() { 54 | local _clean_parameter="$1" 55 | local _formated_parameter="$2" 56 | local _values 57 | 58 | local _clean_parameter_array=`echo $_clean_parameter | sed 's/\./ /g'` 59 | local _formated_parameter_array=`echo $_formated_parameter | sed 's/\./ /g'` 60 | 61 | local i 62 | local j=0 63 | for i in $_formated_parameter_array 64 | do 65 | let j=$j+1 66 | if [ "x$i" == "x{i}" ]; then 67 | # get value for sections maked as {i} 68 | local m 69 | local n=0 70 | for m in $_clean_parameter_array 71 | do 72 | let n=$n+1 73 | if [ $n -eq $j ]; then 74 | if [ "x$_values" == "x" ]; then 75 | _values="$m" 76 | else 77 | _values="$_values $m" 78 | fi 79 | fi 80 | done 81 | else 82 | # check if sections not marked as {i} match 83 | local m 84 | local n=0 85 | for m in $_clean_parameter_array 86 | do 87 | let n=$n+1 88 | if [ $n -eq $j -a "x$m" != "x$i" ]; then 89 | eval "export -- \"$3=-1\"" 90 | return 91 | fi 92 | done 93 | fi 94 | done 95 | 96 | eval "export -- \"$3=0\"" 97 | eval "export -- \"$4=\"\"$_values\"\"\"" 98 | } 99 | 100 | freecwmp_config_cwmp() { 101 | config_get __parameter "$1" "parameter" 102 | config_get __value "$1" "value" 103 | config_get __tags "$1" "tag" 104 | 105 | if [ "$__parameter" = "$4" ]; then 106 | if [ "get" = "$2" ]; then 107 | if [ "value" = "$3" ]; then 108 | eval "export -- \"$5=\"\"$__value\"\"\"" 109 | fi 110 | if [ "tags" = "$3" ]; then 111 | eval "export -- \"$5=\"\"$__tags\"\"\"" 112 | fi 113 | elif [ "set" = "$2" ]; then 114 | if [ "value" = "$3" ]; then 115 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.$1.value=$5 2> /dev/null 116 | fi 117 | elif [ "check" = "$2" ]; then 118 | if [ "parameter" = "$3" ]; then 119 | eval "export -- \"$5=\"$1\"\"" 120 | fi 121 | fi 122 | fi 123 | } 124 | 125 | freecwmp_config_notifications() { 126 | config_get __active "$1" "active" 127 | config_get __passive "$1" "passive" 128 | 129 | for item in $__active 130 | do 131 | if [ "$item" = "$3" ]; then 132 | eval "export -- \"$4=2\"" 133 | return 0 134 | fi 135 | done 136 | for item in $__passive 137 | do 138 | if [ "$item" = "$3" ]; then 139 | eval "export -- \"$4=1\"" 140 | return 0 141 | fi 142 | done 143 | } 144 | 145 | freecwmp_get_parameter_value() { 146 | local _dest="$1" 147 | local _parm="$2" 148 | local _val 149 | config_foreach freecwmp_config_cwmp "cwmp" "get" "value" "$_parm" "_val" 150 | eval "export -- \"$_dest=\"\"$_val\"\"\"" 151 | } 152 | 153 | freecwmp_set_parameter_value() { 154 | local _parm="$1" 155 | local _val="$2" 156 | config_foreach freecwmp_config_cwmp "cwmp" "check" "parameter" "$_parm" "_section" 157 | if [ ! "$_section" = "" ]; then 158 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.$_section.value=$_val 2> /dev/null 159 | else 160 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} batch << EOF 2>&1 >/dev/null 161 | add freecwmp cwmp 162 | set freecwmp.@cwmp[-1].parameter="$_parm" 163 | set freecwmp.@cwmp[-1].value="$_val" 164 | EOF 165 | fi 166 | config_foreach freecwmp_config_notifications "notifications" "get" "$_parm" "tmp" 167 | # TODO: notify freecwmpd about the change 168 | # if [ "$tmp" -eq "2" ]; then 169 | # fi 170 | } 171 | 172 | freecwmp_get_parameter_notification() { 173 | local _dest="$1" 174 | local _parm="$2" 175 | local _val 176 | config_foreach freecwmp_config_notifications "notifications" "get" "$_parm" "_val" 177 | eval "export -- \"$_dest=$_val\"" 178 | } 179 | 180 | freecwmp_set_parameter_notification() { 181 | local _parm="$1" 182 | local _val="$2" 183 | local tmp=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@notifications[0] 2>/dev/null` 184 | if [ "$tmp" = "" ]; then 185 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} add freecwmp notifications 2>&1 >/dev/null 186 | else 187 | uci_remove_list_element "freecwmp.@notifications[0].passive" "$_parm" 2>/dev/null 188 | uci_remove_list_element "freecwmp.@notifications[0].active" "$_parm" 2>/dev/null 189 | fi 190 | if [ "$_val" -eq "1" ]; then 191 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} add_list freecwmp.@notifications[0].passive="$_parm" 2>&1 >/dev/null 192 | elif [ "$_val" -eq "2" ]; then 193 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} add_list freecwmp.@notifications[0].active="$_parm" 2>&1 >/dev/null 194 | fi 195 | } 196 | 197 | freecwmp_get_parameter_tags() { 198 | local _dest="$1" 199 | local _parm="$2" 200 | config_foreach freecwmp_config_cwmp "cwmp" "get" "tags" "$_parm" "_tags" 201 | eval "export -- \"$_dest=\"\"$_tags\"\"\"" 202 | } 203 | 204 | freecwmp_set_parameter_tag() { 205 | local _parm="$1" 206 | local _tag="$2" 207 | config_foreach freecwmp_config_cwmp "cwmp" "check" "parameter" "$_parm" "_section" 208 | if [ ! "$_section" = "" ]; then 209 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} add_list freecwmp.$_section.tag=$_tag 2> /dev/null 210 | else 211 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} batch << EOF 2>&1 >/dev/null 212 | add freecwmp cwmp 213 | set freecwmp.@cwmp[-1].parameter="$_parm" 214 | add_list freecwmp.@cwmp[-1].tag="$_tag" 215 | EOF 216 | fi 217 | } 218 | 219 | delay_service_restart() { 220 | local service="$1" 221 | local delay="$2" 222 | local lock="/tmp/freecwmp_$service" 223 | 224 | if [ ! -x "$lock" ]; then 225 | cat > "$lock" </dev/null 2>/dev/null 227 | sleep $delay 228 | /etc/init.d/$service start >/dev/null 2>/dev/null 229 | rm "$lock" 230 | EOF 231 | chmod +x "$lock" 232 | sh "$lock" & 233 | fi 234 | } 235 | 236 | delay_command() { 237 | local name="$1" 238 | local command="$2" 239 | local delay="$3" 240 | local lock="/tmp/freecwmp_command_$name" 241 | 242 | if [ ! -x "$lock" ]; then 243 | cat > "$lock" </dev/null 2>/dev/null 246 | rm "$lock" 247 | EOF 248 | chmod +x "$lock" 249 | sh "$lock" & 250 | fi 251 | } 252 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/device_hosts: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2012 Luka Perkov 3 | 4 | get_device_hosts_number_of_leases() { 5 | local _static=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} show dhcp 2> /dev/null | fgrep 'dhcp.' | fgrep '.mac=' | wc -l` 6 | local _dynamic=`wc -l /var/dhcp.leases | awk '{ print $1 }'` 7 | eval "export -- \"$2=\"\"$_static\"\"\"" 8 | eval "export -- \"$3=\"\"$_dynamic\"\"\"" 9 | } 10 | 11 | get_device_hosts_ip_address() { 12 | local _leases_file=$1 13 | local _num=$2 14 | local _num_static_leases=$3 15 | local _num_dynamic_leases=$4 16 | local _ip 17 | if [ $_num -le $_num_static_leases ]; then 18 | let local _uci_num=$_num-1 19 | _ip=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get dhcp.@host[$_uci_num].ip 2> /dev/null` 20 | fi 21 | let _num=$_num-$_num_static_leases 22 | if [ $_num -gt 0 -a $_num -le $_num_dynamic_leases ]; then 23 | local _sed_cmd=`echo -n \'$_num; echo p\'` 24 | _ip=`eval sed -n $_sed_cmd $_leases_file | awk '{ print $3 }'` 25 | fi 26 | eval "export -- \"$5=\"\"$_ip\"\"\"" 27 | } 28 | 29 | get_device_hosts() { 30 | local leases_file 31 | if [ -z "$default_dnsmasq_leases_file" ]; then 32 | leases_file="/var/dhcp.leases" 33 | else 34 | leases_file=$default_dnsmasq_leases_file 35 | fi 36 | 37 | local num_static_leases 38 | local num_dynamic_leases 39 | get_device_hosts_number_of_leases "$leases_file" "num_static_leases" "num_dynamic_leases" 40 | 41 | # internal TR-069 to TR-181 parameter transformation 42 | local parameter=`echo -n $1 | sed "s/InternetGatewayDevice\.LANDevice\.1\./Device\./g"` 43 | 44 | case "$parameter" in 45 | Device.Hosts.HostNumberOfEntries) 46 | let local val=$num_static_leases+$num_dynamic_leases 47 | freecwmp_output "$parameter" "$val" 48 | return 49 | ;; 50 | esac 51 | 52 | local rc 53 | local num 54 | 55 | # TODO: Device.Hosts.Host.{i}.Alias (alias support does not exist) 56 | 57 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.PhysAddress" "rc" "num" 58 | if [ $rc -eq 0 ]; then 59 | local val 60 | if [ $num -le $num_static_leases ]; then 61 | let local uci_num=$num-1 62 | val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get dhcp.@host[$uci_num].mac 2> /dev/null` 63 | fi 64 | let num=$num-$num_static_leases 65 | if [ $num -gt 0 -a $num -le $num_dynamic_leases ]; then 66 | local sed_cmd=`echo -n \'$num; echo p\'` 67 | val=`eval sed -n $sed_cmd $leases_file | awk '{ print $2 }'` 68 | fi 69 | freecwmp_value_output "$parameter" "$val" 70 | return 71 | fi 72 | 73 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.IPAddress" "rc" "num" 74 | if [ $rc -eq 0 ]; then 75 | local val 76 | get_device_hosts_ip_address "$leases_file" "$num" "$num_static_leases" "$num_dynamic_leases" "val" 77 | freecwmp_value_output "$parameter" "$val" 78 | return 79 | fi 80 | 81 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.AddressSource" "rc" "num" 82 | if [ $rc -eq 0 ]; then 83 | local val 84 | if [ $num -le $num_static_leases ]; then 85 | val="Static" 86 | fi 87 | let num=$num-$num_static_leases 88 | if [ $num -gt 0 -a $num -le $num_dynamic_leases ]; then 89 | val="DHCP" 90 | fi 91 | freecwmp_value_output "$parameter" "$val" 92 | return 93 | fi 94 | 95 | # TODO: Device.Hosts.Host.{i}.DHCPClient (freecwmp needs to support other parameters first) 96 | 97 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.LeaseTimeRemaining" "rc" "num" 98 | if [ $rc -eq 0 ]; then 99 | local val 100 | if [ $num -le $num_static_leases ]; then 101 | val="-1" 102 | fi 103 | let num=$num-$num_static_leases 104 | if [ $num -gt 0 -a $num -le $num_dynamic_leases ]; then 105 | local sed_cmd=`echo -n \'$num; echo p\'` 106 | local t1=`eval sed -n $sed_cmd $leases_file | awk '{ print $1 }'` 107 | local t2=`date +%s` 108 | let val=$t1-$t2 109 | fi 110 | freecwmp_value_output "$parameter" "$val" 111 | return 112 | fi 113 | 114 | # TODO: Device.Hosts.Host.{i}.AssociatedDevice (freecwmp needs to support other parameters first) 115 | # TODO: Device.Hosts.Host.{i}.Layer1Interface (freecwmp needs to support other parameters first) 116 | # TODO: Device.Hosts.Host.{i}.Layer3Interface (freecwmp needs to support other parameters first) 117 | # TODO: Device.Hosts.Host.{i}.VendorClassID (DHCP option 60 not supported with dnsmasq) 118 | # TODO: Device.Hosts.Host.{i}.ClientID (DHCP option 61 not supported with dnsmasq) 119 | # TODO: Device.Hosts.Host.{i}.UserClassID (DHCP option 77 not supported with dnsmasq) 120 | 121 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.HostName" "rc" "num" 122 | if [ $rc -eq 0 ]; then 123 | local val 124 | if [ $num -le $num_static_leases ]; then 125 | let local uci_num=$num-1 126 | val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get dhcp.@host[$uci_num].name 2> /dev/null` 127 | fi 128 | let num=$num-$num_static_leases 129 | if [ $num -gt 0 -a $num -le $num_dynamic_leases ]; then 130 | local sed_cmd=`echo -n \'$num; echo p\'` 131 | val=`eval sed -n $sed_cmd $leases_file | awk '{ print $4 }'` 132 | if [ "x$val" == "x*" ]; then val=""; fi 133 | fi 134 | freecwmp_value_output "$parameter" "$val" 135 | return 136 | fi 137 | 138 | # TODO: Device.Hosts.Host.{i}.ClientID (DHCP option 61 not supported with dnsmasq) 139 | 140 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.Active" "rc" "num" 141 | if [ $rc -eq 0 ]; then 142 | local val 143 | local ip 144 | get_device_hosts_ip_address "$leases_file" "$num" "$num_static_leases" "$num_dynamic_leases" "ip" 145 | val=`ping -c 1 $ip 2>&1 > /dev/null ; echo $?` 146 | let val=!$val 147 | freecwmp_value_output "$parameter" "$val" 148 | return 149 | fi 150 | 151 | # TODO: we support only one IPv4 address per host 152 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.IPv4AddressNumberOfEntries" "rc" "num" 153 | if [ $rc -eq 0 ]; then 154 | local val 155 | let local n=$num_static_leases+$num_dynamic_leases 156 | if [ $num -le $n ]; then 157 | val=1 158 | fi 159 | freecwmp_value_output "$parameter" "$val" 160 | return 161 | fi 162 | 163 | # TODO: we do not support IPv6 address 164 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.IPv6AddressNumberOfEntries" "rc" "num" 165 | if [ $rc -eq 0 ]; then 166 | local val 167 | let local n=$num_static_leases+$num_dynamic_leases 168 | if [ $num -le $n ]; then 169 | val=0 170 | fi 171 | freecwmp_value_output "$parameter" "$val" 172 | return 173 | fi 174 | 175 | # TODO: we support only one IPv4 address per host 176 | freecwmp_parse_formated_parameter "$parameter" "Device.Hosts.Host.{i}.IPv4Address.{i}.IPAddress" "rc" "num" 177 | if [ $rc -eq 0 ]; then 178 | local val 179 | local num1=`echo $num | awk '{ print $1 }'` 180 | local num2=`echo $num | awk '{ print $2 }'` 181 | let local n=$num_static_leases+$num_dynamic_leases 182 | if [ $num2 -eq 1 ]; then 183 | get_device_hosts_ip_address "$leases_file" "$num1" "$num_static_leases" "$num_dynamic_leases" "val" 184 | fi 185 | freecwmp_value_output "$parameter" "$val" 186 | return 187 | fi 188 | 189 | # TODO: Device.Hosts.Host.{i}.IPv6Address.{i}.IPAddress (no IPv6 support yet) 190 | 191 | } 192 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/device_info: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2011-2012 Luka Perkov 3 | 4 | get_device_info_manufacturer() { 5 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@device[0].manufacturer 2> /dev/null` 6 | freecwmp_output "InternetGatewayDevice.DeviceInfo.Manufacturer" "$val" 7 | } 8 | 9 | set_device_info_manufacturer() { 10 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@device[0].manufacturer="$1" 11 | } 12 | 13 | get_device_info_oui() { 14 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@device[0].oui 2> /dev/null` 15 | freecwmp_output "InternetGatewayDevice.DeviceInfo.ManufacturerOUI" "$val" 16 | } 17 | 18 | set_device_info_oui() { 19 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@device[0].oui="$1" 20 | } 21 | 22 | get_device_info_product_class() { 23 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@device[0].product_class 2> /dev/null` 24 | freecwmp_output "InternetGatewayDevice.DeviceInfo.ProductClass" "$val" 25 | } 26 | 27 | set_device_info_product_class() { 28 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@device[0].product_class="$1" 29 | } 30 | 31 | get_device_info_serial_number() { 32 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@device[0].serial_number 2> /dev/null` 33 | freecwmp_output "InternetGatewayDevice.DeviceInfo.SerialNumber" "$val" 34 | } 35 | 36 | set_device_info_serial_number() { 37 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@device[0].serial_number="$1" 38 | } 39 | 40 | get_device_info_hardware_version() { 41 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@device[0].hardware_version 2> /dev/null` 42 | freecwmp_output "InternetGatewayDevice.DeviceInfo.HardwareVersion" "$val" 43 | } 44 | 45 | set_device_info_hardware_version() { 46 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@device[0].hardware_version="$1" 47 | } 48 | 49 | get_device_info_software_version() { 50 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@device[0].software_version 2> /dev/null` 51 | freecwmp_output "InternetGatewayDevice.DeviceInfo.SoftwareVersion" "$val" 52 | } 53 | 54 | set_device_info_software_version() { 55 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@device[0].software_version="$1" 56 | } 57 | 58 | get_device_info_uptime() { 59 | local val=`cat /proc/uptime | awk -F "." '{ print $1 }'` 60 | freecwmp_output "InternetGatewayDevice.DeviceInfo.UpTime" "$val" 61 | } 62 | 63 | get_device_info_device_log() { 64 | local val="" 65 | if [ ${FLAGS_last} -eq ${FLAGS_TRUE} ]; then 66 | val=`dmesg | tail -n1` 67 | else 68 | val=`dmesg | tail -n10` 69 | fi 70 | freecwmp_output "InternetGatewayDevice.DeviceInfo.DeviceLog" "$val" 71 | } 72 | 73 | get_device_info() { 74 | case "$1" in 75 | InternetGatewayDevice.) 76 | get_device_info_manufacturer 77 | get_device_info_oui 78 | get_device_info_product_class 79 | get_device_info_serial_number 80 | get_device_info_hardware_version 81 | get_device_info_software_version 82 | get_device_info_uptime 83 | get_device_info_device_log 84 | ;; 85 | InternetGatewayDevice.DeviceInfo.) 86 | get_device_info_manufacturer 87 | get_device_info_oui 88 | get_device_info_product_class 89 | get_device_info_serial_number 90 | get_device_info_hardware_version 91 | get_device_info_software_version 92 | get_device_info_uptime 93 | get_device_info_device_log 94 | ;; 95 | InternetGatewayDevice.DeviceInfo.Manufacturer) 96 | get_device_info_manufacturer 97 | ;; 98 | InternetGatewayDevice.DeviceInfo.ManufacturerOUI) 99 | get_device_info_oui 100 | ;; 101 | InternetGatewayDevice.DeviceInfo.ProductClass) 102 | get_device_info_product_class 103 | ;; 104 | InternetGatewayDevice.DeviceInfo.SerialNumber) 105 | get_device_info_serial_number 106 | ;; 107 | InternetGatewayDevice.DeviceInfo.HardwareVersion) 108 | get_device_info_hardware_version 109 | ;; 110 | InternetGatewayDevice.DeviceInfo.SoftwareVersion) 111 | get_device_info_software_version 112 | ;; 113 | InternetGatewayDevice.DeviceInfo.UpTime) 114 | get_device_info_uptime 115 | ;; 116 | InternetGatewayDevice.DeviceInfo.DeviceLog) 117 | get_device_info_device_log 118 | ;; 119 | esac 120 | } 121 | 122 | set_device_info() { 123 | case "$1" in 124 | InternetGatewayDevice.DeviceInfo.Manufacturer) 125 | set_device_info_manufacturer "$2" 126 | ;; 127 | InternetGatewayDevice.DeviceInfo.ManufacturerOUI) 128 | set_device_info_oui "$2" 129 | ;; 130 | InternetGatewayDevice.DeviceInfo.ProductClass) 131 | set_device_info_product_class "$2" 132 | ;; 133 | InternetGatewayDevice.DeviceInfo.SerialNumber) 134 | set_device_info_serial_number "$2" 135 | ;; 136 | InternetGatewayDevice.DeviceInfo.HardwareVersion) 137 | set_device_info_hardware_version "$2" 138 | ;; 139 | InternetGatewayDevice.DeviceInfo.SoftwareVersion) 140 | set_device_info_software_version "$2" 141 | ;; 142 | esac 143 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 144 | } 145 | 146 | check_parameter_device_info_generic() { 147 | case "$1" in 148 | InternetGatewayDevice.DeviceInfo.ModelName|\ 149 | InternetGatewayDevice.DeviceInfo.Description|\ 150 | InternetGatewayDevice.DeviceInfo.ModemFirmwareVersion|\ 151 | InternetGatewayDevice.DeviceInfo.EnabledOptions|\ 152 | InternetGatewayDevice.DeviceInfo.AdditionalHardwareVersion|\ 153 | InternetGatewayDevice.DeviceInfo.AdditionalSoftwareVersion|\ 154 | InternetGatewayDevice.DeviceInfo.SpecVersion|\ 155 | InternetGatewayDevice.DeviceInfo.ProvisioningCode|\ 156 | InternetGatewayDevice.DeviceInfo.FirstUseDate) 157 | return 0 158 | ;; 159 | esac 160 | return 1 161 | } 162 | 163 | get_device_info_generic() { 164 | check_parameter_device_info_generic "$1" ; _tmp=$? ; if [ "$_tmp" -eq 1 ]; then return 0; fi 165 | 166 | freecwmp_get_parameter_value "val" "$1" 167 | freecwmp_value_output "$1" "$val" 168 | } 169 | 170 | set_device_info_generic() { 171 | check_parameter_device_info_generic "$1" ; _tmp=$? ; if [ "$_tmp" -eq 1 ]; then return 0; fi 172 | 173 | freecwmp_set_parameter_value "$1" "$2" 174 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 175 | } 176 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/device_routing: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2012 Luka Perkov 3 | 4 | # TODO: LIMITATIONS: we only handle one device router at the moment 5 | 6 | # ordering of routes: 7 | # 1) inactive routes found in uci network config file 8 | # 2) active routes found in uci network config file 9 | # 3) active routes but not found in uci network config file 10 | 11 | FREECWMP_DEVICE_ROUTES="/tmp/freecwmp_routes" 12 | FREECWMP_DEVICE_ROUTES_STATIC="/tmp/freecwmp_routes_static" 13 | FREECWMP_DEVICE_ROUTES_DYNAMIC="/tmp/freecwmp_routes_dynamic" 14 | 15 | get_device_routing_ipv4_check_route() { 16 | local __uci_target=$1 17 | local __uci_gateway=$2 18 | local __uci_netmask=$3 19 | 20 | local __active=0 21 | 22 | # TODO: remove this file 23 | echo -n > $FREECWMP_DEVICE_ROUTES_DYNAMIC 24 | 25 | local __route_target 26 | local __route_gateway 27 | local __route_netmask 28 | local line 29 | while read line 30 | do 31 | __route_target=`echo -n $line | awk '{ print $1 }'` 32 | __route_gateway=`echo -n $line | awk '{ print $2 }'` 33 | __route_netmask=`echo -n $line | awk '{ print $3 }'` 34 | if [ "x$__uci_target" != "x$__route_target" ]; then 35 | echo $line >> $FREECWMP_DEVICE_ROUTES_DYNAMIC 36 | continue 37 | fi 38 | if [ "x$__uci_gateway" != "x$__route_gateway" ]; then 39 | echo $line >> $FREECWMP_DEVICE_ROUTES_DYNAMIC 40 | continue 41 | fi 42 | if [ "x$__uci_netmask" != "x$__route_netmask" ]; then 43 | echo $line >> $FREECWMP_DEVICE_ROUTES_DYNAMIC 44 | continue 45 | fi 46 | echo $line >> $FREECWMP_DEVICE_ROUTES_STATIC 47 | __active=1 48 | done < $FREECWMP_DEVICE_ROUTES 49 | 50 | eval "export -- \"$4=\"\"$__active\"\"\"" 51 | } 52 | 53 | get_device_routing_ipv4_ordering_information() { 54 | local _static=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} show network 2> /dev/null | grep '=route$' | wc -l` 55 | local _active=`cat $FREECWMP_DEVICE_ROUTES | wc -l` 56 | local _inactive=0 57 | 58 | local _uci_target 59 | local _uci_gateway 60 | local _uci_netmask 61 | local _route_active 62 | 63 | local i 64 | let local _count=$_static-1 65 | for i in `seq 0 $_count` 66 | do 67 | _uci_target=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.@route[$i].target 2> /dev/null` 68 | _uci_gateway=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.@route[$i].gateway 2> /dev/null` 69 | _uci_netmask=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.@route[$i].netmask 2> /dev/null` 70 | get_device_routing_ipv4_check_route "$_uci_target" "$_uci_gateway" "$_uci_netmask" "_route_active" 71 | if [ $_route_active -ne 1 ]; then 72 | let _inactive=$_inactive+1 73 | fi 74 | done 75 | 76 | let local _total=$_active+$_inactive 77 | eval "export -- \"$1=\"\"$_total\"\"\"" 78 | eval "export -- \"$2=\"\"$_active\"\"\"" 79 | eval "export -- \"$3=\"\"$_inactive\"\"\"" 80 | eval "export -- \"$4=\"\"$_static\"\"\"" 81 | } 82 | 83 | get_device_routing() { 84 | local parameter=$1 85 | 86 | case "$parameter" in 87 | Device.Routing.RouterNumberOfEntries) 88 | freecwmp_output "$parameter" "1" 89 | return 90 | ;; 91 | esac 92 | 93 | local rc 94 | local num 95 | 96 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.Enable" "rc" "num" 97 | if [ $rc -eq 0 ]; then 98 | local val 99 | if [ $num -eq 1 ]; then 100 | val="1" 101 | else 102 | val="0" 103 | fi 104 | freecwmp_output "$parameter" "$val" 105 | return 106 | fi 107 | 108 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.Status" "rc" "num" 109 | if [ $rc -eq 0 ]; then 110 | local val 111 | if [ $num -eq 1 ]; then 112 | val="Enabled" 113 | else 114 | val="Disabled" 115 | fi 116 | freecwmp_output "$parameter" "$val" 117 | return 118 | fi 119 | 120 | # TODO: Device.Routing.Router.{i}.Alias (alias support does not exist) 121 | 122 | # TODO: remove this file 123 | route -n | grep -v '^Kernel ' | grep -v '^Destination ' > $FREECWMP_DEVICE_ROUTES 124 | 125 | local total 126 | local active 127 | local inactive 128 | local static 129 | 130 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4ForwardingNumberOfEntries" "rc" "num" 131 | if [ $rc -eq 0 ]; then 132 | if [ "x$num" == "x1" ]; then 133 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 134 | else 135 | return 136 | fi 137 | freecwmp_output "$parameter" "$total" 138 | return 139 | fi 140 | 141 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv6ForwardingNumberOfEntries" "rc" "num" 142 | if [ $rc -eq 0 ]; then 143 | local val 144 | if [ $num -eq 1 ]; then 145 | val=0 146 | else 147 | return 148 | fi 149 | freecwmp_output "$parameter" "$val" 150 | return 151 | fi 152 | 153 | # TODO: Device.Routing.Router.{i}.IPv4Forwarding.{i}.Enable 154 | 155 | # TODO: routes can not be disabled, they should be disabled by default 156 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4Forwarding.{i}.Status" "rc" "num" 157 | if [ $rc -eq 0 ]; then 158 | local num1=`echo $num | awk '{ print $1 }'` 159 | local num2=`echo $num | awk '{ print $2 }'` 160 | if [ $num1 -eq 1 ]; then 161 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 162 | if [ $num2 -le 0 ]; then 163 | return 164 | fi 165 | if [ $num2 -gt $total ]; then 166 | return 167 | fi 168 | if [ $num2 -gt $static ]; then 169 | freecwmp_output "$parameter" "Enabled" 170 | return 171 | fi 172 | if [ $num2 -le $inactive ]; then 173 | freecwmp_output "$parameter" "Error: not active but enabled" 174 | return 175 | fi 176 | if [ $num2 -le $static ]; then 177 | freecwmp_output "$parameter" "Enabled" 178 | return 179 | fi 180 | else 181 | return 182 | fi 183 | fi 184 | 185 | # TODO: Device.Routing.Router.{i}.IPv4Forwarding.{i}.Alias (alias support does not exist) 186 | 187 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4Forwarding.{i}.StaticRoute" "rc" "num" 188 | if [ $rc -eq 0 ]; then 189 | local num1=`echo $num | awk '{ print $1 }'` 190 | local num2=`echo $num | awk '{ print $2 }'` 191 | if [ $num1 -eq 1 ]; then 192 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 193 | if [ $num2 -le 0 ]; then 194 | return 195 | fi 196 | if [ $num2 -gt $total ]; then 197 | return 198 | fi 199 | if [ $num2 -gt $static ]; then 200 | freecwmp_output "$parameter" "0" 201 | return 202 | fi 203 | if [ $num2 -le $static ]; then 204 | freecwmp_output "$parameter" "1" 205 | return 206 | fi 207 | else 208 | return 209 | fi 210 | fi 211 | 212 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4Forwarding.{i}.DestIPAddress" "rc" "num" 213 | if [ $rc -eq 0 ]; then 214 | local target 215 | local num1=`echo $num | awk '{ print $1 }'` 216 | local num2=`echo $num | awk '{ print $2 }'` 217 | if [ $num1 -eq 1 ]; then 218 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 219 | if [ $num2 -le 0 ]; then 220 | return 221 | fi 222 | if [ $num2 -gt $total ]; then 223 | return 224 | fi 225 | if [ $num2 -gt $static ]; then 226 | let local _num=$num2-$static 227 | local _sed_cmd=`echo -n \'$_num; echo p\'` 228 | target=`eval sed -n $_sed_cmd $FREECWMP_DEVICE_ROUTES_DYNAMIC | awk '{ print $1 }'` 229 | elif [ $num2 -le $static ]; then 230 | let local i=$static-$num2 231 | target=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.@route[$i].target 2> /dev/null` 232 | fi 233 | freecwmp_output "$parameter" "$target" 234 | return 235 | else 236 | return 237 | fi 238 | fi 239 | 240 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4Forwarding.{i}.DestSubnetMask" "rc" "num" 241 | if [ $rc -eq 0 ]; then 242 | local netmask 243 | local num1=`echo $num | awk '{ print $1 }'` 244 | local num2=`echo $num | awk '{ print $2 }'` 245 | if [ $num1 -eq 1 ]; then 246 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 247 | if [ $num2 -le 0 ]; then 248 | return 249 | fi 250 | if [ $num2 -gt $total ]; then 251 | return 252 | fi 253 | if [ $num2 -gt $static ]; then 254 | let local _num=$num2-$static 255 | local _sed_cmd=`echo -n \'$_num; echo p\'` 256 | netmask=`eval sed -n $_sed_cmd $FREECWMP_DEVICE_ROUTES_DYNAMIC | awk '{ print $3 }'` 257 | elif [ $num2 -le $static ]; then 258 | let local i=$static-$num2 259 | netmask=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.@route[$i].netmask 2> /dev/null` 260 | fi 261 | freecwmp_output "$parameter" "$netmask" 262 | return 263 | else 264 | return 265 | fi 266 | fi 267 | 268 | # TODO: Device.Routing.Router.{i}.IPv4Forwarding.{i}.ForwardingPolicy 269 | 270 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4Forwarding.{i}.GatewayIPAddress" "rc" "num" 271 | if [ $rc -eq 0 ]; then 272 | local gateway 273 | local num1=`echo $num | awk '{ print $1 }'` 274 | local num2=`echo $num | awk '{ print $2 }'` 275 | if [ $num1 -eq 1 ]; then 276 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 277 | if [ $num2 -le 0 ]; then 278 | return 279 | fi 280 | if [ $num2 -gt $total ]; then 281 | return 282 | fi 283 | if [ $num2 -gt $static ]; then 284 | let local _num=$num2-$static 285 | local _sed_cmd=`echo -n \'$_num; echo p\'` 286 | gateway=`eval sed -n $_sed_cmd $FREECWMP_DEVICE_ROUTES_DYNAMIC | awk '{ print $2 }'` 287 | elif [ $num2 -le $static ]; then 288 | let local i=$static-$num2 289 | gateway=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.@route[$i].gateway 2> /dev/null` 290 | fi 291 | freecwmp_output "$parameter" "$gateway" 292 | return 293 | else 294 | return 295 | fi 296 | fi 297 | 298 | # TODO: Device.Routing.Router.{i}.IPv4Forwarding.{i}.Interface 299 | 300 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4Forwarding.{i}.Origin" "rc" "num" 301 | if [ $rc -eq 0 ]; then 302 | local val 303 | local num1=`echo $num | awk '{ print $1 }'` 304 | local num2=`echo $num | awk '{ print $2 }'` 305 | if [ $num1 -eq 1 ]; then 306 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 307 | if [ $num2 -le 0 ]; then 308 | return 309 | fi 310 | if [ $num2 -gt $total ]; then 311 | return 312 | fi 313 | if [ $num2 -gt $static ]; then 314 | val="Unknown" 315 | elif [ $num2 -le $static ]; then 316 | val="Static" 317 | fi 318 | freecwmp_output "$parameter" "$val" 319 | return 320 | else 321 | return 322 | fi 323 | fi 324 | 325 | freecwmp_parse_formated_parameter "$parameter" "Device.Routing.Router.{i}.IPv4Forwarding.{i}.ForwardingMetric" "rc" "num" 326 | if [ $rc -eq 0 ]; then 327 | local metric 328 | local num1=`echo $num | awk '{ print $1 }'` 329 | local num2=`echo $num | awk '{ print $2 }'` 330 | if [ $num1 -eq 1 ]; then 331 | get_device_routing_ipv4_ordering_information "total" "active" "inactive" "static" 332 | if [ $num2 -le 0 ]; then 333 | return 334 | fi 335 | if [ $num2 -gt $total ]; then 336 | return 337 | fi 338 | if [ $num2 -gt $static ]; then 339 | let local _num=$num2-$static 340 | local _sed_cmd=`echo -n \'$_num; echo p\'` 341 | metric=`eval sed -n $_sed_cmd $FREECWMP_DEVICE_ROUTES_DYNAMIC | awk '{ print $5 }'` 342 | elif [ $num2 -le $static ]; then 343 | let local i=$static-$num2 344 | metric=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.@route[$i].metric 2> /dev/null` 345 | fi 346 | freecwmp_output "$parameter" "$metric" 347 | return 348 | else 349 | return 350 | fi 351 | fi 352 | 353 | } 354 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/device_users: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2012 Luka Perkov 3 | 4 | get_device_users() { 5 | local parameter="$1" 6 | case "$parameter" in 7 | Device.Users.UserNumberOfEntries) 8 | local val=`wc -l /etc/passwd | awk '{ print $1 }'` 9 | freecwmp_value_output "$parameter" "$val" 10 | return 11 | ;; 12 | esac 13 | 14 | local rc 15 | local num 16 | 17 | # TODO: Device.Users.User.{i}.Alias (alias support does not exist) 18 | 19 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.Enable" "rc" "num" 20 | if [ $rc -eq 0 ]; then 21 | # TODO: this is very system dependent, for now just look at users shell 22 | local sed_cmd=`echo -n \'$num; echo p\'` 23 | local val=`eval sed -n $sed_cmd /etc/passwd | grep -v '/bin/false' | wc -l` 24 | freecwmp_value_output "$parameter" "$val" 25 | return 26 | fi 27 | 28 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.RemoteAccessCapable" "rc" "num" 29 | if [ $rc -eq 0 ]; then 30 | # TODO: this is very system dependent, for now just look at users shell 31 | local sed_cmd=`echo -n \'$num; echo p\'` 32 | local val=`eval sed -n $sed_cmd /etc/passwd | grep -v '/bin/false' | wc -l` 33 | freecwmp_value_output "$parameter" "$val" 34 | return 35 | fi 36 | 37 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.Username" "rc" "num" 38 | if [ $rc -eq 0 ]; then 39 | local sed_cmd=`echo -n \'$num; echo p\'` 40 | local val=`eval sed -n $sed_cmd /etc/passwd | awk -F ':' '{ print $1 }'` 41 | freecwmp_value_output "$parameter" "$val" 42 | return 43 | fi 44 | 45 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.Password" "rc" "num" 46 | if [ $rc -eq 0 ]; then 47 | # if we *really* wanted to get the password we could do it like this 48 | # local sed_cmd=`echo -n \'$num; echo p\'` 49 | # local val=`eval sed -n $sed_cmd /etc/shadow | awk -F ':' '{ print $2 }'` 50 | # freecwmp_value_output "$parameter" "$val" 51 | freecwmp_value_output "$parameter" "" 52 | return 53 | fi 54 | 55 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.Language" "rc" "num" 56 | if [ $rc -eq 0 ]; then 57 | freecwmp_value_output "$parameter" "" 58 | return 59 | fi 60 | } 61 | 62 | set_device_users() { 63 | local parameter="$1" 64 | local value="$2" 65 | 66 | local rc 67 | local num 68 | 69 | # TODO: Device.Users.User.{i}.Alias (alias support does not exist) 70 | 71 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.Enable" "rc" "num" 72 | if [ $rc -eq 0 ]; then 73 | # TODO: this is very system dependent, for now just look at users shell 74 | local val 75 | if [ "$value" = "1" ]; then 76 | val="/bin/ash" 77 | else 78 | val="/bin/false" 79 | fi 80 | local sed_cmd 81 | sed_cmd=`echo -n \'$num; echo p\'` 82 | local orig=`eval sed -n $sed_cmd /etc/passwd | awk -F ':' '{ print $7 }'` 83 | sed_cmd=`echo -n \'$num; echo s%:$orig%:$val%\'` 84 | eval sed -i $sed_cmd /etc/passwd 85 | return 86 | fi 87 | 88 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.RemoteAccessCapable" "rc" "num" 89 | if [ $rc -eq 0 ]; then 90 | # TODO: this is very system dependent, for now just look at users shell 91 | local val 92 | if [ "$value" = "1" ]; then 93 | val="/bin/ash" 94 | else 95 | val="/bin/false" 96 | fi 97 | local sed_cmd 98 | sed_cmd=`echo -n \'$num; echo p\'` 99 | local orig=`eval sed -n $sed_cmd /etc/passwd | awk -F ':' '{ print $7 }'` 100 | sed_cmd=`echo -n \'$num; echo s%:$orig%:$val%\'` 101 | eval sed -i $sed_cmd /etc/passwd 102 | return 103 | fi 104 | 105 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.Username" "rc" "num" 106 | if [ $rc -eq 0 ]; then 107 | local sed_cmd 108 | sed_cmd=`echo -n \'$num; echo p\'` 109 | local orig=`eval sed -n $sed_cmd /etc/passwd | awk -F ':' '{ print $1 }'` 110 | sed_cmd=`echo -n \'$num; echo s%$orig:%$value:%\'` 111 | eval sed -i $sed_cmd /etc/passwd 112 | return 113 | fi 114 | 115 | freecwmp_parse_formated_parameter "$parameter" "Device.Users.User.{i}.Password" "rc" "num" 116 | if [ $rc -eq 0 ]; then 117 | local sed_cmd 118 | sed_cmd=`echo -n \'$num; echo p\'` 119 | local orig=`eval sed -n $sed_cmd /etc/shadow | awk -F ':' '{ print $2 }'` 120 | sed_cmd=`echo -n \'$num; echo s%:$orig:%:$value:%\'` 121 | eval sed -i $sed_cmd /etc/shadow 122 | return 123 | fi 124 | 125 | # TODO: Device.Users.User.{i}.Language (why? look at the get value function for this parameter) 126 | } 127 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/lan_device: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2012 Luka Perkov 3 | 4 | get_wlan_enable() { 5 | local num="$1" 6 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get wireless.@wifi-device[$num].disabled 2> /dev/null` 7 | let num=$num+1 8 | if [ "$val" = "1" ]; then 9 | val="0" 10 | else 11 | val="1" 12 | fi 13 | freecwmp_output "InternetGatewayDevice.LANDevice.1.WLANConfiguration.$num.Enable" "$val" 14 | } 15 | 16 | set_wlan_enable() { 17 | local num="$1" 18 | local val="$2" 19 | if [ "$val" = "1" ]; then 20 | val="0" 21 | else 22 | val="1" 23 | fi 24 | delay_command "wifi" "wifi" "45" 25 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set wireless.@wifi-device[$num].disabled="$val" 26 | } 27 | 28 | get_wlan_ssid() { 29 | local num="$1" 30 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get wireless.@wifi-iface[$num].ssid 2> /dev/null` 31 | let num=$num+1 32 | freecwmp_output "InternetGatewayDevice.LANDevice.1.WLANConfiguration.$num.SSID" "$val" 33 | } 34 | 35 | set_wlan_ssid() { 36 | local num="$1" 37 | local val="$2" 38 | delay_command "wifi" "wifi" "45" 39 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set wireless.@wifi-iface[$num].ssid="$val" 40 | } 41 | 42 | get_lan_device() { 43 | case "$1" in 44 | InternetGatewayDevice.) 45 | get_wlan_enable 0 46 | get_wlan_ssid 0 47 | ;; 48 | InternetGatewayDevice.LANDevice.) 49 | get_wlan_enable 0 50 | get_wlan_ssid 0 51 | ;; 52 | InternetGatewayDevice.LANDevice.1.) 53 | get_wlan_enable 0 54 | get_wlan_ssid 0 55 | ;; 56 | InternetGatewayDevice.LANDevice.1.WLANConfiguration.) 57 | get_wlan_enable 0 58 | get_wlan_ssid 0 59 | ;; 60 | InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.) 61 | get_wlan_enable 0 62 | get_wlan_ssid 0 63 | ;; 64 | InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.Enable) 65 | get_wlan_enable 0 66 | ;; 67 | InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID) 68 | get_wlan_ssid 0 69 | ;; 70 | esac 71 | } 72 | 73 | set_lan_device() { 74 | case "$1" in 75 | InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.Enable) 76 | set_wlan_enable 0 "$2" 77 | ;; 78 | InternetGatewayDevice.LANDevice.1.WLANConfiguration.1.SSID) 79 | set_wlan_ssid 0 "$2" 80 | ;; 81 | esac 82 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 83 | } 84 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/management_server: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2011-2012 Luka Perkov 3 | 4 | get_management_server_url() { 5 | local tmp=${FLAGS_value} 6 | FLAGS_value=${FLAGS_TRUE} 7 | local scheme=`get_management_server_x_freecwmp_org__acs_scheme` 8 | local hostname=`get_management_server_x_freecwmp_org__acs_hostname` 9 | local port=`get_management_server_x_freecwmp_org__acs_port` 10 | local path=`get_management_server_x_freecwmp_org__acs_path` 11 | FLAGS_value=$tmp 12 | local val=`echo $scheme://$hostname:$port$path` 13 | freecwmp_output "InternetGatewayDevice.ManagementServer.URL" "$val" 14 | } 15 | 16 | set_management_server_url() { 17 | local url=$1 18 | local scheme 19 | local hostname 20 | local path 21 | local port 22 | 23 | scheme=`echo $url | awk -F "://" '{ print $1 }'` 24 | hostname=`echo $url | awk -F "$scheme://" '{ print $2 }' | awk -F ":" '{ print $1 }' | awk -F "/" '{ print $1 }'` 25 | port=`echo $url | awk -F "$scheme://$hostname:" '{ print $2 }' | awk -F '/' '{ print $1 }'` 26 | 27 | if [ -z "$port" ]; then 28 | port=80 29 | path=`echo $url | awk -F "$scheme://$hostname" '{ print $2 }'` 30 | echo 123 $path 31 | else 32 | path=`echo $url | awk -F "$scheme://$hostname:$port" '{ print $2 }'` 33 | fi 34 | 35 | if [ -z "$path" ]; then 36 | path="/" 37 | fi 38 | 39 | set_management_server_x_freecwmp_org__acs_scheme $scheme 40 | set_management_server_x_freecwmp_org__acs_hostname $hostname 41 | set_management_server_x_freecwmp_org__acs_port $port 42 | set_management_server_x_freecwmp_org__acs_path $path 43 | 44 | ubus ${UBUS_SOCKET:+-s $UBUS_SOCKET} call tr069 inform '{ "event": "value_change" }' & 45 | } 46 | 47 | get_management_server_username() { 48 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@acs[0].username 2> /dev/null` 49 | freecwmp_output "InternetGatewayDevice.ManagementServer.Username" "$val" 50 | } 51 | 52 | set_management_server_username() { 53 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@acs[0].username="$1" 54 | } 55 | 56 | get_management_server_password() { 57 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@acs[0].password 2> /dev/null` 58 | freecwmp_output "InternetGatewayDevice.ManagementServer.Password" "$val" 59 | } 60 | 61 | set_management_server_password() { 62 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@acs[0].password="$1" 63 | } 64 | 65 | get_management_server_periodic_inform_enable() { 66 | local parm="InternetGatewayDevice.ManagementServer.PeriodicInformEnable" 67 | freecwmp_get_parameter_value "val" "$parm" 68 | freecwmp_output "$parm" "$val" 69 | } 70 | 71 | set_management_server_periodic_inform_enable() { 72 | local parm="InternetGatewayDevice.ManagementServer.PeriodicInformEnable" 73 | freecwmp_set_parameter_value "$parm" "$1" 74 | } 75 | 76 | get_management_server_periodic_inform_interval() { 77 | local parm="InternetGatewayDevice.ManagementServer.PeriodicInformInterval" 78 | freecwmp_get_parameter_value "val" "$parm" 79 | freecwmp_output "$parm" "$val" 80 | } 81 | 82 | set_management_server_periodic_inform_interval() { 83 | local parm="InternetGatewayDevice.ManagementServer.PeriodicInformInterval" 84 | freecwmp_set_parameter_value "$parm" "$1" 85 | } 86 | 87 | get_management_server_connection_request_url() { 88 | local val 89 | if [ -z "$default_management_server_connection_request_url" ]; then 90 | local tmp=${FLAGS_value} 91 | FLAGS_value=${FLAGS_TRUE} 92 | local ip=`get_wan_device_mng_interface_ip` 93 | local port=`get_management_server_x_freecwmp_org__connection_request_port` 94 | FLAGS_value=$tmp 95 | 96 | if [ -n "$ip" -a -n "$port" ]; then 97 | val="http://$ip:$port/" 98 | fi 99 | else 100 | val=$default_management_server_connection_request_url 101 | fi 102 | 103 | freecwmp_output "InternetGatewayDevice.ManagementServer.ConnectionRequestURL" "$val" 104 | } 105 | 106 | # TODO: InternetGatewayDevice.ManagementServer.PeriodicInformTime 107 | 108 | get_management_server_x_freecwmp_org__acs_scheme() { 109 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@acs[0].scheme 2> /dev/null` 110 | freecwmp_output "InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Scheme" "$val" 111 | } 112 | 113 | set_management_server_x_freecwmp_org__acs_scheme() { 114 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@acs[0].scheme="$1" 115 | } 116 | 117 | get_management_server_x_freecwmp_org__acs_hostname() { 118 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@acs[0].hostname 2> /dev/null` 119 | freecwmp_output "InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Hostname" "$val" 120 | } 121 | 122 | set_management_server_x_freecwmp_org__acs_hostname() { 123 | if [ -z "$default_management_server_acs_hostname" ]; then 124 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@acs[0].hostname="$1" 125 | else 126 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@acs[0].hostname="$default_management_server_acs_hostname" 127 | fi 128 | } 129 | 130 | get_management_server_x_freecwmp_org__acs_port() { 131 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@acs[0].port 2> /dev/null` 132 | freecwmp_output "InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Port" "$val" 133 | } 134 | 135 | set_management_server_x_freecwmp_org__acs_port() { 136 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@acs[0].port="$1" 137 | } 138 | 139 | get_management_server_x_freecwmp_org__acs_path() { 140 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@acs[0].path 2> /dev/null` 141 | freecwmp_output "InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Path" "$val" 142 | } 143 | 144 | set_management_server_x_freecwmp_org__acs_path() { 145 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@acs[0].path="$1" 146 | } 147 | 148 | get_management_server_x_freecwmp_org__connection_request_port() { 149 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get freecwmp.@local[0].port 2> /dev/null` 150 | freecwmp_output "InternetGatewayDevice.ManagementServer.X_freecwmp_org__Connection_Request_Port" "$val" 151 | } 152 | 153 | set_management_server_x_freecwmp_org__connection_request_port() { 154 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set freecwmp.@local[0].port="$1" 155 | } 156 | 157 | get_management_server() { 158 | case "$1" in 159 | InternetGatewayDevice.) 160 | get_management_server_url 161 | get_management_server_username 162 | get_management_server_password 163 | get_management_server_periodic_inform_enable 164 | get_management_server_periodic_inform_interval 165 | get_management_server_connection_request_url 166 | get_management_server_x_freecwmp_org__acs_scheme 167 | get_management_server_x_freecwmp_org__acs_hostname 168 | get_management_server_x_freecwmp_org__acs_port 169 | get_management_server_x_freecwmp_org__acs_path 170 | get_management_server_x_freecwmp_org__connection_request_port 171 | ;; 172 | InternetGatewayDevice.ManagementServer.) 173 | get_management_server_url 174 | get_management_server_username 175 | get_management_server_password 176 | get_management_server_periodic_inform_enable 177 | get_management_server_periodic_inform_interval 178 | get_management_server_connection_request_url 179 | get_management_server_x_freecwmp_org__acs_scheme 180 | get_management_server_x_freecwmp_org__acs_hostname 181 | get_management_server_x_freecwmp_org__acs_port 182 | get_management_server_x_freecwmp_org__acs_path 183 | get_management_server_x_freecwmp_org__connection_request_port 184 | ;; 185 | InternetGatewayDevice.ManagementServer.URL) 186 | get_management_server_url 187 | ;; 188 | InternetGatewayDevice.ManagementServer.Username) 189 | get_management_server_username 190 | ;; 191 | InternetGatewayDevice.ManagementServer.Password) 192 | get_management_server_password 193 | ;; 194 | InternetGatewayDevice.ManagementServer.PeriodicInformEnable) 195 | get_management_server_periodic_inform_enable 196 | ;; 197 | InternetGatewayDevice.ManagementServer.PeriodicInformInterval) 198 | get_management_server_periodic_inform_interval 199 | ;; 200 | InternetGatewayDevice.ManagementServer.ConnectionRequestURL) 201 | get_management_server_connection_request_url 202 | ;; 203 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Scheme) 204 | get_management_server_x_freecwmp_org__acs_scheme 205 | ;; 206 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Hostname) 207 | get_management_server_x_freecwmp_org__acs_hostname 208 | ;; 209 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Port) 210 | get_management_server_x_freecwmp_org__acs_port 211 | ;; 212 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Path) 213 | get_management_server_x_freecwmp_org__acs_path 214 | ;; 215 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__Connection_Request_Port) 216 | get_management_server_x_freecwmp_org__connection_request_port 217 | ;; 218 | esac 219 | } 220 | 221 | set_management_server() { 222 | case "$1" in 223 | InternetGatewayDevice.ManagementServer.URL) 224 | set_management_server_url "$2" 225 | ;; 226 | InternetGatewayDevice.ManagementServer.Username) 227 | set_management_server_username "$2" 228 | ;; 229 | InternetGatewayDevice.ManagementServer.Password) 230 | set_management_server_password "$2" 231 | ;; 232 | InternetGatewayDevice.ManagementServer.PeriodicInformEnable) 233 | set_management_server_periodic_inform_enable "$2" 234 | ;; 235 | InternetGatewayDevice.ManagementServer.PeriodicInformInterval) 236 | set_management_server_periodic_inform_interval "$2" 237 | ;; 238 | InternetGatewayDevice.ManagementServer.ConnectionRequestURL) 239 | set_management_server_connection_request_url "$2" 240 | ;; 241 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Scheme) 242 | set_management_server_x_freecwmp_org__acs_scheme "$2" 243 | ;; 244 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Hostname) 245 | get_management_server_x_freecwmp_org__acs_hostname "$2" 246 | ;; 247 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Port) 248 | set_management_server_x_freecwmp_org__acs_port "$2" 249 | ;; 250 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__ACS_Path) 251 | set_management_server_x_freecwmp_org__acs_path "$2" 252 | ;; 253 | InternetGatewayDevice.ManagementServer.X_freecwmp_org__Connection_Request_Port) 254 | set_management_server_x_freecwmp_org__connection_request_port "$2" 255 | ;; 256 | esac 257 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 258 | } 259 | 260 | check_parameter_management_server_generic() { 261 | case "$1" in 262 | InternetGatewayDevice.ManagementServer.ConnectionRequestUsername|\ 263 | InternetGatewayDevice.ManagementServer.ConnectionRequestPassword|\ 264 | InternetGatewayDevice.ManagementServer.UpgradesManaged) 265 | return 0 266 | ;; 267 | esac 268 | return 1 269 | } 270 | 271 | get_management_server_generic() { 272 | check_parameter_management_server_generic "$1" ; _tmp=$? ; if [ "$_tmp" -eq 1 ]; then return 0; fi 273 | 274 | freecwmp_get_parameter_value "val" "$1" 275 | freecwmp_value_output "$1" "$val" 276 | } 277 | 278 | set_management_server_generic() { 279 | check_parameter_management_server_generic "$1" ; _tmp=$? ; if [ "$_tmp" -eq 1 ]; then return 0; fi 280 | 281 | freecwmp_set_parameter_value "$1" "$2" 282 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 283 | } 284 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/misc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2012 Luka Perkov 3 | 4 | get_misc_cpu_usage() { 5 | local val=`uptime | awk -F'average: ' '{ print $2 }' | awk -F',' '{ print $1 }' | awk -F'.' '{ print $2 }'` 6 | freecwmp_value_output "Device.DeviceInfo.ProcessStatus.CPUUsage" "$val" 7 | } 8 | 9 | get_misc_process_number() { 10 | local val=`ps | grep -v COMMAND | wc -l` 11 | freecwmp_value_output "Device.DeviceInfo.ProcessStatus.ProcessNumberOfEntries" "$val" 12 | } 13 | 14 | get_misc() { 15 | case "$1" in 16 | Device.DeviceInfo.ProcessStatus.CPUUsage) 17 | get_misc_cpu_usage 18 | ;; 19 | Device.DeviceInfo.ProcessStatus.ProcessNumberOfEntries) 20 | get_misc_process_number 21 | ;; 22 | esac 23 | } 24 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/wan_device: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2011-2012 Luka Perkov 3 | 4 | get_wan_device_mng_status() { 5 | # TODO: Unconfigured ; Connecting ; Connected ; PendingDisconnect ; Disconneting ; Disconnected 6 | local val="Connected" 7 | freecwmp_output "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ConnectionStatus" "$val" 8 | } 9 | 10 | get_wan_device_mng_interface_ip() { 11 | local val 12 | if [ -z "$default_wan_device_mng_interface_ip" ]; then 13 | val=`network_get_ipaddr val mng` 14 | else 15 | val=$default_wan_device_mng_interface_ip 16 | fi 17 | freecwmp_output "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress" "$val" 18 | } 19 | 20 | get_wan_device_mng_interface_mac() { 21 | if [ -z "$default_wan_device_mng_interface_mac" ]; then 22 | val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.mng.macaddr` 23 | else 24 | val=$default_wan_device_mng_interface_mac 25 | fi 26 | freecwmp_output "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress" "$val" 27 | } 28 | 29 | get_wan_device_wan_ppp_enable() { 30 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.wan.auto 2> /dev/null` 31 | if [ -z $val ]; then 32 | val="1" 33 | fi 34 | freecwmp_output "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Enable" "$val" 35 | } 36 | 37 | set_wan_device_wan_ppp_enable() { 38 | local val=$1 39 | if [ "$val" -eq 0 ]; then 40 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set network.wan.auto=0 41 | ifdown wan & 42 | elif [ "$val" -eq 1 ]; then 43 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set network.wan.auto=1 44 | ifup wan & 45 | fi 46 | } 47 | 48 | get_wan_device_wan_ppp_username() { 49 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get network.wan.username 2> /dev/null` 50 | freecwmp_output "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Username" "$val" 51 | } 52 | 53 | set_wan_device_wan_ppp_username() { 54 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set network.wan.username="$1" 55 | } 56 | 57 | get_wan_device_wan_ppp_password() { 58 | freecwmp_output "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Password" "" 59 | } 60 | 61 | set_wan_device_wan_ppp_password() { 62 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set network.wan.password="$1" 63 | } 64 | 65 | get_wan_device() { 66 | case "$1" in 67 | InternetGatewayDevice.) 68 | get_wan_device_mng_status 69 | get_wan_device_mng_interface_ip 70 | get_wan_device_mng_interface_mac 71 | get_wan_device_wan_ppp_enable 72 | get_wan_device_wan_ppp_username 73 | get_wan_device_wan_ppp_password 74 | ;; 75 | InternetGatewayDevice.WANDevice.) 76 | get_wan_device_mng_status 77 | get_wan_device_mng_interface_ip 78 | get_wan_device_mng_interface_mac 79 | get_wan_device_wan_ppp_enable 80 | get_wan_device_wan_ppp_username 81 | get_wan_device_wan_ppp_password 82 | ;; 83 | InternetGatewayDevice.WANDevice.1.) 84 | get_wan_device_mng_status 85 | get_wan_device_mng_interface_ip 86 | get_wan_device_mng_interface_mac 87 | get_wan_device_wan_ppp_enable 88 | get_wan_device_wan_ppp_username 89 | get_wan_device_wan_ppp_password 90 | ;; 91 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.) 92 | get_wan_device_mng_status 93 | get_wan_device_mng_interface_ip 94 | get_wan_device_mng_interface_mac 95 | get_wan_device_wan_ppp_enable 96 | get_wan_device_wan_ppp_username 97 | get_wan_device_wan_ppp_password 98 | ;; 99 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.) 100 | get_wan_device_mng_status 101 | get_wan_device_mng_interface_ip 102 | get_wan_device_mng_interface_mac 103 | get_wan_device_wan_ppp_enable 104 | get_wan_device_wan_ppp_username 105 | get_wan_device_wan_ppp_password 106 | ;; 107 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.) 108 | get_wan_device_mng_status 109 | get_wan_device_mng_interface_ip 110 | get_wan_device_mng_interface_mac 111 | ;; 112 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.) 113 | get_wan_device_mng_status 114 | get_wan_device_mng_interface_ip 115 | get_wan_device_mng_interface_mac 116 | ;; 117 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ConnectionStatus) 118 | get_wan_device_mng_status 119 | ;; 120 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress) 121 | get_wan_device_mng_interface_ip 122 | ;; 123 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.MACAddress) 124 | get_wan_device_mng_interface_mac 125 | ;; 126 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Enable) 127 | get_wan_device_wan_ppp_enable 128 | ;; 129 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Username) 130 | get_wan_device_wan_ppp_username 131 | ;; 132 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Password) 133 | get_wan_device_wan_ppp_password 134 | ;; 135 | esac 136 | } 137 | 138 | set_wan_device() { 139 | case "$1" in 140 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Enable) 141 | set_wan_device_wan_ppp_enable "$2" 142 | ;; 143 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Username) 144 | set_wan_device_wan_ppp_username "$2" 145 | ;; 146 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.2.WANPPPConnection.1.Password) 147 | set_wan_device_wan_ppp_password "$2" 148 | ;; 149 | esac 150 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 151 | } 152 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/functions/x_freecwmp_org: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2011 Luka Perkov 3 | 4 | -------------------------------------------------------------------------------- /ext/openwrt/scripts/unused/owsip_voice_service: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (C) 2012 Luka Perkov 3 | 4 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServer 5 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServerPort 6 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServerTransport 7 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServer 8 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServerPort 9 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServerTransport 10 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.UserAgentDomain 11 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.UserAgentTransport 12 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.OutbandProxy 13 | # OPTIONAL: InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.OutbandProxyPort 14 | 15 | get_line_enable() { 16 | local num="$1" 17 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get telephony.@account[$num].disabled 2> /dev/null` 18 | let num=$num+1 19 | if [ -n "$val" -a "$val" != "0" -o "$val" = "1" ]; then 20 | val="Disabled" 21 | else 22 | val="Enabled" 23 | fi 24 | freecwmp_output "InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.$num.Enable" "$val" 25 | } 26 | 27 | set_line_enable() { 28 | local num="$1" 29 | local val="$2" 30 | if [ "$val" = "Enabled" ]; then 31 | val="0" 32 | else 33 | val="1" 34 | fi 35 | delay_service_restart "telephony" "45" 36 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set telephony.@account[$num].disabled="$val" 37 | } 38 | 39 | get_line_sip_username() { 40 | local num="$1" 41 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get telephony.@account[$num].username 2> /dev/null` 42 | let num=$num+1 43 | freecwmp_output "InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.$num.SIP.AuthUserName" "$val" 44 | } 45 | 46 | set_line_sip_username() { 47 | local num="$1" 48 | local val="$2" 49 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set telephony.@account[$num].username="$val" 50 | } 51 | 52 | get_line_sip_password() { 53 | local num="$1" 54 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get telephony.@account[$num].password 2> /dev/null` 55 | let num=$num+1 56 | freecwmp_output "InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.$num.SIP.AuthPassword" "$val" 57 | } 58 | 59 | set_line_sip_password() { 60 | local num="$1" 61 | local val="$2" 62 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set telephony.@account[$num].password="$val" 63 | } 64 | 65 | get_line_sip_uri() { 66 | local num="$1" 67 | local val=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get telephony.@account[$num].realm 2> /dev/null` 68 | let num=$num+1 69 | freecwmp_output "InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.$num.SIP.URI" "$val" 70 | } 71 | 72 | set_line_sip_uri() { 73 | local num="$1" 74 | local val="$2" 75 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} set telephony.@account[$num].realm="$val" 76 | } 77 | 78 | get_voice_service() { 79 | case "$1" in 80 | InternetGatewayDevice.) 81 | get_line_enable 0 82 | get_line_enable 1 83 | get_line_sip_username 0 84 | get_line_sip_username 1 85 | get_line_sip_password 0 86 | get_line_sip_password 1 87 | get_line_sip_uri 0 88 | get_line_sip_uri 1 89 | ;; 90 | InternetGatewayDevice.Services.) 91 | get_line_enable 0 92 | get_line_enable 1 93 | get_line_sip_username 0 94 | get_line_sip_username 1 95 | get_line_sip_password 0 96 | get_line_sip_password 1 97 | get_line_sip_uri 0 98 | get_line_sip_uri 1 99 | ;; 100 | InternetGatewayDevice.Services.VoiceService.) 101 | get_line_enable 0 102 | get_line_enable 1 103 | get_line_sip_username 0 104 | get_line_sip_username 1 105 | get_line_sip_password 0 106 | get_line_sip_password 1 107 | ;; 108 | InternetGatewayDevice.Services.VoiceService.1.) 109 | get_line_enable 0 110 | get_line_enable 1 111 | get_line_sip_username 0 112 | get_line_sip_username 1 113 | get_line_sip_password 0 114 | get_line_sip_password 1 115 | get_line_sip_uri 0 116 | get_line_sip_uri 1 117 | ;; 118 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.) 119 | get_line_enable 0 120 | get_line_enable 1 121 | get_line_sip_username 0 122 | get_line_sip_username 1 123 | get_line_sip_password 0 124 | get_line_sip_password 1 125 | get_line_sip_uri 0 126 | get_line_sip_uri 1 127 | ;; 128 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.) 129 | get_line_enable 0 130 | get_line_enable 1 131 | get_line_sip_username 0 132 | get_line_sip_username 1 133 | get_line_sip_password 0 134 | get_line_sip_password 1 135 | get_line_sip_uri 0 136 | get_line_sip_uri 1 137 | ;; 138 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.) 139 | get_line_enable 0 140 | get_line_enable 1 141 | get_line_sip_username 0 142 | get_line_sip_username 1 143 | get_line_sip_password 0 144 | get_line_sip_password 1 145 | get_line_sip_uri 0 146 | get_line_sip_uri 1 147 | ;; 148 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServer) 149 | ;; 150 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServerTransport) 151 | ;; 152 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServer) 153 | ;; 154 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServerPort) 155 | ;; 156 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServerTransport) 157 | ;; 158 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.UserAgentDomain) 159 | ;; 160 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.UserAgentTransport) 161 | ;; 162 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.OutbandProxy) 163 | ;; 164 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.OutbandProxyPort) 165 | ;; 166 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.) 167 | get_line_enable 0 168 | get_line_enable 1 169 | get_line_sip_username 0 170 | get_line_sip_username 1 171 | get_line_sip_password 0 172 | get_line_sip_password 1 173 | get_line_sip_uri 0 174 | get_line_sip_uri 1 175 | ;; 176 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.) 177 | get_line_enable 0 178 | get_line_sip_username 0 179 | get_line_sip_password 0 180 | get_line_sip_uri 0 181 | ;; 182 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.Enable) 183 | get_line_enable 0 184 | ;; 185 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.SIP.AuthUserName) 186 | get_line_sip_username 0 187 | ;; 188 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.SIP.AuthPassword) 189 | get_line_sip_password 0 190 | ;; 191 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.SIP.URI) 192 | get_line_sip_uri 0 193 | ;; 194 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.) 195 | get_line_sip_username 1 196 | get_line_sip_password 1 197 | get_line_sip_uri 1 198 | ;; 199 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.Enable) 200 | get_line_enable 1 201 | ;; 202 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.SIP.AuthUserName) 203 | get_line_sip_username 1 204 | ;; 205 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.SIP.AuthPassword) 206 | get_line_sip_password 1 207 | ;; 208 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.SIP.URI) 209 | get_line_sip_uri 1 210 | ;; 211 | esac 212 | } 213 | 214 | set_voice_service() { 215 | case "$1" in 216 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServer) 217 | ;; 218 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServerPort) 219 | ;; 220 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.ProxyServerTransport) 221 | ;; 222 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServer) 223 | ;; 224 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServerPort) 225 | ;; 226 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.RegistrarServerTransport) 227 | ;; 228 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.UserAgentDomain) 229 | ;; 230 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.UserAgentTransport) 231 | ;; 232 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.OutbandProxy) 233 | ;; 234 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.SIP.OutbandProxyPort) 235 | ;; 236 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.Enable) 237 | set_line_enable 0 "$2" 238 | ;; 239 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.SIP.AuthUserName) 240 | set_line_sip_username 0 "$2" 241 | ;; 242 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.SIP.AuthPassword) 243 | set_line_sip_password 0 "$2" 244 | ;; 245 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.1.SIP.URI) 246 | set_line_sip_uri 0 "$2" 247 | ;; 248 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.Enable) 249 | set_line_enable 1 "$2" 250 | ;; 251 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.SIP.AuthUserName) 252 | set_line_sip_username 1 "$2" 253 | ;; 254 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.SIP.AuthPassword) 255 | set_line_sip_password 1 "$2" 256 | ;; 257 | InternetGatewayDevice.Services.VoiceService.1.VoiceProfile.1.Line.2.SIP.URI) 258 | set_line_sip_uri 1 "$2" 259 | ;; 260 | esac 261 | /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} commit 262 | } 263 | -------------------------------------------------------------------------------- /ext/soap_msg_templates/cwmp_inform_message.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 1 21 | 22 | 23 | 24 | 25 | InternetGatewayDevice.DeviceInfo.SpecVersion 26 | 1.0 27 | 28 | 29 | InternetGatewayDevice.DeviceInfo.Manufacturer 30 | 31 | 32 | 33 | InternetGatewayDevice.DeviceInfo.ManufacturerOUI 34 | 35 | 36 | 37 | InternetGatewayDevice.DeviceInfo.ProductClass 38 | 39 | 40 | 41 | InternetGatewayDevice.DeviceInfo.SerialNumber 42 | 43 | 44 | 45 | InternetGatewayDevice.DeviceInfo.HardwareVersion 46 | 47 | 48 | 49 | InternetGatewayDevice.DeviceInfo.SoftwareVersion 50 | 51 | 52 | 53 | InternetGatewayDevice.DeviceInfo.ProvisioningCode 54 | 55 | 56 | 57 | InternetGatewayDevice.ManagementServer.ParameterKey 58 | 59 | 60 | 61 | InternetGatewayDevice.ManagementServer.ConnectionRequestURL 62 | 63 | 64 | 65 | InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /ext/soap_msg_templates/cwmp_response_message.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ext/tmp/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore everything in this directory ; it's used for development (uci) 2 | * 3 | # except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /src/b64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * zstream - Micro URL I/O stream library 3 | * Copyright (C) 2010 Steven Barth 4 | * Copyright (C) 2010 John Crispin 5 | * 6 | * This library is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU Lesser General Public License as published 8 | * by the Free Software Foundation; either version 2.1 of the License, 9 | * or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 | * See the GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 19 | * 20 | */ 21 | 22 | #ifndef HTTP_ZSTREAM 23 | #include 24 | #include 25 | #include 26 | 27 | static const unsigned char b64encode_tbl[] = 28 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 29 | 30 | char* zstream_b64encode(const void *in, size_t *len) { 31 | size_t lenout, pad, i; 32 | const uint8_t *data = (const uint8_t*)in; 33 | 34 | lenout = *len / 3; 35 | lenout *= 4; 36 | pad = *len % 3; 37 | 38 | if (*len == 0) { 39 | return strdup(""); 40 | } else if (pad) { 41 | lenout += 4; 42 | } 43 | 44 | char *out = malloc(lenout + 1); 45 | if (!out) { 46 | return NULL; 47 | } 48 | 49 | uint8_t *o = (uint8_t*)out; 50 | for (i = 0; i < *len; i += 3) { 51 | uint32_t cv = (data[i] << 16) | (data[i+1] << 8) | data[i+2]; 52 | *(o+3) = b64encode_tbl[ cv & 0x3f]; 53 | *(o+2) = b64encode_tbl[(cv >> 6) & 0x3f]; 54 | *(o+1) = b64encode_tbl[(cv >> 12) & 0x3f]; 55 | *o = b64encode_tbl[(cv >> 18) & 0x3f]; 56 | o += 4; 57 | } 58 | 59 | if (pad) { 60 | uint32_t cv = data[*len-pad] << 16; 61 | *(o-1) = '='; 62 | *(o-2) = '='; 63 | if (pad == 2) { 64 | cv |= data[*len-pad+1] << 8; 65 | *(o-2) = b64encode_tbl[(cv >> 6) & 0x3f]; 66 | } 67 | *(o-3) = b64encode_tbl[(cv >> 12) & 0x3f]; 68 | *(o-4) = b64encode_tbl[(cv >> 18) & 0x3f]; 69 | } 70 | 71 | out[lenout] = 0; 72 | *len = lenout; 73 | return out; 74 | } 75 | 76 | static const unsigned char b64decode_tbl[] = { 77 | 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, 78 | 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 79 | 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 80 | 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 81 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 82 | 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 83 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, 84 | 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 85 | 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 86 | 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33 87 | }; 88 | 89 | void* zstream_b64decode(const char *in, size_t *len) { 90 | size_t lenout, i; 91 | 92 | if (*len == 0) { 93 | return strdup(""); 94 | } else if (*len % 4) { 95 | errno = EINVAL; 96 | return NULL; 97 | } 98 | 99 | lenout = *len / 4 * 3; 100 | 101 | unsigned char *out = malloc(lenout); 102 | if (!out) { 103 | return NULL; 104 | } 105 | 106 | unsigned char *o = out; 107 | for (i = 0; i < *len; i += 4) { 108 | uint32_t cv = 0; 109 | uint8_t j; 110 | for (j = 0; j < 4; j++) { 111 | unsigned char c = in[i + j] - 43; 112 | if (c > 79 || (c = b64decode_tbl[c]) == 0xff) { 113 | free(out); 114 | errno = EINVAL; 115 | return NULL; 116 | } 117 | 118 | cv |= c; 119 | if (j != 3) { 120 | cv <<= 6; 121 | } 122 | } 123 | 124 | *(o+2) = (unsigned char)(cv & 0xff); 125 | *(o+1) = (unsigned char)((cv >> 8) & 0xff); 126 | *o = (unsigned char)((cv >> 16) & 0xff); 127 | o += 3; 128 | } 129 | 130 | if (in[*len-1] == '=') { 131 | lenout--; 132 | } 133 | 134 | if (in[*len-2] == '=') { 135 | lenout--; 136 | } 137 | 138 | *len = lenout; 139 | return out; 140 | } 141 | 142 | #endif /* HTTP_ZSTREAM */ 143 | 144 | -------------------------------------------------------------------------------- /src/b64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * zstream - Micro URL I/O stream library 3 | * Copyright (C) 2010 Steven Barth 4 | * Copyright (C) 2010 John Crispin 5 | * 6 | * This library is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU Lesser General Public License as published 8 | * by the Free Software Foundation; either version 2.1 of the License, 9 | * or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 | * See the GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 19 | * 20 | */ 21 | 22 | #ifndef _FREECWMP_B64_H__ 23 | #define _FREECWMP_B64_H__ 24 | 25 | #ifndef HTTP_ZSTREAM 26 | char* zstream_b64encode(const void *in, size_t *len); 27 | void* zstream_b64decode(const char *in, size_t *len); 28 | #endif /* HTTP_ZSTREAM */ 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /src/config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "config.h" 16 | #include "cwmp.h" 17 | 18 | static bool first_run = true; 19 | static struct uci_context *uci_ctx; 20 | static struct uci_package *uci_freecwmp; 21 | 22 | struct core_config *config; 23 | 24 | 25 | static void config_free_local(void) { 26 | FREE(config->local->ip); 27 | FREE(config->local->interface); 28 | FREE(config->local->port); 29 | FREE(config->local->ubus_socket); 30 | FREE(config->local); 31 | cwmp_clear_events(); 32 | } 33 | 34 | static int config_init_local(void) 35 | { 36 | struct uci_section *s; 37 | struct uci_element *e1, *e2; 38 | 39 | uci_foreach_element(&uci_freecwmp->sections, e1) { 40 | s = uci_to_section(e1); 41 | if (strcmp(s->type, "local") == 0) 42 | goto section_found; 43 | } 44 | D("uci section local not found...\n"); 45 | return -1; 46 | 47 | section_found: 48 | config_free_local(); 49 | 50 | uci_foreach_element(&s->options, e1) { 51 | if (!strcmp((uci_to_option(e1))->e.name, "interface")) { 52 | config->local->interface = strdup(uci_to_option(e1)->v.string); 53 | DD("freecwmp.@local[0].interface=%s\n", config->local->interface); 54 | goto next; 55 | } 56 | 57 | if (!strcmp((uci_to_option(e1))->e.name, "port")) { 58 | if (!atoi((uci_to_option(e1))->v.string)) { 59 | D("in section local port has invalid value...\n"); 60 | return -1; 61 | } 62 | config->local->port = strdup(uci_to_option(e1)->v.string); 63 | DD("freecwmp.@local[0].port=%s\n", config->local->port); 64 | goto next; 65 | } 66 | 67 | if (!strcmp((uci_to_option(e1))->e.name, "ubus_socket")) { 68 | config->local->ubus_socket = strdup(uci_to_option(e1)->v.string); 69 | DD("freecwmp.@local[0].ubus_socket=%s\n", config->local->ubus_socket); 70 | goto next; 71 | } 72 | 73 | if (!strcmp((uci_to_option(e1))->e.name, "event") && 74 | (uci_to_option(e1))->type == UCI_TYPE_LIST) { 75 | uci_foreach_element(&((uci_to_option(e1))->v.list), e2) { 76 | if (e2 && e2->name) { 77 | cwmp_add_event(freecwmp_int_event_code(e2->name), NULL); 78 | DD("freecwmp.@local[0].event=%s\n", e2->name); 79 | } 80 | } 81 | } 82 | 83 | next: 84 | ; 85 | } 86 | 87 | if (!config->local->interface) { 88 | D("in local you must define interface\n"); 89 | return -1; 90 | } 91 | 92 | if (!config->local->interface) { 93 | D("in local you must define port\n"); 94 | return -1; 95 | } 96 | 97 | if (!config->local->ubus_socket) { 98 | D("in local you must define ubus_socket\n"); 99 | return -1; 100 | } 101 | 102 | return 0; 103 | } 104 | 105 | static void config_free_acs(void) { 106 | FREE(config->acs->scheme); 107 | FREE(config->acs->username); 108 | FREE(config->acs->password); 109 | FREE(config->acs->hostname); 110 | FREE(config->acs->port); 111 | FREE(config->acs->path); 112 | #ifdef HTTP_CURL 113 | FREE(config->acs->ssl_cert); 114 | FREE(config->acs->ssl_cacert); 115 | #endif 116 | FREE(config->acs); 117 | } 118 | 119 | static int config_init_acs(void) 120 | { 121 | struct uci_section *s; 122 | struct uci_element *e; 123 | 124 | uci_foreach_element(&uci_freecwmp->sections, e) { 125 | s = uci_to_section(e); 126 | if (strcmp(s->type, "acs") == 0) 127 | goto section_found; 128 | } 129 | D("uci section acs not found...\n"); 130 | return -1; 131 | 132 | section_found: 133 | config_free_acs(); 134 | 135 | uci_foreach_element(&s->options, e) { 136 | if (!strcmp((uci_to_option(e))->e.name, "scheme")) { 137 | /* TODO: ok, it's late and this does what i need */ 138 | bool valid = false; 139 | 140 | if (!(strncmp((uci_to_option(e))->v.string, "http", 5))) 141 | valid = true; 142 | 143 | if (!(strncmp((uci_to_option(e))->v.string, "https", 6))) 144 | valid = true; 145 | 146 | if (!valid) { 147 | D("in section acs scheme must be either http or https...\n"); 148 | return -1; 149 | } 150 | 151 | config->acs->scheme = strdup(uci_to_option(e)->v.string); 152 | DD("freecwmp.@acs[0].scheme=%s\n", config->acs->scheme); 153 | goto next; 154 | } 155 | 156 | if (!strcmp((uci_to_option(e))->e.name, "username")) { 157 | config->acs->username = strdup(uci_to_option(e)->v.string); 158 | DD("freecwmp.@acs[0].username=%s\n", config->acs->username); 159 | goto next; 160 | } 161 | 162 | if (!strcmp((uci_to_option(e))->e.name, "password")) { 163 | config->acs->password = strdup(uci_to_option(e)->v.string); 164 | DD("freecwmp.@acs[0].password=%s\n", config->acs->password); 165 | goto next; 166 | } 167 | 168 | if (!strcmp((uci_to_option(e))->e.name, "hostname")) { 169 | config->acs->hostname = strdup(uci_to_option(e)->v.string); 170 | DD("freecwmp.@acs[0].hostname=%s\n", config->acs->hostname); 171 | goto next; 172 | } 173 | 174 | if (!strcmp((uci_to_option(e))->e.name, "port")) { 175 | if (!atoi((uci_to_option(e))->v.string)) { 176 | D("in section acs port has invalid value...\n"); 177 | return -1; 178 | } 179 | config->acs->port = strdup(uci_to_option(e)->v.string); 180 | DD("freecwmp.@acs[0].port=%s\n", config->acs->port); 181 | goto next; 182 | } 183 | 184 | if (!strcmp((uci_to_option(e))->e.name, "path")) { 185 | config->acs->path = strdup(uci_to_option(e)->v.string); 186 | DD("freecwmp.@acs[0].path=%s\n", config->acs->path); 187 | goto next; 188 | } 189 | 190 | #ifdef HTTP_CURL 191 | if (!strcmp((uci_to_option(e))->e.name, "ssl_cert")) { 192 | config->acs->ssl_cert = strdup(uci_to_option(e)->v.string); 193 | DD("freecwmp.@acs[0].ssl_cert=%s\n", config->acs->ssl_cert); 194 | goto next; 195 | } 196 | 197 | if (!strcmp((uci_to_option(e))->e.name, "ssl_cacert")) { 198 | config->acs->ssl_cacert = strdup(uci_to_option(e)->v.string); 199 | DD("freecwmp.@acs[0].ssl_cacert=%s\n", config->acs->ssl_cacert); 200 | goto next; 201 | } 202 | 203 | if (!strcmp((uci_to_option(e))->e.name, "ssl_verify")) { 204 | if (!strcmp((uci_to_option(e))->v.string, "enabled")) { 205 | config->acs->ssl_verify = true; 206 | } else { 207 | config->acs->ssl_verify = false; 208 | } 209 | DD("freecwmp.@acs[0].ssl_verify=%d\n", config->acs->ssl_verify); 210 | goto next; 211 | } 212 | #endif /* HTTP_CURL */ 213 | 214 | next: 215 | ; 216 | } 217 | 218 | if (!config->acs->scheme) { 219 | D("in acs you must define scheme\n"); 220 | return -1; 221 | } 222 | 223 | if (!config->acs->username) { 224 | D("in acs you must define username\n"); 225 | return -1; 226 | } 227 | 228 | if (!config->acs->password) { 229 | D("in acs you must define password\n"); 230 | return -1; 231 | } 232 | 233 | if (!config->acs->hostname) { 234 | D("in acs you must define hostname\n"); 235 | return -1; 236 | } 237 | 238 | if (!config->acs->port) { 239 | D("in acs you must define port\n"); 240 | return -1; 241 | } 242 | 243 | if (!config->acs->path) { 244 | D("in acs you must define path\n"); 245 | return -1; 246 | } 247 | 248 | return 0; 249 | } 250 | 251 | static void config_free_device(void) 252 | { 253 | FREE(config->device->manufacturer); 254 | FREE(config->device->oui); 255 | FREE(config->device->product_class); 256 | FREE(config->device->serial_number); 257 | FREE(config->device->hardware_version); 258 | FREE(config->device->software_version); 259 | FREE(config->device); 260 | } 261 | 262 | static int config_init_device(void) 263 | { 264 | struct uci_section *s; 265 | struct uci_element *e; 266 | 267 | uci_foreach_element(&uci_freecwmp->sections, e) { 268 | s = uci_to_section(e); 269 | if (strcmp(s->type, "device") == 0) 270 | goto section_found; 271 | } 272 | D("uci section device not found...\n"); 273 | return -1; 274 | 275 | section_found: 276 | config_free_device(); 277 | 278 | uci_foreach_element(&s->options, e) { 279 | if (!strcmp((uci_to_option(e))->e.name, "manufacturer")) { 280 | config->device->manufacturer = strdup(uci_to_option(e)->v.string); 281 | DD("freecwmp.@device[0].manufacturer=%s\n", config->device->manufacturer); 282 | goto next; 283 | } 284 | 285 | if (!strcmp((uci_to_option(e))->e.name, "oui")) { 286 | config->device->oui = strdup(uci_to_option(e)->v.string); 287 | DD("freecwmp.@device[0].oui=%s\n", config->device->oui); 288 | goto next; 289 | } 290 | 291 | if (!strcmp((uci_to_option(e))->e.name, "product_class")) { 292 | config->device->product_class = strdup(uci_to_option(e)->v.string); 293 | DD("freecwmp.@device[0].product_class=%s\n", config->device->product_class); 294 | goto next; 295 | } 296 | 297 | if (!strcmp((uci_to_option(e))->e.name, "serial_number")) { 298 | config->device->serial_number = strdup(uci_to_option(e)->v.string); 299 | DD("freecwmp.@device[0].serial_number=%s\n", config->device->serial_number); 300 | goto next; 301 | } 302 | 303 | if (!strcmp((uci_to_option(e))->e.name, "hardware_version")) { 304 | config->device->hardware_version = strdup(uci_to_option(e)->v.string); 305 | DD("freecwmp.@device[0].hardware_version=%s\n", config->device->hardware_version); 306 | goto next; 307 | } 308 | 309 | if (!strcmp((uci_to_option(e))->e.name, "software_version")) { 310 | config->device->software_version = strdup(uci_to_option(e)->v.string); 311 | DD("freecwmp.@device[0].software_version=%s\n", config->device->software_version); 312 | goto next; 313 | } 314 | 315 | next: 316 | ; 317 | } 318 | 319 | if (!config->device->product_class) { 320 | D("in device you must define product_class\n"); 321 | return -1; 322 | } 323 | 324 | if (!config->device->serial_number) { 325 | D("in device you must define serial_number\n"); 326 | return -1; 327 | } 328 | 329 | if (!config->device->hardware_version) { 330 | D("in device you must define hardware_version\n"); 331 | return -1; 332 | } 333 | 334 | if (!config->device->software_version) { 335 | D("in device you must define software_version\n"); 336 | return -1; 337 | } 338 | 339 | return 0; 340 | } 341 | 342 | int config_get_cwmp(char *parameter, char **value) 343 | { 344 | struct uci_section *s; 345 | struct uci_element *e1, *e2; 346 | 347 | uci_foreach_element(&uci_freecwmp->sections, e1) { 348 | s = uci_to_section(e1); 349 | 350 | if (strcmp(s->type, "cwmp")) 351 | continue; 352 | 353 | bool found = false; 354 | uci_foreach_element(&s->options, e2) { 355 | if (!strcmp((uci_to_option(e2))->e.name, "parameter") && 356 | !strcmp((uci_to_option(e2))->v.string, parameter)) { 357 | found = true; 358 | break; 359 | } 360 | } 361 | 362 | uci_foreach_element(&s->options, e2) { 363 | if (!strcmp((uci_to_option(e2))->e.name, "value") && found) { 364 | *value = strdup(uci_to_option(e2)->v.string); 365 | return 0; 366 | } 367 | } 368 | 369 | if (found) return 1; 370 | } 371 | 372 | return 2; 373 | } 374 | 375 | static struct uci_package * 376 | config_init_package(const char *c) 377 | { 378 | struct uci_context *ctx = uci_ctx; 379 | struct uci_package *p = NULL; 380 | 381 | if (first_run) { 382 | config = calloc(1, sizeof(struct core_config)); 383 | if (!config) goto error; 384 | 385 | config->acs = calloc(1, sizeof(struct acs)); 386 | if (!config->acs) goto error; 387 | 388 | config->device = calloc(1, sizeof(struct device)); 389 | if (!config->device) goto error; 390 | 391 | config->local = calloc(1, sizeof(struct local)); 392 | if (!config->local) goto error; 393 | } 394 | 395 | if (!ctx) { 396 | ctx = uci_alloc_context(); 397 | if (!ctx) goto error; 398 | uci_ctx = ctx; 399 | 400 | #ifdef DUMMY_MODE 401 | uci_set_confdir(ctx, "./ext/openwrt/config"); 402 | uci_set_savedir(ctx, "./ext/tmp"); 403 | #endif 404 | 405 | } else { 406 | p = uci_lookup_package(ctx, c); 407 | if (p) 408 | uci_unload(ctx, p); 409 | } 410 | 411 | if (uci_load(ctx, c, &p)) { 412 | uci_free_context(ctx); 413 | return NULL; 414 | } 415 | 416 | return p; 417 | 418 | error: 419 | FREE(config->acs); 420 | FREE(config->device); 421 | FREE(config->local); 422 | FREE(config); 423 | 424 | return NULL; 425 | } 426 | 427 | void config_load(void) 428 | { 429 | if (!first_run && !uci_ctx) { 430 | uci_free_context(uci_ctx); 431 | uci_ctx = NULL; 432 | } 433 | 434 | uci_freecwmp = config_init_package("freecwmp"); 435 | if (!uci_freecwmp) goto error; 436 | 437 | if (config_init_local()) goto error; 438 | if (config_init_acs()) goto error; 439 | if (config_init_device()) goto error; 440 | 441 | first_run = false; 442 | return; 443 | 444 | error: 445 | freecwmp_log_message(NAME, L_CRIT, "configuration (re)loading failed\n"); 446 | D("configuration (re)loading failed\n"); 447 | exit(EXIT_FAILURE); 448 | } 449 | 450 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_CONFIG_H__ 11 | #define _FREECWMP_CONFIG_H__ 12 | 13 | #include 14 | 15 | #include "freecwmp.h" 16 | 17 | void config_load(void); 18 | int config_get_cwmp(char *parameter, char **value); 19 | 20 | struct acs { 21 | char *scheme; 22 | char *username; 23 | char *password; 24 | char *hostname; 25 | char *port; 26 | char *path; 27 | #ifdef HTTP_CURL 28 | char *ssl_cert; 29 | char *ssl_cacert; 30 | bool ssl_verify; 31 | #endif /* HTTP_CURL */ 32 | }; 33 | 34 | struct device { 35 | char *manufacturer; 36 | char *oui; 37 | char *product_class; 38 | char *serial_number; 39 | char *hardware_version; 40 | char *software_version; 41 | }; 42 | 43 | struct local { 44 | char *ip; 45 | char *interface; 46 | char *port; 47 | char *ubus_socket; 48 | }; 49 | 50 | struct core_config { 51 | struct acs *acs; 52 | struct device *device; 53 | struct local *local; 54 | }; 55 | 56 | extern struct core_config *config; 57 | 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /src/cwmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011-2012 Luka Perkov 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include "cwmp.h" 17 | 18 | #include "config.h" 19 | #include "external.h" 20 | #include "freecwmp.h" 21 | #include "http.h" 22 | #include "xml.h" 23 | 24 | struct cwmp_internal *cwmp; 25 | 26 | static struct uloop_timeout inform_timer = { .cb = cwmp_do_inform }; 27 | static struct uloop_timeout periodic_inform_timer = { .cb = cwmp_periodic_inform }; 28 | 29 | pthread_mutex_t event_lock; 30 | pthread_mutex_t notification_lock; 31 | 32 | static void cwmp_periodic_inform(struct uloop_timeout *timeout) 33 | { 34 | if (cwmp->periodic_inform_enabled && cwmp->periodic_inform_interval) { 35 | uloop_timeout_set(&periodic_inform_timer, cwmp->periodic_inform_interval * 1000); 36 | cwmp_add_event(PERIODIC, NULL); 37 | } 38 | 39 | if (cwmp->periodic_inform_enabled) 40 | cwmp_inform(); 41 | } 42 | 43 | static void cwmp_do_inform(struct uloop_timeout *timeout) 44 | { 45 | cwmp_inform(); 46 | } 47 | 48 | void cwmp_init(void) 49 | { 50 | char *c = NULL; 51 | 52 | config_get_cwmp("InternetGatewayDevice.ManagementServer.PeriodicInformInterval", &c); 53 | if (c) { 54 | cwmp->periodic_inform_interval = atoi(c); 55 | uloop_timeout_set(&periodic_inform_timer, cwmp->periodic_inform_interval * 1000); 56 | free(c); 57 | c = NULL; 58 | } 59 | 60 | config_get_cwmp("InternetGatewayDevice.ManagementServer.PeriodicInformEnable", &c); 61 | if (c) { 62 | cwmp->periodic_inform_enabled = atoi(c); 63 | free(c); 64 | c = NULL; 65 | } 66 | 67 | pthread_mutex_init(&event_lock, NULL); 68 | pthread_mutex_init(¬ification_lock, NULL); 69 | 70 | http_server_init(); 71 | } 72 | 73 | void cwmp_exit(void) 74 | { 75 | FREE(cwmp); 76 | http_client_exit(); 77 | xml_exit(); 78 | } 79 | 80 | int cwmp_inform(void) 81 | { 82 | char *msg_in, *msg_out; 83 | msg_in = msg_out = NULL; 84 | 85 | if (http_client_init()) { 86 | D("initializing http client failed\n"); 87 | goto error; 88 | } 89 | 90 | if (xml_prepare_inform_message(&msg_out)) { 91 | D("xml message creating failed\n"); 92 | goto error; 93 | } 94 | 95 | if (http_send_message(msg_out, &msg_in)) { 96 | D("sending http message failed\n"); 97 | goto error; 98 | } 99 | 100 | if (msg_in && xml_parse_inform_response_message(msg_in)) { 101 | D("parse xml message from ACS failed\n"); 102 | goto error; 103 | } 104 | 105 | FREE(msg_in); 106 | FREE(msg_out); 107 | 108 | cwmp->retry_count = 0; 109 | 110 | if (cwmp_handle_messages()) { 111 | D("handling xml message failed\n"); 112 | goto error; 113 | } 114 | 115 | cwmp_clear_notifications(); 116 | http_client_exit(); 117 | xml_exit(); 118 | 119 | return 0; 120 | 121 | error: 122 | FREE(msg_in); 123 | FREE(msg_out); 124 | 125 | http_client_exit(); 126 | xml_exit(); 127 | 128 | cwmp->retry_count++; 129 | if (cwmp->retry_count < 100) { 130 | uloop_timeout_set(&inform_timer, 10000 * cwmp->retry_count); 131 | } else { 132 | /* try every 20 minutes */ 133 | uloop_timeout_set(&inform_timer, 1200000); 134 | } 135 | 136 | return -1; 137 | } 138 | 139 | int cwmp_handle_messages(void) 140 | { 141 | int8_t status; 142 | char *msg_in, *msg_out; 143 | msg_in = msg_out = NULL; 144 | 145 | while (1) { 146 | FREE(msg_in); 147 | 148 | if (http_send_message(msg_out, &msg_in)) { 149 | D("sending http message failed\n"); 150 | goto error; 151 | } 152 | 153 | if (!msg_in) 154 | break; 155 | 156 | FREE(msg_out); 157 | 158 | if (xml_handle_message(msg_in, &msg_out)) { 159 | D("xml handling message failed\n"); 160 | goto error; 161 | } 162 | 163 | if (!msg_out) { 164 | D("acs response message is empty\n"); 165 | goto error; 166 | } 167 | } 168 | 169 | FREE(msg_in); 170 | FREE(msg_out); 171 | 172 | return 0; 173 | 174 | error: 175 | FREE(msg_in); 176 | FREE(msg_out); 177 | 178 | return -1; 179 | } 180 | 181 | void cwmp_connection_request(int code) 182 | { 183 | cwmp_clear_events(); 184 | cwmp_add_event(code, NULL); 185 | uloop_timeout_set(&inform_timer, 500); 186 | } 187 | 188 | void cwmp_add_event(int code, char *key) 189 | { 190 | struct event *e = NULL; 191 | struct list_head *l, *p; 192 | bool uniq = true; 193 | 194 | pthread_mutex_lock(&event_lock); 195 | 196 | list_for_each(p, &cwmp->events) { 197 | e = list_entry(p, struct event, list); 198 | if (e->code == code) { 199 | uniq = false; 200 | break; 201 | } 202 | } 203 | 204 | pthread_mutex_unlock(&event_lock); 205 | 206 | if (uniq) { 207 | int len = key ? strlen(key) : 0; 208 | e = calloc(1, sizeof(*e) + sizeof(int) + sizeof(char *) + len); 209 | if (!e) return; 210 | 211 | pthread_mutex_lock(&event_lock); 212 | 213 | list_add_tail(&e->list, &cwmp->events); 214 | e->code = code; 215 | e->key = key ? strdup(key) : NULL; 216 | 217 | pthread_mutex_unlock(&event_lock); 218 | } 219 | } 220 | 221 | void cwmp_clear_events(void) 222 | { 223 | struct event *n, *p; 224 | 225 | pthread_mutex_lock(&event_lock); 226 | 227 | list_for_each_entry_safe(n, p, &cwmp->events, list) { 228 | FREE(n->key); 229 | list_del(&n->list); 230 | FREE(n); 231 | } 232 | 233 | pthread_mutex_unlock(&event_lock); 234 | } 235 | 236 | void cwmp_add_notification(char *parameter, char *value) 237 | { 238 | char *c = NULL; 239 | external_get_action("notification", parameter, &c); 240 | if (!c) return; 241 | 242 | struct notification *n = NULL; 243 | struct list_head *l, *p; 244 | bool uniq = true; 245 | 246 | pthread_mutex_lock(¬ification_lock); 247 | 248 | list_for_each(p, &cwmp->notifications) { 249 | n = list_entry(p, struct notification, list); 250 | if (!strcmp(n->parameter, parameter)) { 251 | free(n->value); 252 | n->value = strdup(value); 253 | uniq = false; 254 | break; 255 | } 256 | } 257 | 258 | pthread_mutex_unlock(¬ification_lock); 259 | 260 | if (uniq) { 261 | n = calloc(1, sizeof(*n) + sizeof(char *) + strlen(parameter) + strlen(value)); 262 | if (!n) return; 263 | 264 | pthread_mutex_lock(¬ification_lock); 265 | 266 | list_add_tail(&n->list, &cwmp->notifications); 267 | n->parameter = strdup(parameter); 268 | n->value = strdup(value); 269 | 270 | pthread_mutex_unlock(¬ification_lock); 271 | } 272 | 273 | 274 | cwmp_add_event(VALUE_CHANGE, NULL); 275 | if (!strncmp(c, "2", 1)) { 276 | cwmp_inform(); 277 | } 278 | } 279 | 280 | void cwmp_clear_notifications(void) 281 | { 282 | struct notification *n, *p; 283 | 284 | pthread_mutex_lock(¬ification_lock); 285 | 286 | list_for_each_entry_safe(n, p, &cwmp->notifications, list) { 287 | FREE(n->parameter); 288 | FREE(n->value); 289 | list_del(&n->list); 290 | FREE(n); 291 | } 292 | 293 | pthread_mutex_unlock(¬ification_lock); 294 | } 295 | 296 | int cwmp_set_parameter_write_handler(char *name, char *value) 297 | { 298 | if((strcmp(name, "InternetGatewayDevice.ManagementServer.PeriodicInformEnable")) == 0) { 299 | cwmp->periodic_inform_enabled = atoi(value); 300 | } 301 | 302 | if((strcmp(name, "InternetGatewayDevice.ManagementServer.PeriodicInformInterval")) == 0) { 303 | cwmp->periodic_inform_interval = atoi(value); 304 | uloop_timeout_set(&periodic_inform_timer, cwmp->periodic_inform_interval * 1000); 305 | } 306 | 307 | return external_set_action_write("value", name, value); 308 | } 309 | 310 | -------------------------------------------------------------------------------- /src/cwmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_CWMP_H__ 11 | #define _FREECWMP_CWMP_H__ 12 | 13 | #include 14 | 15 | struct event { 16 | struct list_head list; 17 | 18 | int code; 19 | char *key; 20 | }; 21 | 22 | struct notification { 23 | struct list_head list; 24 | 25 | char *parameter; 26 | char *value; 27 | }; 28 | 29 | 30 | struct cwmp_internal { 31 | int periodic_inform_enabled; 32 | uint64_t periodic_inform_interval; 33 | int retry_count; 34 | struct list_head events; 35 | struct list_head notifications; 36 | }; 37 | 38 | extern struct cwmp_internal *cwmp; 39 | extern pthread_mutex_t event_lock; 40 | extern pthread_mutex_t notification_lock; 41 | 42 | static void cwmp_periodic_inform(struct uloop_timeout *timeout); 43 | static void cwmp_do_inform(struct uloop_timeout *timeout); 44 | 45 | void cwmp_init(void); 46 | void cwmp_exit(void); 47 | 48 | int cwmp_inform(void); 49 | int cwmp_handle_messages(void); 50 | void cwmp_connection_request(int code); 51 | 52 | void cwmp_add_event(int code, char *key); 53 | void cwmp_clear_events(void); 54 | 55 | void cwmp_add_notification(char *parameter, char *value); 56 | void cwmp_clear_notifications(void); 57 | 58 | int cwmp_set_parameter_write_handler(char *name, char *value); 59 | 60 | #endif 61 | 62 | -------------------------------------------------------------------------------- /src/external.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "external.h" 24 | 25 | #include "freecwmp.h" 26 | 27 | static struct uloop_process uproc; 28 | 29 | int external_get_action(char *action, char *name, char **value) 30 | { 31 | freecwmp_log_message(NAME, L_NOTICE, 32 | "executing get %s '%s'\n", action, name); 33 | 34 | int pfds[2]; 35 | if (pipe(pfds) < 0) 36 | return -1; 37 | 38 | if ((uproc.pid = fork()) == -1) 39 | goto error; 40 | 41 | if (uproc.pid == 0) { 42 | /* child */ 43 | 44 | const char *argv[8]; 45 | int i = 0; 46 | argv[i++] = "/bin/sh"; 47 | argv[i++] = fc_script; 48 | argv[i++] = "--newline"; 49 | argv[i++] = "--value"; 50 | argv[i++] = "get"; 51 | argv[i++] = action; 52 | argv[i++] = name; 53 | argv[i++] = NULL; 54 | 55 | close(pfds[0]); 56 | dup2(pfds[1], 1); 57 | close(pfds[1]); 58 | 59 | execvp(argv[0], (char **) argv); 60 | exit(ESRCH); 61 | 62 | } else if (uproc.pid < 0) 63 | goto error; 64 | 65 | /* parent */ 66 | close(pfds[1]); 67 | 68 | int status; 69 | while (wait(&status) != uproc.pid) { 70 | DD("waiting for child to exit"); 71 | } 72 | 73 | char buffer[2]; 74 | ssize_t rxed; 75 | 76 | *value = (char *) calloc(1, sizeof(char)); 77 | while ((rxed = read(pfds[0], buffer, sizeof(buffer))) > 0) { 78 | *value = (char *) realloc(*value, (strlen(*value) + rxed + 1) * sizeof(char)); 79 | if (!(*value)) goto error; 80 | bzero(*value + strlen(*value), rxed + 1); 81 | memcpy(*value + strlen(*value), buffer, rxed); 82 | } 83 | 84 | if (!strlen(*value)) { 85 | FREE(*value); 86 | goto done; 87 | } 88 | 89 | if (rxed < 0) 90 | goto error; 91 | 92 | done: 93 | close(pfds[0]); 94 | return 0; 95 | 96 | error: 97 | close(pfds[0]); 98 | return -1; 99 | } 100 | 101 | int external_set_action_write(char *action, char *name, char *value) 102 | { 103 | freecwmp_log_message(NAME, L_NOTICE, 104 | "adding to set %s script '%s'\n", action, name); 105 | 106 | FILE *fp; 107 | 108 | if (access(fc_script_set_actions, R_OK | W_OK | X_OK) != -1) { 109 | fp = fopen(fc_script_set_actions, "a"); 110 | if (!fp) return -1; 111 | } else { 112 | fp = fopen(fc_script_set_actions, "w"); 113 | if (!fp) return -1; 114 | 115 | fprintf(fp, "#!/bin/sh\n"); 116 | 117 | if (chmod(fc_script_set_actions, 118 | strtol("0700", 0, 8)) < 0) { 119 | return -1; 120 | } 121 | } 122 | 123 | #ifdef DUMMY_MODE 124 | fprintf(fp, "/bin/sh `pwd`/%s set %s %s %s\n", fc_script, action, name, value); 125 | #else 126 | fprintf(fp, "/bin/sh %s set %s %s %s\n", fc_script, action, name, value); 127 | #endif 128 | 129 | fclose(fp); 130 | 131 | return 0; 132 | } 133 | 134 | int external_set_action_execute() 135 | { 136 | freecwmp_log_message(NAME, L_NOTICE, "executing set script\n"); 137 | 138 | if ((uproc.pid = fork()) == -1) { 139 | return -1; 140 | } 141 | 142 | if (uproc.pid == 0) { 143 | /* child */ 144 | 145 | const char *argv[3]; 146 | int i = 0; 147 | argv[i++] = "/bin/sh"; 148 | argv[i++] = fc_script_set_actions; 149 | argv[i++] = NULL; 150 | 151 | execvp(argv[0], (char **) argv); 152 | exit(ESRCH); 153 | 154 | } else if (uproc.pid < 0) 155 | return -1; 156 | 157 | /* parent */ 158 | int status; 159 | while (wait(&status) != uproc.pid) { 160 | DD("waiting for child to exit"); 161 | } 162 | 163 | // TODO: add some kind of checks 164 | 165 | if (remove(fc_script_set_actions) != 0) 166 | return -1; 167 | 168 | return 0; 169 | } 170 | 171 | int external_simple(char *arg) 172 | { 173 | freecwmp_log_message(NAME, L_NOTICE, 174 | "executing %s request\n", arg); 175 | 176 | if ((uproc.pid = fork()) == -1) 177 | return -1; 178 | 179 | if (uproc.pid == 0) { 180 | /* child */ 181 | 182 | const char *argv[4]; 183 | int i = 0; 184 | argv[i++] = "/bin/sh"; 185 | argv[i++] = fc_script; 186 | argv[i++] = arg; 187 | argv[i++] = NULL; 188 | 189 | execvp(argv[0], (char **) argv); 190 | exit(ESRCH); 191 | 192 | } else if (uproc.pid < 0) 193 | return -1; 194 | 195 | /* parent */ 196 | int status; 197 | while (wait(&status) != uproc.pid) { 198 | DD("waiting for child to exit"); 199 | } 200 | 201 | // TODO: add some kind of checks 202 | 203 | return 0; 204 | } 205 | 206 | int external_download(char *url, char *size) 207 | { 208 | freecwmp_log_message(NAME, L_NOTICE, 209 | "executing download url '%s'\n", url); 210 | 211 | if ((uproc.pid = fork()) == -1) 212 | return -1; 213 | 214 | if (uproc.pid == 0) { 215 | /* child */ 216 | 217 | const char *argv[8]; 218 | int i = 0; 219 | argv[i++] = "/bin/sh"; 220 | argv[i++] = fc_script; 221 | argv[i++] = "download"; 222 | argv[i++] = "--url"; 223 | argv[i++] = url; 224 | argv[i++] = "--size"; 225 | argv[i++] = size; 226 | argv[i++] = NULL; 227 | 228 | execvp(argv[0], (char **) argv); 229 | exit(ESRCH); 230 | 231 | } else if (uproc.pid < 0) 232 | return -1; 233 | 234 | /* parent */ 235 | int status; 236 | while (wait(&status) != uproc.pid) { 237 | DD("waiting for child to exit"); 238 | } 239 | 240 | if (WIFEXITED(status) && !WEXITSTATUS(status)) 241 | return 0; 242 | else 243 | return 1; 244 | 245 | return 0; 246 | } 247 | 248 | -------------------------------------------------------------------------------- /src/external.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_EXTERNAL_H__ 11 | #define _FREECWMP_EXTERNAL_H__ 12 | 13 | #ifdef DUMMY_MODE 14 | static char *fc_script = "./ext/openwrt/scripts/freecwmp.sh"; 15 | #else 16 | static char *fc_script = "/usr/sbin/freecwmp"; 17 | #endif 18 | static char *fc_script_set_actions = "/tmp/freecwmp_set_action_values.sh"; 19 | 20 | int external_get_action(char *action, char *name, char **value); 21 | int external_set_action_write(char *action, char *name, char *value); 22 | int external_set_action_execute(); 23 | int external_simple(char *arg); 24 | int external_download(char *url, char *size); 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /src/freecwmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011-2012 Luka Perkov 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include "freecwmp.h" 26 | 27 | #include "config.h" 28 | #include "cwmp.h" 29 | #include "ubus.h" 30 | 31 | static void freecwmp_kickoff(struct uloop_timeout *); 32 | static void freecwmp_do_reload(struct uloop_timeout *timeout); 33 | static void netlink_new_msg(struct uloop_fd *ufd, unsigned events); 34 | 35 | static struct uloop_fd netlink_event = { .cb = netlink_new_msg }; 36 | static struct uloop_timeout netlink_timer = { .cb = freecwmp_kickoff }; 37 | static struct uloop_timeout reload_timer = { .cb = freecwmp_do_reload }; 38 | 39 | static void 40 | print_help(void) 41 | { 42 | printf("Usage: %s [OPTIONS]\n", NAME); 43 | printf(" -f, --foreground Run in the foreground\n"); 44 | printf(" -h, --help Display this help text\n"); 45 | } 46 | 47 | static void 48 | freecwmp_kickoff(struct uloop_timeout *timeout) 49 | { 50 | cwmp_exit(); 51 | cwmp_init(); 52 | if (ubus_init()) D("ubus initialization failed\n"); 53 | cwmp_inform(); 54 | } 55 | 56 | static void freecwmp_do_reload(struct uloop_timeout *timeout) 57 | { 58 | config_load(); 59 | } 60 | 61 | void freecwmp_reload(void) 62 | { 63 | uloop_timeout_set(&reload_timer, 100); 64 | } 65 | 66 | 67 | static void 68 | freecwmp_netlink_interface(struct nlmsghdr *nlh) 69 | { 70 | struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh); 71 | struct rtattr *rth = IFA_RTA(ifa); 72 | int rtl = IFA_PAYLOAD(nlh); 73 | char if_name[IFNAMSIZ], if_addr[INET_ADDRSTRLEN]; 74 | 75 | memset(&if_name, 0, sizeof(if_name)); 76 | memset(&if_addr, 0, sizeof(if_addr)); 77 | 78 | while (rtl && RTA_OK(rth, rtl)) { 79 | if (rth->rta_type != IFA_LOCAL) { 80 | rth = RTA_NEXT(rth, rtl); 81 | continue; 82 | } 83 | 84 | uint32_t addr = htonl(* (uint32_t *)RTA_DATA(rth)); 85 | if (htonl(13) == 13) { 86 | // running on big endian system 87 | } else { 88 | // running on little endian system 89 | addr = __builtin_bswap32(addr); 90 | } 91 | 92 | if_indextoname(ifa->ifa_index, if_name); 93 | if (strncmp(config->local->interface, if_name, IFNAMSIZ)) { 94 | rth = RTA_NEXT(rth, rtl); 95 | continue; 96 | } 97 | 98 | inet_ntop(AF_INET, &(addr), if_addr, INET_ADDRSTRLEN); 99 | 100 | FREE(config->local->ip); 101 | config->local->ip = strdup(if_addr); 102 | break; 103 | } 104 | 105 | if (strlen(if_addr) == 0) return; 106 | 107 | freecwmp_log_message(NAME, L_NOTICE, "interface %s has ip %s\n", \ 108 | if_name, if_addr); 109 | uloop_timeout_set(&netlink_timer, 2500); 110 | } 111 | 112 | static void 113 | netlink_new_msg(struct uloop_fd *ufd, unsigned events) 114 | { 115 | struct nlmsghdr *nlh; 116 | char buffer[BUFSIZ]; 117 | int msg_size; 118 | 119 | memset(&buffer, 0, sizeof(buffer)); 120 | 121 | nlh = (struct nlmsghdr *)buffer; 122 | if ((msg_size = recv(ufd->fd, nlh, BUFSIZ, 0)) == -1) { 123 | DD("error receiving netlink message"); 124 | return; 125 | } 126 | 127 | while (msg_size > sizeof(*nlh)) { 128 | int len = nlh->nlmsg_len; 129 | int req_len = len - sizeof(*nlh); 130 | 131 | if (req_len < 0 || len > msg_size) { 132 | DD("error reading netlink message"); 133 | return; 134 | } 135 | 136 | if (!NLMSG_OK(nlh, msg_size)) { 137 | DD("netlink message is not NLMSG_OK"); 138 | return; 139 | } 140 | 141 | if (nlh->nlmsg_type == RTM_NEWADDR) 142 | freecwmp_netlink_interface(nlh); 143 | 144 | msg_size -= NLMSG_ALIGN(len); 145 | nlh = (struct nlmsghdr*)((char*)nlh + NLMSG_ALIGN(len)); 146 | } 147 | } 148 | 149 | static int 150 | netlink_init(void) 151 | { 152 | struct { 153 | struct nlmsghdr hdr; 154 | struct ifaddrmsg msg; 155 | } req; 156 | struct sockaddr_nl addr; 157 | int sock[2]; 158 | 159 | memset(&addr, 0, sizeof(addr)); 160 | memset(&req, 0, sizeof(req)); 161 | 162 | if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { 163 | D("couldn't open NETLINK_ROUTE socket"); 164 | return -1; 165 | } 166 | 167 | addr.nl_family = AF_NETLINK; 168 | addr.nl_groups = RTMGRP_IPV4_IFADDR; 169 | if ((bind(sock[0], (struct sockaddr *)&addr, sizeof(addr))) == -1) { 170 | D("couldn't bind netlink socket"); 171 | return -1; 172 | } 173 | 174 | netlink_event.fd = sock[0]; 175 | uloop_fd_add(&netlink_event, ULOOP_READ | ULOOP_EDGE_TRIGGER); 176 | 177 | if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) { 178 | D("couldn't open NETLINK_ROUTE socket"); 179 | return -1; 180 | } 181 | 182 | req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); 183 | req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; 184 | req.hdr.nlmsg_type = RTM_GETADDR; 185 | req.msg.ifa_family = AF_INET; 186 | 187 | if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1) { 188 | D("couldn't send netlink socket"); 189 | return -1; 190 | } 191 | 192 | struct uloop_fd dummy_event = { .fd = sock[1] }; 193 | netlink_new_msg(&dummy_event, 0); 194 | 195 | return 0; 196 | } 197 | 198 | int main (int argc, char **argv) 199 | { 200 | freecwmp_log_message(NAME, L_NOTICE, "daemon started\n"); 201 | 202 | bool foreground = false; 203 | 204 | setlocale(LC_CTYPE, ""); 205 | umask(0037); 206 | 207 | #ifndef DUMMY_MODE 208 | if (getuid() != 0) { 209 | D("run %s as root\n", NAME); 210 | exit(EXIT_FAILURE); 211 | } 212 | #endif 213 | 214 | struct option long_opts[] = { 215 | {"foreground", no_argument, NULL, 'f'}, 216 | {"help", no_argument, NULL, 'h'}, 217 | {NULL, 0, NULL, 0} 218 | }; 219 | 220 | int c; 221 | while (1) { 222 | c = getopt_long(argc, argv, "fh", long_opts, NULL); 223 | if (c == EOF) 224 | break; 225 | switch (c) { 226 | case 'f': 227 | foreground = true; 228 | break; 229 | case 'h': 230 | print_help(); 231 | exit(EXIT_FAILURE); 232 | default: 233 | fprintf(stderr, "error while parsing options\n"); 234 | exit(EXIT_FAILURE); 235 | } 236 | } 237 | 238 | /* run early cwmp initialization */ 239 | cwmp = calloc(1, sizeof(struct cwmp_internal)); 240 | if (!cwmp) return; 241 | 242 | INIT_LIST_HEAD(&cwmp->events); 243 | INIT_LIST_HEAD(&cwmp->notifications); 244 | 245 | config_load(); 246 | 247 | uloop_init(); 248 | 249 | if (netlink_init()) { 250 | D("netlink initialization failed\n"); 251 | exit(EXIT_FAILURE); 252 | } 253 | 254 | pid_t pid, sid; 255 | if (!foreground) { 256 | pid = fork(); 257 | if (pid < 0) 258 | exit(EXIT_FAILURE); 259 | if (pid > 0) 260 | exit(EXIT_SUCCESS); 261 | 262 | sid = setsid(); 263 | if (sid < 0) { 264 | D("setsid() returned error\n"); 265 | exit(EXIT_FAILURE); 266 | } 267 | 268 | #ifdef DUMMY_MODE 269 | char *directory = "."; 270 | #else 271 | char *directory = "/"; 272 | #endif 273 | if ((chdir(directory)) < 0) { 274 | D("chdir() returned error\n"); 275 | exit(EXIT_FAILURE); 276 | } 277 | 278 | close(STDIN_FILENO); 279 | #ifndef DEBUG 280 | close(STDOUT_FILENO); 281 | close(STDERR_FILENO); 282 | #endif 283 | } 284 | 285 | freecwmp_log_message(NAME, L_NOTICE, "entering main loop\n"); 286 | uloop_run(); 287 | 288 | ubus_exit(); 289 | uloop_done(); 290 | 291 | closelog(); 292 | 293 | freecwmp_log_message(NAME, L_NOTICE, "exiting\n"); 294 | return 0; 295 | } 296 | 297 | -------------------------------------------------------------------------------- /src/freecwmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011-2012 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_FREECWMP_H__ 11 | #define _FREECWMP_FREECWMP_H__ 12 | 13 | #define NAME "freecwmpd" 14 | 15 | #define FREE(x) if (!x) { free(x) ; x = NULL; } 16 | 17 | #ifdef DEBUG 18 | #define D(format, ...) fprintf(stderr, "%s(%d): " format, __func__, __LINE__, ## __VA_ARGS__) 19 | #else 20 | #define D(format, ...) no_debug(0, format, ## __VA_ARGS__) 21 | #endif 22 | 23 | #ifdef DEVEL 24 | #define DD(format, ...) fprintf(stderr, "%s(%d):: " format, __func__, __LINE__, ## __VA_ARGS__) 25 | #define DDF(format, ...) fprintf(stderr, format, ## __VA_ARGS__) 26 | #else 27 | #define DD(format, ...) no_debug(0, format, ## __VA_ARGS__) 28 | #define DDF(format, ...) no_debug(0, format, ## __VA_ARGS__) 29 | #endif 30 | 31 | static inline void no_debug(int level, const char *fmt, ...) 32 | { 33 | } 34 | 35 | void freecwmp_reload(void); 36 | 37 | #endif 38 | 39 | -------------------------------------------------------------------------------- /src/http.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011-2012 Luka Perkov 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #ifdef HTTP_CURL 23 | #include 24 | #endif 25 | 26 | #ifdef HTTP_ZSTREAM 27 | #include 28 | #include 29 | #endif 30 | 31 | #ifndef HTTP_ZSTREAM 32 | #include "b64.h" 33 | #endif 34 | 35 | #include "http.h" 36 | 37 | #include "config.h" 38 | #include "cwmp.h" 39 | #include "freecwmp.h" 40 | 41 | static struct http_client http_c; 42 | static struct http_server http_s; 43 | 44 | int 45 | http_client_init(void) 46 | { 47 | if (asprintf(&http_c.url, "%s://%s:%s@%s:%s%s", 48 | config->acs->scheme, 49 | config->acs->username, 50 | config->acs->password, 51 | config->acs->hostname, 52 | config->acs->port, 53 | config->acs->path) == -1) 54 | return -1; 55 | 56 | DDF("+++ HTTP CLIENT CONFIGURATION +++\n"); 57 | DD("url: %s\n", http_c.url); 58 | #ifdef HTTP_CURL 59 | if (config->acs->ssl_cert) 60 | DD("ssl_cert: %s\n", config->acs->ssl_cert); 61 | if (config->acs->ssl_cacert) 62 | DD("ssl_cacert: %s\n", config->acs->ssl_cacert); 63 | if (!config->acs->ssl_verify) 64 | DD("ssl_verify: SSL certificate validation disabled.\n"); 65 | #endif /* HTTP_CURL */ 66 | DDF("--- HTTP CLIENT CONFIGURATION ---\n"); 67 | 68 | #ifdef HTTP_CURL 69 | http_c.header_list = NULL; 70 | http_c.header_list = curl_slist_append(http_c.header_list, "User-Agent: freecwmp"); 71 | if (!http_c.header_list) return -1; 72 | http_c.header_list = curl_slist_append(http_c.header_list, "Content-Type: text/xml"); 73 | if (!http_c.header_list) return -1; 74 | # ifdef ACS_FUSION 75 | char *expect_header = "Expect:"; 76 | http_c.header_list = curl_slist_append(http_c.header_list, expect_header); 77 | if (!http_c.header_list) return -1; 78 | # endif /* ACS_FUSION */ 79 | #endif /* HTTP_CURL */ 80 | 81 | #ifdef HTTP_ZSTREAM 82 | http_c.stream = zstream_open(http_c.url, ZSTREAM_POST); 83 | if (!http_c.stream) 84 | return -1; 85 | 86 | # ifdef ACS_HDM 87 | if (zstream_http_configure(http_c.stream, ZSTREAM_HTTP_COOKIES, 1)) 88 | # elif ACS_MULTI 89 | if (zstream_http_configure(http_c.stream, ZSTREAM_HTTP_COOKIES, 3)) 90 | # endif 91 | return -1; 92 | 93 | if (zstream_http_addheader(http_c.stream, "User-Agent", "freecwmp")) 94 | return -1; 95 | 96 | if (zstream_http_addheader(http_c.stream, "Content-Type", "text/xml")) 97 | return -1; 98 | #endif /* HTTP_ZSTREAM */ 99 | 100 | freecwmp_log_message(NAME, L_NOTICE, "configured acs url %s", http_c.url); 101 | return 0; 102 | } 103 | 104 | void 105 | http_client_exit(void) 106 | { 107 | FREE(http_c.url); 108 | 109 | #ifdef HTTP_CURL 110 | if (!http_c.header_list) 111 | curl_slist_free_all(http_c.header_list); 112 | if (access(fc_cookies, W_OK) == 0) 113 | remove(fc_cookies); 114 | #endif /* HTTP_CURL */ 115 | 116 | #ifdef HTTP_ZSTREAM 117 | if (http_c.stream) { 118 | zstream_close(http_c.stream); 119 | http_c.stream = NULL; 120 | } 121 | #endif /* HTTP_ZSTREAM */ 122 | } 123 | 124 | #ifdef HTTP_CURL 125 | static size_t 126 | http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in) 127 | { 128 | *msg_in = (char *) realloc(*msg_in, (strlen(*msg_in) + size * rxed + 1) * sizeof(char)); 129 | bzero(*msg_in + strlen(*msg_in), rxed + 1); 130 | memcpy(*msg_in + strlen(*msg_in), buffer, rxed); 131 | 132 | DDF("+++ RECEIVED HTTP RESPONSE (PART) +++\n"); 133 | DDF("%.*s", rxed, buffer); 134 | DDF("--- RECEIVED HTTP RESPONSE (PART) ---\n"); 135 | 136 | return size * rxed; 137 | } 138 | #endif /* HTTP_CURL */ 139 | 140 | int8_t 141 | http_send_message(char *msg_out, char **msg_in) 142 | { 143 | #ifdef HTTP_CURL 144 | CURLcode res; 145 | CURL *curl; 146 | 147 | curl = curl_easy_init(); 148 | if (!curl) return -1; 149 | 150 | curl_easy_setopt(curl, CURLOPT_URL, http_c.url); 151 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_c.header_list); 152 | 153 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_out); 154 | if (msg_out) 155 | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long) strlen(msg_out)); 156 | else 157 | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0); 158 | 159 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_response); 160 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in); 161 | 162 | # ifdef DEVEL 163 | curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); 164 | # endif 165 | 166 | curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies); 167 | curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies); 168 | 169 | /* TODO: test this with real ACS configuration */ 170 | if (config->acs->ssl_cert) 171 | curl_easy_setopt(curl, CURLOPT_SSLCERT, config->acs->ssl_cert); 172 | if (config->acs->ssl_cacert) 173 | curl_easy_setopt(curl, CURLOPT_CAINFO, config->acs->ssl_cacert); 174 | if (!config->acs->ssl_verify) 175 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); 176 | 177 | *msg_in = (char *) calloc (1, sizeof(char)); 178 | 179 | res = curl_easy_perform(curl); 180 | 181 | if (!strlen(*msg_in)) { 182 | free(*msg_in); 183 | *msg_in = NULL; 184 | } 185 | 186 | curl_easy_cleanup(curl); 187 | 188 | if (res) return -1; 189 | 190 | #endif /* HTTP_CURL */ 191 | 192 | #ifdef HTTP_ZSTREAM 193 | char buffer[BUFSIZ]; 194 | ssize_t rxed; 195 | 196 | if (zstream_reopen(http_c.stream, http_c.url, ZSTREAM_POST)) { 197 | /* something not good, let's try recreate */ 198 | http_client_exit(); 199 | if (http_client_init()) return -1; 200 | } 201 | 202 | if(msg_out) { 203 | DDF("+++ SENDING POST MESSAGE +++\n"); 204 | DDF("%s", msg_out); 205 | DDF("--- SENDING POST MESSAGE ---\n"); 206 | } else { 207 | DDF("+++ SENDING EMPTY POST MESSAGE +++\n"); 208 | } 209 | 210 | if (msg_out) { 211 | zstream_write(http_c.stream, msg_out, strlen(msg_out)); 212 | } else { 213 | zstream_write(http_c.stream, NULL , 0); 214 | } 215 | 216 | *msg_in = (char *) calloc (1, sizeof(char)); 217 | while ((rxed = zstream_read(http_c.stream, buffer, sizeof(buffer))) > 0) { 218 | *msg_in = (char *) realloc(*msg_in, (strlen(*msg_in) + rxed + 1) * sizeof(char)); 219 | if (!(*msg_in)) return -1; 220 | bzero(*msg_in + strlen(*msg_in), rxed + 1); 221 | memcpy(*msg_in + strlen(*msg_in), buffer, rxed); 222 | } 223 | 224 | /* we got no response, that is ok and defined in documentation */ 225 | if (!strlen(*msg_in)) { 226 | free(*msg_in); 227 | *msg_in = NULL; 228 | } 229 | 230 | if (rxed < 0) 231 | return -1; 232 | 233 | #endif /* HTTP_ZSTREAM */ 234 | 235 | if (*msg_in) { 236 | DDF("+++ RECEIVED HTTP RESPONSE +++\n"); 237 | DDF("%s", *msg_in); 238 | DDF("--- RECEIVED HTTP RESPONSE ---\n"); 239 | } else { 240 | DDF("+++ RECEIVED EMPTY HTTP RESPONSE +++\n"); 241 | } 242 | 243 | return 0; 244 | } 245 | 246 | void 247 | http_server_init(void) 248 | { 249 | http_s.http_event.cb = http_new_client; 250 | 251 | http_s.http_event.fd = usock(USOCK_TCP | USOCK_SERVER, config->local->ip, config->local->port); 252 | uloop_fd_add(&http_s.http_event, ULOOP_READ | ULOOP_EDGE_TRIGGER); 253 | 254 | DDF("+++ HTTP SERVER CONFIGURATION +++\n"); 255 | if (config->local->ip) 256 | DDF("ip: '%s'\n", config->local->ip); 257 | else 258 | DDF("NOT BOUND TO IP\n"); 259 | DDF("port: '%s'\n", config->local->port); 260 | DDF("--- HTTP SERVER CONFIGURATION ---\n"); 261 | 262 | freecwmp_log_message(NAME, L_NOTICE, "http server initialized"); 263 | } 264 | 265 | static void 266 | http_new_client(struct uloop_fd *ufd, unsigned events) 267 | { 268 | int status; 269 | struct timeval t; 270 | 271 | t.tv_sec = 60; 272 | t.tv_usec = 0; 273 | 274 | for (;;) { 275 | int client = accept(ufd->fd, NULL, NULL); 276 | 277 | /* set one minute timeout */ 278 | if (setsockopt(ufd->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&t, sizeof t)) { 279 | DD("setsockopt() failed\n"); 280 | } 281 | 282 | if (client == -1) 283 | break; 284 | 285 | struct uloop_process *uproc = calloc(1, sizeof(*uproc)); 286 | if (!uproc || (uproc->pid = fork()) == -1) { 287 | free(uproc); 288 | close(client); 289 | } 290 | 291 | if (uproc->pid != 0) { 292 | /* parent */ 293 | /* register an event handler for when the child terminates */ 294 | uproc->cb = http_del_client; 295 | uloop_process_add(uproc); 296 | close(client); 297 | } else { 298 | /* child */ 299 | FILE *fp; 300 | char buffer[BUFSIZ]; 301 | int8_t auth_status = 0; 302 | 303 | fp = fdopen(client, "r+"); 304 | 305 | DDF("+++ RECEIVED HTTP REQUEST +++\n"); 306 | while (fgets(buffer, sizeof(buffer), fp)) { 307 | #ifdef DEVEL 308 | fwrite(buffer, 1, strlen(buffer), stderr); 309 | #endif 310 | 311 | if (!strncasecmp(buffer, "Authorization: Basic ", strlen("Authorization: Basic "))) { 312 | const char *c1, *c2, *min, *val; 313 | char *username = NULL; 314 | char *password = NULL; 315 | char *acs_auth_basic = NULL; 316 | char *auth_basic_check = NULL; 317 | int len; 318 | 319 | username = NULL; 320 | password = NULL; 321 | config_get_cwmp("InternetGatewayDevice.ManagementServer.ConnectionRequestUsername", &username); 322 | config_get_cwmp("InternetGatewayDevice.ManagementServer.ConnectionRequestPassword", &password); 323 | 324 | if (!username || !password) { 325 | // if we dont have username or password configured proceed with connecting to ACS 326 | FREE(username); 327 | FREE(password); 328 | auth_status = 1; 329 | goto http_end_child; 330 | } 331 | 332 | c1 = strrchr(buffer, '\r'); 333 | c2 = strrchr(buffer, '\n'); 334 | 335 | if (!c1) 336 | c1 = c2; 337 | if (!c2) 338 | c2 = c1; 339 | if (!c1 || !c2) 340 | continue; 341 | 342 | min = (c1 < c2) ? c1 : c2; 343 | 344 | val = strrchr(buffer, ' '); 345 | if (!val) 346 | continue; 347 | 348 | val += sizeof(char); 349 | ssize_t size = min - val; 350 | 351 | acs_auth_basic = (char *) zstream_b64decode(val, &size); 352 | if (!acs_auth_basic) 353 | continue; 354 | 355 | freecwmp_snprintf(&auth_basic_check, "%s:%s", username, password); 356 | if (!auth_basic_check) { 357 | FREE(username); 358 | FREE(password); 359 | free(acs_auth_basic); 360 | goto error_child; 361 | } 362 | 363 | if (size == strlen(auth_basic_check)) { 364 | len = size; 365 | } else { 366 | auth_status = 0; 367 | goto free_resources; 368 | } 369 | 370 | if (!memcmp(acs_auth_basic, auth_basic_check, len * sizeof(char))) 371 | auth_status = 1; 372 | else 373 | auth_status = 0; 374 | 375 | free_resources: 376 | FREE(username); 377 | FREE(password); 378 | free(acs_auth_basic); 379 | free(auth_basic_check); 380 | } 381 | 382 | if (buffer[0] == '\r' || buffer[0] == '\n') { 383 | /* end of http request (empty line) */ 384 | goto http_end_child; 385 | } 386 | 387 | } 388 | error_child: 389 | /* here we are because of an error, e.g. timeout */ 390 | status = ETIMEDOUT|ENOMEM; 391 | goto done_child; 392 | 393 | http_end_child: 394 | fflush(fp); 395 | if (auth_status) { 396 | status = 0; 397 | fputs("HTTP/1.1 204 No Content\r\n\r\n", fp); 398 | } else { 399 | status = EACCES; 400 | fputs("HTTP/1.1 401 Unauthorized\r\n", fp); 401 | fputs("Connection: close\r\n", fp); 402 | fputs("WWW-Authenticate: Basic realm=\"default\"\r\n", fp); 403 | } 404 | fputs("\r\n", fp); 405 | goto done_child; 406 | 407 | done_child: 408 | fclose(fp); 409 | DDF("--- RECEIVED HTTP REQUEST ---\n"); 410 | exit(status); 411 | } 412 | } 413 | } 414 | 415 | static void 416 | http_del_client(struct uloop_process *uproc, int ret) 417 | { 418 | free(uproc); 419 | 420 | /* child terminated ; check return code */ 421 | if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) { 422 | DDF("+++ HTTP SERVER CONNECTION SUCCESS +++\n"); 423 | freecwmp_log_message(NAME, L_NOTICE, "acs initiated connection"); 424 | cwmp_connection_request(CONNECTION_REQUEST); 425 | } else { 426 | DDF("+++ HTTP SERVER CONNECTION FAILED +++\n"); 427 | } 428 | } 429 | 430 | -------------------------------------------------------------------------------- /src/http.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_HTTP_H__ 11 | #define _FREECWMP_HTTP_H__ 12 | 13 | #include 14 | 15 | #include 16 | 17 | #ifdef HTTP_CURL 18 | #include 19 | #endif 20 | 21 | #ifdef HTTP_ZSTREAM 22 | #include 23 | #endif 24 | 25 | #ifdef DUMMY_MODE 26 | static char *fc_cookies = "./ext/tmp/freecwmp_cookies"; 27 | #else 28 | static char *fc_cookies = "/tmp/freecwmp_cookies"; 29 | #endif 30 | 31 | struct http_client 32 | { 33 | #ifdef HTTP_CURL 34 | struct curl_slist *header_list; 35 | #endif /* HTTP_CURL */ 36 | #ifdef HTTP_ZSTREAM 37 | zstream_t *stream; 38 | #endif /* HTTP_ZSTREAM */ 39 | char *url; 40 | }; 41 | 42 | struct http_server 43 | { 44 | struct uloop_fd http_event; 45 | }; 46 | 47 | #ifdef HTTP_CURL 48 | static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in); 49 | #endif /* HTTP_CURL */ 50 | 51 | int http_client_init(void); 52 | void http_client_exit(void); 53 | int8_t http_send_message(char *msg_out, char **msg_in); 54 | 55 | void http_server_init(void); 56 | static void http_new_client(struct uloop_fd *ufd, unsigned events); 57 | static void http_del_client(struct uloop_process *uproc, int ret); 58 | 59 | #endif 60 | 61 | -------------------------------------------------------------------------------- /src/messages.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_MESSAGES_H__ 11 | #define _FREECWMP_MESSAGES_H__ 12 | 13 | #define CWMP_INFORM_MESSAGE \ 14 | "" \ 15 | "" \ 21 | "" \ 22 | "" \ 23 | "" \ 24 | "" \ 25 | "" \ 26 | "" \ 27 | "" \ 28 | "" \ 29 | "" \ 30 | "" \ 31 | "" \ 32 | "" \ 33 | "1" \ 34 | "" \ 35 | "" \ 36 | "" \ 37 | "" \ 38 | "InternetGatewayDevice.DeviceInfo.SpecVersion\n" \ 39 | "1.0" \ 40 | "" \ 41 | "" \ 42 | "InternetGatewayDevice.DeviceInfo.Manufacturer\n" \ 43 | "" \ 44 | "" \ 45 | "" \ 46 | "InternetGatewayDevice.DeviceInfo.ManufacturerOUI\n" \ 47 | "" \ 48 | "" \ 49 | "" \ 50 | "InternetGatewayDevice.DeviceInfo.ProductClass\n" \ 51 | "" \ 52 | "" \ 53 | "" \ 54 | "InternetGatewayDevice.DeviceInfo.SerialNumber\n" \ 55 | "" \ 56 | "" \ 57 | "" \ 58 | "InternetGatewayDevice.DeviceInfo.HardwareVersion\n" \ 59 | "" \ 60 | "" \ 61 | "" \ 62 | "InternetGatewayDevice.DeviceInfo.SoftwareVersion\n" \ 63 | "" \ 64 | "" \ 65 | "" \ 66 | "InternetGatewayDevice.DeviceInfo.ProvisioningCode\n" \ 67 | "" \ 68 | "" \ 69 | "" \ 70 | "InternetGatewayDevice.ManagementServer.ParameterKey\n" \ 71 | "" \ 72 | "" \ 73 | "" \ 74 | "InternetGatewayDevice.ManagementServer.ConnectionRequestURL\n" \ 75 | "" \ 76 | "" \ 77 | "" \ 78 | "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress\n" \ 79 | "" \ 80 | "" \ 81 | "" \ 82 | "" \ 83 | "" \ 84 | "" 85 | 86 | 87 | #define CWMP_RESPONSE_MESSAGE \ 88 | "" \ 89 | "" \ 95 | "" \ 96 | "" \ 97 | "" \ 98 | "" \ 99 | "" 100 | 101 | #endif 102 | 103 | -------------------------------------------------------------------------------- /src/time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #include 11 | 12 | #include "time.h" 13 | 14 | #include "freecwmp.h" 15 | 16 | char local_time[26] = {0}; 17 | 18 | char * mix_get_time(void) 19 | { 20 | time_t t_time; 21 | struct tm *t_tm; 22 | 23 | t_time = time(NULL); 24 | t_tm = localtime(&t_time); 25 | if (t_tm == NULL) 26 | return NULL; 27 | 28 | if(strftime(local_time, sizeof(local_time), "%FT%T%z", t_tm) == 0) 29 | return NULL; 30 | 31 | local_time[25] = local_time[24]; 32 | local_time[24] = local_time[23]; 33 | local_time[22] = ':'; 34 | local_time[26] = '\0'; 35 | 36 | return local_time; 37 | } 38 | -------------------------------------------------------------------------------- /src/time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_TIME_H__ 11 | #define _FREECWMP_TIME_H__ 12 | 13 | char * mix_get_time(void); 14 | 15 | #endif 16 | 17 | -------------------------------------------------------------------------------- /src/ubus.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2012 Luka Perkov 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "ubus.h" 15 | 16 | #include "config.h" 17 | #include "cwmp.h" 18 | #include "freecwmp.h" 19 | 20 | static struct ubus_context *ctx = NULL; 21 | 22 | static enum notify { 23 | NOTIFY_PARAM, 24 | NOTIFY_VALUE, 25 | __NOTIFY_MAX 26 | }; 27 | 28 | static const struct blobmsg_policy notify_policy[] = { 29 | [NOTIFY_PARAM] = { .name = "parameter", .type = BLOBMSG_TYPE_STRING }, 30 | [NOTIFY_VALUE] = { .name = "value", .type = BLOBMSG_TYPE_STRING }, 31 | }; 32 | 33 | static int 34 | freecwmpd_handle_notify(struct ubus_context *ctx, struct ubus_object *obj, 35 | struct ubus_request_data *req, const char *method, 36 | struct blob_attr *msg) 37 | { 38 | struct blob_attr *tb[__NOTIFY_MAX]; 39 | 40 | blobmsg_parse(notify_policy, ARRAY_SIZE(notify_policy), tb, 41 | blob_data(msg), blob_len(msg)); 42 | 43 | if (!tb[NOTIFY_PARAM]) 44 | return UBUS_STATUS_INVALID_ARGUMENT; 45 | 46 | if (!tb[NOTIFY_VALUE]) 47 | return UBUS_STATUS_INVALID_ARGUMENT; 48 | 49 | freecwmp_log_message(NAME, L_NOTICE, 50 | "triggered ubus notification parameter %s\n", 51 | blobmsg_data(tb[NOTIFY_PARAM])); 52 | cwmp_add_notification(blobmsg_data(tb[NOTIFY_PARAM]), 53 | blobmsg_data(tb[NOTIFY_VALUE])); 54 | 55 | return 0; 56 | } 57 | 58 | static enum inform { 59 | INFORM_EVENT, 60 | __INFORM_MAX 61 | }; 62 | 63 | static const struct blobmsg_policy inform_policy[] = { 64 | [INFORM_EVENT] = { .name = "event", .type = BLOBMSG_TYPE_STRING }, 65 | }; 66 | 67 | static int 68 | freecwmpd_handle_inform(struct ubus_context *ctx, struct ubus_object *obj, 69 | struct ubus_request_data *req, const char *method, 70 | struct blob_attr *msg) 71 | { 72 | int tmp; 73 | struct blob_attr *tb[__INFORM_MAX]; 74 | 75 | blobmsg_parse(inform_policy, ARRAY_SIZE(inform_policy), tb, 76 | blob_data(msg), blob_len(msg)); 77 | 78 | if (!tb[INFORM_EVENT]) 79 | return UBUS_STATUS_INVALID_ARGUMENT; 80 | 81 | freecwmp_log_message(NAME, L_NOTICE, 82 | "triggered ubus inform %s\n", 83 | blobmsg_data(tb[INFORM_EVENT])); 84 | tmp = freecwmp_int_event_code(blobmsg_data(tb[INFORM_EVENT])); 85 | cwmp_connection_request(tmp); 86 | 87 | return 0; 88 | } 89 | 90 | static int 91 | freecwmpd_handle_reload(struct ubus_context *ctx, struct ubus_object *obj, 92 | struct ubus_request_data *req, const char *method, 93 | struct blob_attr *msg) 94 | { 95 | freecwmp_log_message(NAME, L_NOTICE, "triggered ubus reload\n"); 96 | freecwmp_reload(); 97 | 98 | return 0; 99 | } 100 | 101 | static const struct ubus_method freecwmp_methods[] = { 102 | UBUS_METHOD("notify", freecwmpd_handle_notify, notify_policy), 103 | UBUS_METHOD("inform", freecwmpd_handle_inform, inform_policy), 104 | { .name = "reload", .handler = freecwmpd_handle_reload }, 105 | }; 106 | 107 | static struct ubus_object_type main_object_type = 108 | UBUS_OBJECT_TYPE("freecwmpd", freecwmp_methods); 109 | 110 | static struct ubus_object main_object = { 111 | .name = "tr069", 112 | .type = &main_object_type, 113 | .methods = freecwmp_methods, 114 | .n_methods = ARRAY_SIZE(freecwmp_methods), 115 | }; 116 | 117 | int 118 | ubus_init(void) 119 | { 120 | ctx = ubus_connect(config->local->ubus_socket); 121 | if (!ctx) return -1; 122 | 123 | ubus_add_uloop(ctx); 124 | 125 | if (ubus_add_object(ctx, &main_object)) return -1; 126 | 127 | return 0; 128 | } 129 | 130 | void 131 | ubus_exit(void) 132 | { 133 | if (ctx) ubus_free(ctx); 134 | } 135 | -------------------------------------------------------------------------------- /src/ubus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2012 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_UBUS_H__ 11 | #define _FREECWMP_UBUS_H__ 12 | 13 | int ubus_init(void); 14 | void ubus_exit(void); 15 | 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /src/xml.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011-2012 Luka Perkov 8 | * Copyright (C) 2012 Jonas Gorski 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "xml.h" 16 | 17 | #include "config.h" 18 | #include "cwmp.h" 19 | #include "external.h" 20 | #include "freecwmp.h" 21 | #include "messages.h" 22 | #include "time.h" 23 | 24 | struct rpc_method { 25 | const char *name; 26 | int (*handler)(mxml_node_t *body_in, mxml_node_t *tree_in, 27 | mxml_node_t *tree_out); 28 | }; 29 | 30 | const static char *soap_env_url = "http://schemas.xmlsoap.org/soap/envelope/"; 31 | const static char *soap_enc_url = "http://schemas.xmlsoap.org/soap/encoding/"; 32 | const static char *xsd_url = "http://www.w3.org/2001/XMLSchema"; 33 | const static char *xsi_url = "http://www.w3.org/2001/XMLSchema-instance"; 34 | const static char *cwmp_urls[] = { 35 | "urn:dslforum-org:cwmp-1-0", 36 | "urn:dslforum-org:cwmp-1-1", 37 | "urn:dslforum-org:cwmp-1-2", 38 | NULL }; 39 | 40 | static struct cwmp_namespaces 41 | { 42 | char *soap_env; 43 | char *soap_enc; 44 | char *xsd; 45 | char *xsi; 46 | char *cwmp; 47 | } ns; 48 | 49 | const struct rpc_method rpc_methods[] = { 50 | { "SetParameterValues", xml_handle_set_parameter_values }, 51 | { "GetParameterValues", xml_handle_get_parameter_values }, 52 | { "SetParameterAttributes", xml_handle_set_parameter_attributes }, 53 | { "Download", xml_handle_download }, 54 | { "FactoryReset", xml_handle_factory_reset }, 55 | { "Reboot", xml_handle_reboot }, 56 | }; 57 | 58 | static void xml_recreate_namespace(char *msg) 59 | { 60 | mxml_node_t *tree; 61 | const char *cwmp_urn; 62 | char *c; 63 | int i; 64 | 65 | FREE(ns.soap_env); 66 | FREE(ns.soap_enc); 67 | FREE(ns.xsd); 68 | FREE(ns.xsi); 69 | FREE(ns.cwmp); 70 | 71 | tree = mxmlLoadString(NULL, msg, MXML_NO_CALLBACK); 72 | if (!tree) goto done; 73 | 74 | c = (char *) mxmlElementGetAttrName(tree, soap_env_url); 75 | if (*(c + 5) == ':') { 76 | ns.soap_env = strdup((c + 6)); 77 | } 78 | 79 | c = (char *) mxmlElementGetAttrName(tree, soap_enc_url); 80 | if (*(c + 5) == ':') { 81 | ns.soap_enc = strdup((c + 6)); 82 | } 83 | 84 | c = (char *) mxmlElementGetAttrName(tree, xsd_url); 85 | if (*(c + 5) == ':') { 86 | ns.xsd = strdup((c + 6)); 87 | } 88 | 89 | c = (char *) mxmlElementGetAttrName(tree, xsi_url); 90 | if (*(c + 5) == ':') { 91 | ns.xsi = strdup((c + 6)); 92 | } 93 | 94 | for (i = 0; cwmp_urls[i] != NULL; i++) { 95 | cwmp_urn = cwmp_urls[i]; 96 | c = (char *) mxmlElementGetAttrName(tree, cwmp_urn); 97 | if (c && *(c + 5) == ':') { 98 | ns.cwmp = strdup((c + 6)); 99 | break; 100 | } 101 | } 102 | 103 | done: 104 | mxmlDelete(tree); 105 | } 106 | 107 | void xml_exit(void) 108 | { 109 | FREE(ns.soap_env); 110 | FREE(ns.soap_enc); 111 | FREE(ns.xsd); 112 | FREE(ns.xsi); 113 | FREE(ns.cwmp); 114 | } 115 | 116 | static int xml_prepare_events_inform(mxml_node_t *tree) 117 | { 118 | mxml_node_t *node, *b1, *b2; 119 | char *c; 120 | int n = 0; 121 | struct list_head *p; 122 | struct event *event; 123 | 124 | b1 = mxmlFindElement(tree, tree, "Event", NULL, NULL, MXML_DESCEND); 125 | if (!b1) return -1; 126 | 127 | pthread_mutex_lock(&event_lock); 128 | 129 | list_for_each(p, &cwmp->events) { 130 | event = list_entry (p, struct event, list); 131 | node = mxmlNewElement (b1, "EventStruct"); 132 | if (!node) goto error; 133 | 134 | b2 = mxmlNewElement (node, "EventCode"); 135 | if (!b2) goto error; 136 | 137 | b2 = mxmlNewText(b2, 0, freecwmp_str_event_code(event->code)); 138 | if (!b2) goto error; 139 | 140 | b2 = mxmlNewElement (node, "CommandKey"); 141 | if (!b2) goto error; 142 | 143 | if (event->key) { 144 | b2 = mxmlNewText(b2, 0, event->key); 145 | if (!b2) goto error; 146 | } 147 | 148 | mxmlAdd(b1, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); 149 | n++; 150 | } 151 | 152 | pthread_mutex_unlock(&event_lock); 153 | 154 | if (n) { 155 | if (asprintf(&c, "cwmp:EventStruct[%u]", n) == -1) 156 | return -1; 157 | 158 | mxmlElementSetAttr(b1, "soap_enc:arrayType", c); 159 | FREE(c); 160 | } 161 | 162 | return 0; 163 | 164 | error: 165 | pthread_mutex_unlock(&event_lock); 166 | return -1; 167 | } 168 | 169 | static int xml_prepare_notifications_inform(mxml_node_t *tree) 170 | { 171 | /* notifications */ 172 | mxml_node_t *node, *b; 173 | char *c; 174 | int n = 0; 175 | struct list_head *p; 176 | struct notification *notification; 177 | 178 | b = mxmlFindElement(tree, tree, "Event", NULL, NULL, MXML_DESCEND); 179 | if (!b) return -1; 180 | 181 | pthread_mutex_lock(¬ification_lock); 182 | 183 | list_for_each(p, &cwmp->notifications) { 184 | notification = list_entry(p, struct notification, list); 185 | 186 | c = "InternetGatewayDevice.ManagementServer.ConnectionRequestURL"; 187 | b = mxmlFindElementText(tree, tree, c, MXML_DESCEND); 188 | if (!b) goto error; 189 | 190 | b = b->parent->parent->parent; 191 | b = mxmlNewElement(b, "ParameterValueStruct"); 192 | if (!b) goto error; 193 | 194 | b = mxmlNewElement(b, "Name"); 195 | if (!b) goto error; 196 | 197 | b = mxmlNewText(b, 0, notification->parameter); 198 | if (!b) goto error; 199 | 200 | b = b->parent->parent; 201 | b = mxmlNewElement(b, "Value"); 202 | if (!b) goto error; 203 | 204 | b = mxmlNewText(b, 0, notification->value); 205 | if (!b) goto error; 206 | } 207 | 208 | pthread_mutex_unlock(¬ification_lock); 209 | return 0; 210 | 211 | error: 212 | pthread_mutex_unlock(¬ification_lock); 213 | return -1; 214 | } 215 | 216 | int xml_prepare_inform_message(char **msg_out) 217 | { 218 | mxml_node_t *tree, *b; 219 | char *c, *tmp; 220 | 221 | #ifdef DUMMY_MODE 222 | FILE *fp; 223 | fp = fopen("./ext/soap_msg_templates/cwmp_inform_message.xml", "r"); 224 | tree = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK); 225 | fclose(fp); 226 | #else 227 | tree = mxmlLoadString(NULL, CWMP_INFORM_MESSAGE, MXML_NO_CALLBACK); 228 | #endif 229 | if (!tree) goto error; 230 | 231 | b = mxmlFindElement(tree, tree, "RetryCount", NULL, NULL, MXML_DESCEND); 232 | if (!b) goto error; 233 | 234 | b = mxmlNewInteger(b, cwmp->retry_count); 235 | if (!b) goto error; 236 | 237 | b = mxmlFindElement(tree, tree, "Manufacturer", NULL, NULL, MXML_DESCEND); 238 | if (!b) goto error; 239 | 240 | b = mxmlNewText(b, 0, config->device->manufacturer); 241 | if (!b) goto error; 242 | 243 | b = mxmlFindElement(tree, tree, "OUI", NULL, NULL, MXML_DESCEND); 244 | if (!b) goto error; 245 | 246 | b = mxmlNewText(b, 0, config->device->oui); 247 | if (!b) goto error; 248 | 249 | b = mxmlFindElement(tree, tree, "ProductClass", NULL, NULL, MXML_DESCEND); 250 | if (!b) goto error; 251 | 252 | b = mxmlNewText(b, 0, config->device->product_class); 253 | if (!b) goto error; 254 | 255 | b = mxmlFindElement(tree, tree, "SerialNumber", NULL, NULL, MXML_DESCEND); 256 | if (!b) goto error; 257 | 258 | b = mxmlNewText(b, 0, config->device->serial_number); 259 | if (!b) goto error; 260 | 261 | if (xml_prepare_events_inform(tree)) 262 | goto error; 263 | 264 | b = mxmlFindElement(tree, tree, "CurrentTime", NULL, NULL, MXML_DESCEND); 265 | if (!b) goto error; 266 | 267 | b = mxmlNewText(b, 0, mix_get_time()); 268 | if (!b) goto error; 269 | 270 | b = mxmlFindElementText(tree, tree, "InternetGatewayDevice.DeviceInfo.Manufacturer", MXML_DESCEND); 271 | if (!b) goto error; 272 | 273 | b = b->parent->next->next; 274 | if (mxmlGetType(b) != MXML_ELEMENT) 275 | goto error; 276 | 277 | b = mxmlNewText(b, 0, config->device->manufacturer); 278 | if (!b) goto error; 279 | 280 | b = mxmlFindElementText(tree, tree, "InternetGatewayDevice.DeviceInfo.ManufacturerOUI", MXML_DESCEND); 281 | if (!b) goto error; 282 | 283 | b = b->parent->next->next; 284 | if (mxmlGetType(b) != MXML_ELEMENT) 285 | goto error; 286 | 287 | b = mxmlNewText(b, 0, config->device->oui); 288 | if (!b) goto error; 289 | 290 | b = mxmlFindElementText(tree, tree, "InternetGatewayDevice.DeviceInfo.ProductClass", MXML_DESCEND); 291 | if (!b) goto error; 292 | 293 | b = b->parent->next->next; 294 | if (mxmlGetType(b) != MXML_ELEMENT) 295 | goto error; 296 | 297 | b = mxmlNewText(b, 0, config->device->product_class); 298 | if (!b) goto error; 299 | 300 | b = mxmlFindElementText(tree, tree, "InternetGatewayDevice.DeviceInfo.SerialNumber", MXML_DESCEND); 301 | if (!b) goto error; 302 | 303 | b = b->parent->next->next; 304 | if (mxmlGetType(b) != MXML_ELEMENT) 305 | goto error; 306 | 307 | b = mxmlNewText(b, 0, config->device->serial_number); 308 | if (!b) 309 | goto error; 310 | 311 | b = mxmlFindElementText(tree, tree, "InternetGatewayDevice.DeviceInfo.HardwareVersion", MXML_DESCEND); 312 | if (!b) goto error; 313 | 314 | b = b->parent->next->next; 315 | if (mxmlGetType(b) != MXML_ELEMENT) 316 | goto error; 317 | 318 | b = mxmlNewText(b, 0, config->device->hardware_version); 319 | if (!b) goto error; 320 | 321 | b = mxmlFindElementText(tree, tree, "InternetGatewayDevice.DeviceInfo.SoftwareVersion", MXML_DESCEND); 322 | if (!b) goto error; 323 | 324 | b = b->parent->next->next; 325 | if (mxmlGetType(b) != MXML_ELEMENT) 326 | goto error; 327 | 328 | b = mxmlNewText(b, 0, config->device->software_version); 329 | if (!b) goto error; 330 | 331 | b = mxmlFindElementText(tree, tree, "InternetGatewayDevice.DeviceInfo.ProvisioningCode", MXML_DESCEND); 332 | if (!b) goto error; 333 | 334 | b = b->parent->next->next; 335 | if (mxmlGetType(b) != MXML_ELEMENT) 336 | goto error; 337 | 338 | tmp = "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.WANIPConnection.1.ExternalIPAddress"; 339 | b = mxmlFindElementText(tree, tree, tmp, MXML_DESCEND); 340 | if (!b) goto error; 341 | 342 | b = b->parent->next->next; 343 | if (mxmlGetType(b) != MXML_ELEMENT) 344 | goto error; 345 | 346 | c = NULL; 347 | if (external_get_action("value", tmp, &c)) goto error; 348 | if (c) { 349 | b = mxmlNewText(b, 0, c); 350 | FREE(c); 351 | if (!b) goto error; 352 | } 353 | 354 | tmp = "InternetGatewayDevice.ManagementServer.ConnectionRequestURL"; 355 | b = mxmlFindElementText(tree, tree, tmp, MXML_DESCEND); 356 | if (!b) goto error; 357 | 358 | b = b->parent->next->next; 359 | if (mxmlGetType(b) != MXML_ELEMENT) 360 | goto error; 361 | 362 | c = NULL; 363 | if (external_get_action("value", tmp, &c)) goto error; 364 | if (c) { 365 | b = mxmlNewText(b, 0, c); 366 | FREE(c); 367 | if (!b) goto error; 368 | } 369 | 370 | if (xml_prepare_notifications_inform(tree)) 371 | goto error; 372 | 373 | *msg_out = mxmlSaveAllocString(tree, MXML_NO_CALLBACK); 374 | 375 | mxmlDelete(tree); 376 | return 0; 377 | 378 | error: 379 | mxmlDelete(tree); 380 | return -1; 381 | } 382 | 383 | int xml_parse_inform_response_message(char *msg_in) 384 | { 385 | mxml_node_t *tree, *b; 386 | char *c; 387 | 388 | if (!msg_in) goto error; 389 | 390 | tree = mxmlLoadString(NULL, msg_in, MXML_NO_CALLBACK); 391 | if (!tree) goto error; 392 | 393 | if (asprintf(&c, "%s:%s", ns.soap_env, "Fault") == -1) 394 | goto error; 395 | 396 | b = mxmlFindElement(tree, tree, c, NULL, NULL, MXML_DESCEND); 397 | FREE(c); 398 | 399 | // TODO: ACS responded with error message, right now we are not handeling this 400 | if (b) goto error; 401 | 402 | b = mxmlFindElement(tree, tree, "MaxEnvelopes", NULL, NULL, MXML_DESCEND); 403 | if (!b) goto error; 404 | 405 | b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST); 406 | if (!b || !b->value.text.string) 407 | goto error; 408 | 409 | mxmlDelete(tree); 410 | return 0; 411 | 412 | error: 413 | mxmlDelete(tree); 414 | return -1; 415 | } 416 | 417 | int xml_handle_message(char *msg_in, char **msg_out) 418 | { 419 | mxml_node_t *tree_in, *tree_out, *b; 420 | const struct rpc_method *method; 421 | char *c; 422 | int i; 423 | 424 | #ifdef DUMMY_MODE 425 | FILE *fp; 426 | fp = fopen("./ext/soap_msg_templates/cwmp_response_message.xml", "r"); 427 | tree_out = mxmlLoadFile(NULL, fp, MXML_NO_CALLBACK); 428 | fclose(fp); 429 | #else 430 | tree_out = mxmlLoadString(NULL, CWMP_RESPONSE_MESSAGE, MXML_NO_CALLBACK); 431 | #endif 432 | if (!tree_out) goto error; 433 | 434 | xml_recreate_namespace(msg_in); 435 | 436 | tree_in = mxmlLoadString(NULL, msg_in, MXML_NO_CALLBACK); 437 | if (!tree_in) goto error; 438 | 439 | /* handle cwmp:ID */ 440 | if (asprintf(&c, "%s:%s", ns.cwmp, "ID") == -1) 441 | goto error; 442 | 443 | b = mxmlFindElement(tree_in, tree_in, c, NULL, NULL, MXML_DESCEND); 444 | FREE(c); 445 | 446 | /* ACS did not send ID parameter, we are continuing without it */ 447 | if (!b) goto find_method; 448 | 449 | b = mxmlWalkNext(b, tree_in, MXML_DESCEND_FIRST); 450 | if (!b || !b->value.text.string) goto error; 451 | c = strdup(b->value.text.string); 452 | 453 | b = mxmlFindElement(tree_out, tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); 454 | if (!b) goto error; 455 | 456 | b = mxmlNewText(b, 0, c); 457 | FREE(c); 458 | 459 | if (!b) goto error; 460 | 461 | find_method: 462 | if (asprintf(&c, "%s:%s", ns.soap_env, "Body") == -1) 463 | goto error; 464 | 465 | b = mxmlFindElement(tree_in, tree_in, c, NULL, NULL, MXML_DESCEND); 466 | FREE(c); 467 | if (!b) goto error; 468 | 469 | while (1) { 470 | b = mxmlWalkNext(b, tree_in, MXML_DESCEND_FIRST); 471 | if (!b) goto error; 472 | if (b->type == MXML_ELEMENT) break; 473 | } 474 | 475 | c = b->value.element.name; 476 | /* convert QName to localPart, check that ns is the expected one */ 477 | if (strchr(c, ':')) { 478 | char *tmp = strchr(c, ':'); 479 | size_t ns_len = tmp - c; 480 | 481 | if (strlen(ns.cwmp) != ns_len) 482 | goto error; 483 | 484 | if (strncmp(ns.cwmp, c, ns_len)) 485 | goto error; 486 | 487 | c = tmp + 1; 488 | } else { 489 | goto error; 490 | } 491 | 492 | method = NULL; 493 | for (i = 0; i < ARRAY_SIZE(rpc_methods); i++) { 494 | if (!strcmp(c, rpc_methods[i].name)) { 495 | method = &rpc_methods[i]; 496 | break; 497 | } 498 | } 499 | 500 | if (method) { 501 | if (method->handler(b, tree_in, tree_out)) goto error; 502 | } else { 503 | char *fault_message; 504 | 505 | b = mxmlFindElement(tree_out, tree_out, "soap_env:Body", 506 | NULL, NULL, MXML_DESCEND); 507 | if (!b) goto error; 508 | 509 | if (asprintf(&fault_message, "%s not supported", c) == -1) 510 | goto error; 511 | 512 | if (!xml_create_generic_fault_message(b, true, "9000", fault_message)) { 513 | FREE(fault_message); 514 | goto error; 515 | } 516 | 517 | FREE(fault_message); 518 | } 519 | 520 | *msg_out = mxmlSaveAllocString(tree_out, MXML_NO_CALLBACK); 521 | 522 | if (tree_in) mxmlDelete(tree_in); 523 | if (tree_out) mxmlDelete(tree_out); 524 | return 0; 525 | 526 | error: 527 | if (tree_in) mxmlDelete(tree_in); 528 | if (tree_out) mxmlDelete(tree_out); 529 | return -1; 530 | } 531 | 532 | static int xml_create_generic_fault_message(mxml_node_t *body, 533 | bool client, 534 | char *code, 535 | char *string) 536 | { 537 | mxml_node_t *b, *t, *u; 538 | 539 | b = mxmlNewElement(body, "soap_env:Fault"); 540 | if (!b) return -1; 541 | 542 | t = mxmlNewElement(b, "faultcode"); 543 | if (!t) return -1; 544 | 545 | u = mxmlNewText(t, 0, client ? "Client" : "Server"); 546 | if (!u) return -1; 547 | 548 | t = mxmlNewElement(b, "faultstring"); 549 | if (!t) return -1; 550 | 551 | u = mxmlNewText(t, 0, "CWMP fault"); 552 | if (!u) return -1; 553 | 554 | b = mxmlNewElement(b, "detail"); 555 | if (!b) return -1; 556 | 557 | b = mxmlNewElement(b, "cwmp:Fault"); 558 | if (!b) return -1; 559 | 560 | t = mxmlNewElement(b, "FaultCode"); 561 | if (!t) return -1; 562 | 563 | u = mxmlNewText(t, 0, code); 564 | if (!u) return -1; 565 | 566 | t = mxmlNewElement(b, "FaultString"); 567 | if (!b) return -1; 568 | 569 | u = mxmlNewText(t, 0, string); 570 | if (!u) return -1; 571 | 572 | return 0; 573 | } 574 | 575 | int xml_handle_set_parameter_values(mxml_node_t *body_in, 576 | mxml_node_t *tree_in, 577 | mxml_node_t *tree_out) 578 | { 579 | mxml_node_t *b = body_in; 580 | char *parameter_name = NULL; 581 | char *parameter_value = NULL; 582 | 583 | while (b) { 584 | if (b && b->type == MXML_TEXT && 585 | b->value.text.string && 586 | b->parent->type == MXML_ELEMENT && 587 | !strcmp(b->parent->value.element.name, "Name")) { 588 | parameter_name = b->value.text.string; 589 | } 590 | if (b && b->type == MXML_TEXT && 591 | b->value.text.string && 592 | b->parent->type == MXML_ELEMENT && 593 | !strcmp(b->parent->value.element.name, "Value")) { 594 | parameter_value = b->value.text.string; 595 | } 596 | if (parameter_name && parameter_value) { 597 | if (external_set_action_write("value", 598 | parameter_name, parameter_value)) 599 | return -1; 600 | parameter_name = NULL; 601 | parameter_value = NULL; 602 | } 603 | b = mxmlWalkNext(b, body_in, MXML_DESCEND); 604 | } 605 | 606 | if (external_set_action_execute()) 607 | return -1; 608 | 609 | config_load(); 610 | 611 | b = mxmlFindElement(tree_out, tree_out, "soap_env:Body", 612 | NULL, NULL, MXML_DESCEND); 613 | if (!b) return -1; 614 | 615 | b = mxmlNewElement(b, "cwmp:SetParameterValuesResponse"); 616 | if (!b) return -1; 617 | 618 | b = mxmlNewElement(b, "Status"); 619 | if (!b) return -1; 620 | 621 | b = mxmlNewText(b, 0, "1"); 622 | if (!b) return -1; 623 | 624 | return 0; 625 | } 626 | 627 | int xml_handle_get_parameter_values(mxml_node_t *body_in, 628 | mxml_node_t *tree_in, 629 | mxml_node_t *tree_out) 630 | { 631 | mxml_node_t *n, *b = body_in; 632 | char *parameter_name = NULL; 633 | char *parameter_value = NULL; 634 | char *c; 635 | int counter = 0; 636 | 637 | n = mxmlFindElement(tree_out, tree_out, "soap_env:Body", 638 | NULL, NULL, MXML_DESCEND); 639 | if (!n) return -1; 640 | 641 | n = mxmlNewElement(n, "cwmp:GetParameterValuesResponse"); 642 | if (!n) return -1; 643 | 644 | n = mxmlNewElement(n, "ParameterList"); 645 | if (!n) return -1; 646 | 647 | #ifdef ACS_MULTI 648 | mxmlElementSetAttr(n, "xsi:type", "soap_enc:Array"); 649 | #endif 650 | 651 | while (b) { 652 | if (b && b->type == MXML_TEXT && 653 | b->value.text.string && 654 | b->parent->type == MXML_ELEMENT && 655 | !strcmp(b->parent->value.element.name, "string")) { 656 | parameter_name = b->value.text.string; 657 | } 658 | 659 | if (parameter_name) { 660 | if (!config_get_cwmp(parameter_name, ¶meter_value)) { 661 | // got the parameter value using libuci 662 | } else if (!external_get_action("value", 663 | parameter_name, ¶meter_value)) { 664 | // got the parameter value via external script 665 | } else { 666 | // error occurred when getting parameter value 667 | goto out; 668 | } 669 | counter++; 670 | 671 | n = mxmlFindElement(tree_out, tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); 672 | if (!n) goto out; 673 | 674 | n = mxmlNewElement(n, "ParameterValueStruct"); 675 | if (!n) goto out; 676 | 677 | n = mxmlNewElement(n, "Name"); 678 | if (!n) goto out; 679 | 680 | n = mxmlNewText(n, 0, parameter_name); 681 | if (!n) goto out; 682 | 683 | n = n->parent->parent; 684 | n = mxmlNewElement(n, "Value"); 685 | if (!n) goto out; 686 | 687 | #ifdef ACS_MULTI 688 | mxmlElementSetAttr(n, "xsi:type", "xsd:string"); 689 | #endif 690 | n = mxmlNewText(n, 0, parameter_value); 691 | if (!n) goto out; 692 | 693 | /* 694 | * three day's work to finally find memory leak if we 695 | * free parameter_name; 696 | * it points to: b->value.text.string 697 | * 698 | * also, parameter_value can be NULL so we don't do checks 699 | */ 700 | parameter_name = NULL; 701 | } 702 | 703 | FREE(parameter_value); 704 | b = mxmlWalkNext(b, body_in, MXML_DESCEND); 705 | } 706 | 707 | #ifdef ACS_MULTI 708 | b = mxmlFindElement(tree_out, tree_out, "ParameterList", 709 | NULL, NULL, MXML_DESCEND); 710 | if (!b) goto out; 711 | 712 | if (asprintf(&c, "cwmp:ParameterValueStruct[%d]", counter) == -1) 713 | goto out; 714 | 715 | mxmlElementSetAttr(b, "soap_enc:arrayType", c); 716 | FREE(c); 717 | #endif 718 | 719 | FREE(parameter_value); 720 | return 0; 721 | 722 | out: 723 | FREE(parameter_value); 724 | return -1; 725 | } 726 | 727 | static int xml_handle_set_parameter_attributes(mxml_node_t *body_in, 728 | mxml_node_t *tree_in, 729 | mxml_node_t *tree_out) { 730 | 731 | mxml_node_t *n, *b = body_in; 732 | char *c, *parameter_name, *parameter_notification; 733 | uint8_t attr_notification_update; 734 | 735 | /* handle cwmp:SetParameterAttributes */ 736 | if (asprintf(&c, "%s:%s", ns.cwmp, "SetParameterAttributes") == -1) 737 | return -1; 738 | 739 | n = mxmlFindElement(tree_in, tree_in, c, NULL, NULL, MXML_DESCEND); 740 | FREE(c); 741 | 742 | if (!n) return -1; 743 | b = n; 744 | 745 | while (b != NULL) { 746 | if (b && b->type == MXML_ELEMENT && 747 | !strcmp(b->value.element.name, "SetParameterAttributesStruct")) { 748 | attr_notification_update = 0; 749 | parameter_name = NULL; 750 | parameter_notification = NULL; 751 | } 752 | if (b && b->type == MXML_TEXT && 753 | b->value.text.string && 754 | b->parent->type == MXML_ELEMENT && 755 | !strcmp(b->parent->value.element.name, "Name")) { 756 | parameter_name = b->value.text.string; 757 | } 758 | if (b && b->type == MXML_TEXT && 759 | b->value.text.string && 760 | b->parent->type == MXML_ELEMENT && 761 | !strcmp(b->parent->value.element.name, "NotificationChange")) { 762 | attr_notification_update = (uint8_t) atoi(b->value.text.string); 763 | } 764 | if (b && b->type == MXML_TEXT && 765 | b->value.text.string && 766 | b->parent->type == MXML_ELEMENT && 767 | !strcmp(b->parent->value.element.name, "Notification")) { 768 | parameter_notification = b->value.text.string; 769 | } 770 | if (attr_notification_update && parameter_name && parameter_notification) { 771 | if (external_set_action_write("notification", 772 | parameter_name, parameter_notification)) 773 | return -1; 774 | attr_notification_update = 0; 775 | parameter_name = NULL; 776 | parameter_notification = NULL; 777 | } 778 | b = mxmlWalkNext(b, n, MXML_DESCEND); 779 | } 780 | 781 | if (external_set_action_execute()) 782 | return -1; 783 | 784 | b = mxmlFindElement(tree_out, tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); 785 | if (!b) return -1; 786 | 787 | b = mxmlNewElement(b, "cwmp:SetParameterAttributesResponse"); 788 | if (!b) return -1; 789 | 790 | config_load(); 791 | 792 | return 0; 793 | } 794 | 795 | static int xml_handle_download(mxml_node_t *body_in, 796 | mxml_node_t *tree_in, 797 | mxml_node_t *tree_out) 798 | { 799 | mxml_node_t *n, *t, *b = body_in; 800 | char *c, *download_url, *download_size; 801 | 802 | if (asprintf(&c, "%s:%s", ns.cwmp, "Download") == -1) 803 | return -1; 804 | 805 | n = mxmlFindElement(tree_in, tree_in, c, NULL, NULL, MXML_DESCEND); 806 | FREE(c); 807 | 808 | if (!n) return -1; 809 | b = n; 810 | 811 | download_url = NULL; 812 | download_size = NULL; 813 | while (b != NULL) { 814 | if (b && b->type == MXML_TEXT && 815 | b->value.text.string && 816 | b->parent->type == MXML_ELEMENT && 817 | !strcmp(b->parent->value.element.name, "URL")) { 818 | download_url = b->value.text.string; 819 | } 820 | if (b && b->type == MXML_TEXT && 821 | b->value.text.string && 822 | b->parent->type == MXML_ELEMENT && 823 | !strcmp(b->parent->value.element.name, "FileSize")) { 824 | download_size = b->value.text.string; 825 | } 826 | b = mxmlWalkNext(b, n, MXML_DESCEND); 827 | } 828 | if (!download_url || !download_size) 829 | return -1; 830 | 831 | t = mxmlFindElement(tree_out, tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); 832 | if (!t) return -1; 833 | 834 | t = mxmlNewElement(t, "cwmp:DownloadResponse"); 835 | if (!t) return -1; 836 | 837 | b = mxmlNewElement(t, "Status"); 838 | if (!b) return -1; 839 | 840 | b = mxmlNewElement(t, "StartTime"); 841 | if (!b) return -1; 842 | 843 | b = mxmlNewText(b, 0, mix_get_time()); 844 | if (!b) return -1; 845 | 846 | b = mxmlFindElement(t, tree_out, "Status", NULL, NULL, MXML_DESCEND); 847 | if (!b) return -1; 848 | 849 | if (external_download(download_url, download_size)) 850 | b = mxmlNewText(b, 0, "9000"); 851 | else 852 | b = mxmlNewText(b, 0, "0"); 853 | 854 | b = mxmlNewElement(t, "CompleteTime"); 855 | if (!b) return -1; 856 | 857 | b = mxmlNewText(b, 0, mix_get_time()); 858 | if (!b) return -1; 859 | 860 | return 0; 861 | } 862 | 863 | static int xml_handle_factory_reset(mxml_node_t *node, 864 | mxml_node_t *tree_in, 865 | mxml_node_t *tree_out) 866 | { 867 | mxml_node_t *b; 868 | 869 | b = mxmlFindElement(tree_out, tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); 870 | if (!b) return -1; 871 | 872 | b = mxmlNewElement(b, "cwmp:FactoryResetResponse"); 873 | if (!b) return -1; 874 | 875 | if (external_simple("factory_reset")) 876 | return -1; 877 | 878 | return 0; 879 | } 880 | 881 | static int xml_handle_reboot(mxml_node_t *node, 882 | mxml_node_t *tree_in, 883 | mxml_node_t *tree_out) 884 | { 885 | mxml_node_t *b; 886 | 887 | b = mxmlFindElement(tree_out, tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); 888 | if (!b) return -1; 889 | 890 | b = mxmlNewElement(b, "cwmp:RebootResponse"); 891 | if (!b) return -1; 892 | 893 | if (external_simple("reboot")) 894 | return -1; 895 | 896 | return 0; 897 | } 898 | 899 | -------------------------------------------------------------------------------- /src/xml.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This program is free software: you can redistribute it and/or modify 3 | * it under the terms of the GNU General Public License as published by 4 | * the Free Software Foundation, either version 2 of the License, or 5 | * (at your option) any later version. 6 | * 7 | * Copyright (C) 2011 Luka Perkov 8 | */ 9 | 10 | #ifndef _FREECWMP_XML_H__ 11 | #define _FREECWMP_XML_H__ 12 | 13 | #include 14 | 15 | void xml_exit(void); 16 | 17 | int xml_prepare_inform_message(char **msg_out); 18 | int xml_parse_inform_response_message(char *msg_in); 19 | int xml_handle_message(char *msg_in, char **msg_out); 20 | 21 | static int xml_handle_set_parameter_values(mxml_node_t *body_in, 22 | mxml_node_t *tree_in, 23 | mxml_node_t *tree_out); 24 | 25 | static int xml_handle_get_parameter_values(mxml_node_t *body_in, 26 | mxml_node_t *tree_in, 27 | mxml_node_t *tree_out); 28 | 29 | static int xml_handle_set_parameter_attributes(mxml_node_t *body_in, 30 | mxml_node_t *tree_in, 31 | mxml_node_t *tree_out); 32 | 33 | static int xml_handle_download(mxml_node_t *body_in, 34 | mxml_node_t *tree_in, 35 | mxml_node_t *tree_out); 36 | 37 | static int xml_handle_factory_reset(mxml_node_t *body_in, 38 | mxml_node_t *tree_in, 39 | mxml_node_t *tree_out); 40 | 41 | static int xml_handle_reboot(mxml_node_t *body_in, 42 | mxml_node_t *tree_in, 43 | mxml_node_t *tree_out); 44 | 45 | static int xml_create_generic_fault_message(mxml_node_t *body, 46 | bool client, 47 | char *code, 48 | char *string); 49 | 50 | #endif 51 | 52 | --------------------------------------------------------------------------------