├── .github
└── workflows
│ ├── codacy.yml
│ ├── codeql.yml
│ └── codeql2.yml
├── COPYING
├── Makefile
├── README.md
├── SECURITY.md
├── ipscan.c
├── ipscan.h
├── ipscan_db.c
├── ipscan_general.c
├── ipscan_icmpv6.c
├── ipscan_portlist.h
├── ipscan_tcp.c
├── ipscan_udp.c
├── ipscan_web.c
└── upgrade.bsh
/.github/workflows/codacy.yml:
--------------------------------------------------------------------------------
1 | # This workflow uses actions that are not certified by GitHub.
2 | # They are provided by a third-party and are governed by
3 | # separate terms of service, privacy policy, and support
4 | # documentation.
5 |
6 | # This workflow checks out code, performs a Codacy security scan
7 | # and integrates the results with the
8 | # GitHub Advanced Security code scanning feature. For more information on
9 | # the Codacy security scan action usage and parameters, see
10 | # https://github.com/codacy/codacy-analysis-cli-action.
11 | # For more information on Codacy Analysis CLI in general, see
12 | # https://github.com/codacy/codacy-analysis-cli.
13 |
14 | name: Codacy Security Scan
15 |
16 | on:
17 | push:
18 | branches: [ "master" ]
19 | pull_request:
20 | # The branches below must be a subset of the branches above
21 | branches: [ "master" ]
22 | schedule:
23 | - cron: '0 3 * * 1'
24 | workflow_dispatch:
25 |
26 | permissions:
27 | contents: read
28 |
29 | jobs:
30 | codacy-security-scan:
31 | permissions:
32 | contents: read # for actions/checkout to fetch code
33 | security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
34 | actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
35 | name: Codacy Security Scan
36 | runs-on: ubuntu-latest
37 | steps:
38 | # Checkout the repository to the GitHub Actions runner
39 | - name: Checkout code
40 | uses: actions/checkout@v3
41 |
42 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
43 | - name: Run Codacy Analysis CLI
44 | uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
45 | with:
46 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
47 | # You can also omit the token and run the tools that support default configurations
48 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
49 | verbose: true
50 | output: results.sarif
51 | format: sarif
52 | # Adjust severity of non-security issues
53 | gh-code-scanning-compat: true
54 | # Force 0 exit code to allow SARIF file generation
55 | # This will handover control about PR rejection to the GitHub side
56 | max-allowed-issues: 2147483647
57 |
58 | # Upload the SARIF file generated in the previous step
59 | - name: Upload SARIF results file
60 | uses: github/codeql-action/upload-sarif@v2
61 | with:
62 | sarif_file: results.sarif
63 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | name: "CodeQL"
8 |
9 | on:
10 | push:
11 | branches: [ "master" ]
12 | pull_request:
13 | # The branches below must be a subset of the branches above
14 | branches: [ "master" ]
15 | schedule:
16 | - cron: '0 2 * * 1'
17 | workflow_dispatch:
18 |
19 | jobs:
20 | analyze:
21 | name: Analyze
22 | runs-on: ubuntu-latest
23 | permissions:
24 | actions: read
25 | contents: read
26 | security-events: write
27 |
28 | strategy:
29 | fail-fast: false
30 | matrix:
31 | language: [ 'cpp' ]
32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
33 | # Use only 'java' to analyze code written in Java, Kotlin or both
34 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
35 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
36 |
37 | steps:
38 | - name: Checkout repository
39 | uses: actions/checkout@v3
40 |
41 | # Initializes the CodeQL tools for scanning.
42 | - name: Initialize CodeQL
43 | uses: github/codeql-action/init@v2
44 | with:
45 | languages: ${{ matrix.language }}
46 | # If you wish to specify custom queries, you can do so here or in a config file.
47 | # By default, queries listed here will override any specified in a config file.
48 | # Prefix the list here with "+" to use these queries and those in the config file.
49 |
50 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
51 | # queries: security-extended,security-and-quality
52 |
53 |
54 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
55 | # If this step fails, then you should remove it and run the build manually (see below)
56 | - name: Autobuild
57 | uses: github/codeql-action/autobuild@v2
58 |
59 | # ℹ️ Command-line programs to run using the OS shell.
60 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
61 |
62 | # If the Autobuild fails above, remove it and uncomment the following three lines.
63 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
64 |
65 | # - run: |
66 | # echo "Run, Build Application using script"
67 | # ./location_of_script_within_repo/buildscript.sh
68 |
69 | - name: Perform CodeQL Analysis
70 | uses: github/codeql-action/analyze@v2
71 | with:
72 | category: "/language:${{matrix.language}}"
73 |
--------------------------------------------------------------------------------
/.github/workflows/codeql2.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL Advanced"
13 |
14 | on:
15 | push:
16 | branches: [ "master" ]
17 | pull_request:
18 | branches: [ "master" ]
19 | schedule:
20 | - cron: '28 13 * * 0'
21 |
22 | jobs:
23 | analyze:
24 | name: Analyze (${{ matrix.language }})
25 | # Runner size impacts CodeQL analysis time. To learn more, please see:
26 | # - https://gh.io/recommended-hardware-resources-for-running-codeql
27 | # - https://gh.io/supported-runners-and-hardware-resources
28 | # - https://gh.io/using-larger-runners (GitHub.com only)
29 | # Consider using larger runners or machines with greater resources for possible analysis time improvements.
30 | runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
31 | permissions:
32 | # required for all workflows
33 | security-events: write
34 |
35 | # required to fetch internal or private CodeQL packs
36 | packages: read
37 |
38 | # only required for workflows in private repositories
39 | actions: read
40 | contents: read
41 |
42 | strategy:
43 | fail-fast: false
44 | matrix:
45 | include:
46 | - language: actions
47 | build-mode: none
48 | - language: c-cpp
49 | build-mode: autobuild
50 | # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
51 | # Use `c-cpp` to analyze code written in C, C++ or both
52 | # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
53 | # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
54 | # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
55 | # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
56 | # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
57 | # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
58 | steps:
59 | - name: Checkout repository
60 | uses: actions/checkout@v4
61 |
62 | # Add any setup steps before running the `github/codeql-action/init` action.
63 | # This includes steps like installing compilers or runtimes (`actions/setup-node`
64 | # or others). This is typically only required for manual builds.
65 | # - name: Setup runtime (example)
66 | # uses: actions/setup-example@v1
67 |
68 | # Initializes the CodeQL tools for scanning.
69 | - name: Initialize CodeQL
70 | uses: github/codeql-action/init@v3
71 | with:
72 | languages: ${{ matrix.language }}
73 | build-mode: ${{ matrix.build-mode }}
74 | # If you wish to specify custom queries, you can do so here or in a config file.
75 | # By default, queries listed here will override any specified in a config file.
76 | # Prefix the list here with "+" to use these queries and those in the config file.
77 |
78 | # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
79 | # queries: security-extended,security-and-quality
80 |
81 | # If the analyze step fails for one of the languages you are analyzing with
82 | # "We were unable to automatically build your code", modify the matrix above
83 | # to set the build mode to "manual" for that language. Then modify this step
84 | # to build your code.
85 | # ℹ️ Command-line programs to run using the OS shell.
86 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
87 | - if: matrix.build-mode == 'manual'
88 | shell: bash
89 | run: |
90 | echo 'If you are using a "manual" build mode for one or more of the' \
91 | 'languages you are analyzing, replace this with the commands to build' \
92 | 'your code, for example:'
93 | echo ' make bootstrap'
94 | echo ' make release'
95 | exit 1
96 |
97 | - name: Perform CodeQL Analysis
98 | uses: github/codeql-action/analyze@v3
99 | with:
100 | category: "/language:${{matrix.language}}"
101 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 |
624 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # IPscan - an HTTP-initiated IPv6 port scanner.
2 | #
3 | # (C) Copyright 2011-2025 Tim Chappell.
4 | #
5 | # This file is part of IPscan.
6 | #
7 | # IPscan is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with IPscan. If not, see .
19 |
20 | # Makefile version
21 | # 0.01 - initial version
22 | # 0.02 - added MySQL support
23 | # 0.03 - addition of ping functionality (suid bit set)
24 | # 0.04 - default to MySQL
25 | # 0.05 - remove sqlite support
26 | # 0.06 - move $(LIBS) to the end of each link line
27 | # 0.07 - minor corrections to support FreeBSD gmake builds
28 | # 0.08 - add extra compiler checks
29 | # 0.09 - add 'running as root' check for install step
30 | # 0.10 - strip symbols from the final objects
31 | # 0.11 - add additional object security-related options
32 | # 0.12 - tidy up
33 | # 0.13 - add support for servers where SETUID is missing/unavailable
34 | # 0.14 - add support for servers where UDP is missing/available
35 | # 0.15 - update copyright year
36 | # 0.16 - force warnings to be errors
37 | # 0.17 - update copyright year
38 | # 0.18 - update copyright year
39 | # 0.19 - add debug build capability, update copyright year
40 | # 0.20 - update copyright year
41 | # 0.21 - update copyright year
42 | # 0.22 - update copyright year
43 | # 0.23 - update copyright year
44 |
45 | # Support servers where SETUID is not available
46 | # Set this variable to 0 if you don't have permissions to call SETUID
47 | SETUID_AVAILABLE=1
48 |
49 | # Support servers where UDP port access is disabled
50 | # Set this variable to 0 if you don't have permissions to access UDP ports
51 | UDP_AVAILABLE=1
52 |
53 | # General build variables
54 | SHELL=/bin/sh
55 | LIBPATHS=-L/usr/lib
56 | INCLUDES=-I/usr/include
57 | LIBS=
58 | CC=gcc
59 | CFLAGS=-Wall -Wextra -Werror -Wshadow -Wpointer-arith -Wwrite-strings -Wformat -Wformat-security -O2 -D_FORTIFY_SOURCE=2
60 | CFLAGS+= -fstack-protector-all -fstack-clash-protection -Wstack-protector --param ssp-buffer-size=4
61 | CFLAGS+= -ftrapv -fexceptions -fPIE -fpie -Wl,-pie -Wl,-z,relro -Wl,-z,now -Werror=implicit-function-declaration
62 | # testing CFLAGS+= -D_TIME_BITS=64
63 |
64 | # Install location for the CGI files
65 | TARGETDIR=/var/www/cgi-bin6
66 |
67 | # HTTP URI PATH by which external hosts will access the CGI files.
68 | # This may well be unrelated to the installation path if Apache is configured
69 | # to provide CGI access via an alias.
70 | # NB : the path should begin with a / but must NOT end with one ....
71 | URIPATH=/cgi-bin6
72 |
73 | # Text-version target executable name
74 | TXTTARGET=ipscantxt.cgi
75 | FASTTXTTARGET=ipscanfasttxt.cgi
76 |
77 | # Javascript-version target executable name
78 | JSTARGET=ipscanjs.cgi
79 | FASTJSTARGET=ipscanfastjs.cgi
80 |
81 | ##############################################################################
82 | #
83 | # Hopefully nothing below this point will need changing ....
84 | #
85 | ##############################################################################
86 |
87 | # Determine the appropriate database related include/library paths
88 | # as well as any necessary libraries
89 | LIBS+=$(shell mysql_config --libs)
90 | CFLAGS+=$(shell mysql_config --cflags)
91 | INCLUDES+=$(shell mysql_config --include)
92 |
93 | # No debug by default
94 | DEBUG=
95 | # Determine effective user-id - likely to work in all shells
96 | MYEUID=$(shell id -u)
97 |
98 | # Concatenate the necessary parameters for the two targets
99 | CMNPARAMS= $(DEBUG) -DEXEDIR=\"$(TARGETDIR)\" -DEXETXTNAME=\"$(TXTTARGET)\" -DEXEJSNAME=\"$(JSTARGET)\"
100 | CMNPARAMS+= -DEXEFASTTXTNAME=\"$(FASTTXTTARGET)\" -DEXEFASTJSNAME=\"$(FASTJSTARGET)\"
101 | CMNPARAMS+= -DURIPATH=\"$(URIPATH)\" -DSETUID_AVAILABLE=$(SETUID_AVAILABLE)
102 | CMNPARAMS+= -DUDP_AVAILABLE=$(UDP_AVAILABLE)
103 | TXTPARAMS=$(CFLAGS) -DTEXTMODE=1 -DFAST=0 $(CMNPARAMS)
104 | JSPARAMS =$(CFLAGS) -DTEXTMODE=0 -DFAST=0 $(CMNPARAMS)
105 | FASTTXTPARAMS=$(CFLAGS) -DTEXTMODE=1 -DFAST=1 $(CMNPARAMS)
106 | FASTJSPARAMS =$(CFLAGS) -DTEXTMODE=0 -DFAST=1 $(CMNPARAMS)
107 |
108 | # Common header files which are always a dependancy
109 | HEADERFILES=ipscan.h ipscan_portlist.h
110 | # Any other files on which we depend
111 | DEPENDFILE=Makefile
112 |
113 | # Generate the list of text-version and javascript-version objects from the source files
114 | TXTOBJS=$(patsubst %.c,%-txt.o,$(wildcard *.c))
115 | JSOBJS=$(patsubst %.c,%-js.o,$(wildcard *.c))
116 | FASTTXTOBJS=$(patsubst %.c,%-fast-txt.o,$(wildcard *.c))
117 | FASTJSOBJS=$(patsubst %.c,%-fast-js.o,$(wildcard *.c))
118 |
119 | # default target builds everything
120 | .PHONY: all
121 | all : $(TXTTARGET) $(JSTARGET) $(FASTTXTTARGET) $(FASTJSTARGET)
122 |
123 | # debug target builds objects with debug, defined in ipscan.h, enabled
124 | # Not intended for production use
125 | .PHONY: debug
126 | debug : clean
127 | debug : DEBUG = -DDEBUG=1
128 | debug : $(TXTTARGET) $(JSTARGET) $(FASTTXTTARGET) $(FASTJSTARGET)
129 |
130 | # Rules to build an individual text-version object and the overall text-version target
131 | %-txt.o: %.c $(HEADERFILES) $(DEPENDFILE)
132 | $(CC) $(TXTPARAMS) -c $(INCLUDES) $(LIBPATHS) -o $@ $<
133 | $(TXTTARGET) : $(TXTOBJS) $(HEADERFILES) $(DEPENDFILE)
134 | $(CC) $(TXTPARAMS) -o $(TXTTARGET) $(INCLUDES) $(LIBPATHS) $(TXTOBJS) $(LIBS)
135 |
136 | # Rules to build an individual text-version object and the overall text-version target
137 | %-fast-txt.o: %.c $(HEADERFILES) $(DEPENDFILE)
138 | $(CC) $(FASTTXTPARAMS) -c $(INCLUDES) $(LIBPATHS) -o $@ $<
139 | $(FASTTXTTARGET) : $(FASTTXTOBJS) $(HEADERFILES) $(DEPENDFILE)
140 | $(CC) $(FASTTXTPARAMS) -o $(FASTTXTTARGET) $(INCLUDES) $(LIBPATHS) $(FASTTXTOBJS) $(LIBS)
141 |
142 | # Rules to build an individual jscript-version object and the overall jscript-version target
143 | %-js.o: %.c $(HEADERFILES) $(DEPENDFILE)
144 | $(CC) $(JSPARAMS) -c $(INCLUDES) $(LIBPATHS) -o $@ $<
145 | $(JSTARGET) : $(JSOBJS) $(HEADERFILES) $(DEPENDFILE)
146 | $(CC) $(JSPARAMS) -o $(JSTARGET) $(INCLUDES) $(LIBPATHS) $(JSOBJS) $(LIBS)
147 |
148 | # Rules to build an individual jscript-version object and the overall jscript-version target
149 | %-fast-js.o: %.c $(HEADERFILES) $(DEPENDFILE)
150 | $(CC) $(FASTJSPARAMS) -c $(INCLUDES) $(LIBPATHS) -o $@ $<
151 | $(FASTJSTARGET) : $(FASTJSOBJS) $(HEADERFILES) $(DEPENDFILE)
152 | $(CC) $(FASTJSPARAMS) -o $(FASTJSTARGET) $(INCLUDES) $(LIBPATHS) $(FASTJSOBJS) $(LIBS)
153 |
154 | # Rules to copy the built objects to the target installation directory
155 | # optionally set setuid bit on targets if required
156 | .PHONY: install
157 | install : $(TXTTARGET) $(JSTARGET) $(FASTTXTTARGET) $(FASTJSTARGET)
158 | ifeq ($(UDP_AVAILABLE),1)
159 | @echo
160 | @echo Running with UDP_AVAILABLE in the Makefile set to 1
161 | @echo If you do NOT have root permissions or UDP sockets are NOT available then
162 | @echo please set UDP_AVAILABLE to 0 and re-make.
163 | @echo
164 | else
165 | @echo
166 | @echo Running with UDP_AVAILABLE in the Makefile set to 0
167 | @echo If you do have permissions to create UDP sockets then
168 | @echo please set SETUID_AVAILABLE to 1 and re-make.
169 | @echo
170 | endif
171 | # Strip un-needed symbols from the binaries and copy them to their
172 | # target location
173 | strip --strip-unneeded $(TXTTARGET) $(JSTARGET) $(FASTTXTTARGET) $(FASTJSTARGET)
174 | cp $(TXTTARGET) $(FASTTXTTARGET) $(TARGETDIR)
175 | cp $(JSTARGET) $(FASTJSTARGET) $(TARGETDIR)
176 | ifeq ($(SETUID_AVAILABLE),1)
177 | @echo
178 | @echo Running with SETUID_AVAILABLE in the Makefile set to 1
179 | @echo If you do NOT have root permissions or chmod/setuid is NOT available then
180 | @echo please set SETUID_AVAILABLE to 0 and re-make.
181 | @echo
182 | ifeq ($(MYEUID),0)
183 | chmod 4555 $(TARGETDIR)/$(TXTTARGET)
184 | chmod 4555 $(TARGETDIR)/$(JSTARGET)
185 | chmod 4555 $(TARGETDIR)/$(FASTTXTTARGET)
186 | chmod 4555 $(TARGETDIR)/$(FASTJSTARGET)
187 | else
188 | @echo
189 | @echo ERROR: install must be run as root in order to setuid.
190 | @echo ERROR: user-id is currently $(MYEUID)
191 | @echo
192 | endif
193 | else
194 | @echo
195 | @echo Running with SETUID_AVAILABLE in the Makefile set to 0
196 | @echo If you do have root permissions AND chmod/setuid is available then
197 | @echo please set SETUID_AVAILABLE to 1 and re-make.
198 | @echo
199 | endif
200 |
201 | # Rule to clean the source directory
202 | .PHONY: clean
203 | clean :
204 | rm -f $(TXTTARGET) $(JSTARGET) $(FASTTXTTARGET) $(FASTJSTARGET)
205 | rm -f $(TXTOBJS) $(JSOBJS) $(FASTTXTOBJS) $(FASTJSOBJS)
206 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IPscan
2 | ### An HTTP-initiated IPv6 port scanner, offering text-only and javascript browser compatible versions.
3 |
4 | Copyright (C) 2011-2025 Tim Chappell.
5 |
6 | This file is part of IPscan.
7 |
8 | IPscan is free software: you can redistribute it and/or modify
9 | it under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with IPscan. If not, see .
20 |
21 | ---
22 |
23 | IPscan requires access to a MySQL, or MariaDB, database and the associated client development libraries
24 | (libmysqlclient-dev or similar) to be installed on the server which will act as your scanner. The database
25 | is used to *temporarily* hold scan results until shortly after the test completes.
26 | IPscan is known to build on: openSUSE versions 11.1/11.4/12.1/13.1, Centos 7, Fedora 16,
27 | Ubuntu 12.04, Mint 12, FreeBSD 9, Arch Linux ARM (Raspberry Pi) and Raspbian and run alongside
28 | Apache versions 2.2 and 2.4. Please let me know of any other build successes/failures on
29 | unlisted platforms.
30 |
31 | NOTE: IPscan logging has been updated to aid operators needing to comply with regulatory
32 | requirements for the protection of end-users, e.g. GDPR. Where applicable, the logging-related
33 | recommendations outlined in: https://tools.ietf.org/id/draft-andersdotter-intarea-update-to-rfc6302-00.html#RFC6302
34 | have been implemented, for unmodified ipscan.h configurations.
35 |
36 | Installation Steps:
37 | ===================
38 | IMPORTANT: when UPGRADING from versions before 1.97: a database change has occurred and consequently
39 | it is necessary that you remove your existing database prior to building and installing
40 | versions 1.97 and later. See step 4 below for details.
41 |
42 | 1. edit the Makefile and adjust the following entries as required:
43 | a. TARGETDIR - this should be set to the desired location for the cgi files (e.g. /srv/www/cgi-bin6)
44 | Ensure that the selected target directory exists, with appropriate permissions, before
45 | attempting to install the final executables.
46 | b. URIPATH - this is the request URI by which the cgi files will be accessed from your webserver
47 | e.g. https://www64.chappell-family.co.uk/cgi-bin6/ipscanjs.cgi then set URIPATH=/cgi-bin6
48 | c. TXTTARGET and JSTARGET - these define the names of the two cgi objects that will be created
49 | d. SETUID_AVAILABLE and UDP_AVAILABLE - if you're running the service on a machine where you, or
50 | the web server, don't have permissions to call setuid() or create UDP sockets then these features
51 | need to be disabled.
52 |
53 | 2. edit ipscan.h and adjust *at least* the following entries:
54 | a. EMAILADDRESS - suggest you use a non-personal email address if the webserver will be world-accessible
55 | b. INCLUDETERMSOFUSE and TERMSOFUSEURL if you wish to reference a terms of use page on your website.
56 | c. IPSCAN_INTERFACE_NAME - modify this to match the server's interface to which clients will browse.
57 | d. MYSQL_XXXX - Adjust the following constants to match the settings of your database server:
58 | MYSQL_HOST - the hostname or IP address of the machine hosting the MySQL database
59 | MYSQL_USER - the username used to access the IPscan database.
60 | MYSQL_PASSWD - the password used to identify the MySQL user.
61 | MYSQL_DBNAME - the name of the IPscan database.
62 | MYSQL_TBLNAME - the name of the table in which IPscan results will reside.
63 |
64 | 3. edit ipscan_portlist.h and change the list of ports to be tested, if required. Note that if you add
65 | new UDP ports then you must also add a matching packet generator function to ipscan_udp.c
66 |
67 | 4. Create the database and user and allocate appropriate user privileges, using the following commands within the mysql shell:
68 |
69 | NB: adjust the host, user name, password and database name to match the globals you've edited in step 2 above:
70 |
71 | mysql> create database ipscan;
72 | Query OK, 1 row affected (0.00 sec)
73 |
74 | Note: it is unnecessary to re-create the user if upgrading from a previous version.
75 |
76 | mysql> create user 'ipscan-user'@'localhost' identified by 'ipscan-passwd';
77 | Query OK, 0 rows affected (0.01 sec)
78 |
79 | mysql> grant all privileges on ipscan.* to 'ipscan-user'@'localhost' identified by 'ipscan-passwd';
80 | Query OK, 0 rows affected (0.01 sec)
81 |
82 | mysql> exit
83 | Bye
84 |
85 | If performing an upgrade from an earlier version of IPscan then either drop the table within a mysql shell, e.g. :
86 |
87 | mysql> use ipscan;
88 | mysql> drop table if exists results;
89 |
90 | or use the BASH upgrade script within the IPscan source directory:
91 |
92 | $ ./upgrade.bsh
93 |
94 |
95 | 5. make && make install
96 |
97 | Given that the suid bit is set on the installed executables, in order to support raw sockets for ICMPv6 testing,
98 | it is necessary to perform the 'make install' stage as root user.
99 |
100 | Note: when updating an existing installation to version 1.10 and beyond it may be necessary to manually
101 | remove the ipscan_checks.c file, if it remains in your install directory, prior to building.
102 | The functionality within ipscan_checks.c has been redistributed to separate files which
103 | handle TCP, UDP and ICMPv6 testing.
104 |
105 | Note: please use gmake under FreeBSD.
106 |
107 | 6. Make sure that the URI path directory (which may well be accessed via an Apache alias) is enabled to execute cgi:
108 |
109 | ScriptAlias /cgi-bin6/ "/srv/www/cgi-bin6/"
110 |
111 | AllowOverride None
112 | Options +ExecCGI -Includes
113 | Order allow,deny
114 | Allow from 2000::/3
115 |
116 |
117 | Also disable client caching, having enabled the loading of mod_headers:
118 |
119 |
120 | Header set Cache-Control "private, no-cache, no-store, must-revalidate"
121 | Header set Pragma "no-cache"
122 | Header set Expires "0"
123 |
124 |
125 | Don't forget to restart your web server after making the appropriate modifications.
126 |
127 | 7. If you are using an SELinux-enabled distribution (e.g. Fedora) then it may be necessary to perform additional
128 | steps similar to those outlined below:
129 | a. Ensure that your Apache server is enabled to support cgi, as root type:
130 | # setsebool -P httpd_enable_cgi on
131 | b. Enable the correct execution permissions to the cgi scripts, as root type:
132 | # cd /srv/www/cgi-bin6/ (use your selected installation path)
133 | # chcon -t httpd_unconfined_script_exec_t *.cgi
134 |
135 | IMPORTANT NOTE: the steps listed in step 7 above are only indicative of what may be required, and
136 | depend upon your existing installation. Please consult the SELinux documentation for further details.
137 |
138 | 8. Browse from a machine that you want testing towards your servers' IPv6 address, e.g.
139 | w3m https://www66.chappell-family.co.uk/cgi-bin6/ipscanfasttxt.cgi
140 | or:
141 | w3m https://[2001:470:971f:99::6]/cgi-bin6/ipscantxt.cgi
142 |
143 | 9. Check the web server access/error logs or syslog for messages. IPscan will place summary messages in the
144 | web server error log or syslog if enabled to do so (this is NOT the default option - change
145 | IPSCAN_LOGVERBOSITY to 1 to enable this). It is possible to enable copious amounts of debug by
146 | uncommenting the debug #define statements in ipscan.h.
147 |
148 | 10. If you're providing public access to IPscan then please ensure that you disable verbose reporting,
149 | the summary option and ALL debug facilities.
150 |
151 | Note: versions v1.42 and later of IPscan automatically delete the scan results, for both javascript
152 | and text-only clients, after reporting them to the user. Earlier versions relied on a cron job
153 | to achieve the same end, but this is no longer required for current versions.
154 |
155 | 11. For those considering providing IPscan access on the public internet then consider adding a
156 | landing page which will check for host IP address suitability prior to allowing access to the
157 | cgi script(s) - most (apart from google) search engine spiders/robots currently only use IPv4.
158 | It may be advisable to only offer direct links to the cgi scripts if the address checks
159 | were successful. See https://ipv6.chappell-family.com/ipv6tcptest/ as an example.
160 |
161 | 12. Notes on IPscan binaries: IPscan is provided in two basic versions, one supporting
162 | javascript-enabled browsers and the other for text-based browsers. Additionally, the standard
163 | build provides fast and standard versions of both of these tests. The fast version tests
164 | multiple TCP or UDP ports in parallel, whereas the standard version tests only 1 port at a time,
165 | at a default rate of 1 port per second. Please be aware that some OSes and firewalls apply
166 | rate-limiting to their generation, or passing, of ICMPv6 responses on the basis that this
167 | behaviour is indicative of a port scan being performed. Consequently such rate-limiting might
168 | cause a port which would normally generate an ICMPv6 response (e.g. PHBTD) to send no response
169 | at all, which IPscan would report as STEALTHed. If you are testing a host or firewall (whether
170 | on the client under test or elsewhere in the path between your client and test server) which
171 | implements such rate-limiting then you are advised to use the standard, slower versions of IPscan
172 | which should not trigger the rate-limiting behaviour. If you're unsure which version is appropriate
173 | for your device, then try both and compare the results. Some Linux distributions and some ISP firewalls
174 | are known to implement such rate-limiting.
175 |
176 |
177 | Getting further help:
178 | =====================
179 | A demonstration Raspberry Pi IPv6 firewall checker is available to IPv6 enabled clients at: . If you need further help then please email me at: or visit my IPscan wiki at:
180 |
181 | ---
182 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | The following versions of this project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 1.97 | :white_check_mark: |
11 | | < 1.97 | :x: |
12 |
13 | ## Reporting a Vulnerability
14 |
15 | Please see:
16 | ---
17 |
--------------------------------------------------------------------------------
/ipscan.h:
--------------------------------------------------------------------------------
1 | // IPscan - an HTTP-initiated IPv6 port scanner.
2 | //
3 | // Copyright (C) 2011-2025 Tim Chappell.
4 | //
5 | // This file is part of IPscan.
6 | //
7 | // IPscan is free software: you can redistribute it and/or modify
8 | // it under the terms of the GNU General Public License as published by
9 | // the Free Software Foundation, either version 3 of the License, or
10 | // (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with IPscan. If not, see .
19 |
20 | #include
21 | #include
22 |
23 | #ifndef IPSCAN_H
24 | #define IPSCAN_H 1
25 |
26 | // Handle DEBUG flag
27 | #ifndef DEBUG
28 | #define DEBUG 0
29 | #endif
30 |
31 | // Build-mode for executable
32 | // Note this is controlled by the makefile, but a default is defined here for safety
33 | //
34 | // TEXTMODE == 1 => Text Browser compatible (e.g. lynx or w3m)
35 | // TEXTMODE == 0 => Browser supports Javascript
36 | //
37 | #ifndef TEXTMODE
38 | #define TEXTMODE 0
39 | #endif
40 |
41 | // Parallel scan-mode for executable
42 | // Note this is controlled by the makefile, but a default is defined here for safety
43 | #ifndef FAST
44 | #define FAST 0
45 | #endif
46 |
47 | // Determine which logging target to use stderr (0) or syslog(1)
48 | #define LOGMODE 1
49 |
50 | // Create the appropriate logging macro
51 | #if (LOGMODE == 0)
52 | #define IPSCAN_LOG(...) fprintf(stderr, __VA_ARGS__ )
53 | #else
54 | #define IPSCAN_LOG(...) syslog(LOG_NOTICE, __VA_ARGS__ )
55 | #endif
56 |
57 | //
58 | // VERSION HISTORY
59 | //
60 | // 0.5 first combined text/javascript version
61 | // 0.61 separate closed/timeout [CLOSED] from closed/rejected [FILTER]
62 | // 0.63 further response states
63 | // 0.64 Open, Closed or detailed response names
64 | // 0.65 Added results key
65 | // 0.66 Added Prohibited failure case (ICMPv6 administratively prohibited)
66 | // 0.67 Add ability to create database directory path assuming only 1 additional directory is required to be created
67 | // 0.68 Added unreachable icmpv6 type 1 code 0
68 | // 0.69 Add unreachable stats
69 | // 0.70 Add further potential connect errors
70 | // 0.71 Clean logging output and web reporting
71 | // 0.72 Updated txt browser output and offer email feedback link.
72 | // 0.73 add hostname, time into feedback email body
73 | // 0.74 tidy up noscript link to text-only version, move to structure driven results classification
74 | // 0.75 improved scan summary logging for structure driven approach
75 | // 0.76 improved query string error checking, handling and reporting
76 | // 0.77 added link to source code on github to results page.
77 | // 0.78 added support for HEAD method
78 | // 0.79 Minor tweaks to ipscan_web.c and ipscan.c to remove set but unused variables
79 | // 0.80 include optional MySQL support which touches Makefile, ipscan.h and ipscan_db.c
80 | // 0.81 added Microsoft RDP protocol, port 3389, to list of default ports
81 | // 0.82 added/modified some Apple related ports
82 | // 0.83 added support for syslog logging
83 | // 0.84 renumbered default ports so they are monotonic
84 | // 0.85 tidied up HTML to make Opera happy
85 | // 0.86 added ICMPv6 ping
86 | // 0.87 tidied ipscan_checks
87 | // 0.88 ping logging improvements
88 | // 0.89 further logging improvements for ICMPv6 responses
89 | // 0.90 INNER ICMPv6 packet logging, checking and reporting
90 | // 0.91 further default logging improvements
91 | // 0.92 removal of empty HTML paragraph
92 | // 0.93 default to MySQL, potential query string overflow caught
93 | // 0.94 improve buffer overflow protection, remove SQLITE support
94 | // 0.95 tidy up HTML error reporting for buffer overflow cases.
95 | // 0.96 fix some printf casts
96 | // 0.97 slight improvement to logging for ICMPv6 cases
97 | // 0.98 tweaks for FreeBSD9 support (build under gmake)
98 | // 0.99 first build supporting parallel port scanning
99 | // 1.00 further code improvements, add HTTP-EQUIV to force IE7 mimicry
100 | // 1.01 Minor tweak to add further windows related ports
101 | // 1.02 Minor tweak to non-javascript browser message
102 | // 1.03 Minor tweak to add further parameter checking for customports
103 | // 1.04 Include port descriptive text
104 | // 1.05 Compress kickoff form
105 | // 1.06 Tidy up requestmethod declaration
106 | // 1.07 Introduction of UDP port scans
107 | // 1.08 Estimated run time improvement
108 | // 1.09 UDP responses renamed for improved consistency, ipscan_checks.c split
109 | // 1.10 Parallel UDP processing support added
110 | // 1.11 Separate TCP/UDP logging, all disabled by default
111 | // 1.12 Runtime estimate improvement - separate calc per protocol type
112 | // 1.13 Logging improvement
113 | // 1.14 Add support for scan automation help when offered a bad query string
114 | // 1.15 Incorporate further UDP support
115 | // 1.16 support optional ping for deployment on servers where setuid not possible
116 | // 1.17 support optional UDP for deployment on controlled servers
117 | // 1.18 move to use memset()
118 | // 1.19 support for special test cases
119 | // 1.20 support for TCP/32764 (Router backdoor) and special case debug logging improvements
120 | // 1.21 add minimum per-port timings to ensure Linux 1s ratelimit is not hit
121 | // 1.22 add completion indication to support quicker results deletion
122 | // 1.23 enable automatic results deletion
123 | // 1.24 further javascript improvements and fix for custom ports
124 | // 1.25 fix tidy-up reporting
125 | // 1.26 javascript lint check
126 | // 1.27 move final (javascript) fetch earlier
127 | // 1.28 further javascript improvements
128 | // 1.29 additional debug support to aid javascript optimisation
129 | // 1.30 additional javascript optimisation
130 | // 1.31 removed unused javascript functions
131 | // 1.32 auto-generate normal and fast versions
132 | // 1.33 improved error reporting
133 | // 1.34 added SNMPv2c and SNMPv3 support
134 | // 1.35 move to random(ish) sessions rather than pid()
135 | // 1.36 tidy up for push to github
136 | // 1.37 move to single XML HTTP Request object
137 | // 1.38 Variety of minor tweaks (CGI environment variable parsing)
138 | // 1.39 Add 'navigate away' detection to javascript version
139 | // 1.40 Correct some Coverity reported issues
140 | // 1.41 Add fork() issue reporting to aid debug
141 | // 1.42 Add automatic deletion of all results
142 | // 1.43 Add support for automatic deletion of orphaned results
143 | // 1.44 Add support for RIPng and IKEv2 SA_INIT
144 | // 1.45 Reintroduce MPLS LSP Ping
145 | // 1.46 Further DNS test error handling
146 | // 1.47 SNMP error handling improvement
147 | // 1.48 Different community strings for SNMPv1 and SNMPv2c
148 | // 1.49 Add DHCPv6 support
149 | // 1.50 Use memory engine table by default
150 | // 1.51 Change TCP getaddrinfo call to request AF_INET6
151 | // 1.52 Reduce the debug logging to make testing easier
152 | // 1.53 Add some Microsft Message Queuing ports which appear
153 | // to be open in some Windows 10 installations
154 | // 1.54 Add Intel AMT ports
155 | // 1.55 Remove exit() calls to simplify fuzzing
156 | // 1.56 Add basic HTML5/CSS support for javascript binaries
157 | // 1.57 Add termsaccepted value and further HTML tag tweaks
158 | // 1.58 Add memcache to list of default TCP ports
159 | // 1.59 Add memcache to list of default UDP ports
160 | // 1.60 Reduced logging option by default
161 | // 1.61 Additional JS version debugging
162 | // 1.62 Fixed logging typos
163 | // 1.63 Further client debug logging improvements
164 | // 1.64 Yet more client debug logging improvements
165 | // 1.65 signed/unsigned conflicts corrected
166 | // 1.66 extern redefined
167 | // 1.67 Debug-only build for client debug improvements
168 | // 1.68 Debug-only build for client debug improvements
169 | // 1.69 URL corrections
170 | // 1.70 Fixes for servers without UDP or SUID support
171 | // 1.71 Fixes for warnings raised by Semmle (re-entrant time functions)
172 | // 1.72 Minor HTML fixes - robots and optional icon support
173 | // plus javascript changes to remove eval()
174 | // 1.73 improved tidy_up_db() logging
175 | // 1.74 add missing logs for failed time_r conversions
176 | // 1.75 change text for initiations missing termsaccepted query
177 | // 1.76 add a separate debug build target,
178 | // improved client debug and copyright dates update
179 | // 1.77 Removed summarise_db() functionality - no longer used or desirable
180 | // 1.78 Add update_db to correctly handle test state logging
181 | // 1.79 Changes to use client determined starttime
182 | // 1.80 Additional debug for end-of-test checking
183 | // 1.81 Javascript improvements
184 | // 1.82 Add comments to disregard LGTM SQL injection false positives
185 | // 1.83 Further Javascript improvements
186 | // 1.84 Delete unused code, further Javascript improvements and remove LGTM pragmas
187 | // 1.85 define database delete wait-period separately
188 | // 1.86 Add some LGTM pragmas to hide cross-site scripting false positives
189 | // 1.87 Add some missing inet_ntop return-value checks,
190 | // further database debug and remove LGTM CGI cross-site scripting pragmas
191 | // 1.88 remove LGTM pragmas
192 | // 1.89 further User Agent validation
193 | // 1.90 Adjustments to help text and addition of TCP/20005 (KCodes NetUSB)
194 | // CVE-2021-45608
195 | // 1.91 Fix portlist size calculation and user-defined port value masking
196 | // 1.92 Move to consistent unsigned masks approach (for C, not generated Javscript)
197 | // 1.93 Update copyright year
198 | // 1.94 User-agent reporting improvements - only at scan initialisation, plus support
199 | // for Chrome UA strings
200 | // 1.95 Added count_rows_db() function to improve checking/reporting
201 | // 1.96 increase FETCHEVERY to 6s
202 | // 1.97 add a server timestamp to the database to fix an issue with client timestamps being wrong/offset
203 | // A database update is mandatory - see README.md for details.
204 |
205 | // ipscan Version Number
206 | #define IPSCAN_VERNUM "1.97"
207 |
208 | // ipscan type
209 | #if (TEXTMODE == 0)
210 | #define IPSCAN_VERTYPE "JS-"
211 | #else
212 | #define IPSCAN_VERTYPE "TXT-"
213 | #endif
214 |
215 | // Determine reported version string
216 | // and include a hint if parallel scanning (FAST) is enabled
217 | //
218 | #if (FAST == 1)
219 | #define IPSCAN_VERFAST "-FAST"
220 | #define IPSCAN_VER IPSCAN_VERTYPE IPSCAN_VERNUM IPSCAN_VERFAST
221 | #else
222 | #define IPSCAN_VER IPSCAN_VERTYPE IPSCAN_VERNUM
223 | #endif
224 | //
225 |
226 | //
227 | #define IPSCAN_H_VER IPSCAN_VERNUM
228 | //
229 |
230 | // Email address
231 | #define EMAILADDRESS "webmaster@chappell-family.com"
232 |
233 | // Determine whether to include terms of use link (0 = don't include; 1 = include)
234 | #define INCLUDETERMSOFUSE 1
235 | // Link for terms of use - please update to reference a page from your website
236 | #define TERMSOFUSEURL "https://wiki.chappell-family.com/wiki/index.php?title=Timswiki:About"
237 |
238 | // Determine whether to offer help for bad/incomplete/unrecognised URLs
239 | // 0=offer no help, 1=offer help - need to define URL
240 | #define IPSCAN_BAD_URL_HELP 1
241 | // The link that might provide some help ...
242 | #define IPSCAN_BAD_URL_LINK "https://wiki.chappell-family.com/wiki/index.php?title=ScanAutomation"
243 |
244 | // Determine whether to offer link for restart page if terms and conditions not accepted
245 | // 0=no offer, 1=offer - need to define URL too
246 | #define IPSCAN_TC_MISSING_LINK 1
247 | #define IPSCAN_TC_MISSING_LINK_URL "https://ipv6.chappell-family.com/ipv6tcptest/"
248 |
249 | // URL providing description special protocol tests
250 | #define IPSCAN_SPECIALTESTS_URL "https://wiki.chappell-family.com/wiki/index.php?title=IPv6_SpecialTests"
251 |
252 | // Interface name on which the test server listens
253 | // Note this is only used to determine the IPv6 address inserted in MPLS LSP Ping packets
254 | // and the Link-local address sent in DHCPv6 requests.
255 | #define IPSCAN_INTERFACE_NAME "eth0"
256 |
257 | // MySQL database-related globals
258 | #define MYSQL_HOST "localhost"
259 | #define MYSQL_USER "ipscan-user"
260 | #define MYSQL_PASSWD "ipscan-passwd"
261 | #define MYSQL_DBNAME "ipscan"
262 | #define MYSQL_TBLNAME "results"
263 |
264 | // MySQL - maximum number of rows expected per unique client session (IP/session/starttime)
265 | // expected maximum is TCP+UDP+ICMP+state
266 | // MUST be less than INT_MAX (so can add one futher) to return successfully from count_rows_db()
267 | #define IPSCAN_DB_MAX_EXPECTED_ROWS (999)
268 |
269 | // MySQL - use the InnoDB engine type by default
270 | // You can verify the engine type using:
271 | // mysql --user="ipscan-user" --password="ipscan-passwd" --host=localhost ipscan
272 | // SHOW TABLE STATUS WHERE Name = 'results';
273 | //
274 | // Steps for creating the MySQL database - this MUST be done before tests are performed!
275 | // -------------------------------------------------------------------------------------
276 | //
277 | // NB: adjust the user name, password and database name to match the globals you've edited above:
278 | //
279 | // mysql> create database ipscan;
280 | // Query OK, 1 row affected (0.00 sec)
281 | //
282 | // mysql> create user 'ipscan-user'@'localhost' identified by 'ipscan-passwd';
283 | // Query OK, 0 rows affected (0.01 sec)
284 | //
285 | // mysql> grant all privileges on ipscan.* to 'ipscan-user'@'localhost' identified by 'ipscan-passwd';
286 | // Query OK, 0 rows affected (0.01 sec)
287 | //
288 | // mysql> exit
289 | // Bye
290 | //
291 | // -------------------------------------------------------------------------------------
292 |
293 | // *************************************************************************************
294 | // * *
295 | // * Nothing below this line should need changing *
296 | // * *
297 | // *************************************************************************************
298 |
299 | // DEBUG build options - uncommenting these #defines will result in copious amounts of information
300 | // IMPORTANT NOTE: None of these debug options should be uncommented on internet-facing servers.
301 | //
302 | #if (DEBUG == 1)
303 | // Common options for testing - do NOT use in production
304 | #define IPSCAN_LOGVERBOSITY 3
305 | #define CLIENTDEBUG 1
306 | #endif
307 | //
308 | // database (NOT port scan results) related debug:
309 | // #define DBDEBUG 1
310 | //
311 | // database (port scan results) related debug:
312 | // #define DBPSRDEBUG 1
313 | //
314 | // ICMPv6 ping related debug:
315 | // #define PINGDEBUG 1
316 | //
317 | // Parallel processing related debug:
318 | // #define PARLLDEBUG 1
319 | //
320 | // UDP checks related debug:
321 | // #define UDPDEBUG 1
322 | //
323 | // UDP Parallel processing related debug:
324 | // #define UDPPARLLDEBUG 1
325 | //
326 | // Query string debug:
327 | // #define QUERYDEBUG 1
328 | //
329 | // Results debug:
330 | // #define RESULTSDEBUG 1
331 | //
332 | // Client (remote) debug - signalling, etc.
333 | // Primarily for troublesome Javascript clients.
334 | // #define CLIENTDEBUG 1
335 |
336 | // Decide whether to include ping support (requires setuid which some servers don't allow)
337 | // Do not modify this statement - adjust SETUID_AVAILABLE in the Makefile instead
338 | #ifndef SETUID_AVAILABLE
339 | #define IPSCAN_INCLUDE_PING 0
340 | #else
341 | #define IPSCAN_INCLUDE_PING SETUID_AVAILABLE
342 | #endif
343 |
344 | // Decide whether to include UDP support (access can be restricted on some servers)
345 | // Do not modify this statement - adjust UDP_AVAILABLE in the Makefile instead
346 | #ifndef UDP_AVAILABLE
347 | #define IPSCAN_INCLUDE_UDP 0
348 | #else
349 | #define IPSCAN_INCLUDE_UDP UDP_AVAILABLE
350 | #endif
351 |
352 | // Logging verbosity:
353 | //
354 | // (0) Quiet - program/unexpected response errors only
355 | // (1) Verbose - port scan summary of states is logged (ie number of ports of type OPEN, STLTH, RFSD, etc.)
356 | //
357 | // Do NOT change this value as your server's syslog may then contain personal information
358 | // which you need to obtain permission to capture in order to satisfy your GDPR obligations
359 | //
360 | // #define IPSCAN_LOGVERBOSITY 0
361 |
362 | // Magic number requesting the start of a scan
363 | #define MAGICBEGIN 123456
364 |
365 | // Maximum number of ports to be tested - this should exceed the sum of the default port list
366 | // and the allowed user-defined ports
367 | #define MAXPORTS ( DEFNUMPORTS + NUMUDPPORTS + NUMUSERDEFPORTS + 1 )
368 |
369 | // Define the min/max valid port ranges. This could be used to restrict testing (e.g. >= 1024)
370 | // as long as the default port list is updated as well
371 | #define MINVALIDPORT 0
372 | #define MAXVALIDPORT 65535
373 | #define VALIDPORTMASK ((unsigned)(65535))
374 |
375 | // Enable HTML5 for Javscript
376 | #define IPSCAN_HTML5_ENABLED 1
377 | // Maximum HTML5 body div width (pixels)
378 | #define IPSCAN_BODYDIV_WIDTH 800
379 |
380 | // Ensure IPSCAN_HTML5_ENABLED is defined
381 | #ifndef IPSCAN_HTML5_ENABLED
382 | #define IPSCAN_HTML5_ENABLED 0
383 | #endif
384 |
385 | // Call different HTML headers
386 | #if (IPSCAN_HTML5_ENABLED == 0)
387 | // Default to HTML 4.01
388 | #define HTML_HEADER() create_html_common_header()
389 | #else
390 | // Use HTML 5 everywhere
391 | #define HTML_HEADER() create_html5_common_header()
392 | #endif
393 |
394 | // Enable(1) or disable(0) favicon support
395 | #define IPSCAN_ICON_ENABLED 1
396 | // Icon type - common values include image/x-icon (.ico) and image/png (.png)
397 | #define IPSCAN_ICON_TYPE "image/x-icon"
398 | // Where to find your site icon
399 | #define IPSCAN_ICON_HREF "/favicon.ico"
400 |
401 | // Number of columns for HTML output:
402 | #define MAXCOLS 5
403 | #define COLUMNPCT (100/MAXCOLS)
404 |
405 | // Number of columns for UDP HTML output:
406 | #define MAXUDPCOLS 4
407 | #define COLUMNUDPPCT (100/MAXCOLS)
408 |
409 | // Number of columns for text-only browser output case
410 | #define TXTMAXCOLS 5
411 |
412 | // Number of columns per line in log outputs
413 | #define LOGMAXCOLS 4
414 |
415 | // Maximum size for buffer used to assemble log entries, 20 characters per "column" should be plenty
416 | #define LOGENTRYLEN (20* LOGMAXCOLS)
417 |
418 | // Number of octets per line in log outputs
419 | #define LOGMAXOCTETS 16
420 |
421 | // Maximum size for buffer used to assemble UDP packet debug entries
422 | #define LOGENTRYSIZE (64 + (4 * LOGMAXOCTETS))
423 |
424 | // Maximum number of octets of any UDP packet that can be logged when
425 | // in UDPDEBUG mode and IPSCAN_LOGVERBOSITY = 1
426 | #define UDPMAXLOGOCTETS 128
427 |
428 | // Maximum number of supported query parameters
429 | // Must ensure MAXQUERIES exceeds NUMUSERDEFPORTS by sufficient amount!
430 | #define MAXQUERIES 16
431 | #define MAXQUERYSTRLEN 255
432 | #define MAXQUERYNAMELEN 32
433 | #define MAXQUERYVALLEN 64
434 |
435 | // Maximum length of request-method string
436 | // should be one of GET, HEADER, POST, OPTIONS, etc. so 16 sufficient
437 | #define MAXREQMETHODLEN 16
438 |
439 | // Maximum length of HTTP_USER_AGENT string
440 | #define MAXUSERAGENTLEN 1024
441 |
442 | // Magic to convert from #defined integers to strings (used to protect sscanf)
443 | #define TOSTR1(i) #i
444 | #define TO_STR(i) TOSTR1(i)
445 |
446 | // Determine the executable CGI script filenames
447 | // These SHOULD be defined in the makefile, but provide some defaults in case
448 | #ifndef EXETXTNAME
449 | #define EXETXTNAME "ipscan-txt.cgi"
450 | #endif
451 | #ifndef EXEJSNAME
452 | #define EXEJSNAME "ipscan-js.cgi"
453 | #endif
454 | #ifndef EXEFASTTXTNAME
455 | #define EXETXTNAME "ipscan-fast-txt.cgi"
456 | #endif
457 | #ifndef EXEFASTJSNAME
458 | #define EXEJSNAME "ipscan-fast-js.cgi"
459 | #endif
460 |
461 |
462 | // Determine the executable file name
463 | #if (TEXTMODE == 1)
464 | #if (FAST == 1)
465 | #define EXENAME EXEFASTTXTNAME
466 | #else
467 | #define EXENAME EXETXTNAME
468 | #endif
469 | #else
470 | #if (FAST == 1)
471 | #define EXENAME EXEFASTJSNAME
472 | #else
473 | #define EXENAME EXEJSNAME
474 | #endif
475 | #endif
476 |
477 | // Served HTTP URI directory path - needs a leading /, but not a trailing one ...
478 | // This SHOULD be defined in the makefile, but provide a default here just in case
479 | #ifndef URIPATH
480 | #define URIPATH "/cgi-bin6"
481 | #endif
482 |
483 | // Maximum number of user-defined TCP ports
484 | // Must ensure MAXQUERIES exceeds NUMUSERDEFPORTS by sufficient amount!
485 | #define NUMUSERDEFPORTS 4
486 |
487 | // Logging prefix (goes into apache error_log or syslog)
488 | // #define LOGPREFIX EXENAME" : Version "IPSCAN_VER" : "
489 | #define LOGPREFIX
490 |
491 | //
492 | // Parallel port scanning related
493 | //
494 |
495 | // Determine the maximum number of children and therefore the maximum number of
496 | // port scans that can be running in parallel
497 | // Determine the maximum number of port scans that can be allocated to each child
498 | #if (FAST == 1)
499 | #define MAXCHILDREN 7
500 | #define MAXPORTSPERCHILD 9
501 | #else
502 | #define MAXCHILDREN 1
503 | #define MAXPORTSPERCHILD 9
504 | #endif
505 |
506 | // Determine the maximum number of children and therefore the maximum number of
507 | // UDP port scans that can be running in parallel
508 | // Determine the maximum number of UDP port scans that can be allocated to each child
509 | #if (FAST == 1)
510 | #define MAXUDPCHILDREN 3
511 | #define MAXUDPPORTSPERCHILD 3
512 | #else
513 | #define MAXUDPCHILDREN 1
514 | #define MAXUDPPORTSPERCHILD 9
515 | #endif
516 |
517 |
518 | //
519 | // Database related
520 | //
521 |
522 | // Determine the maximum length of the query-string which is used to insert and select
523 | // results into/out of the database. Currently queries are slightly in excess of 250 characters.
524 | #define MAXDBQUERYSIZE 512
525 |
526 | // Timeout for port response (in seconds)
527 | #define TIMEOUTSECS 1
528 | #define TIMEOUTMICROSECS 20000
529 |
530 | // Minimum time between ports (s)
531 | #define IPSCAN_MINTIME_PER_PORT 1
532 |
533 | // JSON fetch period (seconds) - tradeoff between update rate and webserver load
534 | #define JSONFETCHEVERY 6
535 |
536 | // ICMPv6 ECHO REQUEST packet size - suggest larger than 64 byte minimum is sensible, but as a minimum
537 | // needs to support magic string insertion anyway
538 | #define ICMPV6_PACKET_SIZE 128
539 |
540 | // Size to be allocated for transmit/receive buffer
541 | #define ICMPV6_PACKET_BUFFER_SIZE 2048
542 |
543 | // Magic constants intended to uniquify our packets;
544 | // process id and session start time are also included
545 | #define ICMPV6_MAGIC_SEQ 12478
546 | #define ICMPV6_MAGIC_VALUE1 1289
547 | #define ICMPV6_MAGIC_VALUE2 12569
548 |
549 | // UDP buffer size
550 | #define UDP_BUFFER_SIZE 512
551 |
552 | // UDP timeout (seconds) - needs to exceed UPnP/SSDP response request time (MX field) which is 1
553 | #define UDPTIMEOUTSECS 2
554 | #define UDPTIMEOUTMICROSECS 20000
555 |
556 | // An estimate of the time to perform the test - assumes num ports is always
557 | // smaller than (MAXPORTSPERCHILD * MAX_CHILDREN) for each protocol
558 | #define UDPSTATICTIME 2
559 | #define TCPSTATICTIME 2
560 | #define ICMP6STATICTIME 2
561 |
562 | #if (IPSCAN_INCLUDE_UDP == 1)
563 | #define UDPRUNTIME ((MAXUDPCHILDREN == 1) ? (numudpports * UDPTIMEOUTSECS + UDPSTATICTIME) : ( (numudpports > MAXUDPPORTSPERCHILD) ? (MAXUDPPORTSPERCHILD * UDPTIMEOUTSECS + UDPSTATICTIME) : ( numudpports * UDPTIMEOUTSECS + UDPSTATICTIME) ) )
564 | #else
565 | #define UDPRUNTIME 0
566 | #endif
567 |
568 | #define TCPRUNTIME ( (MAXCHILDREN == 1) ? (numports * TIMEOUTSECS + TCPSTATICTIME) : ( (numports > MAXPORTSPERCHILD) ? (MAXPORTSPERCHILD * TIMEOUTSECS + TCPSTATICTIME) : ( numports * TIMEOUTSECS + TCPSTATICTIME) ) )
569 | #define ICMP6RUNTIME (ICMP6STATICTIME + TIMEOUTSECS)
570 | #define ESTIMATEDTIMETORUN ( UDPRUNTIME + TCPRUNTIME + ICMP6RUNTIME )
571 |
572 | // NTP constants - setup as client (mode 3), unsynchronised, poll interval 8, precision 1 second
573 | #define NTP_LI 0
574 | #define NTP_VN 4
575 | #define NTP_MODE 3
576 | #define NTP_STRATUM 16
577 | #define NTP_POLL 8
578 | #define NTP_PRECISION 2
579 |
580 | // Protocol mappings (stored in database)
581 | // Port number (0-65535) stored in lowest 16 bits, 15-0
582 | // Special case tests indicated by value in bits 17-16
583 | // This allows multiple tests to be targetted at the same port
584 | #define IPSCAN_PORT_WIDTH (16U)
585 | #define IPSCAN_SPECIAL_WIDTH (2U)
586 | #define IPSCAN_PROTO_WIDTH (4U)
587 |
588 | #define IPSCAN_PORT_MASK ((unsigned)((1< this value
634 | //
635 | #define IPSCAN_DELETE_MINIMUM_TIME (1746449000)
636 |
637 | // TIDY UP - either delete everything in the database or 'just' results
638 | #define IPSCAN_DELETE_EVERYTHING (1)
639 | #define IPSCAN_DELETE_RESULTS_ONLY (0)
640 |
641 |
642 | // Flag indicating that the response was indirect rather than from the host under test
643 | // This may be the case if the host under test is behind a firewall or router
644 | #define IPSCAN_INDIRECT_RESPONSE 256
645 | // Mask to extract the response code - used in created Javascript
646 | #define IPSCAN_INDIRECT_MASK ((unsigned)255)
647 |
648 | // Completion indicators (passed in fetch querystring)
649 | //
650 | // IPSCAN_SUCCESSFUL_COMPLETION is used as a marker such that any query string fetch which
651 | // exceeds this value will be assumed to be indicating feedback from the javascript client
652 | //
653 | // IPSCAN_UNEXPECTED_CHANGE MUST be the last entry in the enumerated list
654 | //
655 | enum COMPLETIONSTATE
656 | {
657 | IPSCAN_SUCCESSFUL_COMPLETION = 990,
658 | IPSCAN_HTTPTIMEOUT_COMPLETION,
659 | IPSCAN_EVAL_ERROR,
660 | IPSCAN_OTHER_ERROR,
661 | IPSCAN_UNSUCCESSFUL_COMPLETION,
662 | IPSCAN_NAVIGATE_AWAY,
663 | IPSCAN_BAD_JSON_ERROR,
664 | IPSCAN_DB_ERROR,
665 | IPSCAN_UNEXPECTED_CHANGE,
666 | };
667 |
668 | //
669 | // TESTSTATE browser-signalled values - helps to debug javascript failures
670 | // Mapped to high values so they are all out of range of PORTSTATE
671 | //
672 | // Size of buffer holding the flag descriptions
673 | // Typically each flag is 11 characturs including trailing comma and space
674 | //
675 | #define IPSCAN_FLAGSBUFFER_SIZE (128)
676 | //
677 | #define IPSCAN_TESTSTATE_IDLE (0)
678 | #define IPSCAN_TESTSTATE_RUNNING_BIT (32)
679 | #define IPSCAN_TESTSTATE_COMPLETE_BIT (64)
680 | #define IPSCAN_TESTSTATE_HTTPTIMEOUT_BIT (128)
681 | #define IPSCAN_TESTSTATE_EVALERROR_BIT (256)
682 | #define IPSCAN_TESTSTATE_OTHERERROR_BIT (512)
683 | #define IPSCAN_TESTSTATE_NAVAWAY_BIT (1024)
684 | #define IPSCAN_TESTSTATE_UNEXPCHANGE_BIT (2048)
685 | #define IPSCAN_TESTSTATE_BADCOMPLETE_BIT (4096)
686 | #define IPSCAN_TESTSTATE_DATABASE_ERROR_BIT (8192)
687 |
688 | // Mapping for connection attempt results
689 | // To add a new entry first insert a new internal state in the PORTSTATE enumeration and then add a
690 | // matching entry in the results structure in ipscan.c
691 | // Both should be inserted before the unexpected/unknown, etc. entries
692 | enum PORTSTATE
693 | {
694 | PORTOPEN = 0,
695 | PORTABORT,
696 | PORTREFUSED,
697 | PORTCRESET,
698 | PORTNRESET,
699 | PORTINPROGRESS,
700 | PORTPROHIBITED,
701 | PORTUNREACHABLE,
702 | PORTNOROUTE,
703 | PORTPKTTOOBIG,
704 | PORTPARAMPROB,
705 | ECHONOREPLY,
706 | ECHOREPLY,
707 | /* Addition for UDP port respond/doesn't */
708 | UDPOPEN,
709 | UDPSTEALTH,
710 | /* Unexpected and Unknown error response cases, do NOT change */
711 | PORTUNEXPECTED,
712 | PORTUNKNOWN,
713 | PORTINTERROR,
714 | /* End of list marker, do NOT change */
715 | PORTEOL
716 | };
717 |
718 | // Determine the number of entries
719 | #define NUMRESULTTYPES PORTEOL
720 |
721 | // Results structure
722 | struct rslt_struc
723 | {
724 | int returnval;
725 | int connrc;
726 | int connerrno;
727 | char label[32];
728 | char colour[32];
729 | char description[384];
730 | };
731 |
732 | // Single definition of external : resultsstruct
733 | extern const struct rslt_struc resultsstruct[];
734 |
735 | // Default ports structure
736 | //
737 | // This constant defines the maximum port description size. Bear in mind, irrespective of the
738 | // description used in ipscan_portlist.h it also needs to support the text inserted for
739 | // user specified ports "User-specified: %d" (21 characters plus trailing \0), and so should not be
740 | // reduced below 22.
741 | #define PORTDESCSIZE 48
742 | //
743 | // the structure - consists of a port number, a "special case" indicator and a text description
744 | //
745 | struct portlist_struc
746 | {
747 | uint16_t port_num;
748 | uint8_t special;
749 | char port_desc[PORTDESCSIZE];
750 | };
751 |
752 | // End of defines
753 | #endif
754 |
--------------------------------------------------------------------------------
/ipscan_general.c:
--------------------------------------------------------------------------------
1 | // IPscan - an HTTP-initiated IPv6 port scanner.
2 | //
3 | // Copyright (C) 2011-2025 Tim Chappell.
4 | //
5 | // This file is part of IPscan.
6 | //
7 | // IPscan is free software: you can redistribute it and/or modify
8 | // it under the terms of the GNU General Public License as published by
9 | // the Free Software Foundation, either version 3 of the License, or
10 | // (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with IPscan. If not, see .
19 |
20 | // ipscan_general.c version
21 | // 0.01 - first released version
22 | // 0.02 - update copyright dates
23 | // 0.03 - slight logic change
24 | // 0.04 - update copyright dates
25 | // 0.05 - add proto_to_string()
26 | // 0.06 - add fetch_to_string()
27 | // 0.07 - add state_to_string()
28 | // 0.08 - add result_to_string()
29 | // 0.09 - update copyright dates
30 | // 0.10 - update copyright year
31 | // 0.11 - reorder entries to match definitions, add database error
32 | // 0.12 - update copyright year
33 | // 0.13 - moved to unsigned proto
34 | // 0.14 - update copyright year
35 | // 0.15 - add report_useragent_strings()
36 | // 0.16 - hide leading and trailing spaces
37 | // 0.17 - added flag values
38 | // 0.18 - added report_ipscan_versions()
39 | // 0.19 - CodeQL improvements
40 | // 0.20 - add querystring checkers
41 |
42 | //
43 | #define IPSCAN_GENERAL_VER "0.20"
44 | //
45 |
46 | #include "ipscan.h"
47 | //
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 | #include
56 | #include
57 | // toupper/tolower routines
58 | #include
59 |
60 | // Others that FreeBSD highlighted
61 | #include
62 |
63 | // IPv6 address conversion
64 | #include
65 |
66 | // String comparison
67 | #include
68 |
69 | // errors
70 | #include
71 |
72 | // Logging with syslog requires additional include
73 | #if (LOGMODE == 1)
74 | #include
75 | #endif
76 |
77 | //
78 | // report version
79 | //
80 | const char* ipscan_general_ver(void)
81 | {
82 | return IPSCAN_GENERAL_VER;
83 | }
84 | //
85 | // -----------------------------------------------------------------------------
86 | //
87 | uint64_t get_session(void)
88 | {
89 | uint64_t sessionnum = 0;
90 | uint64_t fetchedsession = 0;
91 | FILE *fp;
92 | fp = fopen("/dev/urandom", "r");
93 |
94 | if (NULL == fp)
95 | {
96 | sessionnum = (uint64_t)getpid();
97 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR : Cannot open /dev/urandom, %d (%s), defaulting session to getpid() = %"PRIu64"\n", errno, strerror(errno), sessionnum);
98 | }
99 | else
100 | {
101 | size_t numitems = fread( &fetchedsession, sizeof(fetchedsession), 1, fp);
102 | fclose(fp);
103 | if (1 == numitems)
104 | {
105 | // Clear the MSB of the random session ID so that we're sure it will fit
106 | // into an int64_t which the QUERY_STRING parser assumes
107 | sessionnum = fetchedsession & ( ((uint64_t)~0) >> 1);
108 |
109 | #ifdef QUERYDEBUG
110 | IPSCAN_LOG( LOGPREFIX "ipscan: Session number modification check, before = %"PRIu64" after = %"PRIu64"\n", fetchedsession, sessionnum);
111 | #endif
112 | }
113 | else
114 | {
115 | sessionnum = (uint64_t)getpid();
116 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR : Cannot read /dev/urandom, defaulting session to getpid() = %"PRIu64"\n", sessionnum);
117 | }
118 | }
119 | return (sessionnum);
120 | }
121 |
122 | //
123 | // -----------------------------------------------------------------------------
124 | //
125 | void proto_to_string(uint32_t proto, char * retstring)
126 | {
127 | int rc = 0;
128 | switch (proto)
129 | {
130 | case IPSCAN_PROTO_TCP:
131 | rc = snprintf(retstring, IPSCAN_PROTO_STRING_MAX, "%s", "TCPv6");
132 | break;
133 |
134 | case IPSCAN_PROTO_UDP:
135 | rc = snprintf(retstring, IPSCAN_PROTO_STRING_MAX, "%s", "UDPv6");
136 | break;
137 |
138 | case IPSCAN_PROTO_ICMPV6:
139 | rc = snprintf(retstring, IPSCAN_PROTO_STRING_MAX, "%s", "ICMPv6");
140 | break;
141 |
142 | case IPSCAN_PROTO_TESTSTATE:
143 | rc = snprintf(retstring, IPSCAN_PROTO_STRING_MAX, "%s", "TESTSTATE");
144 | break;
145 |
146 | default:
147 | rc = snprintf(retstring, IPSCAN_PROTO_STRING_MAX, "%s", "UNDEFINED");
148 | break;
149 |
150 | }
151 | // Report error - does IPSCAN_PROTO_STRING_MAX need increasing?
152 | if (rc < 0 || rc >= IPSCAN_PROTO_STRING_MAX)
153 | {
154 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR : Cannot fit protocol string into buffer, returned %d\n", rc);
155 | }
156 | return;
157 | }
158 |
159 | //
160 | // -----------------------------------------------------------------------------
161 | //
162 | void fetch_to_string(int fetchnum, char * retstring)
163 | {
164 | int rc;
165 | if (IPSCAN_SUCCESSFUL_COMPLETION == fetchnum)
166 | {
167 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "SUCCESSFUL");
168 | }
169 | else if (IPSCAN_HTTPTIMEOUT_COMPLETION == fetchnum)
170 | {
171 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "HTTP-TIMEOUT");
172 | }
173 | else if (IPSCAN_EVAL_ERROR == fetchnum)
174 | {
175 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "EVAL ERROR");
176 | }
177 | else if (IPSCAN_OTHER_ERROR == fetchnum)
178 | {
179 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "OTHER ERROR");
180 | }
181 | else if (IPSCAN_UNSUCCESSFUL_COMPLETION == fetchnum)
182 | {
183 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "UNSUCCESSFUL");
184 | }
185 | else if (IPSCAN_NAVIGATE_AWAY == fetchnum)
186 | {
187 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "NAVIGATEAWAY");
188 | }
189 | else if (IPSCAN_BAD_JSON_ERROR == fetchnum)
190 | {
191 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "BAD JSON ERR");
192 | }
193 | else if (IPSCAN_DB_ERROR == fetchnum)
194 | {
195 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "DATABASE ERR");
196 | }
197 | else if (IPSCAN_UNEXPECTED_CHANGE == fetchnum)
198 | {
199 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s", "UNEXP CHANGE");
200 | }
201 | else
202 | {
203 | rc = snprintf(retstring, IPSCAN_FETCHNUM_STRING_MAX, "%s:%d", "UNKNOWN", fetchnum);
204 | }
205 | // Report error - does IPSCAN_FETCHNUM_STRING_MAX need increasing?
206 | if (rc < 0 || rc >= IPSCAN_FETCHNUM_STRING_MAX)
207 | {
208 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR : Cannot fit fetchnum string into buffer, returned %d\n", rc);
209 | }
210 |
211 | return;
212 | }
213 |
214 |
215 | //
216 | // -----------------------------------------------------------------------------
217 | //
218 | char * state_to_string(int statenum, char * retstringptr, int retstringfree)
219 | {
220 | if (0 >= retstringfree) return (char *)NULL;
221 | char * retstringptrstart = retstringptr;
222 | int rc = 0;
223 | rc = snprintf(retstringptr, retstringfree, "%s", "flags: ");
224 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
225 | retstringptr += rc;
226 | retstringfree -= rc;
227 |
228 | if (0 != (statenum & PORTUNKNOWN))
229 | {
230 | rc = snprintf(retstringptr, retstringfree, "%s", "UNKNOWN, ");
231 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
232 | retstringptr += rc;
233 | retstringfree -= rc;
234 | }
235 | if (0 != (statenum & IPSCAN_TESTSTATE_RUNNING_BIT))
236 | {
237 | rc = snprintf(retstringptr, retstringfree, "%s", "RUNNING, ");
238 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
239 | retstringptr += rc;
240 | retstringfree -= rc;
241 | }
242 | if (0 != (statenum & IPSCAN_TESTSTATE_COMPLETE_BIT))
243 | {
244 | rc = snprintf(retstringptr, retstringfree, "%s", "COMPLETE, ");
245 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
246 | retstringptr += rc;
247 | retstringfree -= rc;
248 | }
249 | if (0 != (statenum & IPSCAN_TESTSTATE_HTTPTIMEOUT_BIT))
250 | {
251 | rc = snprintf(retstringptr, retstringfree, "%s", "TIMEOUT, ");
252 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
253 | retstringptr += rc;
254 | retstringfree -= rc;
255 | }
256 | if (0 != (statenum & IPSCAN_TESTSTATE_EVALERROR_BIT))
257 | {
258 | rc = snprintf(retstringptr, retstringfree, "%s", "EVALERROR, ");
259 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
260 | retstringptr += rc;
261 | retstringfree -= rc;
262 | }
263 | if (0 != (statenum & IPSCAN_TESTSTATE_OTHERERROR_BIT))
264 | {
265 | rc = snprintf(retstringptr, retstringfree, "%s", "OTHERERROR, ");
266 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
267 | retstringptr += rc;
268 | retstringfree -= rc;
269 | }
270 | if (0 != (statenum & IPSCAN_TESTSTATE_NAVAWAY_BIT))
271 | {
272 | rc = snprintf(retstringptr, retstringfree, "%s", "NAVAWAY, ");
273 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
274 | retstringptr += rc;
275 | retstringfree -= rc;
276 | }
277 | if (0 != (statenum & IPSCAN_TESTSTATE_UNEXPCHANGE_BIT))
278 | {
279 | rc = snprintf(retstringptr, retstringfree, "%s", "UNEXPECTED, ");
280 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
281 | retstringptr += rc;
282 | retstringfree -= rc;
283 | }
284 | if (0 != (statenum & IPSCAN_TESTSTATE_BADCOMPLETE_BIT))
285 | {
286 | rc = snprintf(retstringptr, retstringfree, "%s", "BADCOMPLETE, ");
287 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
288 | retstringptr += rc;
289 | retstringfree -= rc;
290 | }
291 | if (0 != (statenum & IPSCAN_TESTSTATE_DATABASE_ERROR_BIT))
292 | {
293 | rc = snprintf(retstringptr, retstringfree, "%s", "DB ERROR, ");
294 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
295 | retstringptr += rc;
296 | retstringfree -= rc;
297 | }
298 | rc = snprintf(retstringptr, retstringfree, "%s", "\n\0");
299 | if (rc < 0 || rc >= retstringfree) return (char *)NULL;
300 | retstringptr += rc;
301 | retstringfree -= rc;
302 | if (0 > retstringfree) return (char *)NULL;
303 | return retstringptrstart;
304 | }
305 |
306 |
307 | //
308 | // -----------------------------------------------------------------------------
309 | //
310 | void result_to_string(int result, char * retstring)
311 | {
312 | int rc;
313 | char hosttype[16];
314 | if (IPSCAN_INDIRECT_RESPONSE <= result)
315 | {
316 | result -= IPSCAN_INDIRECT_RESPONSE;
317 | strncpy(hosttype, "indirect:", 15);
318 | }
319 | else
320 | {
321 | strncpy(hosttype, "", 15);
322 | }
323 |
324 | if (PORTOPEN == result)
325 | {
326 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "OPEN");
327 | }
328 | else if (PORTABORT == result)
329 | {
330 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "ABORT");
331 | }
332 | else if (PORTREFUSED == result)
333 | {
334 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "REFUSED");
335 | }
336 | else if (PORTCRESET == result)
337 | {
338 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "CRESET");
339 | }
340 | else if (PORTNRESET == result)
341 | {
342 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "NRESET");
343 | }
344 | else if (PORTINPROGRESS == result)
345 | {
346 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "IN-PROGRESS");
347 | }
348 | else if (PORTPROHIBITED == result)
349 | {
350 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "PROHIBITED");
351 | }
352 | else if (PORTUNREACHABLE == result)
353 | {
354 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "UNREACHABLE");
355 | }
356 | else if (PORTNOROUTE == result)
357 | {
358 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "NO ROUTE");
359 | }
360 | else if (PORTPKTTOOBIG == result)
361 | {
362 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "PKT TOO BIG");
363 | }
364 | else if (PORTPARAMPROB == result)
365 | {
366 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "PARAM PROBLEM");
367 | }
368 | else if (ECHONOREPLY == result)
369 | {
370 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "ECHO NO-REPLY");
371 | }
372 | else if (ECHOREPLY == result)
373 | {
374 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "ECHO REPLY");
375 | }
376 | else if (UDPOPEN == result)
377 | {
378 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "UDP OPEN");
379 | }
380 | else if (UDPSTEALTH == result)
381 | {
382 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "UDP STEALTH");
383 | }
384 | else if (PORTUNEXPECTED == result)
385 | {
386 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "UNEXPECTED");
387 | }
388 | else if (PORTUNKNOWN == result)
389 | {
390 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "UNKNOWN");
391 | }
392 | else if (PORTINTERROR == result)
393 | {
394 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "INTERNAL ERROR");
395 | }
396 | else if (PORTEOL == result)
397 | {
398 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s%s", hosttype, "");
399 | }
400 | else
401 | {
402 | rc = snprintf(retstring, IPSCAN_RESULT_STRING_MAX, "%s-%s:%d", "", hosttype, result);
403 | }
404 | // Report error - does IPSCAN_RESULT_STRING_MAX need increasing?
405 | if (rc < 0 || rc >= IPSCAN_RESULT_STRING_MAX)
406 | {
407 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR : Cannot fit result string into buffer, returned %d\n", rc);
408 | }
409 |
410 | return;
411 | }
412 |
413 | //
414 | // -----------------------------------------------------------------------------
415 | //
416 | void report_agent_string(char * agentstringvar, const char *varname, unsigned int error1ignore0)
417 | {
418 | // Note that none of this content can be trusted - so agressively limit the character set
419 | char agentstring[ (MAXUSERAGENTLEN + 1) ];
420 | unsigned int i;
421 | // Pre-clear array since using sscanf with %Nc doesn't guarantee string will be 0 terminated
422 | memset(agentstring, 0, sizeof(agentstring));
423 |
424 | if ( NULL == agentstringvar )
425 | {
426 | if (1 == error1ignore0)
427 | {
428 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR : %s variable lookup returned NULL.\n", varname);
429 | }
430 | }
431 | else if ( strnlen(agentstringvar, (MAXUSERAGENTLEN+1)) > MAXUSERAGENTLEN )
432 | {
433 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR: %s variable string is longer than allocated buffer (%d > %d)\n", varname,\
434 | (int)strnlen(agentstringvar, (MAXUSERAGENTLEN+1)), MAXUSERAGENTLEN);
435 | }
436 | else if ( sscanf(agentstringvar,"%"TO_STR(MAXUSERAGENTLEN)"c",agentstring) != EOF )
437 | {
438 | if (strnlen(agentstring, MAXUSERAGENTLEN+1) > MAXUSERAGENTLEN)
439 | {
440 | agentstring[0] = 0; // truncate string
441 | }
442 | else
443 | {
444 | for ( i = 0 ; i < strnlen(agentstring, MAXUSERAGENTLEN+1) ; i++ )
445 | {
446 | // Clamp to printable ASCII range - but ensure 0 is not corrupted
447 | if ( (agentstring[i] > 0 && agentstring[i] < 32) || agentstring[i] > 126 ) agentstring[i] = 32;
448 | // and also protect against special characters which could be used for XSS
449 | switch (agentstring[i])
450 | {
451 | case '<':
452 | case '>':
453 | case ':':
454 | case ';':
455 | case '&':
456 | case '\\':
457 | case '\"':
458 | case '/':
459 | case '=':
460 | case '*':
461 | case ',':
462 | case '^':
463 | case '$':
464 | case '|':
465 | case '%':
466 | case '{':
467 | case '}':
468 | case '!':
469 | case '[':
470 | case ']':
471 | case '?':
472 | agentstring[i] = ' ';
473 | break;
474 |
475 | default:
476 | // do nothing
477 | break;
478 | }
479 | }
480 | }
481 | size_t left = 0;
482 | size_t right = strnlen(agentstring,MAXUSERAGENTLEN+1);
483 | if (MAXUSERAGENTLEN < right)
484 | {
485 | // no end-of-string '0' found, so insert one
486 | agentstring[MAXUSERAGENTLEN] = 0;
487 | right = strnlen(agentstring,MAXUSERAGENTLEN+1);
488 | }
489 | // skip left-leading spaces
490 | while (left < right && left < MAXUSERAGENTLEN && agentstring[left]==' ')
491 | {
492 | left++;
493 | }
494 | // truncate right-trailing spaces and zeroes
495 | while ((agentstring[right]==' ' || agentstring[right]==0) && right > left && right > 0)
496 | {
497 | agentstring[right] = 0;
498 | right--;
499 | }
500 | IPSCAN_LOG( LOGPREFIX "ipscan: INFO: %s = '%s'\n", varname, &agentstring[left]);
501 | }
502 | else
503 | {
504 | IPSCAN_LOG( LOGPREFIX "ipscan: ERROR: %s variable not reportable.\n", varname);
505 | }
506 | }
507 |
508 | //
509 | // -----------------------------------------------------------------------------
510 | //
511 | void report_useragent_strings(char *uavar, char *secchuavar, char *secchuaarchvar, char *secchuaarchplatvar)
512 | {
513 | // Note that content cannot be trusted - so agressively limit the character set
514 | report_agent_string(uavar, "HTTP_USER_AGENT", 1);
515 | report_agent_string(secchuavar, "HTTP_SEC_CH_UA", 0);
516 | report_agent_string(secchuaarchvar, "HTTP_SEC_CH_UA_ARCH", 0);
517 | report_agent_string(secchuaarchplatvar, "HTTP_SEC_CH_UA_PLATFORM", 0);
518 | }
519 |
520 | //
521 | // -----------------------------------------------------------------------------
522 | //
523 | void report_ipscan_versions(const char *mainver, const char *generalver, const char *tcpver, const char *udpver, const char *icmpv6ver, const char *dbver,\
524 | const char *webver, const char *hver, const char *plver)
525 | {
526 | IPSCAN_LOG( LOGPREFIX "ipscan: INFO: IPSCAN_MAIN_VER = %-4s, IPSCAN_GENERAL_VER = %-4s, IPSCAN_WEB_VER = %-4s, IPSCAN_H_VER = %-4s\n", mainver, generalver, webver, hver);
527 | IPSCAN_LOG( LOGPREFIX "ipscan: INFO: IPSCAN_TCP_VER = %-4s, IPSCAN_UDP_VER = %-4s, IPSCAN_ICMPV6_VER = %-4s, IPSCAN_DB_VER = %-4s\n", tcpver, udpver, icmpv6ver, dbver);
528 | IPSCAN_LOG( LOGPREFIX "ipscan: INFO: IPSCAN_PORTLIST_VER = %-4s\n", plver);
529 | }
530 |
531 | //
532 | // -----------------------------------------------------------------------------
533 | //
534 | int querystring_is_alphanum(char check)
535 | {
536 | int retval = 0;
537 | // allow a-z,0-9
538 | if ((check >= 'a' && check <= 'z') || (check >= '0' && check <= '9'))
539 | {
540 | retval = 1;
541 | }
542 | return (retval);
543 | }
544 |
545 | //
546 | // -----------------------------------------------------------------------------
547 | //
548 | int querystring_is_valid(char check)
549 | {
550 | int retval = 0;
551 | // allow &,=,a-z,0-9,+,-
552 | if (check == '&' || check == '=' || (check >= 'a' && check <= 'z') || (check >= '0' && check <= '9') || check == '+' || check == '-')
553 | {
554 | retval = 1;
555 | }
556 | return (retval);
557 | }
558 |
559 | //
560 | // -----------------------------------------------------------------------------
561 | //
562 | int querystring_is_number(char check)
563 | {
564 | int retval = 0;
565 | // allow 0-9,+,-
566 | if ( (check >= '0' && check <= '9') || check == '+' || check == '-' )
567 | {
568 | retval = 1;
569 | }
570 | return (retval);
571 | }
572 |
573 |
--------------------------------------------------------------------------------
/ipscan_icmpv6.c:
--------------------------------------------------------------------------------
1 | // IPscan - an HTTP-initiated IPv6 port scanner.
2 | //
3 | // Copyright (C) 2011-2025 Tim Chappell.
4 | //
5 | // This file is part of IPscan.
6 | //
7 | // IPscan is free software: you can redistribute it and/or modify
8 | // it under the terms of the GNU General Public License as published by
9 | // the Free Software Foundation, either version 3 of the License, or
10 | // (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with IPscan. If not, see .
19 |
20 | // ipscan_icmpv6.c version
21 | // 0.1 initial version after splitting from ipscan_checks.c
22 | // 0.2 add prefixes to debug log output
23 | // 0.3 move to memset()
24 | // 0.4 ensure minimum timings are met
25 | // 0.5 ensure txid doesn't exceed 16-bits (move to random session ID)
26 | // 0.6 clear msghdr.msg_flags
27 | // 0.7 add time() checks
28 | // 0.8 update copyright year
29 | // 0.9 update copyright year
30 | // 0.10 update copyright year
31 | // 0.11 extern no longer defined here
32 | // 0.12 correct signedness of sprintf/sscanf used for packet data
33 | // 0.13 update copyright year
34 | // 0.14 swap comparison terms, where appropriate
35 | // 0.15 delete old comments, update copyright year
36 | // 0.16 add missing error checks for inet_ntop calls
37 | // 0.17 and snprintf for router too
38 | // 0.18 update copyright year
39 | // 0.19 update copyright year
40 | // 0.20 add (potentially) missing length check
41 |
42 | //
43 | #define IPSCAN_ICMPV6_VER "0.20"
44 | //
45 |
46 | #include "ipscan.h"
47 | //
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 | #include
56 | #include
57 | #include
58 |
59 | // IPv6 address conversion
60 | #include
61 |
62 | // String comparison
63 | #include
64 |
65 | // Logging with syslog requires additional include
66 | #if (LOGMODE == 1)
67 | #include
68 | #endif
69 |
70 | // Others that FreeBSD highlighted
71 | #include
72 | #include
73 | #include
74 |
75 | // Other IPv6 related
76 | #include
77 | #include
78 |
79 | //Poll support
80 | #include
81 |
82 | // Define offset into ICMPv6 packet where user-defined data resides
83 | #define ICMP6DATAOFFSET sizeof(struct icmp6_hdr)
84 |
85 | //
86 | // report version
87 | //
88 | const char* ipscan_icmpv6_ver(void)
89 | {
90 | return IPSCAN_ICMPV6_VER;
91 | }
92 |
93 | //
94 | // Send an ICMPv6 ECHO-REQUEST and see whether we receive an ECHO-REPLY in response
95 | //
96 |
97 | uint32_t check_icmpv6_echoresponse(char * hostname, uint64_t starttime, uint64_t session, char * router)
98 | {
99 | struct addrinfo *res;
100 | struct addrinfo hints;
101 |
102 | struct sockaddr_in6 destination;
103 | struct sockaddr_in6 source;
104 |
105 | int sock = -1;
106 | int errsv;
107 | int rc;
108 | int error;
109 | unsigned int sendsize;
110 | const char * rccharptr;
111 |
112 | struct timeval timeout;
113 |
114 | struct icmp6_hdr *txicmp6hdr_ptr;
115 | struct icmp6_hdr *rxicmp6hdr_ptr;
116 |
117 | struct icmp6_filter myfilter;
118 | // reply tracker
119 | unsigned int foundit = 0;
120 |
121 | // send and receive message headers
122 | struct msghdr smsghdr;
123 | struct msghdr rmsghdr;
124 | struct iovec txiov[2], rxiov[2];
125 | char txpackdata[ICMPV6_PACKET_BUFFER_SIZE];
126 | char rxpackdata[ICMPV6_PACKET_BUFFER_SIZE];
127 | char *rxpacket = &rxpackdata[0];
128 | char rxbuf[ICMPV6_PACKET_BUFFER_SIZE];
129 | char tmpbuf[128];
130 |
131 | // set return value to a known default
132 | int retval = PORTUNKNOWN;
133 |
134 | txicmp6hdr_ptr = (struct icmp6_hdr *)txpackdata;
135 |
136 | struct pollfd pollfiledesc[1];
137 |
138 | unsigned int txid = (unsigned int)(session & 0xFFFF); // Maximum 16 bits
139 | unsigned int rxid;
140 | unsigned int txseqno = ICMPV6_MAGIC_SEQ; // MAGIC number - assume no reason to start at 1?
141 | unsigned int rxseqno;
142 |
143 | unsigned int rxicmp6_type, rxicmp6_code;
144 |
145 | memset(&hints, 0, sizeof(hints));
146 | hints.ai_family = AF_INET6;
147 | hints.ai_flags = AI_CANONNAME;
148 | hints.ai_socktype = SOCK_RAW;
149 | hints.ai_protocol = IPPROTO_ICMPV6;
150 |
151 | error = getaddrinfo(hostname, NULL, &hints, &res);
152 | if (error != 0)
153 | {
154 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: getaddrinfo: failed1 %s for host %s\n", gai_strerror(error), hostname);
155 | return (PORTINTERROR);
156 | }
157 |
158 | if (!res->ai_addr)
159 | {
160 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: getaddrinfo: failed2 %s for host %s\n",gai_strerror(error), hostname);
161 | freeaddrinfo(res);
162 | return (PORTINTERROR);
163 | }
164 |
165 | // Copy the resulting address into our destination if there is sufficient room
166 | memset(&destination, 0, sizeof(struct sockaddr_in6));
167 | if (res->ai_addrlen <= sizeof(struct sockaddr_in6))
168 | {
169 | memcpy(&destination, res->ai_addr, res->ai_addrlen);
170 | }
171 | // Done with the address info now, so free the area
172 | freeaddrinfo(res);
173 |
174 | // Set default logged router address to dead::1 (valid format IPv6 address)
175 | rc = snprintf(router, INET6_ADDRSTRLEN, "dead::1");
176 | if (rc < 0 || rc >= INET6_ADDRSTRLEN)
177 | {
178 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Failed to unset logged router address, rc was %d\n", rc);
179 | memset(router, 0, INET6_ADDRSTRLEN);
180 | retval = PORTINTERROR;
181 | }
182 |
183 | // Get root privileges in order to create the raw socket
184 |
185 | uid_t uid = getuid();
186 | uid_t gid = getgid();
187 |
188 | #ifdef PINGDEBUG
189 | uid_t euid = geteuid();
190 | uid_t egid = getegid();
191 | #endif
192 |
193 | #ifdef PINGDEBUG
194 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Entered with real UID %d real GID %d effective UID %d effective GID %d\n", uid, gid, euid, egid);
195 | #endif
196 |
197 | rc = setuid(0);
198 | if (rc != 0)
199 | {
200 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: setuid: failed to gain root privileges - is setuid permission set?\n");
201 | retval = PORTINTERROR;
202 | }
203 |
204 | rc = setgid(0);
205 | if (rc != 0)
206 | {
207 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: setgid: failed to gain root privileges - is setgid permission set?\n");
208 | retval = PORTINTERROR;
209 | }
210 |
211 | // run with ROOT privileges, keep section to a minimum
212 | if (PORTUNKNOWN == retval)
213 | {
214 | sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
215 | errsv = errno;
216 | if (sock < 0)
217 | {
218 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: socket: Error : %s (%d) for host %s\n", strerror(errsv), errsv, hostname);
219 | retval = PORTINTERROR;
220 | }
221 | else
222 | {
223 | memset(&timeout, 0, sizeof(timeout));
224 | timeout.tv_sec = TIMEOUTSECS;
225 | timeout.tv_usec = TIMEOUTMICROSECS;
226 |
227 | rc = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
228 | errsv = errno;
229 | if (rc < 0)
230 | {
231 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Bad setsockopt SO_SNDTIMEO set, returned %d (%s)\n", errsv, strerror(errsv));
232 | retval = PORTINTERROR;
233 | }
234 |
235 | memset(&timeout, 0, sizeof(timeout));
236 | timeout.tv_sec = TIMEOUTSECS;
237 | timeout.tv_usec = TIMEOUTMICROSECS;
238 |
239 | rc = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
240 | errsv = errno;
241 | if (rc < 0)
242 | {
243 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Bad setsockopt SO_RCVTIMEO set, returned %d (%s)\n", errsv, strerror(errsv));
244 | retval = PORTINTERROR;
245 | }
246 |
247 | // Filter out everything except the responses we're looking for
248 | // taken from RFC3542
249 | ICMP6_FILTER_SETBLOCKALL(&myfilter);
250 | ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &myfilter);
251 | ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &myfilter);
252 | ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &myfilter);
253 | ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &myfilter);
254 | ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &myfilter);
255 | rc = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &myfilter, sizeof(myfilter));
256 | errsv = errno;
257 | if (rc < 0)
258 | {
259 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: setsockopt: Error setting ICMPv6 filter: %s (%d)\n", strerror(errsv), errsv);
260 | retval = PORTINTERROR;
261 | }
262 |
263 | #ifdef PINGDEBUG
264 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Exiting privileged user code section\n");
265 | #endif
266 |
267 | } // end if (socket created successfully)
268 | }
269 |
270 | // END OF ROOT PRIVILEGES - Revert to previous privilege level
271 | rc = setgid(gid);
272 | if (rc != 0)
273 | {
274 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: setgid: failed to revoke root gid privileges\n");
275 | retval = PORTINTERROR;
276 | }
277 |
278 | rc = setuid(uid);
279 | if (rc != 0)
280 | {
281 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: setuid: failed to revoke root uid privileges\n");
282 | retval = PORTINTERROR;
283 | }
284 |
285 | // If something bad has happened then return now ...
286 | // mustn't return to caller with root privileges, hence done here ...
287 | if (PORTUNKNOWN != retval)
288 | {
289 | if (-1 != sock) close(sock); // close socket if appropriate
290 | return(retval);
291 | }
292 |
293 | #ifdef PINGDEBUG
294 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Post-revoke real UID %d real GID %d effective UID %d effective GID %d\n", getuid (), getgid (), geteuid(), getegid());
295 | #endif
296 |
297 | // -----------------------------------------------
298 | //
299 | // ICMPv6 ECHO-REQUEST TRANSMIT
300 | //
301 | // -----------------------------------------------
302 |
303 | memset( txicmp6hdr_ptr, 0, sizeof(struct icmp6_hdr));
304 | txicmp6hdr_ptr->icmp6_cksum = 0;
305 | txicmp6hdr_ptr->icmp6_type = ICMP6_ECHO_REQUEST;
306 | txicmp6hdr_ptr->icmp6_code = 0;
307 | txicmp6hdr_ptr->icmp6_id = htons(txid);
308 | txicmp6hdr_ptr->icmp6_seq = htons(txseqno);
309 |
310 | // socket address
311 | memset(&smsghdr, 0, sizeof(smsghdr));
312 | smsghdr.msg_name = (caddr_t)&destination;
313 | smsghdr.msg_namelen = sizeof(destination);
314 |
315 | // Insert the unique data
316 | #ifdef PINGDEBUG
317 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Sending PING unique data starttime=%"PRId64" session=%"PRId64"\n", starttime, session);
318 | #endif
319 |
320 | rc = snprintf(&txpackdata[ICMP6DATAOFFSET],(ICMPV6_PACKET_SIZE-ICMP6DATAOFFSET),"%"PRIu64" %"PRIu64" %u %u", starttime, session, ICMPV6_MAGIC_VALUE1, ICMPV6_MAGIC_VALUE2);
321 | if (rc < (int)0 || rc >= (int)(ICMPV6_PACKET_SIZE-ICMP6DATAOFFSET))
322 | {
323 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: txpackdata snprintf returned %d, expected >=0 but < %d\n", rc, (int)(ICMPV6_PACKET_SIZE-ICMP6DATAOFFSET));
324 | retval = PORTINTERROR;
325 | if (-1 != sock) close(sock); // close socket if appropriate
326 | return(retval);
327 | }
328 |
329 | // Choose a packet slightly bigger than minimum size
330 | sendsize = ICMPV6_PACKET_SIZE;
331 |
332 | rc = getnameinfo((struct sockaddr *)&destination, sizeof(destination), tmpbuf, sizeof(tmpbuf), NULL, 0, NI_NUMERICHOST);
333 | errsv = errno;
334 | if (0 == rc)
335 | {
336 | #ifdef PINGDEBUG
337 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Transmitted destination address was %s\n", tmpbuf);
338 | #endif
339 | }
340 | else
341 | {
342 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: RESTART: getnameinfo returned bad indication %d (%s)\n",errsv, gai_strerror(errsv));
343 | retval = PORTINTERROR;
344 | if (-1 != sock) close(sock); // close socket if appropriate
345 | return(retval);
346 | }
347 |
348 | // scatter/gather array
349 | memset(&txiov, 0, sizeof(txiov));
350 | txiov[0].iov_base = (caddr_t)&txpackdata;
351 | txiov[0].iov_len = sendsize;
352 | smsghdr.msg_iov = txiov;
353 | smsghdr.msg_iovlen = 1;
354 |
355 | rc = sendmsg(sock, &smsghdr, 0);
356 | errsv = errno;
357 |
358 | if (rc < 0)
359 | {
360 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: sendmsg returned error, with errno %d (%s)\n", errsv, strerror(errsv));
361 | retval = PORTINTERROR;
362 | if (-1 != sock) close(sock); // close socket if appropriate
363 | return(retval);
364 | }
365 |
366 | if (rc != (int)sendsize)
367 | {
368 | IPSCAN_LOG( LOGPREFIX"check_icmpv6_echoresponse: requested sendmsg sent %d chars to %s but sendmsg returned %d\n", sendsize, hostname, rc);
369 | retval = PORTINTERROR;
370 | if (-1 != sock) close(sock); // close socket if appropriate
371 | return(retval);
372 | }
373 |
374 | // -----------------------------------------------
375 | //
376 | // // ICMPv6 ECHO-REPLY RECEIVE
377 | //
378 | // -----------------------------------------------
379 |
380 | // indirect determines whether a host other than the intended target has replied
381 | int indirect = 0;
382 | time_t timestart = time(0);
383 | if (timestart < 0)
384 | {
385 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ERROR: time() returned bad value for timestart %d (%s)\n", errno, strerror(errno));
386 | }
387 | time_t timenow = timestart;
388 | unsigned int loopcount = 0;
389 |
390 | // Effectively a promiscuous receive of ICMPv6 packets, so need to discern which are for us
391 | // ... may need to go round this loop more than once ...
392 |
393 | while ( ((timenow - timestart) <= 1+TIMEOUTSECS) && foundit == 0)
394 | {
395 | loopcount++;
396 | #ifdef PINGDEBUG
397 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Beginning time %d through the loop.\n", loopcount);
398 | #endif
399 |
400 | pollfiledesc[0].fd = sock;
401 | // Want indication that there is something to read
402 | pollfiledesc[0].events = POLLIN;
403 | rc = poll(pollfiledesc, 1, 1000*TIMEOUTSECS);
404 | errsv = errno;
405 | // Capture current time for next timeout comparison
406 | timenow = time(0);
407 | if (timenow < 0)
408 | {
409 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ERROR: time() returned bad value for timenow %d (%s)\n", errno, strerror(errno));
410 | }
411 |
412 | if (rc < 0)
413 | {
414 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: RESTART: poll returned bad things : %d (%s)\n", errsv, strerror(errsv));
415 | continue;
416 | }
417 | else if (rc == 0)
418 | {
419 | #ifdef PINGDEBUG
420 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: RESTART: poll returned 0 results\n");
421 | #endif
422 | continue;
423 | }
424 |
425 | #ifdef PINGDEBUG
426 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: poll returned events = %d\n", pollfiledesc[0].revents);
427 | #endif
428 |
429 | if ( (pollfiledesc[0].revents & POLLIN) != POLLIN)
430 | {
431 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: RESTART: poll returned but failed to find POLLIN set: %d\n",pollfiledesc[0].revents);
432 | continue;
433 | }
434 |
435 | rmsghdr.msg_name = (caddr_t)&source;
436 | rmsghdr.msg_namelen = sizeof(source);
437 | memset(&rxiov, 0, sizeof(rxiov));
438 | rxiov[0].iov_base = (caddr_t)rxpacket;
439 | rxiov[0].iov_len = ICMPV6_PACKET_BUFFER_SIZE;
440 | rmsghdr.msg_iov = rxiov;
441 | rmsghdr.msg_iovlen = 1;
442 | rmsghdr.msg_control = (caddr_t)rxbuf;
443 | rmsghdr.msg_controllen = sizeof(rxbuf);
444 | rmsghdr.msg_flags = 0; // filled on receive
445 | rc = recvmsg(sock, &rmsghdr, 0);
446 | errsv = errno;
447 | if (rc < 0)
448 | {
449 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: RESTART: recvmsg returned bad things : %d (%s)\n", errsv, strerror(errsv));
450 | continue;
451 | }
452 | else if (rc == 0)
453 | {
454 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: RESTART: recvmsg returned 0 - is this a control message?\n");
455 | continue;
456 | }
457 | else
458 | {
459 | int rxpacketsize = rc;
460 | #ifdef PINGDEBUG
461 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: recvmsg returned indicating %d bytes received\n",rc);
462 | #endif
463 |
464 | if (rxpacketsize < (int)sizeof(struct icmp6_hdr))
465 | {
466 | #ifdef PINGDEBUG
467 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: Received packet too small - expected at least %d, got %d\n",(int)sizeof(struct icmp6_hdr),rxpacketsize);
468 | #endif
469 | continue;
470 | }
471 |
472 | if (rmsghdr.msg_namelen != sizeof(struct sockaddr_in6))
473 | {
474 | #ifdef PINGDEBUG
475 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: received bad peername length (namelen %d)\n",rmsghdr.msg_namelen);
476 | #endif
477 | continue;
478 | }
479 |
480 | if (((struct sockaddr *)rmsghdr.msg_name)->sa_family != AF_INET6)
481 | {
482 | #ifdef PINGDEBUG
483 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: received bad peername family (sa_family %d)\n",((struct sockaddr *)rmsghdr.msg_name)->sa_family);
484 | #endif
485 | continue;
486 | }
487 |
488 | rc = getnameinfo((struct sockaddr *)&source, sizeof(source), tmpbuf, sizeof(tmpbuf), NULL, 0, NI_NUMERICHOST);
489 | errsv = errno;
490 | if (0 == rc)
491 | {
492 | #ifdef PINGDEBUG
493 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Received source address was %s\n", tmpbuf);
494 | #endif
495 | }
496 | else
497 | {
498 | #ifdef PINGDEBUG
499 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: getnameinfo returned bad indication %d (%s)\n",errsv, gai_strerror(errsv));
500 | #endif
501 | continue;
502 | }
503 |
504 | // Store the outer packet address in case we do have a valid response from a machine(router) other than
505 | // the intended target
506 | rccharptr = inet_ntop(AF_INET6, &(source.sin6_addr), router, INET6_ADDRSTRLEN);
507 | errsv = errno;
508 | if (NULL == rccharptr)
509 | {
510 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ERROR: inet_ntop() for router returned bad indication %d (%s)\n", errsv, strerror(errsv));
511 | memset(router, 0, INET6_ADDRSTRLEN);
512 | }
513 |
514 | // Extract ICMPv6 type and code for checking and reporting
515 | rxicmp6hdr_ptr = (struct icmp6_hdr *)rxpacket;
516 | rxicmp6_type = rxicmp6hdr_ptr->icmp6_type;
517 | rxicmp6_code = rxicmp6hdr_ptr->icmp6_code;
518 | // Extract sequence number and ID
519 | rxseqno = htons(rxicmp6hdr_ptr->icmp6_seq);
520 | rxid = htons(rxicmp6hdr_ptr->icmp6_id);
521 |
522 | #ifdef PINGDEBUG
523 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
524 | #endif
525 |
526 | // Check whether our tx destination address equals our rx source
527 | // RFC3542 section 2.3 macro returns non-zero if addresses equal, otherwise 0
528 | if ( IN6_ARE_ADDR_EQUAL( &(source.sin6_addr), &(destination.sin6_addr) ) == 0 )
529 | {
530 |
531 | #ifdef PINGDEBUG
532 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: OUTER IPv6 hdr src address (%s) did not match our tx dest address\n", router);
533 | #endif
534 |
535 | // if a router replied instead of the host under test then size will be original packet plus an IPv6 header
536 | if ( rxpacketsize == (int)(sizeof(struct ip6_hdr) + 8 + sendsize) )
537 | {
538 | char tx_dst_addr[INET6_ADDRSTRLEN], orig_src_addr[INET6_ADDRSTRLEN], orig_dst_addr[INET6_ADDRSTRLEN];
539 | struct ip6_hdr *rx2ip6hdr_ptr;
540 | struct icmp6_hdr *rx2icmp6hdr_ptr;
541 | rx2ip6hdr_ptr = (struct ip6_hdr *)&rxpacket[sizeof(struct icmp6_hdr)];
542 | // struct in6_addr ip6_src and ip6_dst
543 | struct in6_addr orig_dst = rx2ip6hdr_ptr->ip6_dst;
544 | struct in6_addr orig_src = rx2ip6hdr_ptr->ip6_src;
545 | unsigned int nextheader = rx2ip6hdr_ptr->ip6_nxt;
546 |
547 | rccharptr = inet_ntop(AF_INET6, &orig_src, orig_src_addr, INET6_ADDRSTRLEN);
548 | errsv = errno;
549 | if (NULL == rccharptr)
550 | {
551 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ERROR: inet_ntop() for orig_src_addr returned bad indication %d (%s)\n", errsv, strerror(errsv));
552 | memset(orig_src_addr, 0, INET6_ADDRSTRLEN);
553 | }
554 | // original source address would be our IPv6 address
555 | // TODO - perhaps we should be checking this for completeness ...
556 |
557 | rccharptr = inet_ntop(AF_INET6, &orig_dst, orig_dst_addr, INET6_ADDRSTRLEN);
558 | errsv = errno;
559 | if (NULL == rccharptr)
560 | {
561 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ERROR: inet_ntop() for orig_dst_addr returned bad indication %d (%s)\n", errsv, strerror(errsv));
562 | memset(orig_dst_addr, 0, INET6_ADDRSTRLEN);
563 | }
564 | // original destination should match our transmitted destination address
565 |
566 | rccharptr = inet_ntop(AF_INET6, &(destination.sin6_addr), tx_dst_addr, INET6_ADDRSTRLEN);
567 | errsv = errno;
568 | if (NULL == rccharptr)
569 | {
570 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ERROR: inet_ntop() for tx_dst_addr returned bad indication %d (%s)\n", errsv, strerror(errsv));
571 | memset(tx_dst_addr, 0, INET6_ADDRSTRLEN);
572 | }
573 |
574 | #ifdef PINGDEBUG
575 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
576 | #endif
577 |
578 | // if addresses don't match then it was returned in response to another packet,
579 | // so this packet is not relevant to us ...
580 | if ( IN6_ARE_ADDR_EQUAL( &orig_dst, &(destination.sin6_addr) ) == 0)
581 | {
582 | #ifdef PINGDEBUG
583 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER IPv6 hdr dst %s was != our Tx dst %s\n", orig_dst_addr, tx_dst_addr);
584 | #endif
585 | continue;
586 | }
587 |
588 | // Check that the next header is ICMPv6, otherwise not in response to our tx
589 | if (nextheader == IPPROTO_ICMPV6)
590 | {
591 | rx2icmp6hdr_ptr = (struct icmp6_hdr *)&rxpacket[sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr)];
592 | unsigned int rx2icmp6_type = rx2icmp6hdr_ptr->icmp6_type;
593 | unsigned int rx2icmp6_code = rx2icmp6hdr_ptr->icmp6_code;
594 | // Extract sequence number and ID
595 | unsigned int rx2seqno = htons(rx2icmp6hdr_ptr->icmp6_seq);
596 | unsigned int rx2id = htons(rx2icmp6hdr_ptr->icmp6_id);
597 |
598 | // Check inner ICMPv6 packet was an ECHO_REQUEST
599 | if (rx2icmp6_type != ICMP6_ECHO_REQUEST)
600 | {
601 | #ifdef PINGDEBUG
602 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6_TYPE was not ECHO_REQUEST : %d\n", rx2icmp6_type);
603 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
604 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
605 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
606 | #endif
607 | continue;
608 | }
609 |
610 | // Check inner ICMPv6 code was 0
611 | if (rx2icmp6_code != 0)
612 | {
613 | #ifdef PINGDEBUG
614 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6_CODE was not 0\n");
615 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
616 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
617 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
618 | #endif
619 | continue;
620 | }
621 |
622 | // Check sequence number matches what we transmitted
623 | if (rx2seqno != txseqno)
624 | {
625 | #ifdef PINGDEBUG
626 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6_SEQN was not %d\n", txseqno);
627 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
628 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
629 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
630 | #endif
631 | continue;
632 | }
633 |
634 | // Check ID matches what we transmitted
635 | if (rx2id != txid)
636 | {
637 | #ifdef PINGDEBUG
638 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6_ID was not %d\n", txid);
639 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
640 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
641 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
642 | #endif
643 | continue;
644 | }
645 |
646 | // Check for the expected received data
647 | // sent:
648 | // "%"PRIu64" %"PRIu64" %u %u", starttime, session, ICMPV6_MAGIC_VALUE1, ICMPV6_MAGIC_VALUE2
649 | uint64_t rx2starttime, rx2session;
650 | unsigned int rx2magic1, rx2magic2;
651 |
652 | rc = sscanf(&rxpackdata[sizeof(struct icmp6_hdr)+sizeof(struct ip6_hdr)+ICMP6DATAOFFSET], "%"PRIu64" %"PRIu64" %u %u", &rx2starttime, &rx2session, &rx2magic1, &rx2magic2);
653 | if (rc == 4)
654 | {
655 | if (rx2starttime != starttime)
656 | {
657 | #ifdef PINGDEBUG
658 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6 magic data rx2starttime (%"PRId64") != starttime (%"PRId64")\n", rx2starttime, starttime);
659 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
660 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
661 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
662 | #endif
663 | continue;
664 | }
665 | if (rx2session != session)
666 | {
667 | #ifdef PINGDEBUG
668 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6 magic data rx2session (%"PRId64") != session (%"PRId64")\n", rx2session, session);
669 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
670 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
671 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
672 | #endif
673 | continue;
674 | }
675 | if (ICMPV6_MAGIC_VALUE1 != rx2magic1)
676 | {
677 | #ifdef PINGDEBUG
678 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6 magic data rx2magic1 (%d) != expected %d\n", rx2magic1, ICMPV6_MAGIC_VALUE1);
679 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
680 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
681 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
682 | #endif
683 | continue;
684 | }
685 | if (ICMPV6_MAGIC_VALUE2 != rx2magic2)
686 | {
687 | #ifdef PINGDEBUG
688 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6 magic data rx2magic2 (%d) != expected %d\n", rx2magic2, ICMPV6_MAGIC_VALUE2);
689 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
690 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
691 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
692 | #endif
693 | continue;
694 | }
695 |
696 | //
697 | // If we get to this point then the returned packet was in response to the packet we originally
698 | // transmitted
699 | //
700 | #ifdef PINGDEBUG
701 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Packet from %s contained our tx ECHO-REQUEST, so flagging INDIRECT response\n", router);
702 | #endif
703 | indirect = IPSCAN_INDIRECT_RESPONSE;
704 | }
705 | else
706 | {
707 | // wrong number of parameters
708 | #ifdef PINGDEBUG
709 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER ICMPv6 packet returned number of magic parameters (%d) != 4\n", rc);
710 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
711 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
712 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED INNER packet icmp6 details: type %d; code %d; seq %d; id %d\n", rx2icmp6_type, rx2icmp6_code, rx2seqno, rx2id);
713 | #endif
714 | continue;
715 | }
716 | }
717 | else
718 | {
719 | #ifdef PINGDEBUG
720 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: INNER IPv6 next header didn't indicate an ICMPv6 packet inside\n");
721 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
722 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: INNER packet details: src %s ; dst %s; nextheader %d\n", orig_src_addr, orig_dst_addr, nextheader);
723 | #endif
724 | continue;
725 | }
726 | }
727 | else
728 | {
729 | #ifdef PINGDEBUG
730 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: OUTER address mismatch with INNER unexpected size : %d\n", rxpacketsize);
731 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
732 | #endif
733 | continue;
734 | }
735 |
736 | }
737 |
738 | //
739 | // Check what type of ICMPv6 packet we received and set return value appropriately ...
740 | //
741 | if (rxicmp6_type == ICMP6_ECHO_REPLY)
742 | {
743 | #ifdef PINGDEBUG
744 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ICMP6_TYPE was ICMP6_ECHO_REPLY, with code %d\n", rxicmp6_code);
745 | #endif
746 | }
747 | else if ( rxicmp6_type == ICMP6_DST_UNREACH )
748 | {
749 | switch ( rxicmp6_code )
750 | {
751 | case ICMP6_DST_UNREACH_NOROUTE:
752 | retval = PORTUNREACHABLE;
753 | break;
754 | case ICMP6_DST_UNREACH_ADMIN:
755 | retval = PORTPROHIBITED;
756 | break;
757 | case ICMP6_DST_UNREACH_ADDR:
758 | retval = PORTNOROUTE;
759 | break;
760 | case ICMP6_DST_UNREACH_NOPORT:
761 | retval = PORTREFUSED;
762 | break;
763 | default:
764 | retval = PORTUNREACHABLE;
765 | break;
766 | }
767 |
768 | #ifdef PINGDEBUG
769 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ICMP6_TYPE was DST_UNREACH, with code %d (%s)\n", rxicmp6_code, resultsstruct[retval].label);
770 | #endif
771 |
772 | if (-1 != sock) close(sock); // close socket if appropriate
773 | return(retval+indirect);
774 | }
775 | else if (rxicmp6_type == ICMP6_PARAM_PROB)
776 | {
777 | #ifdef PINGDEBUG
778 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ICMP6_TYPE was PARAM_PROB, with code %d\n", rxicmp6_code);
779 | #endif
780 |
781 | retval = PORTPARAMPROB;
782 | if (-1 != sock) close(sock); // close socket if appropriate
783 | return(retval+indirect);
784 | }
785 | else if (rxicmp6_type == ICMP6_TIME_EXCEEDED)
786 | {
787 | #ifdef PINGDEBUG
788 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ICMP6_TYPE was TIME_EXCEEDED, with code %d\n", rxicmp6_code);
789 | #endif
790 |
791 | retval = PORTNOROUTE;
792 | if (-1 != sock) close(sock); // close socket if appropriate
793 | return(retval+indirect);
794 | }
795 | else if (rxicmp6_type == ICMP6_PACKET_TOO_BIG)
796 | {
797 | #ifdef PINGDEBUG
798 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: ICMP6_TYPE was PACKET_TOO_BIG, with code %d\n", rxicmp6_code);
799 | #endif
800 |
801 | retval = PORTPKTTOOBIG;
802 | if (-1 != sock) close(sock); // close socket if appropriate
803 | return(retval+indirect);
804 | }
805 | else
806 | {
807 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: RESTART: unhandled ICMPv6 packet TYPE was %d CODE was %d\n", rxicmp6_type, rxicmp6_code);
808 | continue;
809 | }
810 |
811 | //
812 | // If we get this far then packet is a direct ECHO-REPLY, so we can check the contents
813 | //
814 |
815 | if (rxseqno != txseqno)
816 | {
817 | #ifdef PINGDEBUG
818 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: Sequence number mismatch - expected %d\n", txseqno);
819 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
820 | #endif
821 | continue;
822 | }
823 |
824 | if (rxid != txid)
825 | {
826 | #ifdef PINGDEBUG
827 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: ICMP6 id mismatch - expected %d\n", txid);
828 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
829 | #endif
830 | continue;
831 | }
832 |
833 | // Check for the expected received data
834 | // sent:
835 | // "%"PRIu64" %"PRIu64" %u %u", starttime, session, ICMPV6_MAGIC_VALUE1, ICMPV6_MAGIC_VALUE2
836 | uint64_t rxstarttime, rxsession;
837 | unsigned int rxmagic1, rxmagic2;
838 |
839 | rc = sscanf(&rxpackdata[ICMP6DATAOFFSET], "%"PRIu64" %"PRIu64" %u %u", &rxstarttime, &rxsession, &rxmagic1, &rxmagic2);
840 | if (rc == 4)
841 | {
842 | if (rxstarttime != starttime)
843 | {
844 | #ifdef PINGDEBUG
845 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: magic data rxstarttime (%"PRId64") != starttime (%"PRId64")\n", rxstarttime, starttime);
846 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
847 | #endif
848 | continue;
849 | }
850 | if (rxsession != session)
851 | {
852 | #ifdef PINGDEBUG
853 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: magic data rxsession (%"PRId64") != session (%"PRId64")\n", rxsession, session);
854 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
855 | #endif
856 | continue;
857 | }
858 | if (ICMPV6_MAGIC_VALUE1 != rxmagic1)
859 | {
860 | #ifdef PINGDEBUG
861 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: RX magic data 1 (%d) != expected %d\n", rxmagic1, ICMPV6_MAGIC_VALUE1);
862 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
863 | #endif
864 | continue;
865 | }
866 | if (ICMPV6_MAGIC_VALUE2 != rxmagic2)
867 | {
868 | #ifdef PINGDEBUG
869 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: RX magic data 2 (%d) != expected %d\n", rxmagic2, ICMPV6_MAGIC_VALUE2);
870 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
871 | #endif
872 | continue;
873 | }
874 |
875 | //
876 | // if we get to this point then everything matches ...
877 | //
878 | #ifdef PINGDEBUG
879 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: Everything matches - it was our expected ICMPv6 ECHO_RESPONSE\n");
880 | #endif
881 | foundit = 1;
882 | }
883 | else
884 | {
885 | #ifdef PINGDEBUG
886 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARD: number of magic parameters mismatched, got %d, expected 4\n", rc);
887 | IPSCAN_LOG( LOGPREFIX "check_icmpv6_echoresponse: DISCARDED OUTER packet details: src %s; type %d; code %d; id %d; seqno %d\n", router, rxicmp6_type, rxicmp6_code, rxid, rxseqno);
888 | #endif
889 | continue;
890 | }
891 |
892 | } // end of if (received some bytes)
893 |
894 | } // end of while
895 |
896 | if (foundit == 1) retval = ECHOREPLY; else retval = ECHONOREPLY;
897 |
898 | // return the status
899 | if (-1 != sock) close(sock); // close socket if appropriate
900 |
901 | // Make sure we wait long enough in all cases
902 | sleep(IPSCAN_MINTIME_PER_PORT);
903 |
904 | return(retval);
905 | }
906 |
907 |
--------------------------------------------------------------------------------
/ipscan_portlist.h:
--------------------------------------------------------------------------------
1 | // IPscan - an HTTP-initiated IPv6 port scanner.
2 | //
3 | // Copyright (C) 2011-2025 Tim Chappell.
4 | //
5 | // This file is part of IPscan.
6 | //
7 | // IPscan is free software: you can redistribute it and/or modify
8 | // it under the terms of the GNU General Public License as published by
9 | // the Free Software Foundation, either version 3 of the License, or
10 | // (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with IPscan. If not, see .
19 | //
20 | // Version Change
21 | // 0.01 Original
22 | // 0.02 Added additional Windows related ports
23 | // 2869 - SSDP event notification
24 | // 5357 - WSDAPI HTTP
25 | // 10243 - WMP HTTP
26 | // 0.03 - add service names to results table (modification to portlist, now structure)
27 | // 0.04 - add UDP ports and service names
28 | // 0.05 - add SNMP (UDP port 161) support
29 | // 0.06 - add NTP special case
30 | // 0.07 - add TCP/32764 router backdoor port (may be IPv4 only)
31 | // 0.08 - add SNMPv2c and SNMPv3
32 | // 0.09 - slight tweaks to a few Microsoft ports
33 | // as per https://msdn.microsoft.com/en-us/library/cc875824.aspx
34 | // 0.10 - added Intel AMT ports
35 | // 0.11 - update copyright dates
36 | // 0.12 - add memcached check (TCP only, UDP not supported for IPv6)
37 | // 0.13 - add memcached UDP check
38 | // 0.14 - update copyright dates
39 | // 0.15 - update copyright dates
40 | // 0.16 - update copyright year
41 | // 0.17 - add whois, TCP/43
42 | // 0.18 - update copyright year
43 | // 0.19 - add TCP/20005 (for KCodes NetUSB - see CVE-2021-45608)
44 | // 0.20 - update copyright year
45 | // 0.21 - const portlist structs
46 |
47 | //
48 | #define IPSCAN_PORTLIST_VER "0.21"
49 | //
50 |
51 | #include "ipscan.h"
52 |
53 | #ifndef IPSCAN_PORTLIST_H
54 | #define IPSCAN_PORTLIST_H 1
55 |
56 | // Determine the default list of ports to be tested
57 | // Note: each entry includes its port number followed by
58 | // a text description (up to PORTDESCSIZE-1 characters long)
59 | //
60 | const struct portlist_struc defportlist[] =
61 | {
62 | { 7, 0, "Echo"},\
63 | { 21, 0, "FTP" },\
64 | { 22, 0, "SSH" },\
65 | { 23, 0, "Telnet" },\
66 | { 25, 0, "SMTP" },\
67 | { 37, 0, "Time" },\
68 | { 43, 0, "WHOIS" },\
69 | { 53, 0, "DNS" },\
70 | { 79, 0, "Finger" },\
71 | { 80, 0, "HTTP" },\
72 | { 110, 0, "POP3" },\
73 | { 111, 0, "SUN-RPC" },\
74 | { 113, 0, "Ident, Auth" },\
75 | { 119, 0, "NNTP" },\
76 | { 135, 0, "Microsoft-EPMAP" },\
77 | { 139, 0, "NetBIOS Session" },\
78 | { 143, 0, "IMAP" },\
79 | { 179, 0, "BGP" },\
80 | { 311, 0, "Apple-WebAdmin" },\
81 | { 389, 0, "LDAP" },\
82 | { 427, 0, "SLP" },\
83 | { 443, 0, "HTTPS" },\
84 | { 445, 0, "Microsoft-DS" },\
85 | { 515, 0, "LPD" },\
86 | { 543, 0, "Kerberos Login" },\
87 | { 544, 0, "Kerberos RSH" },\
88 | { 548, 0, "Apple-File" },\
89 | { 587, 0, "ESMTP" },\
90 | { 631, 0, "IPP" },\
91 | { 749, 0, "Kerberos Admin" },\
92 | { 873, 0, "Rsync" },\
93 | { 993, 0, "IMAPS" },\
94 | { 995, 0, "POP3S" },\
95 | { 1025, 0, "Blackjack, NFS, IIS or RFS" },\
96 | { 1026, 0, "CAP, Microsoft DCOM" },\
97 | { 1029, 0, "Microsoft DCOM" },\
98 | { 1030, 0, "BBN IAD" },\
99 | { 1080, 0, "Socks" },\
100 | { 1720, 0, "H323, Microsoft Netmeeting" },\
101 | { 1723, 0, "PPTP" },\
102 | { 1801, 0, "MSMQ" },\
103 | { 2103, 0, "MSMQ-RPC" },\
104 | { 2105, 0, "MSMQ-RPC" },\
105 | { 2107, 0, "MSMQ-Mgmt" },\
106 | { 2869, 0, "SSDP Event Notification" },\
107 | { 3128, 0, "Active API, or Squid Proxy" },\
108 | { 3306, 0, "MySQL" },\
109 | { 3389, 0, "Microsoft RDP" },\
110 | { 3689, 0, "DAAP, iTunes" },\
111 | { 5000, 0, "UPNP" },\
112 | { 5060, 0, "SIP" },\
113 | { 5100, 0, "Service Mux, Yahoo Messenger" },\
114 | { 5357, 0, "WSDAPI HTTP" },\
115 | { 5900, 0, "VNC" },\
116 | { 8080, 0, "HTTP alternate" },\
117 | { 9090, 0, "WebSM" },\
118 | {10243, 0, "Microsoft WMP HTTP"},\
119 | {11211, 0, "memcache" },\
120 | {16992, 0, "Intel AMT SOAP/HTTP"},\
121 | {16993, 0, "Intel AMT SOAP/HTTPS"},\
122 | {16994, 0, "Intel AMT Redir/TCP"},\
123 | {16995, 0, "Intel AMT Redir/TLS"},\
124 | {20005, 0, "Router KCodes NetUSB port, see CVE-2021-45608"},\
125 | {32764, 0, "Router Backdoor"}\
126 | };
127 |
128 |
129 | // Calculate and record the number of default ports to be tested
130 | #define DEFNUMPORTS ( sizeof(defportlist) / sizeof(struct portlist_struc) )
131 |
132 | const struct portlist_struc udpportlist[] =
133 | {
134 | { 53, 0, "DNS" },\
135 | { 69, 0, "TFTP" },\
136 | { 123, 0, "NTP" },\
137 | { 123, 1, "NTP MONLIST" },\
138 | { 161, 0, "SNMPv1" },\
139 | { 161, 1, "SNMPv2c" },\
140 | { 161, 2, "SNMPv3" },\
141 | { 500, 0, "IKEv2 SA_INIT" },\
142 | { 521, 0, "RIPng" },\
143 | { 547, 0, "DHCPv6" },\
144 | { 1900, 0, "UPnP SSDP" },\
145 | { 3503, 0, "MPLS LSP Ping" },\
146 | { 4500, 0, "IKEv2 NAT-T SA_INIT" },\
147 | {11211, 0, "memcache ASCII" },\
148 | {11211, 1, "memcache binary" },\
149 | };
150 |
151 | #if (IPSCAN_INCLUDE_UDP == 1)
152 | #define NUMUDPPORTS ( sizeof(udpportlist) / sizeof(struct portlist_struc) )
153 | #else
154 | #define NUMUDPPORTS 0
155 | #endif
156 |
157 | #endif /* IPSCAN_PORTLIST_H */
158 |
--------------------------------------------------------------------------------
/ipscan_tcp.c:
--------------------------------------------------------------------------------
1 | // IPscan - an HTTP-initiated IPv6 port scanner.
2 | //
3 | // Copyright (C) 2011-2025 Tim Chappell.
4 | //
5 | // This file is part of IPscan.
6 | //
7 | // IPscan is free software: you can redistribute it and/or modify
8 | // it under the terms of the GNU General Public License as published by
9 | // the Free Software Foundation, either version 3 of the License, or
10 | // (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with IPscan. If not, see .
19 |
20 | // ipscan_tcp.c version
21 | // 0.01 initial version after split from ipscan_checks.c
22 | // 0.02 tidy up logging prefixes
23 | // 0.03 move to memset()
24 | // 0.04 add support for special cases
25 | // 0.05 ensure minimum timings are met
26 | // 0.06 improve error reporting
27 | // 0.07 ensure fd closure is handled cleanly
28 | // 0.08 add null termination to unusedfield
29 | // 0.09 enforce use of AF_INET6
30 | // 0.10 update copyright date
31 | // 0.11 update copyright date
32 | // 0.12 update copyright date
33 | // 0.13 extern updated
34 | // 0.14 update copyright date
35 | // 0.15 update copyright year
36 | // 0.16 update copyright year
37 | // 0.17 update copyright year
38 | // 0.18 reduce scope of multiple variables
39 |
40 | //
41 | #define IPSCAN_TCP_VER "0.18"
42 | //
43 |
44 | #include "ipscan.h"
45 | //
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 | #include
56 |
57 | // IPv6 address conversion
58 | #include
59 |
60 | // String comparison
61 | #include
62 |
63 | // Logging with syslog requires additional include
64 | #if (LOGMODE == 1)
65 | #include
66 | #endif
67 |
68 | // Others that FreeBSD highlighted
69 | #include
70 | #include
71 | #include
72 |
73 | // Other IPv6 related
74 | #include
75 | #include
76 |
77 | //Poll support
78 | #include
79 |
80 | // Parallel processing related
81 | #include
82 |
83 | // Define offset into ICMPv6 packet where user-defined data resides
84 | #define ICMP6DATAOFFSET sizeof(struct icmp6_hdr)
85 |
86 | //
87 | // Prototype declarations
88 | //
89 | int write_db(uint64_t host_msb, uint64_t host_lsb, uint64_t timestamp, uint64_t session, uint32_t port, int32_t result, const char *indirecthost );
90 |
91 | //
92 | // report version
93 | //
94 | const char* ipscan_tcp_ver(void)
95 | {
96 | return IPSCAN_TCP_VER;
97 | }
98 |
99 | //
100 | // Check an individual TCP port
101 | //
102 |
103 | int check_tcp_port(char * hostname, uint16_t port, uint8_t special)
104 | {
105 | struct addrinfo *res, *aip;
106 | struct addrinfo hints;
107 | int error;
108 | struct timeval timeout;
109 | char portnum[8];
110 |
111 | memset(&hints, 0, sizeof(hints));
112 | hints.ai_family = AF_INET6;
113 | hints.ai_flags = AI_NUMERICSERV;
114 | hints.ai_socktype = SOCK_STREAM;
115 |
116 | // set return value to a known default
117 | int retval = PORTUNKNOWN;
118 |
119 | error = snprintf(portnum, 8,"%d", port);
120 | if (error < 0 || error >= 8)
121 | {
122 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: Failed to write portnum, rc was %d\n", error);
123 | retval = PORTINTERROR;
124 | }
125 |
126 | error = getaddrinfo(hostname, portnum, &hints, &res);
127 | if (error != 0)
128 | {
129 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: getaddrinfo: %s for host %s port %d\n", gai_strerror(error), hostname, port);
130 | retval = PORTINTERROR;
131 | }
132 | else
133 | {
134 |
135 | // cycle around the results ...
136 | for (aip = res; (NULL != aip && PORTUNKNOWN == retval) ; aip = aip->ai_next)
137 | {
138 | // If this is not an IPv6 address then skip, should never happen now AF family specified ...
139 | if (aip->ai_family != AF_INET6)
140 | {
141 | // IPSCAN_LOG( LOGPREFIX "Skipping, because ai_family != AF_INET6 (actually %d)\n",aip->ai_family);
142 | continue;
143 | }
144 |
145 | // Attempt to create a socket
146 | int sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
147 | if (sock == -1)
148 | {
149 | int errsv = errno ;
150 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: Bad socket call, returned %d (%s)\n", errsv, strerror(errsv));
151 | retval = PORTINTERROR;
152 | }
153 |
154 | // Assuming something bad hasn't already happened then attempt to set the receive timeout
155 | if (PORTUNKNOWN == retval)
156 | {
157 | // Set send timeout
158 | memset(&timeout, 0, sizeof(timeout));
159 | timeout.tv_sec = TIMEOUTSECS;
160 | timeout.tv_usec = TIMEOUTMICROSECS;
161 | int timeo = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
162 | if (timeo < 0)
163 | {
164 | int errsv = errno ;
165 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: Bad setsockopt SO_SNDTIMEO set, returned %d (%s)\n", errsv, strerror(errsv));
166 | retval = PORTINTERROR;
167 | }
168 | }
169 |
170 | // Assuming something bad hasn't already happened then attempt to set the receive timeout
171 | if (PORTUNKNOWN == retval)
172 | {
173 | // Set receive timeout
174 | memset(&timeout, 0, sizeof(timeout));
175 | timeout.tv_sec = TIMEOUTSECS;
176 | timeout.tv_usec = TIMEOUTMICROSECS;
177 | int timeo = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
178 | if (timeo < 0)
179 | {
180 | int errsv = errno ;
181 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: Bad setsockopt SO_RCVTIMEO set, returned %d (%s)\n", errsv, strerror(errsv));
182 | retval = PORTINTERROR;
183 | }
184 | }
185 |
186 | // Assuming something bad hasn't already happened then attempt to connect
187 | if (PORTUNKNOWN == retval)
188 | {
189 | // attempt to connect
190 | int conn = connect(sock, aip->ai_addr, aip->ai_addrlen);
191 | int errsv = errno ;
192 | // cycle through the expected list of results
193 | for (int i = 0; PORTEOL != resultsstruct[i].returnval && PORTUNKNOWN == retval ; i++)
194 | {
195 |
196 | // Find a matching connect returncode and also errno, if appropriate
197 | if (resultsstruct[i].connrc == conn)
198 | {
199 | // Set the returnvalue if we find a match
200 | if ( conn == 0 || (conn == -1 && resultsstruct[i].connerrno == errsv) )
201 | {
202 | retval = resultsstruct[i].returnval;
203 | }
204 | }
205 | }
206 |
207 | #ifdef RESULTSDEBUG
208 | if (0 != special)
209 | {
210 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: found port %d:%d returned conn = %d, errsv = %d(%s)\n", port, special, conn, errsv, strerror(errsv));
211 | }
212 | else
213 | {
214 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: found port %d returned conn = %d, errsv = %d(%s)\n", port, conn, errsv, strerror(errsv));
215 | }
216 | #endif
217 |
218 | // If we haven't found a matching returncode/errno then log this ....
219 | if (PORTUNKNOWN == retval)
220 | {
221 | if (0 != special)
222 | {
223 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: connect unexpected response, errno is : %d (%s) for host %s port %d:%d\n", \
224 | errsv, strerror(errsv), hostname, port, special);
225 | }
226 | else
227 | {
228 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: connect unexpected response, errno is : %d (%s) for host %s port %d\n", \
229 | errsv, strerror(errsv), hostname, port);
230 | }
231 | retval = PORTUNEXPECTED;
232 | }
233 |
234 | int cl = close(sock);
235 | if (cl == -1)
236 | {
237 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: close unexpected failure : %d (%s)\n", errno, strerror(errno));
238 | }
239 |
240 | }
241 | else
242 | {
243 | // Something bad has happened during setsockopts, but ensure we close an open socket anyway
244 | if (-1 != sock)
245 | {
246 | int cl = close(sock);
247 | if (cl == -1)
248 | {
249 | IPSCAN_LOG( LOGPREFIX "check_tcp_port: close unexpected failure : %d (%s)\n", errno, strerror(errno));
250 | }
251 | }
252 | }
253 |
254 | } // end for loop
255 | freeaddrinfo(res);
256 | }
257 |
258 | // If we received any non-positive feedback then make sure we wait at least IPSCAN_MINTIME_PER_PORT secs
259 | if ((PORTOPEN != retval) && (PORTINPROGRESS != retval)) sleep(IPSCAN_MINTIME_PER_PORT);
260 |
261 | return(retval);
262 | }
263 |
264 |
265 | int check_tcp_ports_parll(char * hostname, unsigned int portindex, unsigned int todo, uint64_t host_msb, uint64_t host_lsb, uint64_t timestamp, uint64_t session, struct portlist_struc *portlist)
266 | {
267 | int rc,result;
268 | pid_t childpid = fork();
269 | if (childpid > 0)
270 | {
271 | // parent
272 | #ifdef PARLLDEBUG
273 | IPSCAN_LOG( LOGPREFIX "check_tcp_ports_parll(): forked and started child PID=%d\n",childpid);
274 | #endif
275 | }
276 | else if (childpid == 0)
277 | {
278 | #ifdef PARLLDEBUG
279 | IPSCAN_LOG( LOGPREFIX "check_tcp_ports_parll(): startindex %d, todo %d\n",portindex,todo);
280 | #endif
281 | // child - actually do the work here - and then exit successfully
282 | const char unusedfield[8] = "unused\0";
283 | for (unsigned int i = 0 ; i < todo ; i++)
284 | {
285 | uint16_t port = portlist[portindex+i].port_num;
286 | uint8_t special = portlist[portindex+i].special;
287 | #ifdef TCPDEBUG
288 | IPSCAN_LOG( LOGPREFIX "check_tcp_ports_parll(): DEBUG: portindex = %d, i = %d, port_num = %d, special = %d\n", portindex, i, portlist[portindex+i].port_num, portlist[portindex+i].special);
289 | IPSCAN_LOG ( LOGPREFIX "check_tcp_ports_parll(): DEBUG: hostname = %s, port = %d, special = %d\n", hostname, port, special);
290 | #endif
291 | result = check_tcp_port(hostname, port, special);
292 | // Put results into database
293 | rc = write_db(host_msb, host_lsb, timestamp, session, (uint32_t)(port + ((special & IPSCAN_SPECIAL_MASK) << IPSCAN_SPECIAL_SHIFT) + (IPSCAN_PROTO_TCP << IPSCAN_PROTO_SHIFT)), result, unusedfield );
294 | if (rc != 0)
295 | {
296 | IPSCAN_LOG( LOGPREFIX "check_tcp_ports_parll(): ERROR: check_tcp_port_parll() write_db returned %d\n", rc);
297 | }
298 | }
299 | // Usual practice to have children _exit() whilst the parent calls exit()
300 | _exit(EXIT_SUCCESS);
301 | }
302 | else
303 | {
304 | IPSCAN_LOG( LOGPREFIX "check_tcp_ports_parll(): fork() failed childpid=%d, errno=%d(%s)\n", childpid, errno, strerror(errno));
305 | exit(EXIT_FAILURE);
306 | }
307 | return( (int)childpid );
308 | }
309 |
--------------------------------------------------------------------------------
/ipscan_web.c:
--------------------------------------------------------------------------------
1 | // IPscan - an HTTP-initiated IPv6 port scanner.
2 | //
3 | // Copyright (C) 2011-2025 Tim Chappell.
4 | //
5 | // This file is part of IPscan.
6 | //
7 | // IPscan is free software: you can redistribute it and/or modify
8 | // it under the terms of the GNU General Public License as published by
9 | // the Free Software Foundation, either version 3 of the License, or
10 | // (at your option) any later version.
11 | //
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 | //
17 | // You should have received a copy of the GNU General Public License
18 | // along with IPscan. If not, see .
19 |
20 | // ipscan_web.c version
21 | // 0.01 - initial version
22 | // 0.02 - improved HTML (transition to styles, general compliance)
23 | // 0.03 - addition of ping functionality
24 | // 0.04 - addition of indirect host support
25 | // 0.05 - removal of empty HTML paragraph
26 | // 0.06 - tidy up URIPATH and comparisons
27 | // 0.07 - move to JSON array which supports port number and result
28 | // 0.08 - remove unused parameters
29 | // 0.09 - add http-equiv to force IE7 mimicry
30 | // 0.10 - minor tweak to expected run-time for non-javascript browser message
31 | // 0.11 - add service names to results table (modification to portlist, now structure)
32 | // 0.12 - compress form vertically
33 | // 0.13 - introduce UDP support
34 | // 0.14 - support the optional removal of ping functionality
35 | // 0.15 - support the optional removal of UDP functionality
36 | // 0.16 - add special case support
37 | // 0.17 - add end of test signalling
38 | // 0.18 - lint improvements
39 | // 0.19 - correct position of request.send()
40 | // 0.20 - handle failure case when HTTP return-code is not 200
41 | // 0.21 - lint check and improvements
42 | // 0.22 - move final fetch earlier
43 | // 0.23 - further javascript improvements
44 | // 0.24 - remove commented-out javascript code
45 | // 0.25 - move to single XML HHTP Request object
46 | // 0.26 - add 'navigate away' handler to javascript version
47 | // 0.27 - fix cut'n'paste error, spotted by coverity
48 | // 0.28 - update copyright year, and ensure charset=iso-8859-1
49 | // 0.29 - update copyright year
50 | // 0.30 - add basic HTML5/CSS support for javascript binaries
51 | // 0.31 - specify value if terms accepted
52 | // 0.32 - update copyright year
53 | // 0.33 - slight tweak to error reporting (myReadyState and myStatus)
54 | // 0.34 - update copyright year
55 | // 0.35 - extern udpated
56 | // 0.36 - semmle re-entrant time functions added
57 | // 0.37 - javascript updates (removal of eval) and tidy
58 | // 0.38 - add log for time_r failures
59 | // 0.39 - update copyright year
60 | // 0.40 - move to use client starttime to ensure unique parameters
61 | // 0.41 - convert some variables to const, re-scope others, update copyright year
62 | // 0.42 - move to client session/starttime generation
63 | // 0.43 - catch bad JSON parse result, return to const and var
64 | // 0.44 - remove commented out code
65 | // 0.45 - make Javascript style more consistent
66 | // 0.46 - add cache-control private
67 | // 0.47 - add LGTM pragmas to ignore cross-site scripting false positives
68 | // 0.48 - remove LGTM pragmas once false positives resolved
69 | // 0.49 - add an additional note regarding normal TCP/UDP port tests
70 | // 0.50 - further clarifications regarding normal TCP/UDP port tests
71 | // 0.51 - move to unsigned shift right (should be of no consequence)
72 | // 0.52 - update copyright year
73 | // 0.53 - change colour of text and buttons to blue (better readability), results still use red
74 | // 0.54 - make robots reponse an optional include
75 | // 0.55 - add a missing clearInterval()
76 | // 0.56 - correct time into seconds since epoch rather than ms
77 | // 0.57 - HTML and javascript improvements/modernisations - use const, let
78 | // 0.58 - javascript changes to handle reporting of current state (hover over scan status cell)
79 | // 0.59 - change timeout calculation to give larger window
80 | // 0.60 - ontimeout change
81 | // 0.61 - further tidying
82 | // 0.62 - portlist structs are now consts
83 | // 0.63 - further CodeQL improvements
84 | // 0.64 - even more CodeQL improvements
85 | // 0.65 - various code quality improvements (scope reductions)
86 |
87 | #define IPSCAN_WEB_VER "0.65"
88 |
89 | #include "ipscan.h"
90 |
91 | #include
92 | #include
93 | #include
94 | #include
95 | #include
96 | #include
97 | #include
98 | #include
99 | #include
100 | #include
101 |
102 | // Logging with syslog requires additional include
103 | #if (1 == LOGMODE)
104 | #include
105 | #endif
106 |
107 | //
108 | // report version
109 | //
110 | const char* ipscan_web_ver(void)
111 | {
112 | return IPSCAN_WEB_VER;
113 | }
114 |
115 | //
116 | // ---------------------------------
117 | //
118 |
119 | void create_html_common_header(void)
120 | {
121 | printf("%s%c%c\n","content-type:text/html;charset=utf-8",13,10);
122 | printf("\n");
123 | printf("\n");
124 | printf("\n");
125 | // Force later IE browsers to mimic IE7 as detailed in http://msdn.microsoft.com/library/cc288325.aspx
126 | printf("\n");
127 | printf("\n");
128 | printf("\n");
129 | printf("\n");
130 | printf("\n");
131 | #ifdef IPSCAN_ICON_ENABLED
132 | printf("\n", IPSCAN_ICON_TYPE, IPSCAN_ICON_HREF);
133 | #endif
134 | #ifdef IPSCAN_NOROBOTS_INCLUDE
135 | printf("\n");
136 | #endif
137 | printf("\n");
138 | }
139 |
140 | #ifdef IPSCAN_HTML5_ENABLED
141 | void create_html5_common_header(void)
142 | {
143 | printf("%s%c%c\n","content-type:text/html;charset=utf-8",13,10);
144 | printf("\n");
145 | printf("\n");
146 | printf("\n");
147 | printf("\n");
148 | printf("\n");
149 | printf("\n");
150 | printf("\n");
151 | #ifdef IPSCAN_ICON_ENABLED
152 | printf("\n", IPSCAN_ICON_TYPE, IPSCAN_ICON_HREF);
153 | #endif
154 | #ifdef IPSCAN_NOROBOTS_INCLUDE
155 | printf("\n");
156 | #endif
157 | printf("\n");
158 |
159 | printf("\n");
200 | }
201 | #endif
202 |
203 | void create_json_header(void)
204 | {
205 | printf("%s%c%c\n","Content-type:application/json;charset=utf-8",13,10);
206 | }
207 |
208 | void create_html_header(uint16_t numports, uint16_t numudpports, char * reconquery)
209 | {
210 | uint16_t i;
211 |
212 | HTML_HEADER();
213 |
214 | printf("IPv6 Port Scanner Version %s\n", IPSCAN_VER);
215 | printf("\n");
635 | printf("\n");
636 | }
637 |
638 |
639 | void create_results_key_table(char * hostname, time_t timestamp)
640 | {
641 | int i;
642 | struct tm timestampbdt; // broken dowm time
643 | struct tm * tsptr = NULL;
644 | tsptr = localtime_r(×tamp, ×tampbdt);
645 |
646 | printf("
");
647 | if (NULL != tsptr)
648 | {
649 | char tstring[64];
650 | if (0 != strftime(tstring, sizeof(tstring),"%a,%%20%d%%20%b%%20%Y%%20%T%%20%z", ×tampbdt))
651 | {
652 | printf("Special protocol tests, signified by [x] after a port number, test for known protocol weaknesses. ");
653 | printf("Further details of these tests can be found at Special protocol tests.\n", IPSCAN_SPECIALTESTS_URL);
654 | // Offer the opportunity for feedback and a link to the source
655 | printf("If you have any queries related to the results of this scan, or suggestions for improvement/additions to its functionality");
656 | printf(" then please email me. ",\
657 | EMAILADDRESS, hostname, tstring );
658 | }
659 | }
660 | else
661 | {
662 | IPSCAN_LOG( LOGPREFIX "ipscan_web: ERROR: localtime_r() in create_results_key_table() returned NULL\n");
663 | }
664 |
665 | printf("The source code for this scanner is freely available at github.
\n");
680 | // Only include if ping is supported
681 | #if (1 == IPSCAN_INCLUDE_PING)
682 | printf("
NOTE: Results in the ICMPv6 ECHO REQUEST test marked as INDIRECT indicate an ICMPv6 error response was received from another host (e.g. a router or firewall) rather");
683 | printf(" than the host under test. In this case the address of the responding host is also displayed.
\n");
684 | printf("
NOTE2: TCP/UDP tests which elicit an active negative response (coloured YELLOW) may come from either the host under test OR another device in the path (e.g. a firewall/router). An indirect response to the ICMPv6 ECHO REQUEST test increases the likelihood that another device may have responded to the TCP/UDP probes.
\n");
685 | #else
686 | printf("
NOTE: TCP/UDP tests which elicit an active negative response (coloured YELLOW) may come from either the host under test OR another device in the path (e.g. a firewall/router).
\n"); position=0; };
982 | }
983 | // end of table
984 | printf("
\n");
985 |
986 | printf("
1. Select whether to include the default list of TCP ports, or not:
\n");
987 | printf("\n");
1016 | printf("
\n");
1017 | }
1018 | #endif
1019 |
--------------------------------------------------------------------------------
/upgrade.bsh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # IPscan - an HTTP-initiated IPv6 port scanner.
4 | #
5 | # (C) Copyright 2011-2025 Tim Chappell.
6 | #
7 | # This file is part of IPscan.
8 | #
9 | # IPscan is free software: you can redistribute it and/or modify
10 | # it under the terms of the GNU General Public License as published by
11 | # the Free Software Foundation, either version 3 of the License, or
12 | # (at your option) any later version.
13 | #
14 | # This program is distributed in the hope that it will be useful,
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | # GNU General Public License for more details.
18 | #
19 | # You should have received a copy of the GNU General Public License
20 | # along with IPscan. If not, see .
21 | #
22 | # upgrade.bsh
23 | # version description
24 | # 0.01 initial version
25 | # 0.02 update copyright year
26 | # 0.03 update copyright year
27 | # 0.04 update copyright year
28 | # 0.05 update copyright year
29 | # 0.06 update copyright year
30 | # 0.07 update copyright year
31 |
32 | SRC=./ipscan.h
33 | if [ -r "${SRC}" ] ; then
34 | echo "Found file containing credentials: "${SRC}
35 | MYSQL_HOST=$(awk 'BEGIN{u="TJC369"};{if ($1 == "#define" && $2 == "MYSQL_HOST") {u=$3;gsub("\"","",u)}};END{print u}' ${SRC})
36 | MYSQL_USER=$(awk 'BEGIN{u="TJC369"};{if ($1 == "#define" && $2 == "MYSQL_USER") {u=$3;gsub("\"","",u)}};END{print u}' ${SRC})
37 | MYSQL_PASSWD=$(awk 'BEGIN{u="TJC369"};{if ($1 == "#define" && $2 == "MYSQL_PASSWD") {u=$3;gsub("\"","",u)}};END{print u}' ${SRC})
38 | MYSQL_DBNAME=$(awk 'BEGIN{u="TJC369"};{if ($1 == "#define" && $2 == "MYSQL_DBNAME") {u=$3;gsub("\"","",u)}};END{print u}' ${SRC})
39 | MYSQL_TBLNAME=$(awk 'BEGIN{u="TJC369"};{if ($1 == "#define" && $2 == "MYSQL_TBLNAME") {u=$3;gsub("\"","",u)}};END{print u}' ${SRC})
40 | if [[ "${MYSQL_HOST}" = "TJC369" || "${MYSQL_USER}" = "TJC369" || "${MYSQL_PASSWD}" = "TJC369" || "${MYSQL_DBNAME}" = "TJC369" || "${MYSQL_TBLNAME}" = "TJC369" ]] ; then
41 | echo ""
42 | echo "ERROR: Failed to find a complete set of MYSQL_ variables:"
43 | echo "MYSQL_HOST ="$MYSQL_HOST
44 | echo "MYSQL_USER ="$MYSQL_USER
45 | echo "MYSQL_PASSWD ="$MYSQL_PASSWD
46 | echo "MYSQL_DBNAME ="$MYSQL_DBNAME
47 | echo "MYSQL_TBLNAME="$MYSQL_TBLNAME
48 | exit 1
49 | fi
50 | # dropping the results table is sufficient to cause the upgrade - it will be automatically created in the new format
51 | mysql --user=${MYSQL_USER} --password=${MYSQL_PASSWD} --host=${MYSQL_HOST} --execute='drop table if exists '${MYSQL_TBLNAME}';' ${MYSQL_DBNAME}
52 | RC=$?
53 | if [ "${RC}" -eq 0 ] ; then
54 | echo "MySQL command finished successfully"
55 | else
56 | echo "MySQL command finished unsuccessfully, with RC="${RC}
57 | fi
58 | else
59 | echo "Failed to find file containing credentials, looking for: "${SRC}
60 | fi
61 |
--------------------------------------------------------------------------------