List of commits:
Subject Hash Author Date (UTC)
First add d3b73b065b617424162195b5dfef2f0121adaa46 Catalin(ux) M. BOIE 2022-07-08 05:54:34
Commit d3b73b065b617424162195b5dfef2f0121adaa46 - First add
Author: Catalin(ux) M. BOIE
Author date (UTC): 2022-07-08 05:54
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2022-07-08 05:54
Parent(s):
Signer:
Signing key:
Signing status: N
Tree: 952e4913c133e135747c087f3779a48ffd5e0755
File Lines added Lines deleted
.gitignore 5 0
LICENSE 674 0
Makefile.in 34 0
README 2 0
TODO 2 0
agent/Makefile 55 0
agent/TODO 43 0
agent/Tech.txt 123 0
agent/ctools.c 882 0
agent/ctools.h 72 0
agent/inet_diag.h 1 0
agent/ninedogs.c 1099 0
agent/ninedogs.h 1 0
agent/ninedogs_dlsym_env.c 37 0
agent/ninedogs_dlsym_func.c 29 0
agent/openssl.TODO 6 0
agent/openssl.c 308 0
agent/openssl.h 207 0
agent/openssl.txt 107 0
agent/php.TODO 2 0
agent/php.c 983 0
agent/php.h 3 0
agent/process.c 16 0
agent/process.h 2 0
agent/process_core.c 82 0
agent/process_core.h 1 0
agent/process_db.c 456 0
agent/process_db.h 38 0
agent/process_misc.c 45 0
agent/process_misc.h 4 0
agent/process_ssl.c 172 0
agent/process_ssl.h 20 0
agent/sock1.c 187 0
agent/sock2.c 260 0
common/Makefile 15 0
common/ids.h 58 0
common/tools.c 353 0
common/tools.h 20 0
configure 3 0
duilder 710 0
ingestd/Makefile 28 0
ingestd/decode.c 70 0
ingestd/decode.h 2 0
ingestd/decode_core.c 228 0
ingestd/decode_core.h 4 0
ingestd/decode_db.c 156 0
ingestd/decode_db.h 4 0
ingestd/decode_ssl.c 98 0
ingestd/decode_ssl.h 6 0
ingestd/gdb.cmd 2 0
ingestd/gdb.sh 3 0
ingestd/ninedogs-ingestd.c 215 0
ingestd/ninedogs-ingestd.service 16 0
ingestd/priv.h 24 0
ingestd/stools.c 122 0
ingestd/stools.h 12 0
File .gitignore added (mode: 100644) (index 0000000..0375b38)
1 /Makefile
2 *.strace
3 *.o
4 *.so
5 *.log
File LICENSE added (mode: 100644) (index 0000000..94a9ed0)
1 GNU GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
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 How to Apply These Terms to Your New Programs
624
625 If you develop a new program, and you want it to be of the greatest
626 possible use to the public, the best way to achieve this is to make it
627 free software which everyone can redistribute and change under these terms.
628
629 To do so, attach the following notices to the program. It is safest
630 to attach them to the start of each source file to most effectively
631 state the exclusion of warranty; and each file should have at least
632 the "copyright" line and a pointer to where the full notice is found.
633
634 <one line to give the program's name and a brief idea of what it does.>
635 Copyright (C) <year> <name of author>
636
637 This program is free software: you can redistribute it and/or modify
638 it under the terms of the GNU General Public License as published by
639 the Free Software Foundation, either version 3 of the License, or
640 (at your option) any later version.
641
642 This program is distributed in the hope that it will be useful,
643 but WITHOUT ANY WARRANTY; without even the implied warranty of
644 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 GNU General Public License for more details.
646
647 You should have received a copy of the GNU General Public License
648 along with this program. If not, see <http://www.gnu.org/licenses/>.
649
650 Also add information on how to contact you by electronic and paper mail.
651
652 If the program does terminal interaction, make it output a short
653 notice like this when it starts in an interactive mode:
654
655 <program> Copyright (C) <year> <name of author>
656 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 This is free software, and you are welcome to redistribute it
658 under certain conditions; type `show c' for details.
659
660 The hypothetical commands `show w' and `show c' should show the appropriate
661 parts of the General Public License. Of course, your program's commands
662 might be different; for a GUI interface, you would use an "about box".
663
664 You should also get your employer (if you work as a programmer) or school,
665 if any, to sign a "copyright disclaimer" for the program, if necessary.
666 For more information on this, and how to apply and follow the GNU GPL, see
667 <http://www.gnu.org/licenses/>.
668
669 The GNU General Public License does not permit incorporating your program
670 into proprietary programs. If your program is a subroutine library, you
671 may consider it more useful to permit linking proprietary applications with
672 the library. If this is what you want to do, use the GNU Lesser General
673 Public License instead of this License. But first, please read
674 <http://www.gnu.org/philosophy/why-not-lgpl.html>.
File Makefile.in added (mode: 100644) (index 0000000..3532107)
1 export CC := gcc
2 export INCS +=
3 export LIBS += -ldl
4 export CFLAGS += @CC_SWITCHES@
5 export CFLAGS += -ggdb -Wall -Wextra -pipe
6 export CFLAGS += -D _FORTIFY_SOURCES=2
7
8 export LIBS += $(shell pkg-config --libs gnutls)
9 export CFLAGS += $(shell pkg-config --cflags gnutls)
10
11 export CFLAGSSO = $(CFLAGS) -ldl -shared -rdynamic -fPIC
12
13 .PHONY: common
14 common:
15 make -C common compile
16
17 .PHONY: agent
18 agent:
19 make -C agent compile
20
21 .PHONY: ingestd
22 ingestd:
23 make -C ingestd compile
24
25 all: common agent ingestd
26
27 .PHONY: clean
28 clean:
29 make -C agent clean
30
31 .PHONY: install
32 install:
33 make -C agent install
34
File README added (mode: 100644) (index 0000000..d7c52eb)
1 sentry/Dynatrace like monitoring program
2
File TODO added (mode: 100644) (index 0000000..2e9f0e9)
1 [ ] For free software project, this software will be free.
2 [ ]
File agent/Makefile added (mode: 100644) (index 0000000..af82878)
1 # This is just to allow us to run make here
2 .PHONY: all
3 all:
4 make -C .. agent
5
6 COMMON_H += ../common/ids.h
7
8 CFLAGS += -I../common
9
10 OBJS := ctools.o php.o process.o process_core.o process_misc.o process_db.o process_ssl.o openssl.o ../common/tools.o
11
12 ninedogs_dlsym_env.so: ninedogs_dlsym_env.c
13 $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_env.so -o $@ $<
14
15 ninedogs_dlsym_func.so: ninedogs_dlsym_func.c
16 $(CC) $(CFLAGSSO) -Wl,-soname,ninedogs_dlsym_func.so -o $@ $<
17
18 ctools.o: ctools.c ctools.h $(COMMON_H) ../common/tools.h
19 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
20
21 php.o: php.c php.h process_db.h $(COMMON_H)
22 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
23
24 openssl.o: openssl.c openssl.h process_ssl.h $(COMMON_H)
25 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
26
27 process.o: process.c process.h $(COMMON_H)
28 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
29
30 process_core.o: process_core.c process_core.h $(COMMON_H)
31 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
32
33 process_misc.o: process_misc.c process_misc.h $(COMMON_H)
34 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
35
36 process_db.o: process_db.c process_db.h $(COMMON_H)
37 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
38
39 process_ssl.o: process_ssl.c process_ssl.h $(COMMON_H)
40 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
41
42 ninedogs.so: ninedogs.c $(OBJS) $(COMMON_H)
43 $(CC) $(CFLAGS) $(CFLAGSSO) -Wl,-soname,ninedogs.so -o $@ ninedogs.c $(OBJS) $(LIBS)
44
45
46 compile: ninedogs_dlsym_env.so ninedogs_dlsym_func.so ninedogs.so
47
48 .PHONY: clean
49 clean:
50 @rm -f ninedogs*.so.* *.strace *.log *.out *.o
51
52 install: all
53 @mkdir -p /usr/lib
54 cp -vd ninedogs*.so /usr/lib
55
File agent/TODO added (mode: 100644) (index 0000000..169a3ee)
1 [ ] Investigate ltrace sources!
2 [ ] Use sbrk to know the heap size.
3 [ ] atexit/on_exit are not executed.
4 [ ] Real-time see reads/writes from open files/disks.
5 [ ] Catch also realloc (also for my allocator), calloc, mmap and munmap!
6 [ ] Capture pthread_setname_np and append the info that ninedogs is there.
7 [ ] Capture certificate expiration.
8 [ ] https://stackoverflow.com/questions/9232892/ld-preload-with-setuid-binary
9 I need to set the setuid bit for my .so.
10 [ ] Allow ninedogs disabling by passing a kernel paramenter.
11 [ ] man sysinfo
12 [ ] By whois, it seems we can get the domain expiration - report it.
13 Mostly for webservers.
14 [ ] Can we report something about SPF/DKIM?
15 [ ] Can we report something for DNSSEC? Key expiration?
16 [ ] At stop, send a message with the error code. Also when SEGV.
17 [ ] Send uptime
18 [ ]
19
20
21 == TLS ==
22 [ ] When connecting to a server and negotiate a vulnerable protocol, signal it.
23 [ ]
24
25 == PHP ==
26 [ ] We may want to catch zend_exception_error
27 [ ] Capture pg_socket to get byte counts with diag?
28 [ ] Catch if pg_free_result is not called! Is it a problem?
29 Seems that pg_free_result is not caled automatically. It's a leak?
30 Seems not, but free_result is not called, probably is somethink internal.
31 [ ] db close conn to free a handle
32 [ ]
33
34
35 == Databases ==
36 [ ] Gather statistics about bytes in/out for every query!
37 In PHP seems we cannot because when .so is loaded, the
38 symbols resolving is not propagated to my preload .so.
39 [ ] If a query was not used at flush time, free it.
40 [ ] Count free_results to see if free_result is called.
41 [ ] Hook [pg]_close functions. We may give a hint for persistent connection.
42 [ ]
43
File agent/Tech.txt added (mode: 100644) (index 0000000..46314d8)
1 set environment NINEDOGS_VERBOSE=100
2 set environment LD_PRELOAD=../../agent/ninedogs.so
3 break zend_fetch_resource
4 =====
5 current_execute_data: exista in Zend/zend_globals.h
6 EG(current_execute_data) pare sa fie struct _zend_executor_globals.current_execute_data
7 gdb: p *executor_globals.current_execute_data
8 =====
9 arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1)
10 ZEND_CALL_VAR_NUM(current_execute_data, i)
11 (((zval*)(current_execute_data)) + (ZEND_CALL_FRAME_SLOT + i)
12 =====
13
14 PHP Fatal error: Uncaught TypeError: pg_query_params():
15 supplied resource is not a valid PostgreSQL result resource
16 in /date/sync/no-crypt/sync1/Dev/ninedogs/test/pg1/1.php:60
17
18 te = (struct zend_execute_data *) 0x5555561a5030
19 old_pg_num_rows(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_ROWS);
20 php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, entry_type=PHP_PG_NUM_ROWS, return_value=0x7fffffffa200);
21 zend_parse_parameters(ZEND_NUM_ARGS(), type_spec="r", &result=0x7fffffffa1f0)
22 zend_parse_va_args(num_args=1, type_spec="r", va=0x7fffffffa0b0, flags=0)
23 zend_parse_arg(arg_num=1, arg=0x7ffff6613190, va=0x7fffffffa0b0, spec=0x7fffffffa068, flags=0)
24 zend_parse_arg_impl (error=0x7fffffffa008, spec=0x7fffffffa078, va=0x7fffffffa0c0, arg=0x7ffff6613190)
25 zval **p = va_arg(*va, zval **);
26 [ arg = (zval *) 0x7ffff6613190 ] [p = (zval **) 0x7fffffffa0c0 ]
27 zend_parse_arg_resource(arg, p, check_null) (check_null=false, dest=<optimized out>, arg=0x7ffff6613190)
28 pg_result = (pgsql_result_handle *)zend_fetch_resource(result.value.res,
29 "PostgreSQL result", le_result[20])
30 # le_result este 20; res->type este 18; 20 e postgres-ul
31 pgsql_result = pg_result->result;
32 RETVAL_LONG(PQntuples(pgsql_result));
33
34 == add a breakpoint to zend_parse_arg to catch full trace
35
36 p *result [cazul care merge]
37 $14 = {value = {lval = 140737327268104, dval = 6.9533478490686681e-310, counted = 0x7ffff6660108, str = 0x7ffff6660108,
38 arr = 0x7ffff6660108, obj = 0x7ffff6660108, res = 0x7ffff6660108, ref = 0x7ffff6660108, ast = 0x7ffff6660108,
39 zv = 0x7ffff6660108, ptr = 0x7ffff6660108, ce = 0x7ffff6660108, func = 0x7ffff6660108, ww = {w1 = 4133880072,
40 w2 = 32767}}, u1 = {type_info = 265, v = {type = 9 '\t', type_flags = 1 '\001', u = {extra = 0}}}, u2 = {
41 next = 1936876900, cache_slot = 1936876900, opline_num = 1936876900, lineno = 1936876900, num_args = 1936876900,
42 fe_pos = 1936876900, fe_iter_idx = 1936876900, access_flags = 1936876900, property_guard = 1936876900,
43 constant_flags = 1936876900, extra = 1936876900}}
44
45 p *result [cazul in care NU merge]
46 $21 = {value = {lval = 140737327268032, dval = 6.9533478490651108e-310, counted = 0x7ffff66600c0, str = 0x7ffff66600c0,
47 arr = 0x7ffff66600c0, obj = 0x7ffff66600c0, res = 0x7ffff66600c0, ref = 0x7ffff66600c0, ast = 0x7ffff66600c0,
48 zv = 0x7ffff66600c0, ptr = 0x7ffff66600c0, ce = 0x7ffff66600c0, func = 0x7ffff66600c0, ww = {w1 = 4133880000,
49 w2 = 32767}}, u1 = {type_info = 265, v = {type = 9 '\t', type_flags = 1 '\001', u = {extra = 0}}}, u2 = {
50 next = 1936876900, cache_slot = 1936876900, opline_num = 1936876900, lineno = 1936876900, num_args = 1936876900,
51 fe_pos = 1936876900, fe_iter_idx = 1936876900, access_flags = 1936876900, property_guard = 1936876900,
52 constant_flags = 1936876900, extra = 1936876900}}
53
54 Bad:
55 dump zed [len=96] [0x55c670f1c200]
56 0000: 746f205554462d38 2e0a3b2068747470 3a2f2f7068702e6e c0bcef70c6550000 to UTF-8. ; http://php.n p U
57 0020: 00000000000000000000000001000000[This] 2030e110a67f0000[prev] 6574203d20225554 0 et = "UT
58 0040: 462d38220a0a3b2050485020696e7465 0801e610a67f0000[para1] 09010000[u1] 68617261 F-8" ; PHP inte hara
59 zed: p=0x55c670f1c200 num_args=1 return_value[0x6e2e7068702f2f3a] + This:
60 zval 0x55c670f1c220: value=0[0x0] type_info=0 type=undef type_flags=0 extra=0 num_args=1
61 para 0: type=resource value=0x7fa610e60108
62 after calling old pg_num_rows: type=undef value=?0: (nil)
63 rz: zval 0x7fff75c2a480: value=0[0x0] type_info=0 type=undef type_flags=0 extra=0 num_args=0
64
65 Good:
66 dump zed [len=96] [0x7fd1ae413140]
67 0000: 746f205554462d38 2e0a3b2068747470 3a2f2f7068702e6e a0118e8fc7550000 to UTF-8. ; http://php.n U
68 0020: 00000000000000000000000001000000[This] 203041aed17f0000[prev] 6574203d20225554 0A et = "UT
69 0040: 462d38220a0a3b2050485020696e7465 080146aed17f0000[para1] 09010000[u1] 65722065 F-8" ; PHP inte F er e
70 zed: p=0x7fd1ae413140 num_args=1 return_value[0x6e2e7068702f2f3a] + This:
71 zval 0x7fd1ae413160: value=0[0x0] type_info=0 type=undef type_flags=0 extra=0 num_args=1
72 para 0: type=resource value=0x7fd1ae460108
73 old my_pg_num_rows: type=long value=2
74 retv: zval 0x7fd1ae413130: value=2[0x2] type_info=4 type=long type_flags=0 extra=0 num_args=544499059
75
76 ===============================================================================
77
78 RETURN_THROWS => PHP Fatal error: Uncaught ArgumentCountError: pg_connect() expects at least 1 argument, 0 given in /date/sync/no-crypt/sync1/Dev/ninedogs/test/pg1/1.php:4
79 Stack trace:
80 #0 /date/sync/no-crypt/sync1/Dev/ninedogs/test/pg1/1.php(4): pg_connect()
81 #1 {main}
82 thrown in /date/sync/no-crypt/sync1/Dev/ninedogs/test/pg1/1.php on line 4
83
84 #define RETURN_THROWS() do { ZEND_ASSERT(EG(exception)); (void) return_value; return; } while (0)
85
86 # define ZEND_ASSERT(c) ZEND_ASSUME(c)
87
88 # define ZEND_ASSUME(c) do { \
89 if (__builtin_expect(!(c), 0)) __builtin_unreachable(); \
90 } while (0)
91
92 # define EG(v) (executor_globals.v)
93 extern ZEND_API zend_executor_globals executor_globals;
94
95
96
97
98
99
100 if (pgsql == NULL || PQstatus(pgsql) == CONNECTION_BAD) {
101 PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql)
102
103 #define PHP_PQ_ERROR(text, pgsql) { \
104 zend_string *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql)); \
105 php_error_docref(NULL, E_WARNING, text, ZSTR_VAL(msgbuf)); \
106 zend_string_release(msgbuf); \
107 } \
108
109 PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format, ...)
110 {
111 va_list args;
112
113 va_start(args, format);
114 php_verror(docref, "", type, format, args);
115 va_end(args);
116 }
117
118
119 #define RETURN_FALSE do { RETVAL_FALSE; return; } while (0)
120 #define RETVAL_FALSE ZVAL_FALSE(return_value)
121 #define ZVAL_FALSE(z) do { \
122 Z_TYPE_INFO_P(z) = IS_FALSE; \
123 } while (0)
File agent/ctools.c added (mode: 100644) (index 0000000..74f47b9)
1 #define _GNU_SOURCE 500
2
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 #include <string.h>
9 #include <sys/socket.h>
10 #include <sys/random.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <arpa/inet.h>
14 #include <netinet/in.h>
15 #include <netinet/tcp.h>
16 #include <poll.h>
17 #include <errno.h>
18 #include <netdb.h>
19 #include <fcntl.h>
20 #include <sys/sysinfo.h>
21
22 #include <gnutls/gnutls.h>
23 #include <gnutls/x509.h>
24
25 #include "ids.h"
26 #include "tools.h"
27 #include "ctools.h"
28
29
30 extern ssize_t (*old_write)(int fd, const void *buf, size_t count);
31 extern void *(*old_malloc)(size_t size);
32 extern void (*old_free)(void *p);
33 extern int (*old_getaddrinfo)(const char *restrict node, const char *restrict service,
34 const struct addrinfo *restrict hints, struct addrinfo **restrict res);
35 extern int (*old_open)(const char *pathname, int flags, ...);
36
37 enum
38 {
39 CONN_STATE_RETRY,
40 CONN_STATE_INIT,
41 CONN_STATE_CONN,
42 CONN_STATE_CONN_WAIT,
43 CONN_STATE_TLS_INIT,
44 CONN_STATE_TLS_HAND,
45 CONN_STATE_WS_SEND,
46 CONN_STATE_WS_WAIT,
47 CONN_STATE_OK
48 };
49
50 static char *conn_state_name(const unsigned int conn_state)
51 {
52 switch (conn_state) {
53 case CONN_STATE_RETRY: return "retry";
54 case CONN_STATE_INIT: return "init";
55 case CONN_STATE_CONN: return "conn";
56 case CONN_STATE_CONN_WAIT: return "conn_wait";
57 case CONN_STATE_TLS_INIT: return "tls_init";
58 case CONN_STATE_TLS_HAND: return "tls_hand";
59 case CONN_STATE_WS_SEND: return "ws_send";
60 case CONN_STATE_WS_WAIT: return "ws_wait";
61 case CONN_STATE_OK: return "ok";
62 }
63
64 return "?";
65 }
66
67 unsigned int verbose = 0;
68 char *log_file = NULL;
69 int Log = -1;
70 struct info fdinfo;
71 static __thread unsigned int my_tid;
72
73
74 char *sdomain(const int domain)
75 {
76 static char tmp[16];
77
78 switch (domain) {
79 case AF_INET: return "IPv4";
80 case AF_INET6: return "IPv6";
81 default: snprintf(tmp, sizeof(tmp), "%d", domain); return tmp;
82 }
83 }
84
85 char *stype(const int type)
86 {
87 static char tmp[16];
88
89 switch (type & 0xfff) {
90 case SOCK_STREAM: return "stream";
91 case SOCK_DGRAM: return "dgram";
92 case SOCK_RAW: return "raw";
93 case SOCK_SEQPACKET: return "seqpacket";
94 case SOCK_DCCP: return "dccp";
95 case SOCK_PACKET: return "packet";
96 default: snprintf(tmp, sizeof(tmp), "%d", type); return tmp;
97 }
98 }
99
100 char *sprotocol(const int protocol)
101 {
102 static char tmp[16];
103
104 switch (protocol) {
105 case IPPROTO_TCP: return "tcp";
106 case IPPROTO_UDP: return "udp";
107 default: snprintf(tmp, sizeof(tmp), "%d", protocol); return tmp;
108 }
109 }
110
111 /*
112 * Fills @out with domain/type/address/port string
113 */
114 void saddr(char *out, const size_t out_len,
115 const struct sockaddr *sa)
116 {
117 struct sockaddr_in *s4;
118 struct sockaddr_in6 *s6;
119 char addr[40], port[8];
120
121 switch (sa->sa_family) {
122 case AF_INET:
123 s4 = (struct sockaddr_in *) sa;
124 inet_ntop(AF_INET, (void *) &s4->sin_addr.s_addr, addr, sizeof(struct sockaddr_in));
125 snprintf(port, sizeof(port), "%d", ntohs(s4->sin_port));
126 break;
127 case AF_INET6:
128 s6 = (struct sockaddr_in6 *) sa;
129 inet_ntop(AF_INET6, (void *) &s6->sin6_addr.s6_addr, addr, sizeof(struct sockaddr_in6));
130 snprintf(port, sizeof(port), "%d", ntohs(s6->sin6_port));
131 break;
132 default:
133 strcpy(addr, "?");
134 strcpy(port, "?");
135 break;
136 }
137
138 snprintf(out, out_len, "%s/%s/%s",
139 sdomain(sa->sa_family), addr, port);
140 }
141
142 void xlog(const unsigned int level, const char *format, ...)
143 {
144 va_list ap;
145 char a[4096];
146 size_t len0, len;
147 struct timeval t;
148
149 if (!old_write)
150 return;
151
152 if (level > verbose)
153 return;
154
155 if (Log == -1)
156 return;
157
158 if (my_tid == 0)
159 my_tid = gettid();
160
161 gettimeofday(&t, NULL);
162 len0 = snprintf(a, sizeof(a), "%ld.%03ld %u ",
163 t.tv_sec, t.tv_usec / 1000, my_tid);
164
165 va_start(ap, format);
166 len = vsnprintf(a + len0, sizeof(a) - len0, format, ap);
167 len += len0;
168 va_end(ap);
169
170 if (len >= sizeof(a) - 1)
171 len = sizeof(a) - 1;
172 old_write(Log, a, len);
173 }
174
175 void dump(const unsigned int level, const char *title, const void *buf,
176 const unsigned int len)
177 {
178 unsigned int i, j, rest;
179 unsigned char *buf2 = (unsigned char *) buf;
180 char out[1024], c;
181
182 if (!buf)
183 return;
184
185 xlog(level, " dump %s [len=%u] [%p]\n", title, len, buf);
186
187 i = 0; rest = len;
188 while (i < len) {
189 sprintf(out, " %04x: ", i);
190 rest = len - i;
191 if (rest > 32)
192 rest = 32;
193
194 for (j = 0; j < 32; j++) {
195 if (j < rest)
196 snprintf(out + 8 + j * 2, 3, "%02x", buf2[i + j]);
197 else
198 sprintf(out + 8 + j * 2, " ");
199 }
200
201 strcat(out, " ");
202
203 for (j = 0; j < rest; j++) {
204 c = buf2[i + j];
205 if ((c < 0x20) || (c > 0x7E))
206 c = ' ';
207 sprintf(out + 8 + 32 * 2 + 2 + j, "%c", c);
208 }
209
210 xlog(level, "%s\n", out);
211 i += rest;
212 }
213 }
214
215 struct node *get(const int fd)
216 {
217 struct node *p;
218
219 p = fdinfo.head;
220 while (p != NULL) {
221 if (p->fd == fd)
222 return p;
223
224 p = p->next;
225 }
226
227 return NULL;
228 }
229
230 /*
231 * List all sockets
232 */
233 void list(const unsigned int level)
234 {
235 struct node *q;
236 struct private *p;
237 char dest[128];
238
239 xlog(level, " list...\n");
240
241 q = fdinfo.head;
242 while (q != NULL) {
243 if (q->fd == -1) {
244 q = q->next;
245 continue;
246 }
247
248 p = &q->priv;
249 saddr(dest, sizeof(dest), (struct sockaddr *) &p->dest);
250 xlog(level, " fd=%4d type=%s flags=%04x limit=%llu"
251 " rest=%llu last=%u.%06u dest=%s\n",
252 q->fd, stype(p->type), p->flags, p->limit,
253 p->rest, p->last.tv_sec, p->last.tv_usec, dest);
254 q = q->next;
255 }
256 }
257
258 void add(const int fd, const struct private *p)
259 {
260 struct node *q;
261
262 //xlog(2, " add(fd=%d, ...)\n", fd);
263
264 /* do we have a copy? */
265 q = get(fd);
266 if (q == NULL) {
267 /* Try to find a free location */
268 q = fdinfo.head;
269 while (q != NULL) {
270 if (q->fd == -1) {
271 q->fd = fd;
272 break;
273 }
274
275 q = q->next;
276 }
277
278 if (q == NULL) {
279 q = (struct node *) old_malloc(sizeof(struct node));
280 if (q == NULL) {
281 xlog(0, " cannot alloc memory"
282 "; ignore fd!\n");
283 return;
284 }
285
286 q->next = NULL;
287 q->fd = fd;
288
289 if (fdinfo.tail == NULL) {
290 fdinfo.head = q;
291 } else {
292 fdinfo.tail->next = q;
293 }
294 fdinfo.tail = q;
295 }
296 }
297 memcpy(&q->priv, p, sizeof(struct private));
298 }
299
300 void del(const int fd)
301 {
302 struct node *p;
303
304 //xlog(2, " del(fd=%d)\n", fd);
305
306 p = fdinfo.head;
307 while (p != NULL) {
308 if (p->fd == fd) {
309 p->fd = -1;
310 break;
311 }
312
313 p = p->next;
314 }
315 }
316
317 void my_time_diff(struct timeval *dst,
318 const struct timeval *e, const struct timeval *s)
319 {
320 dst->tv_sec = e->tv_sec - s->tv_sec;
321 if (e->tv_usec < s->tv_usec) {
322 dst->tv_usec = 1000000UL + e->tv_usec - s->tv_usec;
323 dst->tv_sec--;
324 } else {
325 dst->tv_usec = e->tv_usec - s->tv_usec;
326 }
327 }
328
329 int my_time_compare(const struct timeval *a, const struct timeval *b)
330 {
331 if (a->tv_sec < b->tv_sec)
332 return -1;
333 if (a->tv_sec > b->tv_sec)
334 return 1;
335 if (a->tv_usec < b->tv_usec)
336 return -1;
337 if (a->tv_usec > b->tv_usec)
338 return 1;
339
340 return 0;
341 }
342
343 void my_time_add(struct timeval *dst, const struct timeval *src)
344 {
345 dst->tv_sec += src->tv_sec;
346
347 dst->tv_usec += src->tv_usec;
348 if (dst->tv_usec >= 1000000) {
349 dst->tv_sec++;
350 dst->tv_usec -= 1000000;
351 }
352 }
353
354 struct server_node
355 {
356 void *data;
357 unsigned int data_len;
358 unsigned int data_off;
359 struct server_node *next;
360 };
361 static __thread struct server_node *server_head, *server_tail;
362
363 static char server_is_disabled = 0;
364 static gnutls_certificate_credentials_t xcred;
365 static char *server, *port, *url, id[33];
366
367 void server_init(void)
368 {
369 int r;
370
371 xlog(10, "%s...\n", __func__);
372
373 do {
374 do {
375 char *s = getenv("NINEDOGS_ID");
376 if (s && strlen(s) == 32) {
377 snprintf(id, sizeof(id), "%s", s);
378 break;
379 }
380
381 int fd = old_open("/var/lib/ninedogs/id", O_RDONLY);
382 if (fd != -1) {
383 ssize_t n = read(fd, id, sizeof(id) - 1);
384 close(fd);
385 if (n >= 32) {
386 id[32] = '\0';
387 break;
388 }
389 }
390
391 unsigned char id_bin[16];
392 ssize_t n = getrandom(id_bin, sizeof(id_bin), 0);
393 if (n == -1)
394 memset(id_bin, 0, sizeof(id_bin));
395 for (unsigned char i = 0; i < sizeof(id_bin); i++)
396 snprintf(id + i * 2, 3, "%02hhx", id_bin[i]);
397 fd = old_open("/var/lib/ninedogs/id", O_CREAT | O_WRONLY | O_TRUNC, 0644);
398 if (fd != -1) {
399 write(fd, id, sizeof(id) - 1);
400 close(fd);
401 break;
402 }
403 } while (0);
404 xlog(10, "id is [%s]\n", id);
405
406 server = getenv("NINEDOGS_SERVER_HOSTNAME");
407 port = getenv("NINEDOGS_SERVER_PORT");
408 if (!port || (*port == '\0'))
409 port = "443";
410 url = getenv("NINEDOGS_SERVER_URL");
411 if (!url || (*url == '\0'))
412 url = "/ingest";
413 xlog(20, "server=[%s] port=[%s] url=[%s]\n",
414 server ? server : "n/a", port, url);
415
416 if (!server || (*server == '\0')) {
417 xlog(10, "NINEDOGS_SERVER_HOSTNAME/PORT/URL not defined! Disabling sending.\n");
418 server_is_disabled = 1;
419 break;
420 }
421
422 r = gnutls_global_init();
423 if (r != GNUTLS_E_SUCCESS) {
424 xlog(10, "gnutls error: error calling global_init: %s\n", gnutls_strerror(r));
425 server_is_disabled = 1;
426 break;
427 }
428
429 /* X509 stuff */
430 xlog(20, "Allocating credentials...\n");
431 r = gnutls_certificate_allocate_credentials(&xcred);
432 if (r != GNUTLS_E_SUCCESS) {
433 xlog(10, "gnutls error: cannot allocate credentials!\n");
434 server_is_disabled = 1;
435 break;
436 }
437
438 /* sets the system trusted CAs for Internet PKI */
439 xlog(20, "Setting system trust...\n");
440 r = gnutls_certificate_set_x509_system_trust(xcred);
441 if (r < 0) {
442 xlog(10, "gnutls error: cannot set system trust [%d]!\n", r);
443 server_is_disabled = 1;
444 break;
445 }
446 } while (0);
447
448 xlog(10, "%s done\n", __func__);
449 }
450
451 void server_enqueue(void *buf, const unsigned int len)
452 {
453 struct server_node *p;
454
455 if (len == 0)
456 abort();
457
458 if (server_is_disabled) {
459 xlog(10, "%s: server is disabled!\n", __func__);
460 return;
461 }
462
463 // TODO: keep a pool of nodes to avoid memory allocation
464 p = old_malloc(sizeof(struct server_node));
465 if (!p)
466 return;
467
468 p->data = buf;
469 p->data_off = 0;
470 p->data_len = len;
471 p->next = NULL;
472
473 if (!server_head)
474 server_head = p;
475 else
476 server_tail->next = p;
477 server_tail = p;
478 }
479
480 void server_enqueue_front(void *buf, const unsigned int len)
481 {
482 struct server_node *p;
483
484 if (len == 0)
485 abort();
486
487 if (server_is_disabled) {
488 xlog(10, "%s: server is disabled!\n", __func__);
489 return;
490 }
491
492 // TODO: keep a pool of nodes to avoid memory allocation
493 p = old_malloc(sizeof(struct server_node));
494 if (!p)
495 return;
496
497 p->data = buf;
498 p->data_off = 0;
499 p->data_len = len;
500 if (!server_head)
501 server_tail = p;
502 p->next = server_head;
503 server_head = p;
504 }
505
506 static int server_fd = -1;
507 static gnutls_session_t server_session;
508 static char conn_state = CONN_STATE_INIT;
509 static char server_connect(void)
510 {
511 struct addrinfo hints, *result, *rp;
512 int r;
513 struct pollfd pf;
514 static char xbuf[4096];
515 static unsigned int xoff = 0;
516
517 xlog(50, "%s: conn_state=%s\n", __func__, conn_state_name(conn_state));
518
519 // all ok
520 if (conn_state == CONN_STATE_OK)
521 return 1;
522
523 if (conn_state == CONN_STATE_RETRY) { // delay reconnect
524 sleep(5);
525 conn_state = CONN_STATE_INIT;
526 }
527
528 if (conn_state == CONN_STATE_INIT) { // reset everything
529 xlog(50, " Cleaning everything...\n");
530 if (server_session) {
531 r = gnutls_bye(server_session, GNUTLS_SHUT_RDWR);
532 if (r != GNUTLS_E_SUCCESS)
533 xlog(10, " gnutls warn: cannot say goodbye: %s!\n", gnutls_strerror(r));
534
535 gnutls_deinit(server_session);
536 server_session = NULL;
537 }
538
539 if (server_fd != -1) {
540 close(server_fd);
541 server_fd = -1;
542 }
543
544 conn_state = CONN_STATE_CONN;
545 }
546
547 if (conn_state == CONN_STATE_CONN) {
548 xlog(50, " Resolving name...\n");
549 memset(&hints, 0, sizeof(hints));
550 hints.ai_family = AF_UNSPEC;
551 hints.ai_socktype = SOCK_STREAM;
552 r = old_getaddrinfo(server, port, &hints, &result);
553 if (r != 0) {
554 xlog(10, " getaddrinfo error: %s\n", gai_strerror(r));
555 return 0;
556 }
557
558 xlog(50, " Connecting...\n");
559 for (rp = result; rp != NULL; rp = rp->ai_next) {
560 server_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
561 if (server_fd == -1)
562 continue;
563
564 //int flags = fcntl(server_fd, F_GETFL);
565 //if (flags != -1)
566 // fcntl(server_fd, F_SETFL, flags | O_NONBLOCK);
567
568 r = connect(server_fd, rp->ai_addr, rp->ai_addrlen);
569 if ((r == -1) && (errno != EINPROGRESS)) {
570 close(server_fd); server_fd = -1;
571 xlog(10, " connect error: %m\n");
572 continue;
573 }
574
575 xlog(50, " Connecting to %s/%s; fd=%d!\n", server, port, server_fd);
576 conn_state = CONN_STATE_CONN_WAIT;
577 return 0;
578 }
579 freeaddrinfo(result);
580 if (server_fd == -1)
581 return 0;
582 }
583
584 if (conn_state == CONN_STATE_CONN_WAIT) {
585 xlog(50, " Waiting for conn to become writable...\n");
586 memset(&pf, 0, sizeof(struct pollfd));
587 pf.fd = server_fd;
588 pf.events = POLLOUT;
589 r = poll(&pf, 1, 0);
590 if (r == -1) {
591 xlog(10, " poll error: %m\n");
592 conn_state = CONN_STATE_RETRY;
593 return 0;
594 }
595 if (r == 0)
596 return 0;
597
598 conn_state = CONN_STATE_TLS_INIT;
599 }
600
601 if (conn_state == CONN_STATE_TLS_INIT) { // setup tls
602 xlog(50, " Initialize TLS session...\n");
603 r = gnutls_init(&server_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK);
604 if (r != GNUTLS_E_SUCCESS) {
605 xlog(10, " gnutls error: cannot init session: %s\n", gnutls_strerror(r));
606 conn_state = CONN_STATE_RETRY;
607 return 0;
608 }
609
610 r = gnutls_server_name_set(server_session, GNUTLS_NAME_DNS,
611 server, strlen(server));
612 if (r != GNUTLS_E_SUCCESS) {
613 xlog(10, " gnutls error: cannot set name [%s]: %s!\n",
614 server, gnutls_strerror(r));
615 conn_state = CONN_STATE_RETRY;
616 return 0;
617 }
618
619 /* It is recommended to use the default priorities */
620 r = gnutls_set_default_priority(server_session);
621 if (r != GNUTLS_E_SUCCESS) {
622 xlog(10, " gnutls error: cannot set default priority!\n");
623 conn_state = CONN_STATE_RETRY;
624 return 0;
625 }
626
627 /* put the x509 credentials to the current session */
628 r = gnutls_credentials_set(server_session, GNUTLS_CRD_CERTIFICATE, xcred);
629 if (r != GNUTLS_E_SUCCESS) {
630 xlog(10, " gnutls error: cannot set credentials!\n");
631 conn_state = CONN_STATE_RETRY;
632 return 0;
633 }
634 gnutls_session_set_verify_cert(server_session, server,
635 GNUTLS_VERIFY_ALLOW_UNSORTED_CHAIN);
636
637 gnutls_transport_set_int(server_session, server_fd);
638 gnutls_handshake_set_timeout(server_session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
639 conn_state = CONN_STATE_TLS_HAND;
640 }
641
642 if (conn_state == CONN_STATE_TLS_HAND) {
643 xlog(50, " TLS handshake...\n");
644 /* Perform the TLS handshake */
645
646 r = gnutls_handshake(server_session);
647 if (r < 0) {
648 xlog(10, " TLS handshake returned code %d: %s\n", r, gnutls_strerror(r));
649 if (r == GNUTLS_E_AGAIN)
650 return 0;
651
652 // Sometimes we get this error, but it is fatal! Probably a bug in GnuTLS.
653 // I had to switch to non-blocking.
654 //if (r == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND)
655 // return 0;
656
657 if (r == GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR) {
658 gnutls_datum_t out;
659 int type;
660 unsigned status;
661
662 /* check certificate verification status */
663 type = gnutls_certificate_type_get(server_session);
664 status = gnutls_session_get_verify_cert_status(server_session);
665 r = gnutls_certificate_verification_status_print(status, type, &out, 0);
666 if (r == GNUTLS_E_SUCCESS) {
667 xlog(10, " cert verify output: %s\n", out.data);
668 gnutls_free(out.data);
669 }
670 }
671
672 conn_state = CONN_STATE_RETRY;
673 return 0;
674 }
675
676 char *desc = gnutls_session_get_desc(server_session);
677 xlog(10, " Session info: %s\n", desc);
678 gnutls_free(desc);
679 conn_state = CONN_STATE_WS_SEND;
680 }
681
682 if (conn_state == CONN_STATE_WS_SEND) {
683 xlog(50, " Sending GET...\n");
684 char out[4096];
685 unsigned len = snprintf(out, sizeof(out),
686 "GET %s HTTP/1.1\r\n"
687 "Host: %s:%s\r\n"
688 "Connection: keep-alive, Upgrade\r\n"
689 "Pragma: no-cache\r\n"
690 "Cache-Control: no-cache\r\n"
691 "Upgrade: websocket\r\n"
692 "\r\n",
693 url, server, port);
694 xlog(50, "Sending: %s\n", out);
695 r = gnutls_record_send(server_session, out, len);
696 if (r < 0) {
697 if (r == GNUTLS_E_AGAIN)
698 return 0;
699
700 xlog(1, " Cannot send: %s\n", gnutls_strerror(r));
701 conn_state = CONN_STATE_RETRY;
702 return 0;
703 }
704
705 xoff = 0;
706 conn_state = CONN_STATE_WS_WAIT;
707 }
708
709 if (conn_state == CONN_STATE_WS_WAIT) {
710 xlog(50, " Waiting for ws handshake to finish [xoff=%u]...\n", xoff);
711 r = gnutls_record_recv(server_session, xbuf + xoff, sizeof(xbuf) - xoff - 1);
712 if (r < 0) {
713 xlog(10, " gnutls_record_recv returned %s\n", gnutls_strerror(r));
714 if (r != GNUTLS_E_AGAIN)
715 conn_state = CONN_STATE_RETRY;
716 return 0;
717 }
718 xlog(50, " gnutls_record_recv returned %d\n", r);
719 xoff += r;
720 xbuf[xoff] = '\0';
721 dump(200, " ws answer: ", xbuf, xoff);
722 if (!strstr(xbuf, "\r\n\r\n"))
723 return 0;
724
725 // When we reconnect, we do not want to send a partial request
726 if (server_head)
727 server_head->data_off = 0;
728
729 unsigned char *buf;
730 unsigned int len;
731 pack(&buf, &len, "T4 Is",
732 NINEDOGS_NET_CORE_ID, id, strlen(id));
733 if (buf)
734 server_enqueue_front(buf, len);
735
736 // TODO: send program name
737 struct timeval t; struct timezone tz;
738 gettimeofday(&t, &tz);
739 pack(&buf, &len, "T4 u4 p4 t4" "st z4 Z4",
740 NINEDOGS_NET_CORE_PROC,
741 getuid(), getpid(), my_tid,
742 &t, tz.tz_minuteswest, tz.tz_dsttime);
743 if (buf)
744 server_enqueue(buf, len);
745
746 conn_state = CONN_STATE_OK;
747 }
748
749 if (conn_state == CONN_STATE_OK) {
750 xlog(10, " Connection done!\n");
751 return 1;
752 }
753
754 return 0;
755 }
756
757 /*
758 * This function will try to keep the connection with the server alive
759 */
760 void server_pat(const char sync)
761 {
762 struct server_node *next;
763 static time_t last_conn_try = 0;
764 ssize_t r;
765 unsigned char buf[4 * 4096];
766
767 if (server_is_disabled)
768 return;
769
770 xlog(50, "%s sync=%hhd...\n", __func__, sync);
771
772 do {
773 server_connect();
774 } while ((sync == 1) && (conn_state != CONN_STATE_OK));
775 if (conn_state != CONN_STATE_OK)
776 return;
777
778 if (gnutls_record_check_pending(server_session)) {
779 xlog(10, " %s: checking for a possible command...\n", __func__);
780 r = gnutls_record_recv(server_session, buf, sizeof(buf));
781 if (r < 0) {
782 xlog(10, " gnutls_record_recv returned %s\n", gnutls_strerror(r));
783 if (r != GNUTLS_E_AGAIN) {
784 conn_state = CONN_STATE_RETRY;
785 return;
786 }
787 } else if (r == 0) {
788 xlog(10, "gnutls_record_recv returned 0\n");
789 } else {
790 dump(30, "tls recv", buf, r);
791 // TODO: deal with server messages
792 }
793 }
794
795 if (!server_head) {
796 //xlog(10, "%s: Nothing to send...\n", __func__);
797 return;
798 }
799
800 while (server_head) {
801 dump(100, "tls sending", server_head->data + server_head->data_off,
802 server_head->data_len - server_head->data_off);
803 do {
804 r = gnutls_record_send(server_session,
805 server_head->data + server_head->data_off,
806 server_head->data_len - server_head->data_off);
807 } while ((sync == 1) && (r == GNUTLS_E_AGAIN));
808 if (r == 0) {
809 xlog(1, " server closed connection\n");
810 return;
811 }
812 if (r < 0) {
813 if (r == GNUTLS_E_AGAIN)
814 return;
815
816 xlog(10, " gnutls_record_send returned: %s\n", gnutls_strerror(r));
817 conn_state = CONN_STATE_RETRY;
818 return;
819 }
820
821 server_head->data_off += r;
822 if (server_head->data_off != server_head->data_len) {
823 if (sync)
824 continue;
825 return;
826 }
827
828 next = server_head->next;
829 old_free(server_head->data);
830 old_free(server_head);
831 server_head = next;
832 }
833
834 // TODO: keep alive the connection here
835 }
836
837 void server_stop(void)
838 {
839 int r;
840
841 xlog(10, "%s...\n", __func__);
842
843 server_pat(1);
844
845 if (server_session) {
846 xlog(10, "%s: Sending bye...\n", __func__);
847 do {
848 r = gnutls_bye(server_session, GNUTLS_SHUT_RDWR);
849 //xlog(10, "bye returned: %s\n", gnutls_strerror(r));
850 } while (r == GNUTLS_E_AGAIN);
851 }
852 }
853
854 void send_sysinfo(void)
855 {
856 static time_t last_send = 0;
857 struct sysinfo s;
858 time_t now;
859
860 time(&now);
861 if ((last_send > 0) && (last_send + 60 > now))
862 return;
863
864 last_send = now;
865
866 int r = sysinfo(&s);
867 if (r == -1)
868 return;
869
870 unsigned char *buf;
871 unsigned int len;
872 pack(&buf, &len, "T4 NN u8" "18 58 q8" "r8 f8 s8" "b8 w8 W8" "p2 h8 H8 i4",
873 NINEDOGS_NET_CORE_SYSINFO, s.uptime,
874 s.loads[0], s.loads[1], s.loads[2],
875 s.totalram, s.freeram, s.sharedram,
876 s.bufferram, s.totalswap, s.freeswap,
877 s.procs, s.totalhigh, s.freehigh, s.mem_unit);
878 if (!buf)
879 return;
880 server_enqueue(buf, len);
881 }
882
File agent/ctools.h added (mode: 100644) (index 0000000..08e8346)
1 #include <arpa/inet.h>
2 #include <netinet/in.h>
3 #include <netinet/tcp.h>
4
5 struct private
6 {
7 int domain;
8 int type;
9 unsigned int flags;
10 unsigned int pad1;
11 struct sockaddr_storage dest;
12 socklen_t dest_len;
13 unsigned int pad2;
14
15 struct timeval conn_time;
16
17 /* bandwidth */
18 unsigned long long limit;
19 unsigned long long rest;
20 struct timeval last;
21 };
22
23 struct node
24 {
25 int fd;
26 int pad1;
27 struct private priv;
28 struct node *next;
29 };
30
31 struct info
32 {
33 struct node *head, *tail;
34 };
35
36
37 extern unsigned int verbose;
38 extern char *log_file;
39 extern int Log;
40 extern struct info fdinfo;
41
42
43 char *sdomain(const int domain);
44 char *stype(const int type);
45 char *sprotocol(const int protocol);
46 void saddr(char *out, const size_t out_len,
47 const struct sockaddr *sa);
48
49 void xlog(const unsigned int level, const char *format, ...);
50 void dump(const unsigned int level, const char *title, const void *buf,
51 const unsigned int len);
52
53
54 struct node *get(const int fd);
55 struct node *get(const int fd);
56 void list(const unsigned int level);
57 void add(const int fd, const struct private *p);
58 void del(const int fd);
59
60 void my_time_diff(struct timeval *dst,
61 const struct timeval *e, const struct timeval *s);
62 int my_time_compare(const struct timeval *, const struct timeval *);
63 void my_time_add(struct timeval *dst, const struct timeval *src);
64
65 void server_init(void);
66 void server_pat(const char sync);
67 void server_enqueue(void *buf, const unsigned int len);
68 void server_enqueue_front(void *buf, const unsigned int len);
69 void server_stop(void);
70
71 void send_sysinfo(void);
72
File agent/inet_diag.h added (mode: 120000) (index 0000000..fc2e2e0)
1 /usr/include/linux/inet_diag.h
File agent/ninedogs.c added (mode: 100644) (index 0000000..f22887e)
1 /*
2 * Description: Monitoring application
3 * Author: Catalin(ux) M. BOIE
4 * E-mail: catab at embedromix dot ro
5 * Web: https://rocketgit.com/user/catalinux/ninedogs
6 */
7
8 #define __USE_GNU
9 #define _GNU_SOURCE
10 #define __USE_XOPEN2K
11 #define __USE_LARGEFILE64
12 #define __USE_FILE_OFFSET64
13
14 #include <signal.h>
15 #include <pthread.h>
16 #include <stdarg.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <syslog.h>
20 #include <dlfcn.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <time.h>
29 #include <errno.h>
30 #include <dirent.h>
31 #include <asm/unistd.h>
32 #include <fcntl.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 #include <netinet/in.h>
36 #include <netinet/tcp.h>
37 #include <poll.h>
38 #include <netdb.h>
39 #include <ctype.h>
40 #include <sys/stat.h>
41
42 #include "ninedogs.h"
43 #include "ids.h"
44 #include "php.h"
45 #include "openssl.h"
46 #include "ctools.h"
47 #include "process_core.h"
48
49 #define FB_FLAGS_NETSOCK (1 << 0)
50 #define FB_FLAGS_COMM (1 << 1) // the fd is used to communicate with us
51
52
53 struct mem_node
54 {
55 void *p;
56 size_t size;
57 struct mem_node *next;
58 };
59 struct mem_node *mem_hash[64];
60
61 // Custom allocator
62 static unsigned char my_malloc[200ULL * 65536ULL];
63 static unsigned long my_malloc_pos;
64
65 static char ninedogs_inited;
66 static void *(*old_realloc)(void *ptr, size_t size);
67 void *(*old_malloc)(size_t size);
68 void (*old_free)(void *ptr);
69 static int (*old_bind)(int sockfd, const struct sockaddr *addr, socklen_t addrlen) = NULL;
70 static int (*old_setsockopt)(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
71 static int (*old_socket)(int domain, int type, int protocol);
72 static int (*old_close)(int fd);
73 ssize_t (*old_write)(int fd, const void *buf, size_t len);
74 static ssize_t (*old_send)(int sockfd, const void *buf, size_t len, int flags);
75 static ssize_t (*old_sendto)(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
76 static ssize_t (*old_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
77 static ssize_t (*old_recv)(int sockfd, void *buf, size_t len, int flags);
78 static ssize_t (*old_recvmsg)(int sockfd, struct msghdr *msg, int flags);
79 static int (*old_accept)(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
80 static int (*old_accept4)(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
81 static int (*old_connect)(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
82 static int (*old_poll)(struct pollfd *fds, nfds_t nfds, int timeout);
83 static struct hostent *(*old_gethostbyname)(const char *name);
84 int (*old_getaddrinfo)(const char *restrict node, const char *restrict service,
85 const struct addrinfo *restrict hints, struct addrinfo **restrict res);
86 static int (*old_pthread_create)(pthread_t *restrict thread,
87 const pthread_attr_t *restrict attr,
88 void *(*start_routine)(void *),
89 void *restrict arg);
90 static int (*old_pthread_join)(pthread_t thread, void **retval);
91 static int (*old_pthread_attr_init)(pthread_attr_t *attr);
92 static int (*old_pthread_attr_setstacksize)(pthread_attr_t *attr, size_t stacksize);
93 static void (*old__exit)(int status);
94 static int (*old_getsockopt)(int, int, int, void *restrict, socklen_t *restrict);
95 //static void (*old_php_execute_script)(void *);
96 static int (*old_execve)(const char *pathname, char *const argv[], char *const envp[]);
97 int (*old_open)(const char *pathname, int flags, ...);
98 static int (*old_stat)(const char *restrict pathname,
99 struct stat *restrict statbuf);
100 void *(*old_dlsym)(void *restrict handle, const char *restrict symbol);
101 static void *(*old_dlopen)(const char *filename, int flags);
102
103 /* PHP */
104 //static void (*old_php_module_startup)(void);
105 //static int (*old_php_pdo_register_driver)(void *driver);
106
107 /* PostgreSQL */
108 static void *(*old_PQconnectdb)(const char *conninfo);
109
110
111 /* Functions */
112
113 #if 0
114 static void hookup_php(void)
115 {
116 if (old_php_module_startup != NULL)
117 return;
118
119 xlog(0, "hookup_php\n");
120
121 old_php_pdo_register_driver = dlsym(RTLD_NEXT, "php_pdo_register_driver");
122 if (old_php_pdo_register_driver == NULL) {
123 xlog(0, " cannot resolve 'php_pdo_register_driver'!\n");
124 //exit(1);
125 } else {
126 xlog(0, " php_pdo_register_driver registered\n");
127 }
128
129 /*
130 old_php_execute_script = dlsym(RTLD_NEXT, "php_execute_script");
131 if (old_php_execute_script == NULL) {
132 xlog(0, " cannot resolve 'php_execute_script'!\n");
133 exit(1);
134 }
135 */
136
137 xlog(0, " return\n");
138 }
139 #endif
140
141 static void my_on_exit(int ret, void *junk)
142 {
143 xlog(100, "my_on_exit ret=%d junk=%p!\n", ret, junk);
144 ninedogs_process_core(NINEDOGS_CORE_STOP, &ret);
145 }
146
147 #if 0
148 void _exit(int status)
149 {
150 //write(1, "_exit\n", 6);
151 xlog(1, "my _exit status=%d!\n", status);
152 //hookup_php();
153 old__exit(status);
154 }
155 #endif
156
157 static void my_segv(int sig)
158 {
159 (void) sig;
160 //write(1, "my_segv\n", 8);
161 xlog(1, "my_segv [sig=%d]!\n", sig);
162 exit(1);
163 }
164
165 #if 0
166 /*
167 * We need this because of on_exit cannot be set at the time the init() function is called
168 * Seems I cannot find a good spot where to call this. TODO.
169 */
170 static void init_secondary(void)
171 {
172 static unsigned char inited = 0;
173
174 if (inited == 1)
175 return;
176
177 xlog(1, "%s...\n", __func__);
178
179 // TODO: seems this is not executed!
180 atexit(my_atexit);
181 on_exit(my_on_exit, NULL);
182
183 inited = 1;
184 }
185 #endif
186
187 /*
188 * Please note that this function may be called AFTER other constructors.
189 * For example, Openssl_version is called from libssh, and tis function was not
190 * yet called! So, we need to call this in every exported function.
191 */
192 __attribute__((constructor)) void ninedogs_init(void)
193 {
194 char *x, env[4096];
195 void *dlh;
196
197 if (ninedogs_inited == 1)
198 return;
199
200 //write(1, "ninedogs: init start\n", 21);
201 dlh = dlmopen(LM_ID_BASE, "/date/sync/no-crypt/sync1/Dev/ninedogs/agent/ninedogs_dlsym_env.so",
202 RTLD_LAZY | RTLD_LOCAL | RTLD_DEEPBIND);
203 //write(1, "ae\n", 3);
204 if (!dlh)
205 exit(1);
206 dlclose(dlh);
207
208 //write(1, "b\n", 2);
209 x = getenv("NINEDOGS_DLSYM");
210 if (!x || (x[0] == '\0'))
211 exit(1);
212 old_dlsym = (void *) strtoul(x, NULL, 16);
213 if (old_dlsym == NULL)
214 exit(1);
215
216 //write(1, "c\n", 2);
217 x = getenv("NINEDOGS_DLOPEN");
218 if (!x || (x[0] == '\0'))
219 exit(1);
220 old_dlopen = (void *) strtoul(x, NULL, 16);
221
222 x = getenv("NINEDOGS_OPEN");
223 if (!x || (x[0] == '\0'))
224 exit(1);
225 old_open = (void *) strtoul(x, NULL, 16);
226
227 x = getenv("NINEDOGS_STAT");
228 if (!x || (x[0] == '\0'))
229 exit(1);
230 old_stat = (void *) strtoul(x, NULL, 16);
231
232 fdinfo.head = fdinfo.tail = NULL;
233
234 log_file = getenv("FORCE_NET_LOG");
235 if (log_file != NULL)
236 Log = open(log_file, O_WRONLY | O_APPEND, 0700);
237 else
238 Log = dup(2); // TODO
239
240 /******** Now, hijack system calls ********/
241
242 //write(1, "f\n", 2);
243
244 old_realloc = old_dlsym(RTLD_NEXT, "realloc");
245 if (old_realloc == NULL) {
246 xlog(0, " cannot resolve 'realloc'!\n");
247 exit(1);
248 }
249
250 old_malloc = old_dlsym(RTLD_NEXT, "malloc");
251 if (old_malloc == NULL) {
252 xlog(0, " cannot resolve 'malloc'!\n");
253 exit(1);
254 }
255
256 old_free = old_dlsym(RTLD_NEXT, "free");
257 if (old_free == NULL) {
258 xlog(0, " cannot resolve 'free'!\n");
259 exit(1);
260 }
261
262 old_bind = old_dlsym(RTLD_NEXT, "bind");
263 if (old_bind == NULL) {
264 xlog(0, " cannot resolve 'bind'!\n");
265 exit(1);
266 }
267
268 old_setsockopt = old_dlsym(RTLD_NEXT, "setsockopt");
269 if (old_setsockopt == NULL) {
270 xlog(0, " cannot resolve 'setsockopt'!\n");
271 exit(1);
272 }
273
274 old_socket = old_dlsym(RTLD_NEXT, "socket");
275 if (old_socket == NULL) {
276 xlog(0, " cannot resolve 'socket'!\n");
277 exit(1);
278 }
279
280 old_close = old_dlsym(RTLD_NEXT, "close");
281 if (old_close == NULL) {
282 xlog(0, " cannot resolve 'close'!\n");
283 exit(1);
284 }
285
286 old_write = old_dlsym(RTLD_NEXT, "write");
287 if (old_write == NULL) {
288 xlog(0, " cannot resolve 'write'!\n");
289 exit(1);
290 }
291
292 old_send = old_dlsym(RTLD_NEXT, "send");
293 if (old_send == NULL) {
294 xlog(0, " cannot resolve 'send'!\n");
295 exit(1);
296 }
297
298 old_sendto = old_dlsym(RTLD_NEXT, "sendto");
299 if (old_sendto == NULL) {
300 xlog(0, " cannot resolve 'sendto'!\n");
301 exit(1);
302 }
303
304 old_sendmsg = old_dlsym(RTLD_NEXT, "sendmsg");
305 if (old_sendmsg == NULL) {
306 xlog(0, " cannot resolve 'sendmsg'!\n");
307 exit(1);
308 }
309
310 old_recv = old_dlsym(RTLD_NEXT, "recv");
311 if (old_recv == NULL) {
312 xlog(0, " cannot resolve 'recv'!\n");
313 exit(1);
314 }
315
316 old_recvmsg = old_dlsym(RTLD_NEXT, "recvmsg");
317 if (old_recvmsg == NULL) {
318 xlog(0, " cannot resolve 'recvmsg'!\n");
319 exit(1);
320 }
321
322 old_accept = old_dlsym(RTLD_NEXT, "accept");
323 if (old_accept == NULL) {
324 xlog(0, " cannot resolve 'accept'!\n");
325 exit(1);
326 }
327
328 old_accept4 = old_dlsym(RTLD_NEXT, "accept4");
329 if (old_accept4 == NULL) {
330 xlog(0, " cannot resolve 'accept4'!\n");
331 exit(1);
332 }
333
334 old_connect = old_dlsym(RTLD_NEXT, "connect");
335 if (old_connect == NULL) {
336 xlog(0, " cannot resolve 'connect'!\n");
337 exit(1);
338 }
339
340 old_poll = old_dlsym(RTLD_NEXT, "poll");
341 if (old_poll == NULL) {
342 xlog(0, " cannot resolve 'poll'!\n");
343 exit(1);
344 }
345
346 old_gethostbyname = old_dlsym(RTLD_NEXT, "gethostbyname");
347 if (old_gethostbyname == NULL) {
348 xlog(0, " cannot resolve 'gethostbyname'!\n");
349 exit(1);
350 }
351
352 old_getaddrinfo = old_dlsym(RTLD_NEXT, "getaddrinfo");
353 if (old_getaddrinfo == NULL) {
354 xlog(0, " cannot resolve 'getaddrinfo'!\n");
355 exit(1);
356 }
357
358 old_pthread_create = old_dlsym(RTLD_NEXT, "pthread_create");
359 if (old_pthread_create == NULL) {
360 xlog(0, " cannot resolve 'pthread_create'!\n");
361 exit(1);
362 }
363
364 old_pthread_join = old_dlsym(RTLD_NEXT, "pthread_join");
365 if (old_pthread_join == NULL) {
366 xlog(0, " cannot resolve 'pthread_join'!\n");
367 exit(1);
368 }
369
370 old_pthread_attr_init = old_dlsym(RTLD_NEXT, "pthread_attr_init");
371 if (old_pthread_attr_init == NULL) {
372 xlog(0, " cannot resolve 'pthread_attr_init'!\n");
373 exit(1);
374 }
375
376 old_pthread_attr_setstacksize = old_dlsym(RTLD_NEXT, "pthread_attr_setstacksize");
377 if (old_pthread_attr_setstacksize == NULL) {
378 xlog(0, " cannot resolve 'pthread_attr_setstacksize'!\n");
379 exit(1);
380 }
381
382 old__exit = old_dlsym(RTLD_NEXT, "_exit");
383 if (old__exit == NULL) {
384 xlog(0, " cannot resolve '_exit'!\n");
385 exit(1);
386 }
387
388 old_getsockopt = old_dlsym(RTLD_NEXT, "getsockopt");
389 if (old_getsockopt == NULL) {
390 xlog(0, " cannot resolve 'getsockopt'!\n");
391 exit(1);
392 }
393
394 old_execve = old_dlsym(RTLD_NEXT, "execve");
395 if (old_execve == NULL) {
396 xlog(0, " cannot resolve 'execve'!\n");
397 exit(1);
398 }
399
400 old_open = old_dlsym(RTLD_NEXT, "open");
401 if (old_open == NULL) {
402 xlog(0, " cannot resolve 'open'!\n");
403 exit(1);
404 }
405
406 old_stat = old_dlsym(RTLD_NEXT, "stat");
407 if (old_stat == NULL) {
408 xlog(0, " cannot resolve 'stat'!\n");
409 exit(1);
410 }
411
412
413 /* PostgreSQL start */
414
415 old_PQconnectdb = old_dlsym(RTLD_NEXT, "PQconnectdb");
416 if (old_PQconnectdb == NULL) {
417 xlog(0, " cannot resolve 'PQconnectdb'!\n");
418 //exit(1);
419 }
420
421 /* PostgreSQL end */
422
423 x = getenv("NINEDOGS_VERBOSE");
424 if (x != NULL)
425 verbose = (unsigned int) strtoul(x, NULL, 10);
426
427 // Trap SEGV - TODO: a user may want to install her handler
428 signal(SIGSEGV, my_segv);
429
430 on_exit(my_on_exit, NULL);
431
432 ninedogs_inited = 1;
433 //xlog(1, " init ended.\n");
434 //write(1, "ninedogs: init done\n", 20);
435
436 server_init();
437
438 /* Java stuff */
439 x = getenv("JAVA_TOOL_OPTIONS");
440 if (!x)
441 x = "";
442 snprintf(env, sizeof(env), "-javaagent:../../agent/java/agent0/ninedogs-agent.jar %s", x);
443 setenv("JAVA_TOOL_OPTIONS", env, 1);
444
445 /* .NET stuff */
446 /*
447 snprintf(env, sizeof(env), "-javaagent:../../agent/java/agent0/ninedogs-agent.jar %s", x);
448 setenv("COR_ENABLE_PROFILING", "1", 1);
449 setenv("COR_PROFILER", "ninedogs", 1);
450 // or
451 setenv("CORECLR_PROFILER", "ninedogs", 1);
452 setenv("CORECLR_ENABLE_PROFILING", "1", 1);
453 setenv("CORECLR_PROFILER_PATH", "/date/sync/no-crypt/sync1/Dev/ninedogs/agent/dotnet/profiler.so", 1);
454 */
455
456 ninedogs_process_core(NINEDOGS_CORE_START, NULL);
457 }
458
459 void *realloc(void *ptr, size_t size)
460 {
461 void *r, *p;
462 size_t msize;
463 //char s[32];
464
465 //sprintf(s, "%s(%p, %zu)\n", __func__, ptr, size);
466 //write(1, s, strlen(s));
467
468 if ((ptr >= (void *) my_malloc) && (ptr <= (void *) my_malloc + my_malloc_pos)) {
469 r = malloc(size);
470 if (r == NULL)
471 return NULL;
472 // we do not call free
473
474 if (ptr) {
475 p = ptr - 16;
476 memcpy(&msize, p, sizeof(size_t));
477 memcpy(r, ptr, msize);
478 }
479
480 //sprintf(s, " my: %p\n", r);
481 //write(1, s, strlen(s));
482
483 return r;
484 }
485
486 if (!old_realloc)
487 return malloc(size);
488
489 return old_realloc(ptr, size);
490 }
491
492 void *malloc(size_t size)
493 {
494 struct mem_node *z;
495 unsigned int key;
496 void *p;
497 //char s[32];
498
499 //sprintf(s, "%s(%zu)\n", __func__, size);
500 //write(1, s, strlen(s));
501
502 if (!old_malloc) {
503 p = my_malloc + my_malloc_pos;
504
505 // Store the size of the allocation - wee need it in realloc
506 memcpy(p, &size, sizeof(size));
507 p += 16;
508
509 //sprintf(s, " my: %p\n", p);
510 //write(1, s, strlen(s));
511
512 my_malloc_pos += 16 + ((15 + size) / 16) * 16;
513 return p;
514 }
515
516 p = old_malloc(size);
517 if (p == NULL)
518 return p;
519
520 z = old_malloc(sizeof(struct mem_node));
521 if (z == NULL)
522 return p;
523
524 key = ((unsigned long long) p >> 8) % 64;
525
526 z->size = size;
527 z->p = p;
528 z->next = mem_hash[key];
529 mem_hash[key] = z;
530
531 //sprintf(s, " %p\n", p);
532 //write(1, s, strlen(s));
533
534 return p;
535 }
536
537 void free(void *ptr)
538 {
539 struct mem_node *q, *prev;
540 unsigned int key;
541 //char s[32];
542
543 //sprintf(s, "free(%p)\n", ptr);
544 //write(1, s, strlen(s));
545
546 if (!old_free)
547 return;
548
549 if (!ptr)
550 return;
551
552 if ((ptr >= (void *) my_malloc) && (ptr <= (void *) my_malloc + my_malloc_pos))
553 return;
554
555 old_free(ptr);
556
557 key = ((unsigned long long) ptr >> 8) % 64;
558 q = mem_hash[key];
559 prev = NULL;
560 while (q) {
561 if (q->p == ptr) {
562 if (prev)
563 prev->next = q->next;
564 else
565 mem_hash[key] = q->next;
566 old_free(q);
567 return;
568 }
569
570 prev = q;
571 q = q->next;
572 }
573 }
574
575 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
576 {
577 struct node *q;
578 struct sockaddr_storage new;
579 char tmp[128];
580
581 if (!old_bind)
582 return -1;
583
584 saddr(tmp, sizeof(tmp), (struct sockaddr *) addr);
585 xlog(1, "bind(sockfd=%d, %s)\n", sockfd, tmp);
586
587 memcpy(&new, addr, addrlen);
588
589 /* We do not touch non network sockets */
590 q = get(sockfd);
591 do {
592 if (q == NULL)
593 break;
594
595 if ((q->priv.flags & FB_FLAGS_NETSOCK) == 0)
596 break;
597
598 //q->priv.flags |= FB_FLAGS_BIND_CALLED;
599 } while (0);
600
601 return old_bind(sockfd, (struct sockaddr *) &new, addrlen);
602 }
603
604 int setsockopt(int sockfd, int level, int optname, const void *optval,
605 socklen_t optlen)
606 {
607 #if 0
608 if (level == SOL_SOCKET) {
609 if (optname == SO_KEEPALIVE)
610 return 1; //set_ka(sockfd);
611 if (optname == SO_REUSEADDR)
612 return 1; //set_reuseaddr(sockfd);
613 if (optname == SO_MARK)
614 return 1; //set_fwmark(sockfd);
615 if (optname == SO_PRIORITY)
616 return 1; //set_prio(sockfd);
617 }
618
619 if (level == IPPROTO_IP) {
620 if (optname == IP_TOS)
621 return 1; //set_tos(sockfd);
622 if (optname == IP_TTL)
623 return 1; //set_ttl(sockfd);
624 }
625
626 if (level == IPPROTO_TCP) {
627 if (optname == TCP_KEEPIDLE)
628 return 1; //set_ka_idle(sockfd);
629 if (optname == TCP_MAXSEG)
630 return 1; //set_mss(sockfd);
631 if (optname == TCP_NODELAY)
632 return 1; //set_nodelay(sockfd);
633 }
634 #endif
635
636 return old_setsockopt(sockfd, level, optname, optval, optlen);
637 }
638
639 /*
640 * Helper called when a socket is created: socket, accept
641 */
642 static void socket_create_callback(const int sockfd, int domain, int type)
643 {
644 struct private p;
645
646 xlog(60, " socket_create_callback(%d, %s, %s)\n",
647 sockfd, sdomain(domain), stype(type));
648
649 p.domain = domain;
650 p.type = type;
651 p.flags = FB_FLAGS_NETSOCK;
652 memset(&p.dest, 0, sizeof(struct sockaddr_storage));
653 p.dest_len = 0;
654 p.limit = 0;
655 p.rest = 0;
656 p.last.tv_sec = p.last.tv_usec = 0;
657 add(sockfd, &p);
658 }
659
660 /*
661 * 'socket' is hijacked to be able to call setsockopt on it.
662 */
663 int socket(int domain, int type, int protocol)
664 {
665 int sockfd;
666
667 xlog(50, "socket(domain=%s, type=%s, protocol=%s)\n",
668 sdomain(domain), stype(type), sprotocol(protocol));
669
670 sockfd = old_socket(domain, type, protocol);
671 if (sockfd == -1)
672 return -1;
673
674 socket_create_callback(sockfd, domain, type);
675
676 return sockfd;
677 }
678
679 int close(int fd)
680 {
681 if (!old_close)
682 return 0;
683
684 //xlog(1, "close(fd=%d)\n", fd);
685
686 del(fd);
687
688 return old_close(fd);
689 }
690
691 ssize_t write(int fd, const void *buf, size_t len)
692 {
693 struct node *q;
694 ssize_t n;
695
696 if (old_write == NULL)
697 return len;
698
699 q = get(fd);
700 if (q) {
701 if ((len >= 8) && (strncmp(buf, "ninedogs", 8) == 0))
702 q->priv.flags |= FB_FLAGS_COMM;
703
704 // Just a way to be able to send debug from tests
705 if ((q->priv.flags & FB_FLAGS_COMM) && (len >= 9)
706 && (strncmp(buf, "ninedogs ", 9) == 0)) {
707 xlog(0, "SIG %s", buf);
708 return len;
709 }
710 }
711
712 //xlog(1, "%s(fd=%d, len=%zu)\n", __func__, fd, len);
713
714 /* We deal only with network sockets */
715 if (q && (q->priv.flags & FB_FLAGS_NETSOCK)) {
716 dump(200, "write", buf, len);
717 }
718
719 n = old_write(fd, buf, len);
720
721 return n;
722 }
723
724 ssize_t send(int sockfd, const void *buf, size_t len, int flags)
725 {
726 struct node *q;
727 ssize_t n;
728
729 xlog(50, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
730 __func__, sockfd, len, flags);
731
732 /* We do not touch non network sockets */
733 q = get(sockfd);
734 if (q && (q->priv.flags & FB_FLAGS_NETSOCK)) {
735 dump(200, "send", buf, len);
736 }
737
738 n = old_send(sockfd, buf, len, flags);
739
740 return n;
741 }
742
743 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
744 const struct sockaddr *dest_addr, socklen_t addrlen)
745 {
746 struct node *q;
747 ssize_t n;
748
749 xlog(50, "sendto(sockfd, %d, buf, len=%zu, flags=0x%x, ...)\n",
750 sockfd, len, flags);
751
752 /* We do not touch non network sockets */
753 q = get(sockfd);
754 if (q && (q->priv.flags & FB_FLAGS_NETSOCK)) {
755 dump(200, "send", buf, len);
756 }
757
758 n = old_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
759
760 return n;
761 }
762
763 /*
764 * TODO: Add sendmmsg
765 */
766 ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
767 {
768 ssize_t n;
769 /* see below
770 struct sockaddr_storage new_dest;
771 */
772
773 xlog(50, "sendmsg(sockfd=%d, ..., flags=0x%x)\n",
774 sockfd, flags);
775
776 /* TODO: log also this! */
777 for (unsigned i = 0; i < msg->msg_iovlen; i++)
778 dump(200, "sendmsg", msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
779
780 n = old_sendmsg(sockfd, msg, flags);
781 xlog(50, " returned %zd\n", n);
782
783 return n;
784 }
785
786 ssize_t recv(int sockfd, void *buf, size_t len, int flags)
787 {
788 struct node *q;
789 ssize_t n;
790
791 xlog(50, "%s(sockfd=%d, buf, len=%zu, flags=0x%x)\n",
792 __func__, sockfd, len, flags);
793
794 n = old_recv(sockfd, buf, len, flags);
795
796 /* We do not touch non network sockets */
797 q = get(sockfd);
798 if (q && (q->priv.flags & FB_FLAGS_NETSOCK)) {
799 xlog(200, " recv returned %d\n", n);
800 if (n > 0)
801 dump(200, "recv", buf, n);
802 }
803
804 return n;
805 }
806
807 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
808 {
809 struct node *q;
810 ssize_t n, max;
811 unsigned int i;
812 size_t rest;
813
814 xlog(50, "%s(sockfd=%d, msg, flags=0x%x)\n",
815 __func__, sockfd, flags);
816
817 n = old_recvmsg(sockfd, msg, flags);
818
819 /* We do not touch non network sockets */
820 q = get(sockfd);
821 if (q && (q->priv.flags & FB_FLAGS_NETSOCK) && (n != -1)) {
822 rest = n;
823 for (i = 0; (i < msg->msg_iovlen) && (rest > 0); i++) {
824 max = msg->msg_iov[i].iov_len <= rest ? msg->msg_iov[i].iov_len : rest;
825 dump(200, "recvmsg", msg->msg_iov[i].iov_base, max);
826 rest -= msg->msg_iov[i].iov_len;
827 }
828 }
829
830 return n;
831 }
832
833 /*
834 * We have to hijack accept because the program may be a daemon.
835 */
836 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
837 {
838 int new_sock;
839 struct node *q;
840 struct private *p;
841
842 xlog(2, "accept(sockfd=%d, ...)\n", sockfd);
843
844 new_sock = old_accept(sockfd, addr, addrlen);
845 if (new_sock == -1)
846 return -1;
847
848 /* We must find out domain and type for accepting socket */
849 q = get(sockfd);
850 if (q != NULL) {
851 p = &q->priv;
852
853 socket_create_callback(new_sock, p->domain, p->type);
854 }
855
856 return new_sock;
857 }
858
859 /*
860 * We have to hijack accept4 because the program may be a daemon.
861 */
862 int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
863 {
864 int new_sock;
865 struct node *q;
866 struct private *p;
867
868 xlog(2, "accept4(sockfd=%d, ...flags=0x%x)\n", sockfd, flags);
869
870 new_sock = old_accept4(sockfd, addr, addrlen, flags);
871 if (new_sock == -1)
872 return -1;
873
874 /* We must find out domain and type for accepting socket */
875 q = get(sockfd);
876 if (q != NULL) {
877 p = &q->priv;
878
879 socket_create_callback(new_sock, p->domain, p->type);
880 }
881
882 return new_sock;
883 }
884
885 int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
886 {
887 struct node *q;
888 int r;
889 char sdest[128];
890
891 saddr(sdest, sizeof(sdest), addr);
892 xlog(2, "connect(sockfd=%d, %s)\n", sockfd, sdest);
893
894 q = get(sockfd);
895 if (q)
896 gettimeofday(&q->priv.conn_time, NULL);
897
898 r = old_connect(sockfd, addr, addrlen);
899 if (r == 0) {
900 struct timeval e, f;
901
902 gettimeofday(&e, NULL);
903 my_time_diff(&f, &e, &q->priv.conn_time);
904 xlog(3, " took %u.%03u\n", f.tv_sec, f.tv_usec / 1000);
905 } else {
906 xlog(3, " failed: %m\n");
907 }
908
909 return r;
910 }
911
912 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
913 {
914 xlog(40, "poll(fds, %d, %d)\n", nfds, timeout);
915
916 return old_poll(fds, nfds, timeout);
917 }
918
919 struct hostent *gethostbyname(const char *name)
920 {
921 xlog(2, "gethostbyname(%s)\n", name);
922
923 return old_gethostbyname(name);
924 }
925
926 int getaddrinfo(const char *restrict node, const char *restrict service,
927 const struct addrinfo *restrict hints, struct addrinfo **restrict res)
928 {
929 xlog(2, "getaddrinfo(node=%s, service=%s, hints=0x%x)\n",
930 node, service, hints ? hints : 0);
931
932 return old_getaddrinfo(node, service, hints, res);
933 }
934
935 int pthread_create(pthread_t *restrict thread,
936 const pthread_attr_t *restrict attr, void *(*start_routine)(void *),
937 void *restrict arg)
938 {
939 int r;
940
941 //xlog(2, "pthread_create\n");
942
943 r = old_pthread_create(thread, attr, start_routine, arg);
944 return r;
945 }
946
947 int pthread_join(pthread_t thread, void **retval)
948 {
949 int r;
950
951 //xlog(2, "pthread_join\n");
952
953 r = old_pthread_join(thread, retval);
954 return r;
955 }
956
957 #if 0
958 // this crashes!
959 int pthread_attr_init(pthread_attr_t *attr)
960 {
961 int r;
962
963 xlog(2, "pthread_attr_init\n");
964
965 r = old_pthread_attr_init(attr);
966 return r;
967 }
968 #endif
969
970 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
971 {
972 //xlog(2, "pthread_attr_setstacksize(%zu)\n", stacksize);
973
974 return old_pthread_attr_setstacksize(attr, stacksize);
975 }
976
977 int getsockopt(int sockfd, int level, int optname, void *restrict optval,
978 socklen_t *restrict optlen)
979 {
980 int r;
981
982 xlog(2, "%s(%d, %d, %d, %p, %u)\n",
983 __func__, sockfd, level, optname, optval, optlen);
984
985 r = old_getsockopt(sockfd, level, optname, optval, optlen);
986 while ((level == SOL_SOCKET) && (optname == SO_ERROR)) {
987 struct node *q;
988 int err = *(int *) optval;
989 struct timeval e, f;
990
991 q = get(sockfd);
992 if (!q)
993 break;
994
995 if (q->priv.conn_time.tv_sec == 0)
996 break;
997
998 gettimeofday(&e, NULL);
999 my_time_diff(&f, &e, &q->priv.conn_time);
1000
1001 xlog(3, " err=%d; took %u.%03u\n", err, f.tv_sec, f.tv_usec / 1000);
1002 break;
1003 }
1004
1005 return r;
1006 }
1007
1008 #if 0
1009 void *PQconnectdb(const char *conninfo)
1010 {
1011 void *p;
1012
1013 xlog(2, "%s(%s)\n", __func__, conninfo);
1014
1015 p = old_PQconnectdb(conninfo);
1016 xlog(2, " %p\n", p);
1017
1018 return p;
1019 }
1020 #endif
1021
1022 int execve(const char *pathname, char *const argv[], char *const envp[])
1023 {
1024 int ret;
1025
1026 xlog(2, "%s(%s, ...)\n", __func__, pathname);
1027 ret = old_execve(pathname, argv, envp);
1028 xlog(2, " ret=%d\n", ret);
1029
1030 return ret;
1031 }
1032
1033 static int my_open(const char *pathname, int flags, ...)
1034 {
1035 int ret;
1036 mode_t mode = 0;
1037 va_list va;
1038
1039 if (__OPEN_NEEDS_MODE(flags)) {
1040 va_start(va, flags);
1041 mode = va_arg(va, mode_t);
1042 va_end(va);
1043 }
1044
1045 xlog(2, "%s(%s, %d, %d)\n", __func__, pathname, flags, mode);
1046 ret = old_open(pathname, flags, mode);
1047 xlog(2, " ret=%d\n", ret);
1048
1049 return ret;
1050 }
1051
1052 static int my_stat(const char *restrict pathname, struct stat *restrict statbuf)
1053 {
1054 int ret;
1055
1056 xlog(2, "%s(%s, %p)\n", __func__, pathname, statbuf);
1057 ret = old_stat(pathname, statbuf);
1058 xlog(2, " ret=%d\n", ret);
1059
1060 return ret;
1061 }
1062
1063 void *dlsym(void *restrict handle, const char *restrict symbol)
1064 {
1065 void *ret;
1066
1067 if (!old_dlsym)
1068 return NULL;
1069
1070 xlog(50, "%s(%p, %s)\n", __func__, handle, symbol);
1071
1072 ret = old_dlsym(handle, symbol);
1073
1074 if (ret) {
1075 if (strcmp(symbol, "get_module") == 0)
1076 ret = php_hook(ret);
1077 else if (strcmp(symbol, "open") == 0)
1078 ret = my_open;
1079 else if (strcmp(symbol, "stat") == 0)
1080 ret = my_stat;
1081 }
1082
1083 return ret;
1084 }
1085
1086
1087 void *dlopen(const char *filename, int flags)
1088 {
1089 void *ret;
1090
1091 if (!old_dlopen)
1092 return NULL;
1093
1094 ret = old_dlopen(filename, flags);
1095 xlog(100, "%s(%s, 0x%x) = %p\n", __func__, filename, flags, ret);
1096
1097 return ret;
1098 }
1099
File agent/ninedogs.h added (mode: 100644) (index 0000000..6966b8b)
1 void ninedogs_init(void);
File agent/ninedogs_dlsym_env.c added (mode: 100644) (index 0000000..099623f)
1 /*
2 * Description: Monitoring application
3 * Author: Catalin(ux) M. BOIE
4 * E-mail: catab at embedromix dot ro
5 * Web: https://rocketgit.com/user/catalinux/ninedogs
6 */
7
8 #define __USE_GNU
9 #define _GNU_SOURCE
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <dlfcn.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18
19 __attribute__((constructor)) static void my_init(void)
20 {
21 char sptr[32];
22
23 write(1, "env beg\n", 8);
24 sprintf(sptr, "%p", dlsym);
25 setenv("NINEDOGS_DLSYM", sptr, 1);
26
27 sprintf(sptr, "%p", dlopen);
28 setenv("NINEDOGS_DLOPEN", sptr, 1);
29
30 sprintf(sptr, "%p", open);
31 setenv("NINEDOGS_OPEN", sptr, 1);
32
33 sprintf(sptr, "%p", stat);
34 setenv("NINEDOGS_STAT", sptr, 1);
35
36 write(1, "env end\n", 8);
37 }
File agent/ninedogs_dlsym_func.c added (mode: 100644) (index 0000000..dd6b00d)
1 /*
2 * Description: Monitoring application
3 * Author: Catalin(ux) M. BOIE
4 * E-mail: catab at embedromix dot ro
5 * Web: https://rocketgit.com/user/catalinux/ninedogs
6 */
7
8 #define __USE_GNU
9 #define _GNU_SOURCE
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <dlfcn.h>
14 #include <string.h>
15
16 extern void *(*old_dlsym)(void *restrict handle, const char *restrict symbol);
17
18 void *dlsym(void *restrict handle, const char *restrict symbol)
19 {
20 void *ret;
21
22 fprintf(stderr, "%s: symbol=%s\n", __func__, symbol);
23
24 if (!old_dlsym)
25 return NULL;
26
27 ret = old_dlsym(handle, symbol);
28 return ret;
29 }
File agent/openssl.TODO added (mode: 100644) (index 0000000..2393d49)
1 [ ] openssl x509 -in seems to call PEM_read_bio_X509_AUX and is NOT
2 calling PEM_ASN1_read_bio. See example 'openssl'.
3 [ ] Can we check SSH certificates?
4 [ ]
5
6
File agent/openssl.c added (mode: 100644) (index 0000000..fd48466)
1 /*
2 * Description: Monitoring application
3 * Author: Catalin(ux) M. BOIE
4 * E-mail: catab at embedromix dot ro
5 * Web: https://rocketgit.com/user/catalinux/ninedogs
6 */
7
8 #define __USE_GNU
9 #define _GNU_SOURCE
10 #define __USE_XOPEN2K
11 #define __USE_LARGEFILE64
12 #define __USE_FILE_OFFSET64
13
14 #include <string.h>
15 #include <stdlib.h>
16 #include <dlfcn.h>
17 #include <stdio.h>
18
19 #include "ninedogs.h"
20 #include "ids.h"
21 #include "openssl.h"
22 #include "ctools.h"
23 #include "process_ssl.h"
24
25
26 //extern void *(*old_malloc)(size_t size);
27 //extern void (*old_free)(void *p);
28 extern void *(*old_dlsym)(void *restrict handle, const char *restrict symbol);
29 //extern ssize_t (*old_write)(int fd, const void *buf, size_t len);
30
31 static const char *(*old_OpenSSL_version)(int t);
32
33 static void prepare_info(void)
34 {
35 static char done = 0;
36 struct ssl_info i;
37
38 if (done == 1)
39 return;
40
41 i.info = old_OpenSSL_version(6);
42 i.info_len = strlen(i.info);
43 xlog(40, "%s: [%s]\n", __func__, i.info);
44 ninedogs_process_ssl(NINEDOGS_SSL_INFO, &i);
45 done = 1;
46 }
47
48
49 static void *last_bio;
50 static char last_bio_file[512];
51 static BIO *(*old_BIO_new_file)(const char *filename, const char *mode);
52 BIO *BIO_new_file(const char *filename, const char *mode)
53 {
54 BIO *r;
55
56 ninedogs_init();
57
58 xlog(10, "sizeof(X509)=%u\n", sizeof(struct X509));
59 xlog(10, "%s: filename=%s mode=%s\n", __func__, filename, mode);
60
61 if (old_BIO_new_file == NULL) {
62 old_BIO_new_file = old_dlsym(RTLD_NEXT, "BIO_new_file");
63 if (old_BIO_new_file == NULL) {
64 xlog(0, " cannot resolve 'BIO_new_file'!\n");
65 exit(1);
66 }
67 }
68
69 r = old_BIO_new_file(filename, mode);
70 xlog(10, " %s: old returned r=%p\n", __func__, r);
71
72 prepare_info();
73
74 last_bio = r;
75 snprintf(last_bio_file, sizeof(last_bio_file), "%s", filename);
76
77 return r;
78 }
79
80 static void process_x509(char *uri, struct X509 *x)
81 {
82 char subj[512], *add = "";
83 unsigned int off;
84 struct cert c;
85
86 if (!x)
87 return;
88
89 xlog(10, "%s: uri=%s\n", __func__, uri);
90
91 prepare_info();
92
93 //dump(10, "subject.entries", x->cert_info.subject->entries, 128);
94 //xlog(10, " subject: num=%d\n", x->cert_info.subject->entries->num);
95 subj[0] = '\0';
96 off = 0;
97 for (int i = 0; i < x->cert_info.subject->entries->num; i++) {
98 const struct X509_name_entry_st *p;
99 char s[128];
100 unsigned max;
101
102 p = x->cert_info.subject->entries->data[i];
103
104 max = p->value->length + 1;
105 if (max > sizeof(s))
106 max = sizeof(s);
107 strncpy(s, (char *) p->value->data, max - 1);
108 s[max - 1] = '\0';
109 //xlog(10, " %s=[%s] len=%d\n", p->object->sn, s, p->value->length);
110 unsigned x = snprintf(subj + off, sizeof(subj) - off, "%s%s=%s",
111 add, p->object->sn, s);
112 off += x;
113 add = " ";
114 }
115 //xlog(10, " subj: [%s]\n", subj);
116
117 //dump(10, "ctx", ctx, 128);
118 //dump(10, "x509", x, 128);
119 //dump(10, "x509 serial", x->cert_info.serialNumber.data, 128);
120 //dump(10, "validity notBefore", x->cert_info.validity.notBefore->data, 13);
121 //dump(10, "validity notAfter", x->cert_info.validity.notAfter->data, 13);
122
123 c.uri = uri; c.uri_len = strlen(uri);
124 c.subj = subj; c.subj_len = strlen(subj);
125 c.not_before = (char *) x->cert_info.validity.notBefore->data;
126 c.not_before_len = x->cert_info.validity.notBefore->length;
127 c.not_after = (char *) x->cert_info.validity.notAfter->data;
128 c.not_after_len = x->cert_info.validity.notAfter->length;
129 ninedogs_process_ssl(NINEDOGS_SSL_CERT, &c);
130 }
131
132 static struct X509 *(*old_PEM_read_bio_X509)(BIO *bp, struct X509 **x, pem_password_cb *cb, void *u);
133 struct X509 *PEM_read_bio_X509(BIO *bp, struct X509 **x, pem_password_cb *cb, void *u)
134 {
135 struct X509 *r;
136
137 ninedogs_init();
138
139 xlog(10, "%s: bp=%p x=%p cb=%p u=%p\n", __func__, bp, x, cb, u);
140
141 if (old_PEM_read_bio_X509 == NULL) {
142 old_PEM_read_bio_X509 = old_dlsym(RTLD_NEXT, "PEM_read_bio_X509");
143 if (old_PEM_read_bio_X509 == NULL) {
144 xlog(0, " cannot resolve 'PEM_read_bio_X509'!\n");
145 exit(1);
146 }
147 }
148
149 r = old_PEM_read_bio_X509(bp, x, cb, u);
150 xlog(10, " %s: old returned r=%p x=%p\n", __func__, r, x);
151
152 process_x509(last_bio == bp ? last_bio_file : "n/a", r);
153
154 return r;
155 }
156
157 static struct X509 *(*old_PEM_read_bio_X509_AUX)(BIO *bp, struct X509 **x, pem_password_cb *cb, void *u);
158 struct X509 *PEM_read_bio_X509_AUX(BIO *bp, struct X509 **x, pem_password_cb *cb, void *u)
159 {
160 struct X509 *r;
161
162 ninedogs_init();
163
164 xlog(10, "%s: bp=%p x=%p cb=%p u=%p\n", __func__, bp, x, cb, u);
165
166 if (old_PEM_read_bio_X509_AUX == NULL) {
167 old_PEM_read_bio_X509_AUX = old_dlsym(RTLD_NEXT, "PEM_read_bio_X509_AUX");
168 if (old_PEM_read_bio_X509_AUX == NULL) {
169 xlog(0, " cannot resolve 'PEM_read_bio_X509_AUX'!\n");
170 exit(1);
171 }
172 }
173
174 r = old_PEM_read_bio_X509_AUX(bp, x, cb, u);
175 xlog(10, " %s: old returned r=%p x=%p\n", __func__, r, x);
176
177 process_x509(last_bio == bp ? last_bio_file : "n/a", r);
178
179 return r;
180 }
181
182 #include <unistd.h>
183
184 const char *OpenSSL_version(int t)
185 {
186 const char *old;
187
188 ninedogs_init();
189
190 xlog(10, "%s: t=%d\n", __func__, t);
191
192 if (old_OpenSSL_version == NULL) {
193 old_OpenSSL_version = old_dlsym(RTLD_NEXT, "OpenSSL_version");
194 if (old_OpenSSL_version == NULL) {
195 xlog(0, " cannot resolve 'OpenSSL_version'!\n");
196 exit(1);
197 }
198 }
199
200 prepare_info();
201
202 old = old_OpenSSL_version(t);
203 xlog(40, " returning [%s]\n", old);
204 return old;
205 }
206
207 static char last_store_uri[512];
208 static OSSL_STORE_CTX *last_store_ctx;
209 static OSSL_STORE_CTX *(*old_OSSL_STORE_open)(const char *uri,
210 const UI_METHOD *ui_method, void *ui_data,
211 OSSL_STORE_post_process_info_fn post_process,
212 void *post_process_data);
213 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
214 const UI_METHOD *ui_method, void *ui_data,
215 OSSL_STORE_post_process_info_fn post_process,
216 void *post_process_data)
217 {
218 OSSL_STORE_CTX *r;
219
220 ninedogs_init();
221
222 xlog(10, "%s: uri=%s\n", __func__, uri);
223
224 if (old_OSSL_STORE_open == NULL) {
225 old_OSSL_STORE_open = old_dlsym(RTLD_NEXT, "OSSL_STORE_open");
226 if (old_OSSL_STORE_open == NULL) {
227 xlog(0, " cannot resolve 'OSSL_STORE_open'!\n");
228 exit(1);
229 }
230 }
231
232 r = old_OSSL_STORE_open(uri, ui_method, ui_data,
233 post_process, post_process_data);
234
235 last_store_ctx = r;
236 snprintf(last_store_uri, sizeof(last_store_uri), "%s", uri);
237
238 return r;
239 }
240
241
242 static OSSL_STORE_CTX *(*old_OSSL_STORE_open_ex)(const char *uri,
243 OSSL_LIB_CTX *libctx, const char *propq,
244 const UI_METHOD *ui_method, void *ui_data,
245 const OSSL_PARAM params[],
246 OSSL_STORE_post_process_info_fn post_process,
247 void *post_process_data);
248 OSSL_STORE_CTX *OSSL_STORE_open_ex(const char *uri,
249 OSSL_LIB_CTX *libctx, const char *propq,
250 const UI_METHOD *ui_method, void *ui_data,
251 const OSSL_PARAM params[],
252 OSSL_STORE_post_process_info_fn post_process,
253 void *post_process_data)
254 {
255 OSSL_STORE_CTX *r;
256
257 ninedogs_init();
258
259 xlog(10, "%s: uri=%s\n", __func__, uri);
260
261 if (old_OSSL_STORE_open_ex == NULL) {
262 old_OSSL_STORE_open_ex = old_dlsym(RTLD_NEXT, "OSSL_STORE_open_ex");
263 if (old_OSSL_STORE_open_ex == NULL) {
264 xlog(0, " cannot resolve 'OSSL_STORE_open_ex'!\n");
265 exit(1);
266 }
267 }
268
269 r = old_OSSL_STORE_open_ex(uri, libctx, propq, ui_method, ui_data,
270 params, post_process, post_process_data);
271
272 last_store_ctx = r;
273 snprintf(last_store_uri, sizeof(last_store_uri), "%s", uri);
274
275 return r;
276 }
277
278 #define OSSL_STORE_INFO_CERT 5
279 static OSSL_STORE_INFO *(*old_OSSL_STORE_load)(OSSL_STORE_CTX *ctx);
280 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx)
281 {
282 OSSL_STORE_INFO *r;
283
284 ninedogs_init();
285
286 xlog(10, "%s: ctx=%p\n", __func__, ctx);
287
288 if (old_OSSL_STORE_load == NULL) {
289 old_OSSL_STORE_load = old_dlsym(RTLD_NEXT, "OSSL_STORE_load");
290 if (old_OSSL_STORE_load == NULL) {
291 xlog(0, " cannot resolve 'OSSL_STORE_load'!\n");
292 exit(1);
293 }
294 }
295
296 r = old_OSSL_STORE_load(ctx);
297 xlog(20, "%s: r=%p\n", __func__, r);
298 if (!r)
299 return NULL;
300
301 if (r->type != OSSL_STORE_INFO_CERT)
302 return r;
303
304 process_x509(last_store_ctx == ctx ? last_store_uri : "n/a", r->x509);
305
306 return r;
307 }
308
File agent/openssl.h added (mode: 100644) (index 0000000..d600bf2)
1 #include <netdb.h> // uint32_t
2
3 typedef void BIO;
4 typedef void pem_password_cb;
5 typedef void d2i_of_void;
6
7 struct stack_st
8 {
9 int num;
10 int pad;
11 const void **data;
12 int sorted;
13 int num_alloc;
14 void *comp; // OPENSSL_sk_compfunc comp;
15 };
16
17 struct asn1_string
18 {
19 int length;
20 int type;
21 unsigned char *data;
22 long flags;
23 };
24
25 struct asn1_object
26 {
27 const char *sn;
28 const char *ln;
29 int nid;
30 int length;
31 const unsigned char *data;
32 int flags;
33 int pad;
34 };
35
36 struct X509_algor
37 {
38 struct asn1_object *algorithm;
39 void *parameter; // ASN1_TYPE *
40 };
41
42 struct X509_val
43 {
44 struct asn1_string *notBefore; // ASN1_TIME
45 struct asn1_string *notAfter; // ASN1_TIME
46 };
47
48 struct X509_name_entry_st
49 {
50 struct asn1_object *object;
51 struct asn1_string *value;
52 int set;
53 int size;
54 };
55 struct X509_name_st
56 {
57 struct stack_st *entries; // struct stack_st_X509_NAME_ENTRY *entries;
58 int modified;
59 int pad1;
60 void *bytes; // BUF_MEM *bytes;
61 unsigned char *canon_enc;
62 int canon_enclen;
63 int pad2;
64 };
65 typedef struct X509_name_st X509_NAME;
66
67 struct asn1_encoding
68 {
69 unsigned char *enc;
70 long len;
71 int modified;
72 int pad;
73 };
74
75 struct X509_CINF
76 {
77 struct asn1_string *version; // ASN1_INTEGER *;[ 0 ] default of v1 // 8
78 struct asn1_string serialNumber; // ASN1_INTEGER // 24
79 struct X509_algor signature; // // 16
80 void *issuer; // X509_NAME * - I cannot find it! // 8
81 struct X509_val validity; // // 16
82 X509_NAME *subject; // X509_NAME *; // 8
83 void *pubkey; // X509_PUBKEY *key; // 8
84 void *issuerUID; // ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ // 8
85 void *subjectUID; // ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ // 8
86 void *extensions; // STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ // 8
87 struct asn1_encoding enc; // ASN1_ENCODING // 24
88 };
89
90 struct crypto_ex_data
91 {
92 // ctx seems to not be present in openssl 1.1.1n
93 //void *ctx; // OSSL_LIB_CTX *
94 void *sk; // STACK_OF(void) *sk;
95 };
96
97 struct x509_sig_info
98 {
99 int mdnid;
100 int pknid;
101 int secbits;
102 uint32_t flags;
103 };
104
105 struct X509 // 352 bytes in 1.1.1n
106 {
107 struct X509_CINF cert_info;
108 struct X509_algor sig_alg; // X509_ALGOR
109 struct asn1_string signature; // ASN1_BIT_STRING
110 struct x509_sig_info siginf; // X509_SIG_INFO
111 int references; // CRYPTO_REF_COUNT
112 int pad1;
113 struct crypto_ex_data ex_data; // CRYPTO_EX_DATA
114 long ex_pathlen;
115 long ex_pcpathlen;
116 uint32_t ex_flags;
117 uint32_t ex_kusage;
118 uint32_t ex_xkusage;
119 uint32_t ex_nscert;
120 struct asn1_string *skid; // ASN1_OCTET_STRING *
121 void *akid; // AUTHORITY_KEYID *
122 void *policy_cache; // X509_POLICY_CACHE *
123 void *crldp; // STACK_OF(DIST_POINT) *
124 void *altname; // STACK_OF(GENERAL_NAME) *
125 void *nc; // NAME_CONSTRAINTS *
126 //ifndef OPENSSL_NO_RFC3779 // in 1.1.1n it is not defined
127 void *rfc3779_addr; // STACK_OF(IPAddressFamily);
128 void *rfc3779_asid; // struct ASIdentifiers_st
129 //endif
130 unsigned char sha1_hash[20]; // SHA_DIGEST_LENGTH
131 unsigned char pad2[4];
132 void *aux; // X509_CERT_AUX *
133 void *lock; // CRYPTO_RWLOCK
134 volatile int ex_cached;
135 // below seems to be added later (in v3)
136 //struct asn1_string *distinguishing_id; // ASN1_OCTET_STRING *
137 //void *libctx; // OSSL_LIB_CTX *
138 //char *propq;
139 int pad3;
140 };
141
142 typedef struct
143 {
144 int x;
145 } SSL_CTX;
146
147 struct ossl_store_info_st
148 {
149 int type;
150 int pad;
151 union {
152 void *data;
153 struct X509 *x509;
154 };
155 };
156 typedef struct ossl_store_info_st OSSL_STORE_INFO;
157 typedef OSSL_STORE_INFO *(*OSSL_STORE_post_process_info_fn)(OSSL_STORE_INFO *, void *);
158
159 struct ossl_store_ctx_st
160 {
161 const void *loader; // const OSSL_STORE_LOADER *loader;
162 void *fetched_loader; // OSSL_STORE_LOADER *fetched_loader;
163 void *load_ctx; // OSSL_STORE_LOADER_CTX *loader_ctx;
164 OSSL_STORE_post_process_info_fn post_process;
165 void *post_process_data;
166 int expected_type;
167 int pad;
168 char *properties;
169 int loading;
170 int error_flag;
171 void *cached_info; // struct stack_st_OSSL_STORE_INFO *cached_info;
172 void *pwdata; // struct ossl_passphrase_data_st pwdata;
173 };
174 typedef struct ossl_store_ctx_st OSSL_STORE_CTX;
175 typedef void OSSL_LIB_CTX;
176 struct ossl_param_st
177 {
178 const char *key;
179 unsigned int data_type;
180 unsigned int pad;
181 void *data;
182 size_t data_size;
183 size_t return_size;
184 };
185 typedef struct ossl_param_st OSSL_PARAM;
186 typedef void UI_METHOD;
187
188
189 BIO *BIO_new_file(const char *filename, const char *mode);
190 struct X509 *PEM_read_bio_X509(BIO *bp, struct X509 **x, pem_password_cb *cb, void *u);
191 struct X509 *PEM_read_bio_X509_AUX(BIO *bp, struct X509 **x, pem_password_cb *cb, void *u);
192 const char *OpenSSL_version(int t);
193
194 OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
195 const UI_METHOD *ui_method, void *ui_data,
196 OSSL_STORE_post_process_info_fn post_process,
197 void *post_process_data);
198
199 OSSL_STORE_CTX *OSSL_STORE_open_ex(const char *uri,
200 OSSL_LIB_CTX *libctx, const char *propq,
201 const UI_METHOD *ui_method, void *ui_data,
202 const OSSL_PARAM params[],
203 OSSL_STORE_post_process_info_fn post_process,
204 void *post_process_data);
205
206 OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx);
207
File agent/openssl.txt added (mode: 100644) (index 0000000..d1c8656)
1 == TODO ==
2 [ ] Verify also client certificates.
3 [ ]
4
5 Data:
6 Version: 3 (0x2)
7 Serial Number:
8 0f:7d:3e:8b:35:d8:66:5a:ba:ce:44:47:f9:8a:e7:60:71:9e:bd:b3
9 Signature Algorithm: sha256WithRSAEncryption
10 Issuer: C = XX, L = Default City, O = Default Company Ltd
11 Validity
12 Not Before: May 24 05:47:45 2022 GMT
13 Not After : May 24 05:47:45 2023 GMT
14 Subject: C = XX, L = Default City, O = Default Company Ltd
15 Subject Public Key Info:
16 Public Key Algorithm: rsaEncryption
17 RSA Public-Key: (4096 bit)
18 Modulus:
19 00:b3:03:a7:88:34:02:ef:e9:8c:ca:80:89:5a:4f:
20 a2:91:e5:3f:a2:5e:d0:9d:bd:36:c5:01:10:af:e3:
21 7c:3b:5d:91:8b:ae:f6:b9:f0:0f:2d:04:02:31:7a:
22 da:15:29:93:70:df:2f:1c:5f:63:1a:35:77:1b:1a:
23 e4:7a:77:18:93:43:ff:4d:89:c3:0f:5c:69:c0:f3:
24 f1:56:b3:fd:21:26:7b:61:b3:c2:44:88:45:7b:f9:
25 4b:67:2d:7b:d6:dd:0e:34:05:eb:bf:12:38:21:91:
26 2b:0e:5b:9f:07:86:48:36:90:b3:17:15:ea:8f:c9:
27 14:5a:b6:f7:46:15:b8:d3:a2:6d:df:1b:77:ee:20:
28 11:3c:4b:d4:96:71:e6:fa:15:24:86:d6:c3:45:f6:
29 ef:2b:ce:26:62:db:aa:bb:ed:dc:62:a1:e0:b7:58:
30 cb:72:0b:87:e5:0e:bc:ea:36:f9:90:6f:73:b0:13:
31 b8:64:d4:97:a9:72:65:ef:c9:77:8f:f7:ef:a1:1d:
32 89:07:b6:37:47:50:e8:85:ed:17:82:c6:17:4c:8b:
33 10:93:af:fd:b3:f8:48:9a:28:b8:45:99:96:a2:b3:
34 10:2c:66:9e:f5:13:42:ac:e7:d9:86:11:32:ca:fa:
35 85:9f:82:8a:da:20:1a:cb:76:9e:4f:66:0d:b8:65:
36 42:2f:5a:a8:59:c7:d9:e3:17:b8:eb:0f:21:f9:3b:
37 75:18:d4:7d:f9:3c:ed:17:60:3d:e3:b8:e3:a6:7d:
38 9c:d6:81:c5:97:6d:bd:d5:da:31:15:9e:b8:75:c7:
39 0a:c2:d3:7c:24:a7:ab:a5:1e:a1:da:84:e6:e1:27:
40 1a:cb:14:17:76:8d:12:7d:da:03:c4:4a:28:dd:c5:
41 43:cc:45:53:31:a7:5b:c7:4f:70:c2:ff:92:21:e1:
42 b4:d1:de:36:c0:5f:04:19:f5:1d:4b:18:2f:27:be:
43 53:65:6e:b9:06:5b:5b:9c:84:db:3e:56:47:e0:0f:
44 62:48:b9:a4:75:62:c3:a7:34:71:58:a1:49:c0:40:
45 ff:4a:c6:13:46:87:d1:dd:98:30:e0:b3:d1:51:e0:
46 f2:89:33:9c:38:d2:98:71:d5:f4:a9:c3:fc:e9:a2:
47 09:17:21:c0:f0:31:3f:a1:c4:02:fb:0f:1c:43:a2:
48 ef:16:fa:f3:ae:da:8a:47:c0:05:a8:b0:b8:fa:b1:
49 4c:e7:86:46:d1:da:c7:8f:d2:1e:48:5e:0a:e2:09:
50 de:57:15:5c:47:2c:e8:a2:49:3d:77:1f:1b:a6:e3:
51 55:97:0e:fe:7f:dd:24:cf:85:4a:2d:01:7e:7c:88:
52 d5:52:1a:32:68:47:40:ba:56:05:0f:93:be:fc:e8:
53 5c:8c:0b
54 Exponent: 65537 (0x10001)
55 X509v3 extensions:
56 X509v3 Subject Key Identifier:
57 39:66:86:B8:9E:89:8B:50:7F:38:37:B6:85:28:E9:4E:A9:DB:AE:65
58 X509v3 Authority Key Identifier:
59 keyid:39:66:86:B8:9E:89:8B:50:7F:38:37:B6:85:28:E9:4E:A9:DB:AE:65
60
61 X509v3 Basic Constraints: critical
62 CA:TRUE
63 Signature Algorithm: sha256WithRSAEncryption
64 5c:b6:ac:bd:95:10:19:12:56:e1:33:7e:ab:52:cf:38:ed:37:
65 a9:a8:44:c3:2a:a6:35:35:c5:69:8e:f1:f8:c4:a6:50:9a:45:
66 b1:c6:57:2f:9e:7c:25:b5:82:93:94:26:6f:50:17:bd:09:d5:
67 bd:12:e5:20:81:dd:f0:b4:1f:f6:1c:42:eb:d7:8c:1c:b6:d6:
68 e0:03:a6:5e:62:d8:66:8f:ba:7f:1c:ed:11:ea:fe:84:77:12:
69 29:a7:50:1b:87:7e:48:87:0e:e7:54:df:76:2a:6c:95:65:5f:
70 91:69:2c:2f:ee:c5:fc:93:fe:5f:47:0f:59:79:92:75:d9:c6:
71 69:5c:18:8b:6b:6b:b7:38:b0:6b:1d:af:71:be:7e:23:4c:47:
72 17:d4:7b:70:98:d3:4b:cc:19:c2:18:e3:ed:d0:78:80:3e:e0:
73 dd:9e:11:46:51:37:fb:92:e3:6b:9a:7f:b1:ca:69:0d:9b:bc:
74 1f:8c:3d:79:67:27:92:ed:b8:3e:c2:88:44:96:f0:d1:df:c0:
75 c4:cc:39:28:cb:6a:94:af:af:85:43:f0:1c:90:89:92:3c:6f:
76 ac:c7:5e:70:c1:ac:55:97:47:c0:71:7e:f9:86:75:7d:5b:43:
77 aa:cf:fc:d0:35:22:64:59:55:63:f2:f4:e3:7c:25:05:90:a2:
78 df:3c:97:d3:a2:34:1d:33:d2:e6:ff:b1:23:5f:fb:0c:a7:c2:
79 9e:d6:07:d8:0f:2d:5b:0d:84:c5:20:9b:d3:46:33:75:5e:f5:
80 51:e8:62:a5:7f:0f:a9:59:4a:2d:be:b6:64:ec:71:cd:51:0d:
81 4d:51:32:4c:82:2a:c9:32:45:29:d5:3b:2d:9f:b0:f8:27:a7:
82 b5:f6:f4:63:dd:b2:81:c9:16:01:37:2d:1e:df:23:a3:98:f4:
83 c1:15:48:cf:a3:e4:6a:74:a4:a8:5a:06:5b:5f:83:30:c9:e5:
84 9a:60:fe:0c:e5:b9:67:29:40:4b:d6:fb:34:d0:21:4b:2b:5c:
85 69:f6:96:0b:d4:7c:82:16:6b:de:42:4d:b3:05:a7:11:b8:10:
86 5d:54:68:34:f1:57:2c:61:f2:33:c4:00:0b:4a:4f:15:ba:f4:
87 60:41:44:9b:29:a5:9c:c4:75:57:9a:ed:a5:50:62:cd:41:83:
88 3f:20:46:cb:90:1e:60:75:5d:83:91:cf:74:4a:1d:ee:d6:ca:
89 5c:97:4c:6a:ac:7f:1c:dd:5f:d0:d5:17:29:a0:bd:5a:1f:96:
90 d8:32:3b:23:21:c3:55:ee:c6:ca:d4:3b:25:11:e6:ac:62:ca:
91 c5:ab:d3:c1:4b:9c:7c:38:d2:b7:03:da:b7:ac:e8:f4:46:6a:
92 d7:65:ff:78:da:bb:08:0d
93
94
95 version serial
96 length=20 type *data flags
97 0000: 40ca2fa28e550000 14000000 02000000 c0ca2fa28e550000 8000000000000000
98 serial=0f:7d:3e:8b:35:d8:66:5a:ba:ce:44:47:f9:8a:e7:60:71:9e:bd:b3
99 signature.a signature.b *issuer validity.notBefore: len=0d000000 type=17000000 data=40f3d6311b560000[3232303532343035343734355a = 220524054745Z] flags=4000000000000000
100 0020: 006935728c7f0000 00cb2fa28e550000 902824a28e550000 b01215a28e550000
101
102 validity.notAfter
103 0040: 501407a28e550000 c0d22da28e55000070ec2ca28e5500000000000000000000
104 0060: 0000000000000000806112a28e5500000027faa18e5500005103000000000000
105
106 dump x509 serial [len=20] [0x55e021f742d0]
107 0000: 0f7d3e8b35d8665abace4447f98ae760719ebdb3
File agent/php.TODO added (mode: 100644) (index 0000000..14540c1)
1 [ ] We need to fill qs->err_code using PGSQL_DIAG_SQLSTATE.
2 [ ]
File agent/php.c added (mode: 100644) (index 0000000..4c434b8)
1 /*
2 * Description: Monitoring application
3 * Author: Catalin(ux) M. BOIE
4 * E-mail: catab at embedromix dot ro
5 * Web: https://rocketgit.com/user/catalinux/ninedogs
6 */
7
8 #define __USE_GNU
9 #define _GNU_SOURCE
10 #define __USE_XOPEN2K
11 #define __USE_LARGEFILE64
12 #define __USE_FILE_OFFSET64
13
14 #include <signal.h>
15 #include <pthread.h>
16 #include <stdarg.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <syslog.h>
20 #include <dlfcn.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <time.h>
29 #include <errno.h>
30 #include <dirent.h>
31 #include <asm/unistd.h>
32 #include <fcntl.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 #include <netinet/in.h>
36 #include <netinet/tcp.h>
37 #include <poll.h>
38 #include <netdb.h>
39 #include <ctype.h>
40
41 #include "ids.h"
42 #include "php.h"
43 #include "tools.h"
44 #include "ctools.h"
45 #include "process_db.h"
46
47
48 extern void *(*old_malloc)(size_t size);
49 extern void (*old_free)(void *p);
50
51
52 struct zend_function_entry
53 {
54 const char *fname;
55 void *handler;
56 void *arg_info;
57 unsigned int num_args;
58 unsigned int flags;
59 };
60
61 struct zend_module_entry
62 {
63 unsigned short size;
64 unsigned short pad1;
65 unsigned int zend_api;
66 unsigned char zend_debug;
67 unsigned char zts;
68 unsigned char pad2[6];
69 void *ini_entry;
70 void *deps;
71 char *name;
72 struct zend_function_entry *functions;
73 void *junk[5];
74 const char *version;
75 size_t globals_size;
76 };
77
78 typedef long zend_long;
79 typedef unsigned long zend_ulong;
80
81 struct zend_refcounted_h
82 {
83 unsigned int refcount;
84 unsigned int type_info;
85 };
86
87 struct zend_resource
88 {
89 struct zend_refcounted_h gc;
90 int handle;
91 int type;
92 void *ptr;
93 };
94
95 struct zend_string
96 {
97 struct zend_refcounted_h gc;
98 zend_ulong hash;
99 size_t len;
100 char val[1];
101 char pad1[7];
102 };
103
104 struct zend_array
105 {
106 struct zend_refcounted_h gc;
107 union {
108 struct {
109 unsigned char flags;
110 unsigned char _unused;
111 unsigned char nIteratorsCount;
112 unsigned char _unused2;
113 } v;
114 unsigned int flags;
115 } u;
116 unsigned int nTableMask;
117 struct Bucket *arData;
118 unsigned int nNumUsed;
119 unsigned int nNumOfElements;
120 unsigned int nTableSize;
121 unsigned int nInternalPointer;
122 zend_long nNextFreeElement;
123 void *dtor;
124 };
125
126 union zend_value
127 {
128 zend_long lval;
129 double dval;
130 void *p;
131 struct zend_string *str;
132 struct zend_array *arr;
133 struct zend_resource *res;
134 struct zend_reference *ref;
135 struct zval *zv;
136 struct {
137 unsigned int w1;
138 unsigned int w2;
139 } ww;
140 };
141
142 struct zval
143 {
144 union zend_value value;
145 union {
146 unsigned int type_info;
147 struct {
148 unsigned char type;
149 unsigned char type_flags;
150 union {
151 unsigned short extra;
152 } u;
153 } v;
154 } u1;
155 union {
156 unsigned int num_args;
157 } u2;
158 };
159
160 struct Bucket
161 {
162 struct zval val;
163 zend_ulong h;
164 struct zend_string *key;
165 };
166
167 struct zend_reference
168 {
169 unsigned int refcount;
170 unsigned int pad1;
171 struct zval val;
172 /* more thigs follows */
173 };
174
175 struct zend_execute_data
176 {
177 void *opline;
178 struct zend_execute_data *call;
179 struct zval *return_value;
180 void *func;
181 struct zval This;
182 struct zend_execute_data *prev;
183 struct zend_array *symbol_table;
184 void **runtime_cache;
185 struct zend_array *extra_named_params;
186 };
187
188 struct TODOpgsql_link_handle
189 {
190 void *conn; // PGconn
191 struct zend_string *hash;
192 struct HashTable *notices;
193 unsigned char persistent; // bool
194 //zend_object std;
195 unsigned char pad1[7];
196 };
197
198 static char *php_get_value(const struct zval *z)
199 {
200 static char ret[4096];
201 const struct zval *next;
202
203 if (!z)
204 return "NULL";
205
206 switch (z->u1.v.type) {
207 case 0: return "";
208 case 1: return "";
209 case 2: return "";
210 case 3: return "";
211 case 4: snprintf(ret, sizeof(ret), "%ld", z->value.lval); return ret;
212 case 5: snprintf(ret, sizeof(ret), "%f", z->value.dval); return ret;
213 case 6:
214 struct zend_string *zs = z->value.str;
215 return zs->val;
216 case 8:
217 snprintf(ret, sizeof(ret), "%p", z->value.p); return ret;
218 case 9:
219 snprintf(ret, sizeof(ret), "%p", z->value.p); return ret;
220 case 10:
221 next = &z->value.ref->val;
222 return php_get_value(next);
223 case 12:
224 next = z->value.zv;
225 return php_get_value(next);
226 default:
227 snprintf(ret, sizeof(ret), "?%hhu: %p",
228 z->u1.v.type, z->value.str); return ret;
229 }
230 }
231
232 static char *php_get_type(const struct zval *z)
233 {
234 static char s[8];
235
236 if (!z)
237 return "NULL";
238
239 switch (z->u1.v.type) {
240 case 0: return "undef";
241 case 1: return "null";
242 case 2: return "false";
243 case 3: return "true";
244 case 4: return "long";
245 case 5: return "double";
246 case 6: return "string";
247 case 7: return "array";
248 case 8: return "object";
249 case 9: return "resource";
250 case 10: return "ref";
251 case 12: return "indirect";
252 default: sprintf(s, "?%hhu", z->u1.v.type); return s;
253 }
254 }
255
256 static void php_zval_dump_buf(char *buf, const size_t size,
257 const char *prefix, const struct zval *z)
258 {
259 if (!z) {
260 snprintf(buf, size, "zval is null");
261 return;
262 }
263
264 snprintf(buf, size, "%s%p: type=%s value=[%s] type_flags=%hhu extra=%hu num_args=%u",
265 prefix, z, php_get_type(z), php_get_value(z),
266 z->u1.v.type_flags,
267 z->u1.v.u.extra, z->u2.num_args);
268 }
269
270 static void php_zval_dump(const char *prefix, const struct zval *z)
271 {
272 char s[4096];
273
274 php_zval_dump_buf(s, sizeof(s), prefix, z);
275 xlog(100, "%s\n", s);
276 }
277
278 static void php_zed_dump(const char *prefix, struct zend_execute_data *p)
279 {
280 unsigned int num_args, s, i;
281 struct zval *z;
282 char x[64];
283
284 if (!p) {
285 xlog(100, "%szed is null!\n", prefix);
286 return;
287 }
288
289 num_args = p->This.u2.num_args;
290 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
291 dump(100, "zed", p, sizeof(struct zval) * (s + num_args));
292
293 xlog(100, "%szed: p=%p num_args=%hu return_value=%p\n",
294 prefix, p, num_args, p->return_value);
295 //php_zval_dump(prefix, p->return_value);
296 snprintf(x, sizeof(x), "%s This: ", prefix);
297 php_zval_dump(x, &p->This);
298
299 for (i = 0; i < num_args; i++) {
300 char zs[1024];
301
302 z = (struct zval *) p + s; s++;
303 php_zval_dump_buf(zs, sizeof(zs), "", z);
304 xlog(100, "%s para %u: %s\n", prefix, i, zs);
305 }
306 }
307
308 void *(*old_pg_last_error)(struct zend_execute_data *, struct zval *);
309 static void *my_pg_last_error(struct zend_execute_data *e, struct zval *retv)
310 {
311 void *ret;
312 unsigned int num_args;
313
314 num_args = e->This.u2.num_args;
315 xlog(1, "%s: e=%p num_args=%hu\n",
316 __func__, e, num_args);
317
318 ret = old_pg_last_error(e, retv);
319 if (!retv)
320 return ret;
321
322 //php_zval_dump(" retv: ", retv);
323
324 return ret;
325 }
326
327 void *(*old_pg_connect)(struct zend_execute_data *, struct zval *);
328 static void *my_pg_connect(struct zend_execute_data *e, struct zval *retv)
329 {
330 void *ret;
331 unsigned int num_args, s;
332 struct zval *z;
333 struct zend_string *q;
334 struct conn cs;
335
336 num_args = e->This.u2.num_args;
337 xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
338
339 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
340 cs.type = 'P';
341
342 // connection string
343 z = (struct zval *) e + s; s++;
344 q = z->value.str;
345 cs.conn_str = q->val;
346 cs.conn_str_len = q->len;
347 xlog(50, " conn: %s\n", cs.conn_str);
348
349 ninedogs_now(&cs.start);
350 ret = old_pg_connect(e, retv);
351 if (!retv)
352 return ret;
353 ninedogs_now(&cs.end);
354
355 //php_zval_dump(" retv: ", retv);
356 // TODO: how to test for error? if (core_globals.last_error_message) {
357
358 // PHP7 returns resource, PHP8.1 returns object
359 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) {
360 cs.dbh = retv->value.p;
361 ninedogs_process_db(NINEDOGS_DB_CONN, &cs);
362 }
363
364 return ret;
365 }
366
367 void *(*old_pg_pconnect)(struct zend_execute_data *, struct zval *);
368 static void *my_pg_pconnect(struct zend_execute_data *e, struct zval *retv)
369 {
370 void *ret;
371 unsigned int num_args, s;
372 struct zval *z;
373 struct zend_string *q;
374 struct conn cs;
375
376 num_args = e->This.u2.num_args;
377 xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
378
379 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
380 cs.type = 'P';
381
382 // connection string
383 z = (struct zval *) e + s; s++;
384 q = z->value.str;
385 cs.conn_str = q->val;
386 cs.conn_str_len = q->len;
387 xlog(50, " conn: %s\n", cs.conn_str);
388
389 ninedogs_now(&cs.start);
390 ret = old_pg_pconnect(e, retv);
391 if (!retv)
392 return ret;
393 ninedogs_now(&cs.end);
394
395 //php_zval_dump(" retv: ", retv);
396 // TODO: how to test for error? if (core_globals.last_error_message) {
397
398 // PHP7 returns resource, PHP8.1 returns object
399 if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) {
400 cs.dbh = retv->value.p;
401 ninedogs_process_db(NINEDOGS_DB_CONN, &cs);
402 }
403
404 return ret;
405 }
406
407 void *(*old_pg_affected_rows)(struct zend_execute_data *, struct zval *);
408
409 void *(*old_pg_free_result)(struct zend_execute_data *, struct zval *);
410 static void *my_pg_free_result(struct zend_execute_data *e, struct zval *retv)
411 {
412 void *ret;
413 unsigned int s;
414 struct free_result fr;
415
416 //unsigned int num_args = e->This.u2.num_args;
417 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
418 //php_zed_dump(" e: ", e);
419 //php_zval_dump(" retv: ", retv);
420
421 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
422 struct zval *z = (struct zval *) e + s;
423
424 fr.type = 'P';
425 fr.res = z->value.p;
426
427 ret = old_pg_free_result(e, retv);
428 if (!ret)
429 return NULL;
430 //php_zval_dump(" retv: ", retv);
431
432 if (retv->u1.v.type == 3) { // true
433 fr.ok = 1;
434 } else {
435 // TODO: can we get an error code here?
436 fr.ok = 0;
437 }
438
439 ninedogs_process_db(NINEDOGS_DB_FREE_RESULT, &fr);
440
441 return ret;
442 }
443
444 void *(*old_pg_num_rows)(struct zend_execute_data *, struct zval *);
445 static void *my_pg_num_rows(struct zend_execute_data *e, struct zval *retv)
446 {
447 void *ret;
448
449 //unsigned int num_args = e->This.u2.num_args;
450 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
451 //php_zed_dump(" e: ", e);
452 //php_zval_dump(" retv: ", retv);
453
454 ret = old_pg_num_rows(e, retv);
455 if (!retv)
456 return ret;
457
458 //php_zval_dump(" retv: ", retv);
459
460 return ret;
461 }
462
463 static void php_set_para(struct zend_execute_data *e, const unsigned int i,
464 const struct zval *para)
465 {
466 unsigned int s;
467 struct zval *dst;
468
469 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
470 dst = (struct zval *) e + s + i;
471 memcpy(dst, para, sizeof(struct zval));
472 }
473
474 static void php_set_last_error(struct zend_execute_data *e,
475 struct zval *dbh, struct query *q)
476 {
477 struct zval rz;
478
479 e->This.u2.num_args = dbh ? 1 : 0;
480 if (dbh)
481 php_set_para(e, 0, dbh);
482
483 // TODO: we need also the numeric representation of the error!
484 xlog(50, " calling pg_last_error...\n");
485 old_pg_last_error(e, &rz);
486 //xlog(1, " pg_last_error returned %p; type=%s value=%s\n",
487 // tr, php_get_type(&rz), php_get_value(&rz));
488
489 if (rz.u1.v.type == 6) { // string
490 q->err = rz.value.str->val;
491 q->err_len = rz.value.str->len;
492 xlog(40, "%s: set error to [%s]\n", __func__, q->err);
493 } else {
494 q->err = "?";
495 q->err_len = 1;
496 }
497 }
498
499 static void php_set_num_aff(struct zend_execute_data *e, struct zval *res,
500 struct query *q)
501 {
502 struct zval rz;
503
504 e->This.u2.num_args = 1;
505
506 php_set_para(e, 0, res);
507
508 //xlog(1, " calling old pg_num_rows...\n");
509 //php_zed_dump(" e: ", e);
510 old_pg_num_rows(e, &rz);
511 //php_zval_dump(" rz: ", &rz);
512 q->num = rz.value.lval;
513
514 //xlog(1, " calling old pg_affected_rows...\n");
515 //php_zed_dump(" e: ", e);
516 old_pg_affected_rows(e, &rz);
517 //php_zval_dump(" rz: ", &rz);
518 q->aff = rz.value.lval;
519 }
520
521 void *(*old_pg_query)(struct zend_execute_data *, struct zval *);
522 static void *my_pg_query(struct zend_execute_data *e, struct zval *retv)
523 {
524 void *ret;
525 unsigned int num_args, copy_num_args, s;
526 struct zend_string *q;
527 struct zval *dbh = NULL, *z, copy_para, *para;
528 char do_restore = 0;
529 struct query qs;
530
531 num_args = e->This.u2.num_args;
532
533 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
534
535 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
536 para = (struct zval *) e + s;
537 qs.type = 'P'; // if dbh is null, we do not know the type
538
539 if (num_args == 2) {
540 // link
541 z = (struct zval *) e + s; s++;
542 //php_zval_dump(" dbh: ", z);
543 qs.dbh = z->value.p;
544 } else {
545 qs.dbh = NULL;
546 }
547
548 // query
549 z = (struct zval *) e + s; s++;
550 q = z->value.str;
551 xlog(50, " query=%s\n", q->val);
552 qs.q = q->val;
553 qs.q_len = q->len;
554
555 ninedogs_now(&qs.start);
556 ret = old_pg_query(e, retv);
557 if (!retv)
558 return ret;
559 ninedogs_now(&qs.end);
560
561 xlog(100, " old %s returned type=%s value=%s\n",
562 __func__, php_get_type(retv), php_get_value(retv));
563
564 copy_num_args = num_args;
565 memcpy(&copy_para, para, sizeof(struct zval));
566
567 if (retv->u1.v.type == 2) { // false
568 php_set_last_error(e, dbh, &qs);
569 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
570 qs.res = retv->value.str;
571 php_set_num_aff(e, retv, &qs);
572 do_restore = 1;
573 }
574
575 e->This.u2.num_args = copy_num_args;
576 if (do_restore)
577 memcpy(para, &copy_para, sizeof(struct zval));
578
579 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
580
581 return ret;
582 }
583
584 void *(*old_pg_send_query)(struct zend_execute_data *, struct zval *);
585 static void *my_pg_send_query(struct zend_execute_data *e, struct zval *retv)
586 {
587 void *ret;
588 unsigned int num_args, s;
589 struct zend_string *q;
590 struct zval *dbh = NULL, *z;
591 struct query qs;
592
593 num_args = e->This.u2.num_args;
594 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
595
596 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
597 qs.type = 'P';
598
599 // link
600 z = (struct zval *) e + s; s++;
601 php_zval_dump(" dbh: ", z);
602 qs.dbh = z->value.p;
603
604 // query
605 z = (struct zval *) e + s; s++;
606 q = z->value.str;
607 qs.q = q->val;
608 qs.q_len = q->len;
609 xlog(100, " query=%s\n", qs.q);
610
611 ninedogs_now(&qs.start);
612 ret = old_pg_send_query(e, retv);
613 if (!retv)
614 return ret;
615 ninedogs_now(&qs.end);
616
617 xlog(1, " old %s returned type=%s value=%s\n",
618 __func__, php_get_type(retv), php_get_value(retv));
619
620 qs.res = NULL;
621 if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int
622 php_set_last_error(e, dbh, &qs);
623 } else if (retv->u1.v.type == 3) { // true = success
624 qs.num = qs.aff = 0;
625 }
626
627 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
628
629 return ret;
630 }
631
632 // TODO: not clear if on PHP 7 the parameter could be null
633 void *(*old_pg_get_result)(struct zend_execute_data *, struct zval *);
634 static void *my_pg_get_result(struct zend_execute_data *e, struct zval *retv)
635 {
636 void *ret;
637 unsigned int num_args, copy_num_args, s;
638 struct zval *dbh = NULL, *z, copy_para, *para;
639 char do_restore = 0;
640 struct query qs;
641
642 num_args = e->This.u2.num_args;
643 xlog(100, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
644
645 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
646 para = (struct zval *) e + s;
647 qs.type = 'P';
648 qs.q = NULL;
649
650 // link
651 z = (struct zval *) e + s; s++;
652 //php_zval_dump(" dbh: ", z);
653 qs.dbh = z->value.p;
654
655 ninedogs_now(&qs.start);
656 ret = old_pg_get_result(e, retv);
657 if (!retv)
658 return ret;
659 ninedogs_now(&qs.end);
660
661 xlog(100, " old %s returned type=%s value=%s\n",
662 __func__, php_get_type(retv), php_get_value(retv));
663
664 copy_num_args = num_args;
665 memcpy(&copy_para, para, sizeof(struct zval));
666
667 if (retv->u1.v.type == 2) { // false
668 php_set_last_error(e, dbh, &qs);
669 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
670 qs.err = NULL;
671 qs.res = retv->value.str;
672 php_set_num_aff(e, retv, &qs);
673 do_restore = 1;
674 }
675
676 e->This.u2.num_args = copy_num_args;
677 if (do_restore)
678 memcpy(para, &copy_para, sizeof(struct zval));
679
680 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
681
682 return ret;
683 }
684
685 void *(*old_pg_query_params)(struct zend_execute_data *, struct zval *);
686 static void *my_pg_query_params(struct zend_execute_data *e, struct zval *retv)
687 {
688 void *ret;
689 unsigned int num_args, s;
690 struct zval copy_para, *para, *z;
691 struct zend_string *q;
692 unsigned int copy_num_args;
693 void *dbh = NULL;
694 char do_restore = 0;
695 struct query qs;
696
697 num_args = e->This.u2.num_args;
698 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
699 //php_zed_dump(" e0: ", e);
700 //php_zval_dump(" retv0: ", retv);
701
702 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
703 para = (struct zval *) e + s;
704 qs.type = 'P';
705
706 if (num_args == 3) {
707 // link
708 z = (struct zval *) e + s; s++;
709 qs.dbh = z->value.p;
710 } else {
711 qs.dbh = NULL;
712 }
713
714 // query
715 z = (struct zval *) e + s; s++;
716 q = z->value.str;
717 qs.q = q->val;
718 qs.q_len = q->len;
719
720 // params (array)
721 z = (struct zval *) e + s; s++;
722 #if 1
723 struct zend_array *za;
724 za = z->value.arr;
725 xlog(200, " nTableMask=%u nNumUsed=%u nNumOfElements=%u nTableSize=%u nInternalPointer=%u\n",
726 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nInternalPointer);
727
728 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
729 unsigned int i = 1;
730 for (; bs != be; bs++) {
731 struct zval *_z = &bs->val;
732
733 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
734 _z = _z->value.zv;
735
736 if (_z->u1.v.type == 0 /*IS_UNDEF*/) continue;
737
738 if (_z->u1.v.type == 10) { // REFERENCE
739 xlog(1, " is a reference!\n");
740 _z = &_z->value.ref->val;
741 }
742
743 xlog(200, " para %u: type %s: val: %s\n",
744 i, php_get_type(_z), php_get_value(_z));
745 i++;
746 }
747 #endif
748
749 ninedogs_now(&qs.start);
750 ret = old_pg_query_params(e, retv);
751 ninedogs_now(&qs.end);
752 //xlog(200, " old %s: type=%s value=%s\n",
753 // __func__, php_get_type(retv), php_get_value(retv));
754 //php_zed_dump(" e1: ", e);
755 //php_zval_dump(" retv1 after calling old func: ", retv);
756
757 copy_num_args = e->This.u2.num_args;
758 memcpy(&copy_para, para, sizeof(struct zval));
759
760 if (retv->u1.v.type == 2) { // false
761 php_set_last_error(e, dbh, &qs);
762 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
763 qs.res = retv->value.str;
764 php_set_num_aff(e, retv, &qs);
765 do_restore = 1;
766 }
767
768 //php_zval_dump(" retv before ret: ", retv);
769
770 e->This.u2.num_args = copy_num_args;
771 if (do_restore)
772 memcpy(para, &copy_para, sizeof(struct zval));
773
774 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
775
776 return ret;
777 }
778
779 void *(*old_pg_send_query_params)(struct zend_execute_data *, struct zval *);
780 static void *my_pg_send_query_params(struct zend_execute_data *e, struct zval *retv)
781 {
782 void *ret;
783 unsigned int s;
784 struct zval *z;
785 struct zval *dbh;
786 struct zend_string *q;
787 struct query qs;
788
789 //unsigned int num_args = e->This.u2.num_args;
790 //xlog(1, "%s: e=%p num_args=%hu\n", __func__, e, num_args);
791 //php_zed_dump(" e0: ", e);
792 //php_zval_dump(" retv0: ", retv);
793
794 s = (sizeof(struct zend_execute_data) + sizeof(struct zval) - 1) / sizeof(struct zval);
795 qs.type = 'P';
796
797 // link
798 dbh = (struct zval *) e + s; s++;
799 qs.dbh = dbh->value.p;
800
801 // query
802 z = (struct zval *) e + s; s++;
803 q = z->value.str;
804 qs.q = q->val;
805 qs.q_len = q->len;
806
807 // params (array)
808 z = (struct zval *) e + s; s++;
809 #if 1
810 struct zend_array *za;
811 za = z->value.arr;
812 xlog(200, " nTableMask=%u nNumUsed=%u nNumOfElements=%u nTableSize=%u nInternalPointer=%u\n",
813 za->nTableMask, za->nNumUsed, za->nNumOfElements, za->nTableSize, za->nInternalPointer);
814
815 struct Bucket *bs = za->arData, *be = za->arData + za->nNumUsed;
816 unsigned int i = 1;
817 for (; bs != be; bs++) {
818 struct zval *_z = &bs->val;
819
820 if (_z && (_z->u1.v.type == 12)) // 12=IS_INDIRECT
821 _z = _z->value.zv;
822
823 if (_z->u1.v.type == 0 /*IS_UNDEF*/) continue;
824
825 if (_z->u1.v.type == 10) { // REFERENCE
826 xlog(1, " is a reference!\n");
827 _z = &_z->value.ref->val;
828 }
829
830 xlog(200, " para %u: type %s: val: %s\n",
831 i, php_get_type(_z), php_get_value(_z));
832 i++;
833 }
834 #endif
835
836 ninedogs_now(&qs.start);
837 ret = old_pg_send_query_params(e, retv);
838 ninedogs_now(&qs.end);
839 //xlog(200, " old %s: type=%s value=%s\n",
840 // __func__, php_get_type(retv), php_get_value(retv));
841 //php_zed_dump(" e1: ", e);
842 //php_zval_dump(" retv1 after calling old func: ", retv);
843
844 qs.res = NULL;
845 if ((retv->u1.v.type == 2) || (retv->u1.v.type == 4)) { // false or int (probably 0)
846 php_set_last_error(e, dbh, &qs);
847 } else if ((retv->u1.v.type == 8) || (retv->u1.v.type == 9)) { // object or resource
848 qs.num = qs.aff = 0;
849 }
850
851 ninedogs_process_db(NINEDOGS_DB_QUERY, &qs);
852
853 return ret;
854 }
855
856 struct zend_module_entry *(*old_get_module)(void);
857 static struct zend_module_entry *php_hook_get_module_func(void)
858 {
859 struct zend_module_entry *z, *new;
860 struct zend_function_entry *fe;
861 unsigned int count;
862
863 z = old_get_module();
864 if (!z)
865 return NULL;
866
867 if (strcmp(z->name, "pgsql") != 0)
868 return z;
869
870 xlog(100, " %s: name=%s size=%hu zend_api=%u zts=%hhu version=%s functions=%p\n",
871 __func__, z->name, z->size, z->zend_api, z->zts, z->version, z->functions);
872
873 count = 0;
874 fe = z->functions;
875 while (fe->fname) {
876 count++;
877 fe++;
878 }
879 //xlog(1, " %u functions\n", count);
880
881 // We have to make a copy of the read-only structure
882 new = old_malloc(z->size);
883 if (!new) {
884 xlog(1, "%s: cannot alloc memory! Returning old table!\n");
885 return z;
886 }
887
888 memcpy(new, z, z->size);
889
890 new->functions = old_malloc((count + 1) * sizeof(struct zend_function_entry));
891 if (!new->functions) {
892 old_free(new);
893 return z;
894 }
895
896 memcpy(new->functions, z->functions, (count + 1) * sizeof(struct zend_function_entry));
897
898 fe = new->functions;
899 while (fe->fname) {
900 //xlog(2, " func %s handler=%p\n", fe->fname, fe->handler);
901 if (strcmp(fe->fname, "pg_connect") == 0) {
902 old_pg_connect = fe->handler;
903 fe->handler = my_pg_connect;
904 } else if (strcmp(fe->fname, "pg_pconnect") == 0) {
905 old_pg_pconnect = fe->handler;
906 fe->handler = my_pg_pconnect;
907 } else if (strcmp(fe->fname, "pg_num_rows") == 0) {
908 old_pg_num_rows = fe->handler;
909 fe->handler = my_pg_num_rows;
910 } else if (strcmp(fe->fname, "pg_affected_rows") == 0) {
911 old_pg_affected_rows = fe->handler;
912 } else if (strcmp(fe->fname, "pg_free_result") == 0) {
913 old_pg_free_result = fe->handler;
914 fe->handler = my_pg_free_result;
915 } else if (strcmp(fe->fname, "pg_query") == 0) {
916 old_pg_query = fe->handler;
917 fe->handler = my_pg_query;
918 } else if (strcmp(fe->fname, "pg_send_query") == 0) {
919 old_pg_send_query = fe->handler;
920 fe->handler = my_pg_send_query;
921 } else if (strcmp(fe->fname, "pg_query_params") == 0) {
922 old_pg_query_params = fe->handler;
923 fe->handler = my_pg_query_params;
924 } else if (strcmp(fe->fname, "pg_send_query_params") == 0) {
925 old_pg_send_query_params = fe->handler;
926 fe->handler = my_pg_send_query_params;
927 } else if (strcmp(fe->fname, "pg_last_error") == 0) {
928 old_pg_last_error = fe->handler;
929 fe->handler = my_pg_last_error;
930 } else if (strcmp(fe->fname, "pg_get_result") == 0) {
931 old_pg_get_result = fe->handler;
932 fe->handler = my_pg_get_result;
933 } else {
934 xlog(100, " %s: do not hook [%s]!\n", __func__, fe->fname);
935 }
936 fe++;
937 }
938
939 return new;
940 }
941
942 void *php_hook(void *x)
943 {
944 old_get_module = x;
945 return php_hook_get_module_func;
946 }
947
948 typedef struct {
949 const char *driver_name;
950 size_t driver_name_len;
951 unsigned long api_version;
952 int (*db_handle_factory)(void *dbh, void *driver_options);
953 } pdo_driver_t;
954
955 #if 0
956 pdo_driver_t old, my_driver;
957 int php_pdo_register_driver(pdo_driver_t *driver)
958 {
959 int r;
960
961 hookup_php();
962
963 xlog(2, "%s driver=%p name=%s\n", __func__, driver, driver->driver_name);
964 if (driver) {
965 if (strcmp(driver->driver_name, "pgsql") == 0) {
966 xlog(2, " hook db_handle_factory\n");
967 memcpy(&my_driver, driver, sizeof(pdo_driver_t));
968 old.db_handle_factory = driver->db_handle_factory;
969 my_driver.db_handle_factory = my_db_handle_factory;
970 r = old_php_pdo_register_driver(&my_driver);
971 } else {
972 xlog(2, " NOT hooking db_handle_factory\n");
973 r = old_php_pdo_register_driver(driver);
974 }
975 } else {
976 r = -1;
977 }
978
979 return r;
980 }
981
982 #endif
983
File agent/php.h added (mode: 100644) (index 0000000..b2242cd)
1
2 void *php_hook(void *x);
3
File agent/process.c added (mode: 100644) (index 0000000..99f624a)
1 #include <sys/time.h>
2 #include <stddef.h>
3 #include <sys/utsname.h>
4 #include <string.h>
5
6 #include "ids.h"
7 #include "ctools.h"
8 #include "process.h"
9
10
11 void ninedogs_process_post(void)
12 {
13 send_sysinfo();
14 server_pat(0);
15 }
16
File agent/process.h added (mode: 100644) (index 0000000..799e7e6)
1 void ninedogs_process_post(void);
2
File agent/process_core.c added (mode: 100644) (index 0000000..87a1c5d)
1 #include <sys/time.h>
2 #include <stddef.h>
3 #include <sys/utsname.h>
4 #include <string.h>
5
6 #include "ids.h"
7 #include "tools.h"
8 #include "ctools.h"
9 #include "process.h"
10 #include "process_core.h"
11 #include "process_misc.h"
12 #include "process_db.h"
13 #include "process_ssl.h"
14
15 static struct timeval start, stop;
16
17
18 static char *type2name(const unsigned int type)
19 {
20 switch (type) {
21 case NINEDOGS_CORE_START: return "start";
22 case NINEDOGS_CORE_STOP: return "stop";
23 }
24
25 return "?";
26 }
27
28 void ninedogs_process_core(const unsigned int type, const void *d)
29 {
30 unsigned char *buf;
31 unsigned int len;
32
33 xlog(10, "%s: type=%s\n", __func__, type2name(type));
34
35 switch (type) {
36 case NINEDOGS_CORE_START:
37 if (start.tv_sec > 0)
38 return;
39
40 ninedogs_now(&start);
41 xlog(100, "%s: DEBUG: set start to %ld.%03ld\n",
42 __func__, start.tv_sec, start.tv_usec / 1000);
43
44 do {
45 struct utsname u;
46
47 int r = uname(&u);
48 if (r == -1) {
49 xlog(1, "Cannot call uname: %m\n");
50 break;
51 }
52
53 pack(&buf, &len, "T4 NN ss ns" "rs vs" "ms",
54 NINEDOGS_NET_CORE_UNAME,
55 u.sysname, strlen(u.sysname), u.nodename, strlen(u.nodename),
56 u.release, strlen(u.release), u.version, strlen(u.version),
57 u.machine, strlen(u.machine));
58 if (buf)
59 server_enqueue(buf, len);
60 } while (0);
61 break;
62
63 case NINEDOGS_CORE_STOP:
64 int *exit_code = (int *) d;
65
66 ninedogs_now(&stop);
67 xlog(50, "%s: DEBUG: set stop to %ld.%03ld\n", __func__, stop.tv_sec, stop.tv_usec / 1000);
68
69 // TODO: add page faults, wall time, sys time etc. (getrusage)
70 pack(&buf, &len, "T4 st tt x4",
71 NINEDOGS_NET_CORE_STOP, &start, &stop, *exit_code);
72 if (buf)
73 server_enqueue(buf, len);
74
75 ninedogs_process_db_flush();
76 ninedogs_process_misc_flush();
77 ninedogs_process_ssl_flush();
78 server_stop();
79 break;
80 }
81 }
82
File agent/process_core.h added (mode: 100644) (index 0000000..7a0fbfd)
1 void ninedogs_process_core(const unsigned int type, const void *d);
File agent/process_db.c added (mode: 100644) (index 0000000..6a49805)
1 #include <stdio.h>
2 #include <string.h>
3 #include <pthread.h>
4 #include <sys/time.h>
5 #include <stdarg.h>
6
7 #include "ids.h"
8 #include "tools.h"
9 #include "ctools.h"
10 #include "process.h"
11 #include "process_db.h"
12
13 extern void *(*old_malloc)(size_t size);
14 extern void (*old_free)(void *p);
15
16 static unsigned int gran = 60; // granularity of reports, in seconds
17 static unsigned int max_query_len = 8192;
18
19 // query stuff
20 static __thread void *last_db_handle;
21
22 struct query_node
23 {
24 char *query;
25 unsigned char hash[32];
26 void *res;
27 struct timeval ts, min, max, elap, process_sum; // "ts" is the granularity interval timestamp
28 struct timeval last_start; // this is used for get_result
29 unsigned long rows, aff;
30 unsigned long count, free_calls, free_errs;
31 unsigned int query_len;
32 unsigned int pad1;
33 struct query_node *next;
34 };
35
36 static void query_reset_node(struct query_node *qn)
37 {
38 qn->elap.tv_sec = qn->elap.tv_usec = 0;
39 qn->min.tv_sec = 2000000000; qn->min.tv_usec = 0;
40 qn->max.tv_sec = qn->max.tv_usec = 0;
41 qn->ts.tv_sec = 0;
42 qn->process_sum.tv_sec = qn->process_sum.tv_usec = 0;
43 qn->rows = qn->aff = qn->count = 0;
44 qn->free_calls = qn->free_errs = 0;
45 }
46
47 static void query_init_node(struct query_node *qn)
48 {
49 qn->ts.tv_usec = 0;
50 query_reset_node(qn);
51 }
52
53 static void query_dump_node(const unsigned int level,
54 const struct query_node *qn)
55 {
56 char hash[65];
57
58 bin2hex(hash, qn->hash, sizeof(qn->hash));
59 xlog(level, " query=[%s] hash=%s res=%p count=%u rows=%lu aff=%lu"
60 " free_calls/errs=%lu/%lu"
61 " ts=%ld.%03ld min=%ld.%03ld max=%ld.%03ld elap=%ld.%03ld"
62 " process_sum=%ld.%03ld\n",
63 qn->query, hash, qn->res, qn->count, qn->rows, qn->aff,
64 qn->free_calls, qn->free_errs,
65 qn->ts.tv_sec, qn->ts.tv_usec / 1000,
66 qn->min.tv_sec, qn->min.tv_usec / 1000,
67 qn->max.tv_sec, qn->max.tv_usec / 1000,
68 qn->elap.tv_sec, qn->elap.tv_usec / 1000,
69 qn->process_sum.tv_sec, qn->process_sum.tv_usec / 1000);
70 }
71
72 // We may not send the query because it may be big.
73 // The server will request it if it doesn't have it.
74 static void query_send_node(const struct query_node *qn)
75 {
76 unsigned char *buf;
77 unsigned int len;
78
79 xlog(50, "%s: qn=%p\n", __func__, qn);
80 pack(&buf, &len, "T4 hs c8 r8 A8" "_t it at et x8 y8" "qs",
81 NINEDOGS_NET_DB_QUERY_STATS, qn->hash, sizeof(qn->hash), qn->count, qn->rows, qn->aff,
82 &qn->ts, &qn->min, &qn->max, &qn->elap,
83 &qn->free_calls, &qn->free_errs,
84 qn->query, qn->query_len);
85 if (!buf)
86 return;
87
88 server_enqueue(buf, len);
89 }
90
91 static void query_hash(unsigned char *hash, const char *q, const unsigned int q_len)
92 {
93 ninedogs_sha256(hash, q, q_len);
94 }
95
96 ///////////////////////////////////////////////////// conn stuff
97
98 struct conn_node
99 {
100 char type;
101 char pad1[3];
102 unsigned int count; // how many connections took place
103 const void *handle;
104 char *conn_str;
105 unsigned int conn_str_len;
106 unsigned int pad2;
107 struct timeval last_query_try;
108 struct timeval ts, min, max, elap;
109 struct query_node *qh, *qt;
110 struct conn_node *next;
111 };
112
113 static __thread struct conn_node *conn_head, *conn_tail;
114
115 static struct conn_node *conn_get(const char type, const char *conn_str,
116 const unsigned int conn_str_len)
117 {
118 struct conn_node *cn;
119
120 xlog(50, "%s: searching for conn_str [%s]\n", __func__, conn_str);
121 cn = conn_head;
122 while (cn) {
123 if ((cn->type == type)
124 && (cn->conn_str_len == conn_str_len)
125 && (strcmp(cn->conn_str, conn_str) == 0)) {
126 xlog(50, " found it; cn=%p cn->handle=%p\n", cn, cn->handle);
127 return cn;
128 }
129 cn = cn->next;
130 }
131
132 xlog(50, " found NO prev conn\n");
133 return NULL;
134 }
135
136 static struct conn_node *conn_get_by_handle(const void *handle)
137 {
138 struct conn_node *cn;
139
140 xlog(50, "%s: searching for conn handle [%p]\n", __func__, handle);
141 cn = conn_head;
142 while (cn) {
143 if (cn->handle == handle) {
144 xlog(50, " found a prev conn cn=%p\n", cn);
145 return cn;
146 }
147 cn = cn->next;
148 }
149
150 xlog(50, " found NO prev conn\n");
151 return NULL;
152 }
153
154 static void conn_reset_node(struct conn_node *cn)
155 {
156 struct query_node *qn;
157
158 cn->count = 0;
159 cn->ts.tv_sec = 0;
160 cn->min.tv_sec = 2000000000; cn->min.tv_usec = 0;
161 cn->max.tv_sec = cn->max.tv_usec = 0;
162 cn->elap.tv_sec = cn->elap.tv_usec = 0;
163
164 qn = cn->qh;
165 while (qn) {
166 // TODO: we may want to remove old ones
167 query_reset_node(qn);
168 qn = qn->next;
169 }
170 }
171
172 static void conn_init_node(struct conn_node *cn)
173 {
174 cn->type = '0';
175 cn->handle = NULL;
176 cn->qh = cn->qt = NULL;
177 cn->ts.tv_usec = 0;
178 conn_reset_node(cn);
179 }
180
181 static void conn_dump_node(const unsigned int level,
182 const struct conn_node *cn)
183 {
184 struct query_node *qn;
185
186 xlog(level, " type=%c count=%u handle=%p conn_str=[%s]"
187 " ts=%ld.%03ld min=%ld.%03ld max=%ld.%03ld elap=%ld.%03ld\n",
188 cn->type, cn->count, cn->handle, cn->conn_str,
189 cn->ts.tv_sec, cn->ts.tv_usec / 1000,
190 cn->min.tv_sec, cn->min.tv_usec / 1000,
191 cn->max.tv_sec, cn->max.tv_usec / 1000,
192 cn->elap.tv_sec, cn->elap.tv_usec / 1000);
193
194 qn = cn->qh;
195 while (qn) {
196 query_dump_node(level, qn);
197 qn = qn->next;
198 }
199 }
200
201 static void conn_dump(const unsigned int level)
202 {
203 struct conn_node *cn;
204
205 xlog(level, " Dumping conns:\n");
206 cn = conn_head;
207 while (cn) {
208 conn_dump_node(level, cn);
209 cn = cn->next;
210 }
211 xlog(level, " Dumping stop\n");
212 }
213
214 static void conn_send_node(const struct conn_node *cn)
215 {
216 struct query_node *qn;
217 unsigned char *buf;
218 unsigned int len;
219
220 // TODO: mask password; before storing it in memory
221
222 xlog(50, "%s: cn=%p\n", __func__, cn);
223 pack(&buf, &len, "T4 tc c4" "ss" "_t it at et",
224 NINEDOGS_NET_DB_CONN, cn->type, cn->count,
225 cn->conn_str, strlen(cn->conn_str),
226 &cn->ts, &cn->min, &cn->max, &cn->elap);
227 if (!buf)
228 return;
229
230 server_enqueue(buf, len);
231
232 qn = cn->qh;
233 while (qn) {
234 query_send_node(qn);
235 qn = qn->next;
236 }
237 }
238
239 static void conn_flush_node(struct conn_node *cn, const unsigned int u)
240 {
241 if (cn->ts.tv_sec == 0)
242 cn->ts.tv_sec = u * gran;
243 if (cn->ts.tv_sec / gran == u)
244 return;
245
246 xlog(40, "%s: cn->ts.tv_sec/gran=%u u=%u\n",
247 __func__, cn->ts.tv_sec / gran, u);
248 conn_send_node(cn);
249 conn_reset_node(cn); // TODO: what if sending is not working?
250 }
251
252 static void conn_flush(void)
253 {
254 struct conn_node *cn;
255
256 cn = conn_head;
257 while (cn) {
258 conn_flush_node(cn, 0); // 0 to force flush
259 cn = cn->next;
260 }
261 }
262
263 //////////////////// common section
264 static struct query_node *query_get_by_res(const char type, const void *res)
265 {
266 struct conn_node *cn;
267 struct query_node *qn;
268
269 xlog(50, "%s: searching for res %p\n", __func__, res);
270 cn = conn_head;
271 while (cn) {
272 if (cn->type == type) {
273 qn = cn->qh;
274 while (qn) {
275 if (qn->res == res) {
276 xlog(50, " found it; qn=%p\n", qn);
277 return qn;
278 }
279 qn = qn->next;
280 }
281 }
282 cn = cn->next;
283 }
284
285 xlog(50, " NOT found it\n");
286 return NULL;
287 }
288
289 static char *type2name(const unsigned int type)
290 {
291 switch (type) {
292 case NINEDOGS_DB_CONN: return "conn";
293 case NINEDOGS_DB_QUERY: return "query";
294 case NINEDOGS_DB_FREE_RESULT: return "free_result";
295 }
296
297 return "?";
298 }
299
300 void ninedogs_process_db(const unsigned int type, const void *d)
301 {
302 struct query_node *qn;
303 unsigned char hash[32];
304 struct timeval t, elap;
305 unsigned int u;
306
307 xlog(50, "%s: type=%s\n", __func__, type2name(type));
308
309 switch (type) {
310 case NINEDOGS_DB_CONN:
311 const struct conn *cs = (const struct conn *) d;
312 u = cs->end.tv_sec / gran;
313 struct conn_node *cn = conn_get(cs->type, cs->conn_str, cs->conn_str_len);
314 if (!cn) {
315 char *conn_str_copy = old_malloc(cs->conn_str_len + 1);
316 if (!conn_str_copy) {
317 xlog(1, " cannot alloc memory!\n");
318 break;
319 }
320 memcpy(conn_str_copy, cs->conn_str, cs->conn_str_len);
321 conn_str_copy[cs->conn_str_len] = '\0';
322
323 cn = old_malloc(sizeof(struct conn_node));
324 if (!cn) {
325 xlog(1, " cannot alloc memory!\n");
326 old_free(conn_str_copy);
327 break;
328 }
329 xlog(50, " allocated conn cn=%p\n", cn);
330 cn->conn_str = conn_str_copy;
331 cn->conn_str_len = cs->conn_str_len;
332 conn_init_node(cn);
333 cn->next = conn_head;
334 cn->type = cs->type;
335 cn->handle = cs->dbh;
336 cn->ts.tv_sec = u * gran;
337
338 conn_head = cn;
339 if (!conn_tail)
340 conn_tail = cn;
341 } else {
342 conn_flush_node(cn, u);
343 }
344
345 cn->count++;
346 my_time_diff(&elap, &cs->end, &cs->start);
347 my_time_add(&cn->elap, &elap);
348 if (my_time_compare(&cn->min, &elap) > 0)
349 cn->min = elap;
350 if (my_time_compare(&cn->max, &elap) < 0)
351 cn->max = elap;
352 last_db_handle = cn;
353 break;
354
355 case NINEDOGS_DB_QUERY:
356 struct timeval start;
357 const struct query *qs = (const struct query *) d;
358 u = cs->end.tv_sec / gran;
359 char *q_copy;
360
361 u = qs->end.tv_sec / gran;
362 if (qs->dbh == NULL) {
363 if (last_db_handle == NULL) {
364 xlog(1, " last_db_handle is NULL!\n");
365 break;
366 }
367 cn = last_db_handle;
368 } else {
369 cn = conn_get_by_handle(qs->dbh);
370 if (!cn)
371 break;
372 }
373 conn_flush_node(cn, u);
374
375 if (qs->q == NULL) { // pg_get_result will not have qs->q set
376 qn = cn->qh; // first in list is the last one
377 if (qn == NULL)
378 break;
379 start = qn->last_start;
380 } else {
381 // find query
382 query_hash(hash, qs->q, qs->q_len);
383 qn = cn->qh;
384 while (qn) {
385 if ((memcmp(qn->hash, hash, sizeof(qn->hash)) == 0)
386 && (qn->query_len == qs->q_len))
387 break;
388 qn = qn->next;
389 }
390 start = qs->start;
391 }
392 if (!qn) {
393 q_copy = old_malloc(qs->q_len + 1);
394 if (!q_copy) {
395 xlog(1, " cannot alloc memory!\n");
396 break;
397 }
398 memcpy(q_copy, qs->q, qs->q_len);
399 q_copy[qs->q_len] = '\0';
400
401 qn = old_malloc(sizeof(struct query_node));
402 if (!qn) {
403 old_free(q_copy);
404 break;
405 }
406 xlog(40, " allocated qn=%p for res %p\n", qn, qs->res);
407 query_init_node(qn);
408 memcpy(qn->hash, hash, sizeof(qn->hash));
409 qn->res = qs->res;
410 qn->query = q_copy;
411 qn->query_len = qs->q_len;
412 qn->ts.tv_sec = u * gran;
413
414 qn->next = cn->qh;
415 cn->qh = qn;
416 if (!cn->qt)
417 cn->qt = qn;
418 }
419
420 qn->count++;
421 qn->rows += qs->num;
422 qn->aff += qs->aff;
423 my_time_diff(&elap, &qs->end, &start);
424 my_time_add(&qn->elap, &elap);
425 if (my_time_compare(&qn->min, &elap) > 0)
426 qn->min = elap;
427 if (my_time_compare(&qn->max, &elap) < 0)
428 qn->max = elap;
429 if (qs->q)
430 qn->last_start = start;
431 break;
432
433 case NINEDOGS_DB_FREE_RESULT:
434 const struct free_result *fr = (const struct free_result *) d;
435
436 qn = query_get_by_res(fr->type, fr->res);
437 if (!qn)
438 break;
439
440 qn->free_calls++;
441 qn->free_errs += fr->ok;
442 ninedogs_now(&t);
443 //my_time_diff(&elap, &t, &qn->start); TODO - we may not have start because we may flushed the query!
444 my_time_add(&qn->process_sum, &elap);
445 break;
446 }
447
448 ninedogs_process_post();
449 }
450
451 void ninedogs_process_db_flush(void)
452 {
453 xlog(50, "%s...\n", __func__);
454
455 conn_flush();
456 }
File agent/process_db.h added (mode: 100644) (index 0000000..a85f6fc)
1 struct conn
2 {
3 char type;
4 char pad1[3];
5 unsigned int conn_str_len;
6 char *conn_str;
7 void *dbh;
8 struct timeval start, end;
9 };
10
11 struct query
12 {
13 char type;
14 char pad1[3];
15 unsigned int q_len;
16 void *dbh;
17 struct timeval start, end;
18 char *q;
19 unsigned short err_len, err_code_len;
20 unsigned int pad2;
21 char *err, *err_code;
22 unsigned long num, aff;
23 void *res;
24 };
25
26 struct free_result
27 {
28 char type;
29 char pad1[3];
30 unsigned int ok:1;
31 unsigned int pad2:31;
32 void *res;
33 };
34
35 void ninedogs_process_db(const unsigned int type, const void *d);
36
37 void ninedogs_process_db_flush(void);
38
File agent/process_misc.c added (mode: 100644) (index 0000000..70e0b69)
1 #include <stdio.h>
2 #include <string.h>
3 #include <pthread.h>
4 #include <sys/time.h>
5
6 #include "ids.h"
7 #include "ctools.h"
8 #include "process.h"
9 #include "process_misc.h"
10
11 //extern void *(*old_malloc)(size_t size);
12 //extern void (*old_free)(void *p);
13
14
15 static char *type2name(const unsigned int type)
16 {
17 switch (type) {
18 //case NINEDOGS_MISC_START: return "start";
19 //case NINEDOGS_MISC_STOP: return "stop";
20 }
21
22 return "?";
23 }
24
25 void ninedogs_process_misc(const unsigned int type, const void *p, const unsigned long x)
26 {
27 xlog(10, "%s: type=%s p=%p x=%lu\n", __func__, type2name(type), p, x);
28
29 //switch (type) {
30 //case NINEDOGS_MISC_START:
31 // gettimeofday(&start, NULL);
32 // break;
33
34 //case NINEDOGS_MISC_STOP:
35 // gettimeofday(&stop, NULL);
36 // break;
37 //}
38
39 ninedogs_process_post();
40 }
41
42 void ninedogs_process_misc_flush(void)
43 {
44 }
45
File agent/process_misc.h added (mode: 100644) (index 0000000..9a72d56)
1 void ninedogs_process_misc(const unsigned int type, const void *p, const unsigned long x);
2
3 void ninedogs_process_misc_flush(void);
4
File agent/process_ssl.c added (mode: 100644) (index 0000000..4204698)
1 #include <stdio.h>
2 #include <string.h>
3 #include <pthread.h>
4 #include <sys/time.h>
5
6 #include "ids.h"
7 #include "ctools.h"
8 #include "process.h"
9 #include "process_ssl.h"
10
11 extern void *(*old_malloc)(size_t size);
12 extern void (*old_free)(void *p);
13
14 static void send_info(const char *info, const unsigned short info_len)
15 {
16 unsigned char *buf;
17 unsigned int len;
18
19 pack(&buf, &len, "T4 NN vs",
20 NINEDOGS_NET_SSL_INFO, info, info_len);
21 if (!buf)
22 return;
23
24 server_enqueue(buf, len);
25 }
26
27 static struct cert *cert_head, *cert_tail;
28
29 static void cert_send_node(const struct cert *cn)
30 {
31 unsigned char *buf;
32 unsigned int len;
33
34 pack(&buf, &len, "T4 NN ps" "us" "ss es",
35 NINEDOGS_NET_SSL_CERT, cn->uri, cn->uri_len,
36 cn->subj, cn->subj_len,
37 cn->not_before, strlen(cn->not_before), cn->not_after, strlen(cn->not_after));
38 if (!buf)
39 return;
40
41 server_enqueue(buf, len);
42 }
43
44 // TODO: what if we have a relative uri? Shouldn't we get the current dir?
45
46 static char *type2name(const unsigned int type)
47 {
48 switch (type) {
49 case NINEDOGS_SSL_INFO: return "info";
50 case NINEDOGS_SSL_CERT: return "cert";
51 }
52
53 return "?";
54 }
55
56 static struct cert *cert_get_by_uri(const char *uri)
57 {
58 struct cert *q;
59
60 if (uri == NULL)
61 return NULL;
62
63 q = cert_head;
64 while (q) {
65 if (strcmp(q->uri, uri) == 0)
66 return q;
67
68 q = q->next;
69 }
70
71 return NULL;
72 }
73
74 static int dup_cert(struct cert *cn, const struct cert *c)
75 {
76 do {
77 if (!cn->uri) {
78 cn->uri = old_malloc(c->uri_len + 1);
79 if (!cn->uri)
80 break;
81 memcpy(cn->uri, c->uri, c->uri_len);
82 cn->uri_len = c->uri_len;
83 cn->uri[cn->uri_len] = '\0';
84 }
85
86 cn->subj = old_malloc(c->subj_len + 1);
87 if (!cn->subj)
88 break;
89 memcpy(cn->subj, c->subj, c->subj_len);
90 cn->subj_len = c->subj_len;
91 cn->subj[cn->subj_len] = '\0';
92
93 cn->not_before = old_malloc(c->not_before_len + 1);
94 if (!cn->not_before)
95 break;
96 memcpy(cn->not_before, c->not_before, c->not_before_len);
97 cn->not_before_len = c->not_before_len;
98 cn->not_before[cn->not_before_len] = '\0';
99
100 cn->not_after = old_malloc(c->not_after_len + 1);
101 if (!cn->not_after)
102 break;
103 memcpy(cn->not_after, c->not_after, c->not_after_len);
104 cn->not_after_len = c->not_after_len;
105 cn->not_after[cn->not_after_len] = '\0';
106
107 return 1;
108 } while (0);
109
110 old_free(cn->uri);
111 old_free(cn->subj);
112 old_free(cn->not_before);
113 old_free(cn->not_after);
114 old_free(cn);
115
116 return 0;
117 }
118
119 void ninedogs_process_ssl(const unsigned int type, const void *d)
120 {
121 struct cert *cn;
122
123 xlog(10, "%s: type=%s d=%p\n", __func__, type2name(type), d);
124
125 switch (type) {
126 case NINEDOGS_SSL_INFO:
127 const struct ssl_info *i = (const struct ssl_info *) d;
128 send_info(i->info, i->info_len);
129 break;
130
131 case NINEDOGS_SSL_CERT:
132 const struct cert *c = (const struct cert *) d;
133 char send = 0;
134 cn = cert_get_by_uri(c->uri);
135 if (!cn) {
136 cn = old_malloc(sizeof(struct cert));
137 if (!cn)
138 break;
139
140 cn->uri = NULL; // signal that we need duplication
141 cn->next = cert_head;
142 cert_head = cn;
143 if (!cert_tail)
144 cert_tail = cn;
145
146 send = 1;
147 } else {
148 // if expiration changes, we need to resend
149 if ((strncmp(cn->not_before, c->not_before, c->not_before_len) != 0)
150 || (strncmp(cn->not_after, c->not_after, c->not_after_len) != 0)
151 || (strncmp(cn->subj, c->subj, c->subj_len) != 0)) {
152 old_free(cn->not_before);
153 old_free(cn->not_after);
154 old_free(cn->subj);
155 send = 1;
156 }
157 }
158
159 if (!dup_cert(cn, c))
160 break;
161
162 if (send)
163 cert_send_node(cn);
164 break;
165 }
166
167 ninedogs_process_post();
168 }
169
170 void ninedogs_process_ssl_flush(void)
171 {
172 }
File agent/process_ssl.h added (mode: 100644) (index 0000000..7637e20)
1 struct cert
2 {
3 char *uri, *subj;
4 char *not_before, *not_after;
5 unsigned short uri_len, subj_len;
6 unsigned short not_before_len, not_after_len;
7 struct cert *next;
8 };
9
10 struct ssl_info
11 {
12 const char *info;
13 unsigned short info_len;
14 unsigned short pad1[3];
15 };
16
17 void ninedogs_process_ssl(const unsigned int type, const void *d);
18
19 void ninedogs_process_ssl_flush(void);
20
File agent/sock1.c added (mode: 100644) (index 0000000..477c886)
1 #include <errno.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/socket.h>
6 #include <sys/un.h>
7 #include <linux/netlink.h>
8 #include <linux/rtnetlink.h>
9 #include <linux/sock_diag.h>
10 #include <linux/unix_diag.h>
11
12 static int
13 send_query(int fd)
14 {
15 struct sockaddr_nl nladdr = {
16 .nl_family = AF_NETLINK
17 };
18 struct {
19 struct nlmsghdr nlh;
20 struct unix_diag_req udr;
21 } req = {
22 .nlh = {
23 .nlmsg_len = sizeof(req),
24 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
25 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP
26 },
27 .udr = {
28 .sdiag_family = AF_UNIX,
29 .udiag_states = -1,
30 .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER
31 }
32 };
33 struct iovec iov = {
34 .iov_base = &req,
35 .iov_len = sizeof(req)
36 };
37 struct msghdr msg = {
38 .msg_name = &nladdr,
39 .msg_namelen = sizeof(nladdr),
40 .msg_iov = &iov,
41 .msg_iovlen = 1
42 };
43
44 for (;;) {
45 if (sendmsg(fd, &msg, 0) < 0) {
46 if (errno == EINTR)
47 continue;
48 perror("sendmsg");
49 return -1;
50 }
51 return 0;
52 }
53 }
54
55 static int print_diag(const struct unix_diag_msg *diag, unsigned int len)
56 {
57 if (len < NLMSG_LENGTH(sizeof(*diag))) {
58 fputs("short response\n", stderr);
59 return -1;
60 }
61 if (diag->udiag_family != AF_UNIX) {
62 fprintf(stderr, "unexpected family %u\n", diag->udiag_family);
63 return -1;
64 }
65
66 unsigned int rta_len = len - NLMSG_LENGTH(sizeof(*diag));
67 unsigned int peer = 0;
68 size_t path_len = 0;
69 char path[sizeof(((struct sockaddr_un *) 0)->sun_path) + 1];
70
71 for (struct rtattr *attr = (struct rtattr *) (diag + 1);
72 RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) {
73 switch (attr->rta_type) {
74 case UNIX_DIAG_NAME:
75 if (!path_len) {
76 path_len = RTA_PAYLOAD(attr);
77 if (path_len > sizeof(path) - 1)
78 path_len = sizeof(path) - 1;
79 memcpy(path, RTA_DATA(attr), path_len);
80 path[path_len] = '\0';
81 }
82 break;
83
84 case UNIX_DIAG_PEER:
85 if (RTA_PAYLOAD(attr) >= sizeof(peer))
86 peer = *(unsigned int *) RTA_DATA(attr);
87 break;
88 }
89 }
90
91 printf("inode=%u", diag->udiag_ino);
92
93 if (peer)
94 printf(", peer=%u", peer);
95
96 if (path_len)
97 printf(", name=%s%s", *path ? "" : "@",
98 *path ? path : path + 1);
99
100 putchar('\n');
101 return 0;
102 }
103
104 static int receive_responses(int fd)
105 {
106 long buf[8192 / sizeof(long)];
107 struct sockaddr_nl nladdr;
108 struct iovec iov = {
109 .iov_base = buf,
110 .iov_len = sizeof(buf)
111 };
112 int flags = 0;
113
114 for (;;) {
115 struct msghdr msg = {
116 .msg_name = &nladdr,
117 .msg_namelen = sizeof(nladdr),
118 .msg_iov = &iov,
119 .msg_iovlen = 1
120 };
121
122 ssize_t ret = recvmsg(fd, &msg, flags);
123 if (ret < 0) {
124 if (errno == EINTR)
125 continue;
126
127 perror("recvmsg");
128 return -1;
129 }
130 if (ret == 0)
131 return 0;
132
133 if (nladdr.nl_family != AF_NETLINK) {
134 fputs("!AF_NETLINK\n", stderr);
135 return -1;
136 }
137
138 const struct nlmsghdr *h = (struct nlmsghdr *) buf;
139
140 if (!NLMSG_OK(h, ret)) {
141 fputs("!NLMSG_OK\n", stderr);
142 return -1;
143 }
144
145 for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
146 if (h->nlmsg_type == NLMSG_DONE)
147 return 0;
148
149 if (h->nlmsg_type == NLMSG_ERROR) {
150 const struct nlmsgerr *err = NLMSG_DATA(h);
151
152 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) {
153 fputs("NLMSG_ERROR\n", stderr);
154 } else {
155 errno = -err->error;
156 perror("NLMSG_ERROR");
157 return -1;
158 }
159
160 return -1;
161 }
162
163 if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
164 fprintf(stderr, "unexpected nlmsg_type %u\n",
165 (unsigned) h->nlmsg_type);
166 return -1;
167 }
168
169 if (print_diag(NLMSG_DATA(h), h->nlmsg_len))
170 return -1;
171 }
172 }
173 }
174
175 int main(void)
176 {
177 int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
178 if (fd < 0) {
179 perror("socket");
180 return 1;
181 }
182
183 int ret = send_query(fd) || receive_responses(fd);
184
185 close(fd);
186 return ret;
187 }
File agent/sock2.c added (mode: 100644) (index 0000000..ee9802b)
1 #include <errno.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/socket.h>
6 #include <sys/un.h>
7 #include <linux/netlink.h>
8 #include <netinet/in.h>
9 #include <linux/rtnetlink.h>
10 #include <linux/sock_diag.h>
11 #include <linux/unix_diag.h>
12 #include <linux/inet_diag.h>
13 #include <linux/tcp.h>
14
15 #define TCP_LISTEN (1 << 10)
16
17 static int send_query(int fd)
18 {
19 struct sockaddr_nl nladdr = {
20 .nl_family = AF_NETLINK
21 };
22 struct {
23 struct nlmsghdr nlh;
24 struct inet_diag_req_v2 udr;
25 } req = {
26 .nlh = {
27 .nlmsg_len = sizeof(req),
28 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
29 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP
30 },
31 .udr = {
32 .sdiag_family = AF_INET,
33 .sdiag_protocol = IPPROTO_TCP,
34 .idiag_ext = (1 << (INET_DIAG_MEMINFO - 1)) | (1 << (INET_DIAG_SKMEMINFO - 1)) | (1 << (INET_DIAG_INFO - 1)), // see struct tcp_info
35 .idiag_states = TCP_LISTEN // -1,
36 }
37 };
38 struct iovec iov = {
39 .iov_base = &req,
40 .iov_len = sizeof(req)
41 };
42 struct msghdr msg = {
43 .msg_name = &nladdr,
44 .msg_namelen = sizeof(nladdr),
45 .msg_iov = &iov,
46 .msg_iovlen = 1
47 };
48
49 for (;;) {
50 if (sendmsg(fd, &msg, 0) < 0) {
51 if (errno == EINTR)
52 continue;
53 perror("sendmsg");
54 return -1;
55 }
56 return 0;
57 }
58 }
59
60 static void dump(const char *title, const void *buf,
61 const unsigned int len)
62 {
63 unsigned int i, j, rest;
64 unsigned char *buf2 = (unsigned char *) buf;
65 char out[1024], c;
66
67 i = 0; rest = len;
68 while (i < len) {
69 sprintf(out, " %04x: ", i);
70 rest = len - i;
71 if (rest > 16)
72 rest = 16;
73
74 for (j = 0; j < rest; j++)
75 snprintf(out + 8 + j * 2, 4, "%02x", buf2[i + j]);
76
77 strcat(out, " ");
78
79 for (j = 0; j < rest; j++) {
80 c = buf2[i + j];
81 if ((c < 0x20) || (c > 0x7E))
82 c = '.';
83 sprintf(out + 8 + rest * 2 + 2 + j, "%c", c);
84 }
85
86 fprintf(stderr, "%s\n", out);
87 i += rest;
88 }
89 }
90
91 static int print_diag(const struct inet_diag_msg *diag, unsigned int len)
92 {
93 unsigned int x32;
94 unsigned int *p32;
95
96 fprintf(stderr, "\n");
97
98 if (len < NLMSG_LENGTH(sizeof(*diag))) {
99 fputs("short response\n", stderr);
100 return -1;
101 }
102 if (diag->idiag_family != AF_INET) {
103 fprintf(stderr, "unexpected family %u\n", diag->idiag_family);
104 return -1;
105 }
106
107 fprintf(stderr, "state=0x%x timer=0x%02hhx"
108 " retrans=%hhu expires=%ums"
109 " rq=%u wq=%u uid=%u inode=%u ports=%hu/%hu\n",
110 diag->idiag_state, diag->idiag_timer,
111 diag->idiag_retrans, diag->idiag_expires,
112 diag->idiag_rqueue, diag->idiag_wqueue,
113 diag->idiag_uid, diag->idiag_inode,
114 ntohs(diag->id.idiag_sport), ntohs(diag->id.idiag_dport));
115
116 unsigned int rta_len = len - NLMSG_LENGTH(sizeof(*diag));
117
118 for (struct rtattr *attr = (struct rtattr *) (diag + 1);
119 RTA_OK(attr, rta_len); attr = RTA_NEXT(attr, rta_len)) {
120 fprintf(stderr, "type=%hu RTA_PAYLOAD=%hu\n",
121 attr->rta_type, RTA_PAYLOAD(attr));
122 dump("x", RTA_DATA(attr), RTA_PAYLOAD(attr));
123 switch (attr->rta_type) {
124 case INET_DIAG_TOS: fprintf(stderr, " Received INET_DIAG_TOS\n"); break;
125
126 case INET_DIAG_TCLASS: fprintf(stderr, " Received INET_DIAG_TCLASS\n"); break;
127
128 case INET_DIAG_CONG: fprintf(stderr, " Received INET_DIAG_CONG\n"); break;
129
130 case INET_DIAG_SOCKOPT: fprintf(stderr, " Received INET_DIAG_SOCKOPT\n"); break;
131 case INET_DIAG_CGROUP_ID: fprintf(stderr, " Received INET_DIAG_CGROUP_ID\n"); break;
132
133 case INET_DIAG_MARK:
134 x32 = * (unsigned int *) RTA_DATA(attr);
135 fprintf(stderr, " Received INET_DIAG_MARK: 0x%08x\n", x32);
136 break;
137
138 case INET_DIAG_SHUTDOWN: fprintf(stderr, " Received INET_DIAG_SHUTDOWN\n"); break;
139 case INET_DIAG_PAD: fprintf(stderr, " Received INET_DIAG_PAD\n"); break;
140
141 case SK_MEMINFO_RMEM_ALLOC: fprintf(stderr, " Received SK_MEMINFO_RMEM_ALLOC!!!\n"); break;
142
143 case INET_DIAG_MEMINFO:
144 struct inet_diag_meminfo *mi;
145
146 if (RTA_PAYLOAD(attr) >= sizeof(*mi)) {
147 mi = (struct inet_diag_meminfo *) RTA_DATA(attr);
148 fprintf(stderr, " Received INET_DIAG_MEMINFO:"
149 " rmem=%u wmem=%u fmem=%u tmem=%u\n",
150 mi->idiag_rmem, mi->idiag_wmem, mi->idiag_fmem, mi->idiag_tmem);
151 }
152 break;
153
154 case INET_DIAG_SKMEMINFO:
155 p32 = (unsigned int *) RTA_DATA(attr);
156 fprintf(stderr, " Received INET_DIAG_SKMEMINFO:"
157 " RMEM_ALLOC=%u RCVBUF=%u WMEM_ALLOC=%u SNDBUF=%u"
158 " FWD_ALLOC=%u WMEM_QUEUED=%u OPTMEM=%u BACKLOG=%u"
159 " DROPS=%u\n",
160 p32[0], p32[1], p32[2], p32[3], p32[4], p32[5], p32[6], p32[7], p32[8]);
161 break;
162
163 case INET_DIAG_INFO:
164 //struct inet_diag_meminfo *mi;
165
166 //if (RTA_PAYLOAD(attr) >= sizeof(*mi))
167 // mi = (struct inet_diag_meminfo *) RTA_DATA(attr);
168 fprintf(stderr, " Received INET_DIAG_INFO\n");
169 break;
170 }
171 }
172 fprintf(stderr, "\n");
173
174 return 0;
175 }
176
177 static int receive_responses(int fd)
178 {
179 long buf[8192 / sizeof(long)];
180 struct sockaddr_nl nladdr;
181 struct iovec iov = {
182 .iov_base = buf,
183 .iov_len = sizeof(buf)
184 };
185 int flags = 0;
186
187 for (;;) {
188 struct msghdr msg = {
189 .msg_name = &nladdr,
190 .msg_namelen = sizeof(nladdr),
191 .msg_iov = &iov,
192 .msg_iovlen = 1
193 };
194
195 ssize_t ret = recvmsg(fd, &msg, flags);
196 if (ret < 0) {
197 if (errno == EINTR)
198 continue;
199
200 perror("recvmsg");
201 return -1;
202 }
203 if (ret == 0)
204 return 0;
205
206 if (nladdr.nl_family != AF_NETLINK) {
207 fputs("!AF_NETLINK\n", stderr);
208 return -1;
209 }
210
211 const struct nlmsghdr *h = (struct nlmsghdr *) buf;
212
213 if (!NLMSG_OK(h, ret)) {
214 fputs("!NLMSG_OK\n", stderr);
215 return -1;
216 }
217
218 for (; NLMSG_OK(h, ret); h = NLMSG_NEXT(h, ret)) {
219 if (h->nlmsg_type == NLMSG_DONE)
220 return 0;
221
222 if (h->nlmsg_type == NLMSG_ERROR) {
223 const struct nlmsgerr *err = NLMSG_DATA(h);
224
225 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) {
226 fputs("NLMSG_ERROR\n", stderr);
227 } else {
228 errno = -err->error;
229 perror("NLMSG_ERROR");
230 return -1;
231 }
232
233 return -1;
234 }
235
236 if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
237 fprintf(stderr, "unexpected nlmsg_type %u\n",
238 (unsigned) h->nlmsg_type);
239 return -1;
240 }
241
242 if (print_diag(NLMSG_DATA(h), h->nlmsg_len))
243 return -1;
244 }
245 }
246 }
247
248 int main(void)
249 {
250 int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
251 if (fd < 0) {
252 perror("socket");
253 return 1;
254 }
255
256 int ret = send_query(fd) || receive_responses(fd);
257
258 close(fd);
259 return ret;
260 }
File common/Makefile added (mode: 100644) (index 0000000..87c535d)
1 # This is just to allow us to run make here
2 .PHONY: all
3 all:
4 make -C .. common
5
6 OBJS := tools.o
7
8 tools.o: tools.c tools.h $(COMMON_H)
9 $(CC) $(CFLAGS) -fPIC -c -o $@ $<
10
11 .PHONY: clean
12 clean:
13 @rm -f *.o
14
15 compile: $(OBJS)
File common/ids.h added (mode: 100644) (index 0000000..da391e8)
1 #define NINEDOGS_PROTOCOL_VERSION 1
2
3 // Only append here! Do not remove/reorder!
4
5 // These are for network protocol
6 enum
7 {
8 NINEDOGS_NET_CORE_ID = 0x00000000,
9 NINEDOGS_NET_CORE_PROC,
10 NINEDOGS_NET_CORE_UNAME,
11 NINEDOGS_NET_CORE_SYSINFO,
12 NINEDOGS_NET_CORE_STOP,
13 NINEDOGS_NET_CORE_MAX,
14
15 NINEDOGS_NET_MISC_ID = 0x00001000,
16 NINEDOGS_NET_MISC_MAX,
17
18 NINEDOGS_NET_DB_CONN = 0x00002000,
19 NINEDOGS_NET_DB_QUERY_STATS,
20 NINEDOGS_NET_DB_QUERY_STRING,
21 NINEDOGS_NET_DB_MAX, // this is the last element of NINEDOGS_NET_DB_*
22
23 NINEDOGS_NET_SSL_INFO = 0x00003000,
24 NINEDOGS_NET_SSL_CERT,
25 NINEDOGS_NET_SSL_MAX // this is the last element of NINEDOGS_NET_SSL_*
26 };
27
28
29 // These are for communication between the replaced functions and agent
30 enum
31 {
32 NINEDOGS_CORE_START = 1,
33 NINEDOGS_CORE_STOP,
34 NINEDOGS_CORE_MAX // this must be last
35 };
36
37 enum
38 {
39 NINEDOGS_MISC_START = 1,
40 NINEDOGS_MISC_MAX // this must be last
41 };
42
43 enum
44 {
45 NINEDOGS_DB_TYPE = 3000,
46 NINEDOGS_DB_CONN,
47 NINEDOGS_DB_QUERY,
48 NINEDOGS_DB_FREE_RESULT,
49 NINEDOGS_DB_MAX // this must be last
50 };
51
52 enum
53 {
54 NINEDOGS_SSL_INFO = 0x00003000,
55 NINEDOGS_SSL_CERT,
56 NINEDOGS_SSL_MAX // this is the last element of NINEDOGS_SSL_*
57 };
58
File common/tools.c added (mode: 100644) (index 0000000..e1e9cb8)
1 #define _GNU_SOURCE 500
2
3 #include <stdio.h>
4 #include <ctype.h>
5 #include <unistd.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdarg.h>
9 #include <string.h>
10 #include <sys/socket.h>
11 #include <sys/random.h>
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <arpa/inet.h>
15 #include <netinet/in.h>
16 #include <netinet/tcp.h>
17 #include <poll.h>
18 #include <errno.h>
19 #include <netdb.h>
20 #include <fcntl.h>
21 #include <sys/sysinfo.h>
22 #include <sys/stat.h>
23
24 #include <gnutls/gnutls.h>
25 #include <gnutls/x509.h>
26 #include <gnutls/crypto.h>
27
28 #include "tools.h"
29
30
31 extern void *(*old_malloc)(size_t size);
32
33
34 void ninedogs_now(struct timeval *tv)
35 {
36 gettimeofday(tv, NULL);
37 }
38
39 int ninedogs_sha256(void *out, const void *in, size_t len)
40 {
41 int r;
42 r = gnutls_hash_fast (GNUTLS_DIG_SHA256, in, len, out);
43
44 return r == 0 ? 0 : -1;
45 }
46
47 void bin2hex(char *out, const void *buf, const unsigned int len)
48 {
49 unsigned char *buf2 = (unsigned char *) buf;
50
51 if (!buf)
52 return;
53
54 for (unsigned int i = 0; i < len; i++)
55 snprintf(out + i * 2, 3, "%02hhx", buf2[i]);
56 }
57
58 /*
59 * First char is the subtype, the second is var type
60 * Example: "T4 h8 c8 r8 a8"
61 */
62 void pack(unsigned char **pbuf, unsigned int *len, const char *fmt, ...)
63 {
64 unsigned char u8;
65 unsigned short u16, u16be;
66 unsigned int needed, u32, u32be;
67 unsigned long u64, u64be;
68 va_list va;
69 unsigned char *p, *q;
70 char *s;
71 const char *f;
72
73 //xlog(10, "%s fmt=[%s]\n", __func__, fmt);
74
75 // compute needed size
76 needed = 4; // first 4 bytes are the size of the block
77 va_start(va, fmt);
78 f = fmt;
79 while (*f) {
80 while (*f == ' ')
81 f++;
82
83 f++; needed++;
84
85 switch (*f) {
86 case 'c': needed += 1; va_arg(va, unsigned int); break; // unsigned char
87 case 'p': needed += 8; va_arg(va, unsigned long); break; // pointer
88 case 's': needed += 4; va_arg(va, char *); needed += va_arg(va, unsigned int); break; // string
89 case '2': needed += 2; va_arg(va, unsigned int); break; // 16 bits unsigned
90 case '4': needed += 4; va_arg(va, unsigned int); break; // 32 bits unsigned
91 case '8': needed += 8; va_arg(va, unsigned long); break; // 64 bits unsigned
92 case 't': needed += 8; va_arg(va, struct timeval *); break; // timeval
93 case 'N': needed += 8; break; // "now"
94 default:
95 //xlog(10, "invalid format [%c]!\n", *f);
96 abort();
97 }
98
99 f++;
100 }
101 va_end(va);
102 //xlog(10, " needed for [%s] = %u\n", fmt, needed);
103
104 q = p = old_malloc(needed);
105 if (!p) {
106 //xlog(10, "cannot alloc mem [%u]!\n", needed);
107 return;
108 }
109
110 u32 = htobe32(needed - 4);
111 memcpy(q, &u32, 4); q += 4;
112
113 va_start(va, fmt);
114 f = fmt;
115 while (*f) {
116 while (*f == ' ')
117 f++;
118
119 // First char is the cell type
120 *q = *f; q++; f++;
121
122 switch (*f) {
123 case 'c': // char, unsigned
124 u8 = va_arg(va, unsigned int);
125 memcpy(q, &u8, 1); q += 1;
126 break;
127
128 case 'p': // pointer
129 u64 = va_arg(va, unsigned long);
130 u64be = htobe64(u64);
131 memcpy(q, &u64be, 8); q += 8;
132 break;
133
134 case 's': // string
135 s = va_arg(va, char *); // string
136 u32 = va_arg(va, unsigned int); // length
137 u32be = htobe32(u32);
138 memcpy(q, &u32be, 4); q += 4;
139 memcpy(q, s, u32); q += u32;
140 break;
141
142 case '2': // 16 bits, unsigned
143 u16 = va_arg(va, unsigned int);
144 u16be = htobe16(u16);
145 memcpy(q, &u16be, 2); q += 2;
146 break;
147
148 case '4': // 32 bits, unsigned
149 u32 = va_arg(va, unsigned int);
150 u32be = htobe32(u32);
151 memcpy(q, &u32be, 4); q += 4;
152 break;
153
154 case '8': // 64 bits, unsigned
155 u64 = va_arg(va, unsigned long);
156 u64be = htobe64(u64);
157 memcpy(q, &u64be, 8); q += 8;
158 break;
159
160 case 't': // struct timeval
161 struct timeval *tv = va_arg(va, struct timeval *);
162 u64 = tv->tv_sec * 1000 + tv->tv_usec / 1000;
163 u64be = htobe64(u64);
164 memcpy(q, &u64be, 8); q += 8;
165 break;
166
167 case 'N': // struct timeval "now"
168 struct timeval now;
169 ninedogs_now(&now);
170 u64 = now.tv_sec * 1000 + now.tv_usec / 1000;
171 u64be = htobe64(u64);
172 memcpy(q, &u64be, 8); q += 8;
173 break;
174
175 default:
176 //xlog(10, "invalid format [%c]!\n", *f);
177 abort();
178 }
179
180 f++;
181 }
182 va_end(va);
183
184 *pbuf = p;
185 *len = q - p;
186 }
187
188 /*
189 * Returns 1 when ok, 0 on error
190 */
191 unsigned char unpack(void *dst, const char type, const unsigned int max,
192 const unsigned char *buf, const unsigned int len,
193 unsigned int *off)
194 {
195 unsigned short u16;
196 unsigned int u32;
197 unsigned long u64;
198
199 //Log(60, "%s: type=%c max=%u len=%u *off=%u\n",
200 // __func__, type, max, len, *off);
201
202 switch (type) {
203 case 'c': // char
204 if (*off + 1 > len)
205 return 0;
206 if (max != 1) {
207 //Log(1, "sizeof mismatch!\n");
208 return 0;
209 }
210 unsigned char *dst2 = (unsigned char *) dst;
211 *dst2 = buf[*off]; *off = *off + 1;
212 //Log(60, " decoded char [%c]\n", *dst2);
213 break;
214
215 case 's': // string
216 if (*off + 4 > len)
217 return 0;
218 memcpy(&u32, buf + *off, 4); *off = *off + 4;
219 u32 = be32toh(u32);
220 if (*off + u32 > len) {
221 //Log(60, " *off[%u] + u32[%u] > len[%u]\n", *off, u32, len);
222 return 0;
223 }
224 if (u32 + 1 > max) {
225 //Log(60, " u32[%u] + 1 > max[%u]\n", u32, max);
226 return 0;
227 }
228 memcpy(dst, buf + *off, u32); *off = *off + u32;
229 memset(dst + u32, 0, 1);
230 //Log(60, " decoded string [%s]\n", dst);
231 break;
232
233 case '2': // u16, unsigned
234 if (*off + 2 > len)
235 return 0;
236 if (max != 2) {
237 //Log(1, "sizeof mismatch!\n");
238 return 0;
239 }
240 memcpy(&u16, buf + *off, 2); *off = *off + 2;
241 u16 = be16toh(u16);
242 memcpy(dst, &u16, 2);
243 //Log(60, " decoded u16 %hu\n", u16);
244 break;
245
246 case '4': // u32, unsigned
247 if (*off + 4 > len)
248 return 0;
249 if (max != 4) {
250 //Log(1, "sizeof mismatch!\n");
251 return 0;
252 }
253 memcpy(&u32, buf + *off, 4); *off = *off + 4;
254 u32 = be32toh(u32);
255 memcpy(dst, &u32, 4);
256 //Log(60, " decoded u32 %u\n", u32);
257 break;
258
259 case 'N': // "now", timestamp
260 case '8': // u64, unsigned
261 case 't': // timeval
262 if (*off + 8 > len)
263 return 0;
264 if (max != 8) {
265 //Log(1, "sizeof mismatch!\n");
266 return 0;
267 }
268 memcpy(&u64, buf + *off, 8); *off = *off + 8;
269 u64 = be64toh(u64);
270 memcpy(dst, &u64, 8);
271 //Log(60, " decoded long/timeval %llu\n", u64);
272 break;
273
274 default:
275 //Log(1, "%s: Invalid type [0x%02hhx=%c]\n", __func__, type, type);
276 return 0;
277 }
278
279 return 1;
280 }
281
282 char is_hexa_string(const char *s)
283 {
284 while (*s != '\0') {
285 if (!isxdigit(*s))
286 return 0;
287 s++;
288 }
289
290 return 1;
291 }
292
293 char mkdir_recursive(const char *dir, const mode_t mode)
294 {
295 char *p, *q;
296 int r;
297 char path[4096];
298
299 snprintf(path, sizeof(path), "%s", dir);
300
301 q = path;
302 if (*path == '/')
303 q++;
304 do {
305 p = strchr(q, '/');
306 if (!p)
307 break;
308 *p = '\0';
309 r = mkdir(path, mode);
310 *p = '/';
311 if ((r == -1) && (errno != EEXIST))
312 return -1;
313 q = p + 1;
314 } while (1);
315
316 r = mkdir(path, mode);
317 if ((r == -1) && (errno != EEXIST))
318 return -1;
319
320 return 0;
321 }
322
323 unsigned long long get_day(time_t now)
324 {
325 struct tm tm;
326
327 if (now == 0)
328 now = time(NULL);
329
330 gmtime_r(&now, &tm);
331
332 tm.tm_hour = 0;
333 tm.tm_min = 0;
334 tm.tm_sec = 0;
335
336 return mktime(&tm);
337 }
338
339 unsigned long long get_hour(time_t now)
340 {
341 struct tm tm;
342
343 if (now == 0)
344 now = time(NULL);
345
346 gmtime_r(&now, &tm);
347
348 tm.tm_min = 0;
349 tm.tm_sec = 0;
350
351 return mktime(&tm);
352 }
353
File common/tools.h added (mode: 100644) (index 0000000..486d0df)
1 #include <sys/time.h>
2 #include <stdlib.h>
3
4 void ninedogs_now(struct timeval *tv);
5
6 int ninedogs_sha256(void *out, const void *in, size_t len);
7
8 void bin2hex(char *out, const void *buf, const unsigned int len);
9
10 void pack(unsigned char **pbuf, unsigned int *len, const char *fmt, ...);
11 unsigned char unpack(void *dst, const char type, const unsigned int max,
12 const unsigned char *buf, const unsigned int len,
13 unsigned int *off);
14
15 char is_hexa_string(const char *s);
16
17 char mkdir_recursive(const char *dir, const mode_t mode);
18
19 unsigned long long get_day(time_t now);
20 unsigned long long get_hour(time_t now);
File configure added (mode: 100755) (index 0000000..92c4bc4)
1 #!/bin/bash
2
3 ./duilder "${@}"
File duilder added (mode: 100755) (index 0000000..090eaa8)
1 #!/bin/bash
2
3 set -e
4
5 function duilder_final()
6 {
7 PRJ="${1}"
8 VER="${2}"
9 RELEASE_SCRIPT="${3}"
10
11 # Run release script
12 if [ ! -z "${RELEASE_SCRIPT}" -a -x "${RELEASE_SCRIPT}" ]; then
13 echo "[*] Running ${RELEASE_SCRIPT}..."
14 ${RELEASE_SCRIPT}
15 fi
16 }
17
18 function duilder_docs()
19 {
20 PRJ="${1}"
21 VER="${2}"
22 EXPORT_PATH="${3}"
23
24 if [ ! -d "${EXPORT_PATH}" ]; then
25 echo "[*] WARN: ${EXPORT_PATH} does not exists. Creating it..."
26 mkdir -p "${EXPORT_PATH}"
27 fi
28
29 if [ "${BUILD_SDEB}" = "1" ]; then
30 if [ -d "debian" ]; then
31 >debian/docs
32 fi
33 fi
34
35 echo "[*] Copying docs to [${EXPORT_PATH}]..."
36 for f in README License LICENSE Changelog Changelog-last TODO FAQ INSTALL AUTHORS samples; do
37 [ ! -r "${f}" ] && continue
38
39 cp -avp "${f}" "${EXPORT_PATH}/"
40 if [ "${BUILD_SDEB}" = "1" ]; then
41 # No need to install the license file
42 if [ "${f}" = "LICENSE" ]; then
43 continue
44 fi
45 echo "${f}" >> debian/docs
46 fi
47 done
48 echo
49
50 if [ -d "screenshot" ]; then
51 echo "[*] Copying screenshots..."
52 mkdir -p "${EXPORT_PATH}"
53 cp -vp screenshot/* "${EXPORT_PATH}/"
54 echo
55 fi
56 }
57
58 function duilder_git()
59 {
60 PRJ="${1}"; shift
61 GIT_DEST="${1}"; shift
62 EXPORT_GIT="${1}"; shift
63 EXPORT_PATH="${1}"; shift
64 GIT_CHANGELOG="${1}"; shift
65 GIT_PUSH="${1}"; shift
66
67 if [ ! -x /usr/bin/git ]; then
68 echo "[*] Warning: Git not found!"
69 exit 0
70 fi
71
72 if [ ! -d .git ]; then
73 echo "[*] Warning: I cannot find .git directory!"
74 exit 0
75 fi
76
77 echo "[*] Testing if a tag is present for HEAD..."
78 D=`git describe | sed -e 's/^.*-g[0-9a-fA-F]*$//'`
79 if [ "${D}" = "" ]; then
80 echo "No annotated tag preset for HEAD! Please add one!"
81 exit 1
82 fi
83
84 if [ "${EXPORT_GIT}" = "1" ]; then
85 echo "[*] Generating GIT tree for HTTP transport..."
86 if [ ! -d "${GIT_DEST}/${PRJ}.git" ]; then
87 git clone --bare . "${GIT_DEST}/${PRJ}.git"
88
89 # Activate post-update hook
90 cp "${GIT_DEST}/${PRJ}.git/hooks/post-update.sample" \
91 "${GIT_DEST}/${PRJ}.git/hooks/post-update"
92 chmod a+x "${GIT_DEST}/${PRJ}.git/hooks/post-update"
93
94 # add project name and description
95 echo "${PRJ}" > "${GIT_DEST}/${PRJ}.git/description"
96
97 # allow export by git daemon?
98 #touch "${GIT_DEST}/${PRJ}.git/git-daemon-export-ok
99 else
100 # --force?
101 echo "Running git push -v --all \"${GIT_DEST}/${PRJ}.git\"..."
102 git push -v --all "${GIT_DEST}/${PRJ}.git"
103 echo "Running git push -v --tags \"${GIT_DEST}/${PRJ}.git\"..."
104 git push -v --tags "${GIT_DEST}/${PRJ}.git"
105 fi
106 (cd "${GIT_DEST}/${PRJ}.git" && git update-server-info)
107 fi
108
109 if [ "${GIT_PUSH}" = "1" ]; then
110 echo "[*] Git push..."
111 git push -v --all
112 fi
113
114 if [ "${GIT_CHANGELOG}" = "1" ]; then
115 echo "[*] Generating Changelog from git..."
116 echo -n > Changelog
117
118 # get the list of tags
119 number_of_tags=0
120 git show-ref --tags -d | grep refs/tags/v > duilder.tmp
121 while read sha1 full_tag; do
122 tag=`echo ${full_tag} | sed -e 's#refs/tags/##' | cut -d'^' -f1`
123 tags[${number_of_tags}]=${tag}
124 tags_commit[${number_of_tags}]=${sha1}
125 number_of_tags=$[${number_of_tags}+1]
126 done < duilder.tmp
127 rm -f duilder.tmp
128
129 # get the list of commits, test if is a tag and do the diff
130 prev=""
131 add=""
132 first=1
133 git log --pretty=oneline | cut -f1 | \
134 while read commit junk; do
135 # test if it is a tag
136 tag=""
137 i=0
138 while [ "${i}" -lt "${number_of_tags}" ]; do
139 if [ "${commit}" = "${tags_commit[${i}]}" ]; then
140 tag="${tags[${i}]}"
141 break
142 fi
143
144 i=$[${i}+1]
145 done
146
147 if [ -z "${tag}" ]; then
148 continue
149 fi
150
151 if [ ! -z "${prev}" ]; then
152 echo "[*] Generating Changelog from ${tag} -> ${prev}..."
153 echo -en "${add}" >> Changelog
154 add="\n"
155 echo "[${tag} -> ${prev}]" >> Changelog
156 git shortlog ${tag}..${prev} | \
157 (IFS=""
158 while read line; do
159 echo " ${line}"
160 done) \
161 >> Changelog
162
163 if [ "${first}" = "1" ]; then
164 echo "[*] Generating Changelog-last..."
165 cp Changelog Changelog-last
166 first=0
167 fi
168 fi
169 prev=${tag}
170 done
171 fi
172 }
173
174 function duilder_srpm()
175 {
176 PRJ="${1}"
177 VER="${2}"
178 EXPORT_PATH="${3}"
179 BUILD_SRPM="${4}"
180 SRPM_DEST="${5}"
181 SRPM_POST_RUN="${6}"
182
183 P="${PRJ}-${VER}"
184
185 if [ "${BUILD_SRPM}" != "1" ]; then
186 exit 0
187 fi
188
189 if [ ! -d "${EXPORT_PATH}" ]; then
190 echo "WARN: ${EXPORT_PATH} does not exists. Creating it..."
191 mkdir -p "${EXPORT_PATH}"
192 fi
193
194 echo "[*] Building SRPM..."
195 rpmbuild -ts "${P}.tar.gz"
196 echo
197
198 PKG="${RPMBUILD}/SRPMS/${P}-${REV}.src.rpm"
199
200 # Run a rpmlint on it
201 if [ -x /usr/bin/rpmlint ]; then
202 echo "[*] RPMlinting..."
203 rpmlint -iv "${PKG}" > rpmlint.out
204 else
205 echo "[*] WARN: rpmlint is missing!"
206 fi
207
208 if [ ! -z "${SRPM_DEST}" ]; then
209 if [ -r "${SRPM_DEST}/${PKG}" ]; then
210 mv "${SRPM_DEST}/${PKG}" "${SRPM_DEST}/${PKG}.old"
211 fi
212 echo "[*] Copying [${PKG}] to [${SRPM_DEST}]..."
213 cp -vp "${PKG}" "${SRPM_DEST}/"
214 fi
215
216 echo "[*] Copying to export dir [${EXPORT_PATH}]..."
217 mkdir -p "${EXPORT_PATH}"
218 cp -vp "${PKG}" "${EXPORT_PATH}/"
219 echo
220
221 if [ -x "${SRPM_POST_RUN}" ]; then
222 echo "[*] Running post SRPM build script [${SRPM_POST_RUN}]..."
223 ${SRPM_POST_RUN} "${PKG}"
224 fi
225 }
226
227 function duilder_sdeb()
228 {
229 PRJ="${1}"
230 VER="${2}"
231 EXPORT_PATH="${3}"
232 BUILD_SDEB="${4}"
233 SDEB_DEST="${5}"
234 SDEB_POST_RUN="${6}"
235
236 P="${PRJ}-${VER}"
237
238 if [ "${BUILD_SDEB}" != "1" ]; then
239 exit 0
240 fi
241
242 if [ ! -d "${EXPORT_PATH}" ]; then
243 echo "WARN: ${EXPORT_PATH} does not exists. Creating it..."
244 mkdir -p "${EXPORT_PATH}"
245 fi
246
247 echo "[*] Copying SDEB..."
248 PKG="${PRJ}_${VER}.orig.tar.gz"
249
250 if [ -n "${SDEB_DEST}" ]; then
251 cp -vp "${P}.tar.gz" "${SDEB_DEST}/${PKG}"
252 fi
253
254 echo "[*] Copying to export dir [${DEB_EXPORT_PATH}]..."
255 mkdir -p "${EXPORT_PATH}"
256 cp -vp "${P}.tar.gz" "${EXPORT_PATH}/${PKG}"
257 echo
258
259 if [ -x "${SDEB_POST_RUN}" ]; then
260 echo "[*] Running post SDEB build script [${SDEB_POST_RUN}]..."
261 ${SDEB_POST_RUN} "${SDEB}/${PKG}"
262 fi
263 }
264
265 function duilder_tar()
266 {
267 PRJ="${1}"
268 VER="${2}"
269 EXPORT_PATH="${3}"
270 EXCLUDE="${4}"
271
272 P="${PRJ}-${VER}"
273
274 if [ ! -d "${EXPORT_PATH}" ]; then
275 echo "[*] WARN: ${EXPORT_PATH} does not exists. Creating it..."
276 mkdir -p "${EXPORT_PATH}"
277 fi
278
279 echo "[*] Generating tarball [${P}.tar.gz]..."
280 ADD_EXCLUDE=""
281 if [ -r "${EXCLUDE}" ]; then
282 ADD_EXCLUDE="--exclude-from ${P}/${EXCLUDE}"
283 echo "[*] ADD_EXCLUDE=${ADD_EXCLUDE}"
284 fi
285
286 (cd .. \
287 && rm -rf "${P}" \
288 && cp -a --link "${PRJ}" "${P}" \
289 && tar czf "${PRJ}/${P}.tar.gz" \
290 --exclude-vcs \
291 --exclude ${P}/Makefile \
292 ${ADD_EXCLUDE} \
293 "${P}" \
294 && rm -rf "${P}"
295 )
296
297 echo "[*] Copying source to ${EXPORT_PATH}..."
298 mkdir -p "${EXPORT_PATH}"
299 cp -vp "${P}.tar.gz" "${EXPORT_PATH}/"
300 echo
301 }
302
303 ####################################################################
304
305 # Variables
306 if [ -d "${HOME}/rpmbuild" ]; then
307 RPMBUILD="${HOME}/rpmbuild"
308 else
309 RPMBUILD="/usr/src/redhat"
310 fi
311
312
313 if [ ! -r duilder.conf ]; then
314 echo "[*] You do not have a duilder.conf file. Trying to continue."
315 else
316 source ${PWD}/duilder.conf 2>/dev/null
317 fi
318
319
320 # fixes
321 if [ -z "${GIT_DEST}" ]; then
322 GIT_DEST="${EXPORT_PATH}"
323 fi
324
325 if [ -z "${PRJ}" ]; then
326 echo "WARN: PRJ= parameter is missing."
327 fi
328
329 if [ -z "${VER}" ]; then
330 echo "WARN: VER= parameter is missing."
331 fi
332
333 if [ -z "${REV}" ]; then
334 echo "WARN: REV= parameter is missing."
335 fi
336
337 # export variables - just in case a script cares
338 export PRJ VER REV SHORT_DESCRIPTION EXPORT_PATH EXPORT_GIT GIT_PUSH GIT_DEST
339 export SRPM_DEST SDEB_DEST LICENSE MAINTAINER_NAME MAINTAINER_EMAIL
340 export HOME_PAGE BUILD_SRPM BUILD_SDEB
341
342
343 # Multiplexer
344 if [ "${1}" = "docs" ]; then
345 shift
346 duilder_docs "$@"
347 exit $?
348 fi
349
350 if [ "${1}" = "tar" ]; then
351 shift
352 duilder_tar "$@"
353 exit $?
354 fi
355
356 if [ "${1}" = "git" ]; then
357 shift
358 duilder_git "$@"
359 exit $?
360 fi
361
362 if [ "${1}" = "srpm" ]; then
363 shift
364 duilder_srpm "$@"
365 exit $?
366 fi
367
368 if [ "${1}" = "sdeb" ]; then
369 shift
370 duilder_sdeb "$@"
371 exit $?
372 fi
373
374 if [ "${1}" = "final" ]; then
375 shift
376 duilder_final "$@"
377 exit $?
378 fi
379
380
381 ###### Main stuff
382 echo "[*] Duilder builder script"
383 echo "[*] Copyright Catalin(ux) M. BOIE - catab at embedromix dot ro"
384 echo "[*] PRJ=${PRJ}, VER=${VER}, REV=${REV}"
385 echo "[*] System: `uname -a`"
386 echo "[*] Parameters: ${@}"
387
388 ETC="/etc"
389 BIN="/bin"
390 USR="/usr"
391 USR_BIN="/usr/bin"
392 USR_SBIN="/usr/sbin"
393 USR_INCLUDE="/usr/include"
394 if [ "`uname -m`" = "i686" ]; then
395 USR_LIB="/usr/lib"
396 else
397 USR_LIB="/usr/lib64"
398 fi
399 USR_SHARE="/usr/share"
400 USR_SHARE_DOC="/usr/share/doc/${PRJ}"
401 SBIN="/usr/sbin"
402 VAR="/var"
403 VAR_LIB="/var/lib"
404 MAN="/usr/share/man"
405 PREFIX="/usr"
406
407 while [ "${1}" != "" ]; do
408 xVAR="`echo ${1} | cut -d'=' -f1`"
409 xVAL="`echo ${1} | cut -d'=' -f2 | sed -e "s|\\${prefix}|${PREFIX}|"`"
410 shift
411 case ${xVAR} in
412 --sysconfdir)
413 ETC="${xVAL}"
414 ;;
415 --bindir)
416 USR_BIN="${xVAL}"
417 ;;
418 --sbindir)
419 USR_SBIN="${xVAL}"
420 ;;
421 --includedir)
422 USR_INCLUDE="${xVAL}"
423 ;;
424 --libdir)
425 USR_LIB="${xVAL}"
426 ;;
427 --localstatedir)
428 VAR="${xVAL}"
429 ;;
430 --sharedstatedir)
431 VAR_LIB="${xVAL}"
432 ;;
433 --datadir)
434 USR_SHARE="${xVAL}"
435 ;;
436 --mandir)
437 MAN="${xVAL}"
438 ;;
439 --prefix)
440 PREFIX="${xVAL}"
441 USR="${xVAL}"
442 ;;
443 esac
444 done
445
446 # Last fixes
447 VAR_LOG="${VAR}/log"
448 VAR_RUN="${VAR}/run"
449 DUILDER_SYSTEMD="${USR}/lib/systemd"
450
451 for i in ETC BIN USR USR_BIN USR_SBIN USR_INCLUDE USR_LIB USR_SHARE USR_SHARE_DOC SBIN VAR VAR_LIB MAN VAR_LOG VAR_RUN DUILDER_SYSTEMD; do
452 eval value=\$$i
453 echo "[*] Var ${i}=${value}"
454 done
455
456 # Truncate future sed file
457 > tmp.sed
458
459 DB_SUPPORT=0
460
461 echo -n "[*] Searching for PostgreSQL..."
462 set +e
463 PG_VERSION="`pg_config --version 2>/dev/null`"
464 set -e
465 if [ -z "${PG_VERSION}" ]; then
466 echo " not found."
467 PG_FOUND=0
468 else
469 echo " found version ${PG_VERSION}."
470 PG_FOUND=1
471 PG_INC="-I`pg_config --includedir`"
472 PG_LIB="-L`pg_config --libdir` -lpq"
473
474 echo "s#@PG_VERSION@#${PG_VERSION}#g" >> tmp.sed
475 echo "s#@PG_INC@#${PG_INC}#g" >> tmp.sed
476 echo "s#@PG_LIB@#${PG_LIB}#g" >> tmp.sed
477
478 DB_SUPPORT=1
479 echo "s#@DB_SUPPORT@#${DB_SUPPORT}#g" >> tmp.sed
480 fi
481 echo "s#@PG_FOUND@#${PG_FOUND}#g" >> tmp.sed
482
483
484 echo -n "[*] Searching for MySQL..."
485 set +e
486 MYSQL_VERSION="`mysql_config --version 2>/dev/null`"
487 set -e
488 if [ -z "${MYSQL_VERSION}" ]; then
489 echo " not found."
490 MYSQL_FOUND=0
491 else
492 echo " found version ${MYSQL_VERSION}."
493 MYSQL_FOUND=1
494 MYSQL_INC="`mysql_config --include`"
495 MYSQL_LIB="`mysql_config --libs`"
496
497 echo "s#@MYSQL_VERSION@#${MYSQL_VERSION}#g" >> tmp.sed
498 echo "s#@MYSQL_INC@#${MYSQL_INC}#g" >> tmp.sed
499 echo "s#@MYSQL_LIB@#${MYSQL_LIB}#g" >> tmp.sed
500
501 DB_SUPPORT=1
502 echo "s#@DB_SUPPORT@#${DB_SUPPORT}#g" >> tmp.sed
503 fi
504 echo "s#@MYSQL_FOUND@#${MYSQL_FOUND}#g" >> tmp.sed
505
506 echo -n "[*] Searching for poll..."
507 set +e
508 echo -e "#include <poll.h> \n int main(void) { return poll(0, 0, 0); }" | gcc -x c -pipe - -o /dev/null 2>/dev/null
509 E="${?}"
510 set -e
511 if [ "${E}" != "0" ]; then
512 echo " not found."
513 echo "s#@POLL_FOUND@#0#g" >> tmp.sed
514 else
515 echo " found."
516 echo "s#@POLL_FOUND@#1#g" >> tmp.sed
517 fi
518
519 echo -n "[*] Searching for epoll..."
520 set +e
521 echo -e "#include <sys/epoll.h> \n int main(void) { return epoll_create(64); }" | gcc -x c -pipe - -o /dev/null 2>/dev/null
522 E="${?}"
523 set -e
524 if [ "${E}" != "0" ]; then
525 echo " not found."
526 echo "s#@EPOLL_FOUND@#0#g" >> tmp.sed
527 else
528 echo " found."
529 echo "s#@EPOLL_FOUND@#1#g" >> tmp.sed
530 fi
531
532 echo -n "[*] Searching for ncurses..."
533 set +e
534 echo -e "#include <ncurses.h> \n int main(void) { initscr(); return 0; }" | gcc -x c -pipe - -o /dev/null -lncurses 2>/dev/null
535 E="${?}"
536 set -e
537 if [ "${E}" != "0" ]; then
538 echo " not found."
539 echo "s#@NCURSES_FOUND@#0#g" >> tmp.sed
540 else
541 echo " found."
542 echo "s#@NCURSES_FOUND@#1#g" >> tmp.sed
543 fi
544
545 if [ "${CC_SWITCHES}" = "" ]; then
546 CC_SWITCHES="-O3 -fstack-reuse=all -flto -Wtrampolines -Wl,-z,noexecstack -Wl,-z,now -Wl,-z,relro -Wl,-O1 -Wl,-z,noexecstack -fstack-protector-all -Wcast-align -Wformat=2 -Wformat-security -fno-common -Wmissing-prototypes -Wmissing-declarations -Wstrict-overflow -Wstrict-prototypes -fno-guess-branch-probability -fbounds-check -Wl,-O3 -Wpadded -ftree-loop-distribution -ftree-vectorize -ftree-loop-if-convert -ftree-loop-im -ftree-parallelize-loops=4 -fcf-protection -fstack-clash-protection -Wimplicit-fallthrough -fanalyzer"
547 fi
548
549 if [ "1" = "1" ]; then
550 _CC_SWITCHES=""
551 echo "[*] Search for valid compiler flags..."
552 add=""
553 for s in ${CC_SWITCHES}; do
554 echo -n " [*] Testing switch [${s}]..."
555 case ${s} in
556 -Wformat-security) extra=" -Wformat" ;;
557 *) extra="" ;;
558 esac
559 set +e
560 echo "int main(void) { return 0; }" \
561 | gcc ${extra} ${s} -x c -pipe - -o /dev/null 2>>duilder.log
562 E=${?}
563 set -e
564 if [ "${E}" != "0" ]; then
565 echo "not supported"
566 else
567 echo "supported"
568 _CC_SWITCHES="${_CC_SWITCHES}${add}${s}"
569 add=" "
570 fi
571 done
572 fi
573
574 # generic stuff
575 echo "s#@PRJ@#${PRJ}#g" >> tmp.sed
576 echo "s#@VER@#${VER}#g" >> tmp.sed
577 echo "s#@REV@#${REV}#g" >> tmp.sed
578 echo "s#@ETC@#${ETC}#g" >> tmp.sed
579 echo "s#@BIN@#${BIN}#g" >> tmp.sed
580 echo "s#@USR@#${USR}#g" >> tmp.sed
581 echo "s#@USR_BIN@#${USR_BIN}#g" >> tmp.sed
582 echo "s#@SBIN@#${SBIN}#g" >> tmp.sed
583 echo "s#@USR_SBIN@#${USR_SBIN}#g" >> tmp.sed
584 echo "s#@VAR@#${VAR}#g" >> tmp.sed
585 echo "s#@VAR_LIB@#${VAR_LIB}#g" >> tmp.sed
586 echo "s#@VAR_LOG@#${VAR_LOG}#g" >> tmp.sed
587 echo "s#@VAR_RUN@#${VAR_RUN}#g" >> tmp.sed
588 echo "s#@USR_INCLUDE@#${USR_INCLUDE}#g" >> tmp.sed
589 echo "s#@USR_INC@#${USR_INCLUDE}#g" >> tmp.sed
590 echo "s#@USR_LIB@#${USR_LIB}#g" >> tmp.sed
591 echo "s#@USR_SHARE@#${USR_SHARE}#g" >> tmp.sed
592 echo "s#@USR_SHARE_DOC@#${USR_SHARE_DOC}#g" >> tmp.sed
593 echo "s#@MAN@#${MAN}#g" >> tmp.sed
594 echo "s#@DUILDER_SYSTEMD@#${DUILDER_SYSTEMD}#g" >> tmp.sed
595 # Export stuff
596 echo "s#@EXPORT_PATH@#${EXPORT_PATH}#g" >> tmp.sed
597 # cc_switches
598 echo "s#@CC_SWITCHES@#${_CC_SWITCHES}#g" >> tmp.sed
599 echo "s#@MAINTAINER_NAME@#${MAINTAINER_NAME}#g" >> tmp.sed
600 echo "s#@MAINTAINER_EMAIL@#${MAINTAINER_EMAIL}#g" >> tmp.sed
601 echo "s#@SHORT_DESCRIPTION@#${SHORT_DESCRIPTION}#g" >> tmp.sed
602 echo "s#@HOME_PAGE@#${HOME_PAGE}#g" >> tmp.sed
603
604
605
606 if [ -r Makefile.in ]; then
607 echo "[*] Building Makefile..."
608 echo -n > Makefile
609 echo "# duilder header starts #" >> Makefile
610 echo "export PRJ := ${PRJ}" >> Makefile
611 echo "export VER := ${VER}" >> Makefile
612 echo "export REV := ${REV}" >> Makefile
613 echo "export DESTDIR" >> Makefile
614 echo >> Makefile
615 echo "export I_ETC := \$(DESTDIR)${ETC}" >> Makefile
616 echo "export I_BIN := \$(DESTDIR)${BIN}" >> Makefile
617 echo "export I_SBIN := \$(DESTDIR)${SBIN}" >> Makefile
618 echo "export I_USR := \$(DESTDIR)${USR}" >> Makefile
619 echo "export I_USR_BIN := \$(DESTDIR)${USR_BIN}" >> Makefile
620 echo "export I_USR_SBIN := \$(DESTDIR)${USR_SBIN}" >> Makefile
621 echo "export I_USR_INCLUDE := \$(DESTDIR)${USR_INCLUDE}" >> Makefile
622 echo "export I_USR_INC := \$(DESTDIR)${USR_INCLUDE}" >> Makefile
623 echo "export I_USR_SHARE := \$(DESTDIR)${USR_SHARE}" >> Makefile
624 echo "export I_USR_SHARE_DOC := \$(DESTDIR)${USR_SHARE_DOC}" >> Makefile
625 echo "export I_USR_LIB := \$(DESTDIR)${USR_LIB}" >> Makefile
626 echo "export I_LIB := \$(DESTDIR)${USR_LIB}" >> Makefile
627 echo "export I_VAR := \$(DESTDIR)${VAR}" >> Makefile
628 echo "export I_VAR_LIB := \$(DESTDIR)${VAR_LIB}" >> Makefile
629 echo "export I_VAR_LOG := \$(DESTDIR)${VAR_LOG}" >> Makefile
630 echo "export I_VAR_RUN := \$(DESTDIR)${VAR_RUN}" >> Makefile
631 echo "export I_MAN := \$(DESTDIR)${MAN}" >> Makefile
632 echo "export I_DUILDER_SYSTEMD := \$(DESTDIR)${DUILDER_SYSTEMD}" >> Makefile
633 echo >> Makefile
634 echo "# DB stuff" >> Makefile
635 echo "export DB_SUPPORT := ${DB_SUPPORT}" >> Makefile
636 echo "# PG" >> Makefile
637 echo "export PG_FOUND := ${PG_FOUND}" >> Makefile
638 echo "export PG_INC := ${PG_INC}" >> Makefile
639 echo "export PG_LIB := ${PG_LIB}" >> Makefile
640 echo "# MySQL" >> Makefile
641 echo "export MYSQL_FOUND := ${MYSQL_FOUND}" >> Makefile
642 echo "export MYSQL_INC := ${MYSQL_INC}" >> Makefile
643 echo "export MYSQL_LIB := ${MYSQL_LIB}" >> Makefile
644 echo >> Makefile
645 echo "# duilder header ends #" >> Makefile
646 echo >> Makefile
647
648 sed -f tmp.sed Makefile.in >> Makefile
649
650 echo >> Makefile
651 echo "# duilder tail starts #" >> Makefile
652 echo >> Makefile
653 echo "# This is to allow exporting only the git tree" >> Makefile
654 echo "dist_git:" >> Makefile
655 echo " @./duilder git \"\$(PRJ)\" \"${GIT_DEST}\" \"${EXPORT_GIT}\" \"${EXPORT_PATH}\" \"${GIT_CHANGELOG}\" \"${GIT_PUSH}\"" >> Makefile
656 echo >> Makefile
657 echo "# This is to allow making the tar" >> Makefile
658 echo "dist_tar:" >> Makefile
659 echo " @./duilder tar \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\" \"${EXCLUDE}\"" >> Makefile
660 echo >> Makefile
661 echo "# This is to allow making rpm" >> Makefile
662 echo "dist_srpm: dist_tar" >> Makefile
663 echo " @./duilder srpm \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\" \"${BUILD_SRPM}\" \"${SRPM_DEST}\" \"${SRPM_POST_RUN}\"" >> Makefile
664 echo >> Makefile
665 echo ".PHONY: dist" >> Makefile
666 echo "dist: clean" >> Makefile
667 echo " @./duilder git \"\$(PRJ)\" \"${GIT_DEST}\" \"${EXPORT_GIT}\" \"${GIT_CHANGELOG}\"" \"${GIT_PUSH}\" >> Makefile
668 echo " @./duilder tar \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\" \"${EXCLUDE}\"" >> Makefile
669 echo " @./duilder srpm \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\" \"${BUILD_SRPM}\" \"${SRPM_DEST}\" \"${SRPM_POST_RUN}\"" >> Makefile
670 echo " @./duilder sdeb \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\" \"${BUILD_SDEB}\" \"${SDEB_DEST}\" \"${SDEB_POST_RUN}\"" >> Makefile
671 echo " @./duilder docs \"\$(PRJ)\" \"\$(VER)\" \"${EXPORT_PATH}\"" >> Makefile
672 echo " @./duilder final \"\$(PRJ)\" \"\$(VER)\" \"${RELEASE_SCRIPT}\"" >> Makefile
673 echo " @rm -f \"\$(PRJ)-\$(VER).tar.gz\"" >> Makefile
674 echo >> Makefile
675 fi
676
677 if [ -r "${PRJ}.spec.in" ]; then
678 echo "[*] Generating .spec file..."
679 sed -f tmp.sed ${PRJ}.spec.in > ${PRJ}.spec
680 fi
681
682 if [ ! -z "${CONFIG_H}" ]; then
683 echo "[*] Generating ${CONFIG_H} file..."
684 sed -f tmp.sed ${CONFIG_H}.in > ${CONFIG_H}
685 fi
686
687 if [ "${BUILD_SDEB}" = "1" ]; then
688 AUTOGENERATE="${AUTOGENERATE} debian/control.in debian/changelog.in"
689 AUTOGENERATE="${AUTOGENERATE} debian/copyright.in debian/rules.in"
690 fi
691
692 echo "[*] Autogenerate files from .in..."
693 for f in ${AUTOGENERATE}; do
694 if [ -r "${f}" ]; then
695 dst="${f%.in}"
696 echo " [*] Autogenerate ${dst} from ${f}..."
697 sed -f tmp.sed "${f}" > "${dst}"
698 # We need to have the same rights (maybe is executable...)
699 chmod --reference="${f}" "${dst}"
700 fi
701 done
702
703 rm -f tmp.sed
704
705 if [ "`basename ${0}`" = "duilderx" ]; then
706 echo "[*] Cloning myself to destination as 'duilder'..."
707 cp -vpf "${0}" ${PWD}/duilder
708 fi
709
710 echo "[*] Done. Run make."
File ingestd/Makefile added (mode: 100644) (index 0000000..28d0e46)
1 COMMON_H += ../common/ids.h ../common/tools.h stools.h priv.h
2 OBJS := ../common/tools.o stools.o decode.o decode_core.o decode_db.o decode_ssl.o
3
4 CFLAGS += -I../common
5
6 all:
7 make -C .. ingestd
8
9 compile: ninedogs-ingestd
10
11 decode.o: decode.c decode.h $(COMMON_H)
12 gcc $(CFLAGS) -c $<
13
14 decode_core.o: decode_core.c decode_core.h $(COMMON_H)
15 gcc $(CFLAGS) -c $<
16
17 decode_db.o: decode_db.c decode_db.h $(COMMON_H)
18 gcc $(CFLAGS) -c $<
19
20 decode_ssl.o: decode_ssl.c decode_ssl.h $(COMMON_H)
21 gcc $(CFLAGS) -c $<
22
23 ninedogs-ingestd: ninedogs-ingestd.c $(OBJS) stools.h
24 gcc $(CFLAGS) $@.c -o $@ $(OBJS) -lConn
25
26 .PHONY: clean
27 clean:
28 @-rm -f ninedogs-ingestd *.log core *.o
File ingestd/decode.c added (mode: 100644) (index 0000000..b8e2c3b)
1 #include <string.h>
2 #include <time.h>
3 #include <errno.h>
4 #include <unistd.h>
5
6 #include <Conn.h>
7
8 #include "ids.h"
9 #include "priv.h"
10 #include "stools.h"
11 #include "decode.h"
12 #include "decode_core.h"
13 #include "decode_db.h"
14 #include "decode_ssl.h"
15
16
17 unsigned int decode(struct Conn *C, unsigned char *buf, const unsigned int len)
18 {
19 unsigned int plen, type, off = 0, ioff, flags;
20 int r;
21 unsigned long long ts = 0;
22
23 char *dump = Conn_dump(buf, len);
24 Log(1, "%s: dump: len=%u %s\n", __func__, len, dump);
25 free(dump);
26
27 while (off + 4 + 1 + 4 < len) {
28 flags = 0;
29 ioff = off;
30 memcpy(&plen, buf + off, 4); off += 4;
31 plen = be32toh(plen);
32 if (off + plen > len)
33 return 0;
34
35 if (buf[off++] != 'T') {
36 Log(2, "Invalid frame (not starting with T)!\n");
37 Conn_close(C);
38 return 0;
39 }
40
41 memcpy(&type, buf + off, 4); off += 4;
42 type = be32toh(type);
43
44 if (type < NINEDOGS_NET_CORE_MAX) {
45 r = decode_core(C, type, buf + off, plen - 1 - 4, &flags, &ts);
46 } else if (type < NINEDOGS_NET_DB_MAX) {
47 r = decode_db(C, type, buf + off, plen - 1 - 4, &ts);
48 } else if (type < NINEDOGS_NET_SSL_MAX) {
49 r = decode_ssl(type, buf + off, plen - 1 - 4, &flags);
50 } else {
51 Log(2, "%s: Invalid type %08x\n", __func__, type, &flags, &ts);
52 r = -1;
53 }
54
55 if (r == -1) {
56 Conn_close(C);
57 return 0;
58 }
59
60 Log(10, " flags=0x%08x ts=%llu\n", flags, ts);
61 if (flags & DECODE_FLAGS_CHECK)
62 save_data_check(C, buf + ioff, 4 + plen, ts);
63 else if ((flags & DECODE_FLAGS_NO_SAVE) == 0)
64 save_data(C, buf + ioff, 4 + plen, ts);
65
66 off += plen - 1 - 4;
67 }
68
69 return off;
70 }
File ingestd/decode.h added (mode: 100644) (index 0000000..7329ea6)
1 unsigned int decode(struct Conn *C, unsigned char *buf, const unsigned int len);
2
File ingestd/decode_core.c added (mode: 100644) (index 0000000..62c7167)
1 #include <string.h>
2 #include <sys/time.h>
3 #include <sys/sysinfo.h>
4
5 #include <Conn.h>
6
7 #include "ids.h"
8 #include "decode_core.h"
9 #include "tools.h"
10 #include "stools.h"
11 #include "priv.h"
12
13 static int decode_core_id(struct Conn *C,
14 unsigned char *buf, const unsigned int len)
15 {
16 unsigned int off = 0, ioff;
17 struct priv *p = Conn_get_private(C);
18 unsigned char r;
19 char c;
20
21 Log(10, "%s: len=%u\n", __func__, len);
22
23 while (off + 1 + 1 <= len) {
24 ioff = off;
25 c = buf[off++];
26 switch (c) {
27 case 'I': r = unpack(&p->id.id, 's', 33, buf, len, &off); break;
28 default: r = 0; break;
29 }
30 if (r == 0) {
31 char *d = Conn_dump(buf + ioff, len - off);
32 Log(1, "%s: Cannot decode core id code [0x%02hhx][%c] off=%u/%u [%s]!\n",
33 __func__, c, c, ioff, len, d);
34 free(d);
35 return -1;
36 }
37 }
38
39 // TODO: we need a separate folder per client
40 p->id.client_id = 1;
41
42 if (!is_hexa_string(p->id.id)) {
43 Log(1, "Invalid id [%s]!\n", p->id.id);
44 return -1;
45 }
46
47 return 0;
48 }
49
50 static int decode_core_proc(struct Conn *C,
51 unsigned char *buf, const unsigned int len)
52 {
53 unsigned int off = 0, ioff;
54 struct priv *p = Conn_get_private(C);
55 unsigned char r;
56 struct timeval now;
57 char c;
58
59 Log(10, "%s: len=%u\n", __func__, len);
60
61 while (off + 1 + 1 <= len) {
62 ioff = off;
63 c = buf[off++];
64 switch (c) {
65 case 'u': r = unpack(&p->id.uid, '4', sizeof(p->id.uid), buf, len, &off); break;
66 case 'p': r = unpack(&p->id.pid, '4', sizeof(p->id.pid), buf, len, &off); break;
67 case 't': r = unpack(&p->id.tid, '4', sizeof(p->id.tid), buf, len, &off); break;
68 case 's': r = unpack(&p->id.remote_conn_time, 't', sizeof(p->id.remote_conn_time), buf, len, &off); break;
69 case 'z': r = unpack(&p->id.minutes_west, '4', sizeof(p->id.minutes_west), buf, len, &off); break;
70 case 'Z': r = unpack(&p->id.dsttime, '4', sizeof(p->id.dsttime), buf, len, &off); break;
71 default: r = 0; break;
72 }
73 if (r == 0) {
74 char *d = Conn_dump(buf + ioff, len - off);
75 Log(1, "%s: Cannot decode core proc code [0x%02hhx][%c] off=%u/%u [%s]!\n",
76 __func__, c, c, ioff, len, d);
77 free(d);
78 return -1;
79 }
80 }
81
82 gettimeofday(&now, NULL);
83 p->id.local_conn_time = now.tv_sec * 1000000 + now.tv_usec;
84
85 return 0;
86 }
87
88 static int decode_core_uname(struct Conn *C,
89 unsigned char *buf, const unsigned int len, unsigned long long *ts)
90 {
91 unsigned int off = 0, ioff;
92 struct priv *p = Conn_get_private(C);
93 unsigned char r;
94 char c;
95
96 while (off + 1 + 1 <= len) {
97 ioff = off;
98 c = buf[off++];
99 switch (c) {
100 case 'N': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break;
101 case 's': r = unpack(&p->uname.sysname, 's', sizeof(p->uname.sysname), buf, len, &off); break;
102 case 'n': r = unpack(&p->uname.nodename, 's', sizeof(p->uname.nodename), buf, len, &off); break;
103 case 'r': r = unpack(&p->uname.release, 's', sizeof(p->uname.release), buf, len, &off); break;
104 case 'v': r = unpack(&p->uname.version, 's', sizeof(p->uname.version), buf, len, &off); break;
105 case 'm': r = unpack(&p->uname.machine, 's', sizeof(p->uname.machine), buf, len, &off); break;
106 default: r = 0; break;
107 }
108 if (r == 0) {
109 Log(1, "%s: Cannot decode core uname code [0x%02hhx][%c] off=%u/%u!\n",
110 __func__, c, c, ioff, len);
111 return -1;
112 }
113 }
114
115 Log(10, "%s: ts=%llu sys=%s node=%s rel=%s ver=%s mach=%s\n",
116 __func__, *ts, p->uname.sysname, p->uname.nodename,
117 p->uname.release, p->uname.version, p->uname.machine);
118
119 return 0;
120 }
121
122 static int decode_core_sysinfo(unsigned char *buf, const unsigned int len,
123 unsigned long long *ts)
124 {
125 unsigned int off = 0, ioff;
126 unsigned char r;
127 char c;
128 struct sysinfo s;
129
130 while (off + 1 + 1 <= len) {
131 ioff = off;
132 c = buf[off++];
133 switch (c) {
134 case 'N': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break;
135 case 'u': r = unpack(&s.uptime, '8', sizeof(s.uptime), buf, len, &off); break;
136 case '1': r = unpack(&s.loads[0], '8', sizeof(s.loads[0]), buf, len, &off); break;
137 case '5': r = unpack(&s.loads[1], '8', sizeof(s.loads[1]), buf, len, &off); break;
138 case 'q': r = unpack(&s.loads[2], '8', sizeof(s.loads[2]), buf, len, &off); break;
139 case 'r': r = unpack(&s.totalram, '8', sizeof(s.totalram), buf, len, &off); break;
140 case 'f': r = unpack(&s.freeram, '8', sizeof(s.freeram), buf, len, &off); break;
141 case 's': r = unpack(&s.sharedram, '8', sizeof(s.sharedram), buf, len, &off); break;
142 case 'b': r = unpack(&s.bufferram, '8', sizeof(s.bufferram), buf, len, &off); break;
143 case 'w': r = unpack(&s.totalswap, '8', sizeof(s.totalswap), buf, len, &off); break;
144 case 'W': r = unpack(&s.freeswap, '8', sizeof(s.freeswap), buf, len, &off); break;
145 case 'p': r = unpack(&s.procs, '2', sizeof(s.procs), buf, len, &off); break;
146 case 'h': r = unpack(&s.totalhigh, '8', sizeof(s.totalhigh), buf, len, &off); break;
147 case 'H': r = unpack(&s.freehigh, '8', sizeof(s.freehigh), buf, len, &off); break;
148 case 'i': r = unpack(&s.mem_unit, '4', sizeof(s.mem_unit), buf, len, &off); break;
149 default: r = 0; break;
150 }
151 if (r == 0) {
152 Log(1, "%s: Cannot decode core sysinfo code [0x%02hhx][%c] off=%u/%u!\n",
153 __func__, c, c, ioff, len);
154 return -1;
155 }
156 }
157
158 Log(10, "%s: ts=%llu uptime=%lu loads1=%lu loads5=%lu loads15=%lu totalram=%lu"
159 " freeram=%lu sharedram=%lu bufferram=%lu totalswap=%lu"
160 " freeswap=%lu procs=%u totalhigh=%lu freehigh=%lu mem_unit=%u\n",
161 __func__, *ts, s.uptime, s.loads[0], s.loads[1], s.loads[2], s.totalram,
162 s.freeram, s.sharedram, s.bufferram, s.totalswap,
163 s.freeswap, s.procs, s.totalhigh, s.freehigh, s.mem_unit);
164
165 return 0;
166 }
167
168 static int decode_core_stop(unsigned char *buf, const unsigned int len)
169 {
170 unsigned int off = 0, ioff, exit_code;
171 unsigned char r;
172 char c;
173 unsigned long long start, stop;
174
175 Log(10, "%s: len=%u\n", __func__, len);
176
177 while (off + 1 + 1 <= len) {
178 ioff = off;
179 c = buf[off++];
180 switch (c) {
181 case 's': r = unpack(&start, 't', sizeof(start), buf, len, &off); break;
182 case 't': r = unpack(&stop, 't', sizeof(stop), buf, len, &off); break;
183 case 'x': r = unpack(&exit_code, '4', sizeof(exit_code), buf, len, &off); break;
184 default: r = 0; break;
185 }
186 if (r == 0) {
187 char *d = Conn_dump(buf + ioff, len - off);
188 Log(1, "%s: Cannot decode core stop code [0x%02hhx][%c] off=%u/%u [%s]!\n",
189 __func__, c, c, ioff, len, d);
190 free(d);
191 return -1;
192 }
193 }
194
195 Log(10, "%s: start=%llu stop=%llu exit_code=%u\n",
196 __func__, start, stop, exit_code);
197
198 return 0;
199 }
200
201 int decode_core(struct Conn *C, const unsigned int type,
202 unsigned char *buf, const unsigned int len, unsigned int *flags,
203 unsigned long long *ts)
204 {
205 char *dump = Conn_dump(buf, len);
206 Log(1, "%s: dump: type=%u len=%u %s\n", __func__, type, len, dump);
207 free(dump);
208
209 if (len <= 2)
210 return 0;
211
212 switch (type) {
213 case NINEDOGS_NET_CORE_ID:
214 *flags = *flags | DECODE_FLAGS_NO_SAVE;
215 return decode_core_id(C, buf, len);
216 case NINEDOGS_NET_CORE_PROC:
217 return decode_core_proc(C, buf, len);
218 case NINEDOGS_NET_CORE_UNAME:
219 return decode_core_uname(C, buf, len, ts);
220 case NINEDOGS_NET_CORE_SYSINFO:
221 return decode_core_sysinfo(buf, len, ts);
222 case NINEDOGS_NET_CORE_STOP:
223 return decode_core_stop(buf, len);
224 default:
225 Log(2, "%s: unknown core type %08x!\n", __func__, type);
226 return -1;
227 }
228 }
File ingestd/decode_core.h added (mode: 100644) (index 0000000..b1c18c9)
1 int decode_core(struct Conn *C, const unsigned int type,
2 unsigned char *buf, const unsigned int len, unsigned int *flags,
3 unsigned long long *ts);
4
File ingestd/decode_db.c added (mode: 100644) (index 0000000..7371efd)
1 #include <string.h>
2 #include <sys/stat.h>
3
4 #include <Conn.h>
5
6 #include "ids.h"
7 #include "decode_db.h"
8 #include "tools.h"
9 #include "stools.h"
10 #include "priv.h"
11
12 static int decode_conn(unsigned char *buf, const unsigned int len,
13 unsigned long long *ts)
14 {
15 unsigned int off = 0;
16 unsigned char r;
17 char type;
18 unsigned int count;
19 char c, conn_str[4096];
20 unsigned long long min, max, elap;
21
22 while (off + 1 + 1 <= len) {
23 c = buf[off++];
24 switch (c) {
25 case '_': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break;
26 case 't': r = unpack(&type, 'c', sizeof(type), buf, len, &off); break;
27 case 'c': r = unpack(&count, '4', sizeof(count), buf, len, &off); break;
28 case 's': r = unpack(&conn_str, 's', sizeof(conn_str), buf, len, &off); break;
29 case 'i': r = unpack(&min, 't', sizeof(min), buf, len, &off); break;
30 case 'a': r = unpack(&max, 't', sizeof(max), buf, len, &off); break;
31 case 'e': r = unpack(&elap, 't', sizeof(elap), buf, len, &off); break;
32 default: r = 0; break;
33 }
34 if (r == 0) {
35 Log(1, "%s: Cannot decode db query code [0x%02hhx][%c] off=%u/%u!\n",
36 __func__, c, c, off, len);
37 return -1;
38 }
39 }
40
41 Log(10, "%s: type=%c count=%lu conn_str=[%s] ts=%llu min=%llu max=%llu elap=%llu\n",
42 __func__, type, count, conn_str, *ts, min, max, elap);
43
44 return 0;
45 }
46
47 static int decode_query_stats(struct Conn *C, unsigned char *buf, const unsigned int len,
48 unsigned long long *ts)
49 {
50 unsigned int off = 0;
51 unsigned char r;
52 unsigned long count, rows, aff, free_calls, free_errs;
53 unsigned char hash[32];
54 unsigned long long min, max, elap;
55 char shash[65], path[4096];
56 char c;
57 struct stat s;
58 struct priv *p;
59
60 while (off + 1 + 1 <= len) {
61 c = buf[off++];
62 switch (c) {
63 case '_': r = unpack(ts, 't', sizeof(*ts), buf, len, &off); break;
64 case 'h': r = unpack(hash, 's', sizeof(hash), buf, len, &off); break;
65 case 'c': r = unpack(&count, '8', sizeof(count), buf, len, &off); break;
66 case 'r': r = unpack(&rows, '8', sizeof(rows), buf, len, &off); break;
67 case 'A': r = unpack(&aff, '8', sizeof(aff), buf, len, &off); break;
68 case 'i': r = unpack(&min, 't', sizeof(min), buf, len, &off); break;
69 case 'a': r = unpack(&max, 't', sizeof(max), buf, len, &off); break;
70 case 'e': r = unpack(&elap, 't', sizeof(elap), buf, len, &off); break;
71 case 'x': r = unpack(&free_calls, '8', sizeof(free_calls), buf, len, &off); break;
72 case 'y': r = unpack(&free_errs, '8', sizeof(free_errs), buf, len, &off); break;
73 default: r = 0; break;
74 }
75 if (r == 0) {
76 Log(1, "%s: Cannot decode db query code [0x%02hhx][%c] off=%u/%u!\n",
77 __func__, c, c, off, len);
78 return -1;
79 }
80 }
81
82 bin2hex(shash, hash, sizeof(hash));
83 Log(10, "%s: hash=%lu count=%lu rows=%hu aff=%hu free_calls/errs=%lu/%lu"
84 " ts=%llu min=%llu max=%llu elap=%llu\n",
85 __func__, hash, count, rows, aff, free_calls, free_errs,
86 *ts, min, max, elap);
87
88 // If we cannot find the query, we need to request it
89 p = Conn_get_private(C);
90 snprintf(path, sizeof(path), "/var/lib/ninedogs/%02hhx/%02hhx/%02hhx/%02hhx/q/%c%c/%c%c/%s",
91 p->id.client_id >> 24, p->id.client_id >> 16,
92 p->id.client_id >> 8, p->id.client_id,
93 shash[0], shash[1], shash[2], shash[3], shash + 4);
94 int r2 = stat(path, &s);
95 if (r2 == -1) {
96 unsigned char *b;
97 unsigned int blen;
98 Log(1, " Requesting query %s from client because [%s] not found (%m)...\n", shash, path);
99 pack(&b, &blen, "T4 hs",
100 NINEDOGS_NET_DB_QUERY_STRING, hash, sizeof(hash));
101 if (b)
102 Conn_enqueue(C, b, blen);
103 }
104
105 return 0;
106 }
107
108 static int decode_query_string(unsigned char *buf, const unsigned int len)
109 {
110 unsigned int off = 0;
111 unsigned char r;
112 unsigned char hash[32];
113 char shash[65], query[8192 + 1];
114 char c;
115
116 while (off + 1 + 1 <= len) {
117 c = buf[off++];
118 switch (c) {
119 case 'h': r = unpack(hash, 's', sizeof(hash), buf, len, &off); break;
120 case 'q': r = unpack(query, 's', sizeof(query), buf, len, &off); break;
121 default: r = 0; break;
122 }
123 if (r == 0) {
124 Log(1, "%s: Cannot decode db query string code [0x%02hhx][%c] off=%u/%u!\n",
125 __func__, c, c, off, len);
126 return -1;
127 }
128 }
129
130 bin2hex(shash, hash, sizeof(hash));
131 Log(10, "%s: hash=%s q=%s\n",
132 __func__, shash, query);
133
134 return 0;
135 }
136
137 int decode_db(struct Conn *C, const unsigned int type,
138 unsigned char *buf, const unsigned int len,
139 unsigned long long *ts)
140 {
141 char *dump = Conn_dump(buf, len);
142 Log(50, "%s: dump: %s\n", __func__, dump);
143 free(dump);
144
145 if (len <= 2)
146 return 0;
147
148 switch (type) {
149 case NINEDOGS_NET_DB_CONN: return decode_conn(buf, len, ts);
150 case NINEDOGS_NET_DB_QUERY_STRING: return decode_query_string(buf, len);
151 case NINEDOGS_NET_DB_QUERY_STATS: return decode_query_stats(C, buf, len, ts);
152 default:
153 Log(2, "%s: unknown db type %08x!\n", __func__, type);
154 return -1;
155 }
156 }
File ingestd/decode_db.h added (mode: 100644) (index 0000000..15696cf)
1 int decode_db(struct Conn *C, const unsigned int type,
2 unsigned char *buf, const unsigned int len,
3 unsigned long long *ts);
4
File ingestd/decode_ssl.c added (mode: 100644) (index 0000000..58fefdc)
1 #include <string.h>
2 #include <stdlib.h>
3
4 #include <Conn.h>
5
6 #include "ids.h"
7 #include "decode_ssl.h"
8 #include "tools.h"
9 #include "stools.h"
10 #include "priv.h"
11
12 int decode_info(unsigned char *buf, const unsigned int len)
13 {
14 unsigned int off = 0;
15 unsigned char r;
16 char c, info[128];
17 unsigned long long ts;
18
19 Log(10, "%s: len=%u\n", __func__, len);
20
21 while (off + 1 + 1 <= len) {
22 c = buf[off++];
23 switch (c) {
24 case 'N': r = unpack(&ts, 't', sizeof(ts), buf, len, &off); break;
25 case 'v': r = unpack(info, 's', sizeof(info), buf, len, &off); break;
26 default: r = 0; break;
27 }
28 if (r == 0) {
29 char *d = Conn_dump(buf, len);
30 Log(1, "%s: Cannot decode ssl info [0x%02hhx][%c] off=%u/%u [%s]!\n",
31 __func__, c, c, off, len, d);
32 free(d);
33 return -1;
34 }
35 }
36
37 Log(10, "%s: ts=%llu info=[%s]\n", __func__, ts, info);
38
39 return 0;
40 }
41
42 int decode_cert(unsigned char *buf, const unsigned int len)
43 {
44 char c;
45 unsigned int off = 0;
46 unsigned char r;
47 char path[256], subj[512], not_before[32], not_after[32];
48 unsigned long long ts;
49
50 Log(10, "%s: len=%u\n", __func__, len);
51
52 while (off + 1 + 1 <= len) {
53 c = buf[off++];
54 switch (c) {
55 case 'N': r = unpack(&ts, 't', sizeof(ts), buf, len, &off); break;
56 case 'p': r = unpack(path, 's', sizeof(path), buf, len, &off); break;
57 case 'u': r = unpack(subj, 's', sizeof(subj), buf, len, &off); break;
58 case 's': r = unpack(not_before, 's', sizeof(not_before), buf, len, &off); break;
59 case 'e': r = unpack(not_after, 's', sizeof(not_after), buf, len, &off); break;
60 default: r = 0; break;
61 }
62 if (r == 0) {
63 char *d = Conn_dump(buf, len);
64 Log(1, "%s: Cannot decode ssl cert [0x%02hhx][%c] off=%u/%u [%s]!\n",
65 __func__, c, c, off, len, d);
66 free(d);
67 return -1;
68 }
69 }
70
71 Log(1, "%s: ts=%llu path=[%s] subj=[%s] not_before=[%s] not_after=[%s]\n",
72 __func__, ts, path, subj, not_before, not_after);
73
74 return 0;
75 }
76
77 int decode_ssl(const unsigned int type,
78 unsigned char *buf, const unsigned int len, unsigned int *flags)
79 {
80 char *dump = Conn_dump(buf, len);
81 Log(1, "%s: dump: len=%u %s\n", __func__, len, dump);
82 free(dump);
83
84 if (len <= 2)
85 return 0;
86
87 switch (type) {
88 case NINEDOGS_NET_SSL_INFO:
89 *flags = *flags | DECODE_FLAGS_CHECK;
90 return 0;
91 case NINEDOGS_NET_SSL_CERT:
92 *flags = *flags | DECODE_FLAGS_CHECK;
93 return 0;
94 default:
95 Log(2, "%s: unknown ssl type 0x%08x!\n", __func__, type);
96 return -1;
97 }
98 }
File ingestd/decode_ssl.h added (mode: 100644) (index 0000000..96f2396)
1 int decode_info(unsigned char *buf, const unsigned int len);
2 int decode_cert(unsigned char *buf, const unsigned int len);
3
4 int decode_ssl(const unsigned int type,
5 unsigned char *buf, const unsigned int len, unsigned int *flags);
6
File ingestd/gdb.cmd added (mode: 100644) (index 0000000..2d77937)
1
2 r
File ingestd/gdb.sh added (mode: 100755) (index 0000000..aa6716b)
1 #!/bin/bash
2
3 gdb --command gdb.cmd ninedogs-ingestd
File ingestd/ninedogs-ingestd.c added (mode: 100644) (index 0000000..8e3fd9d)
1 #define _GNU_SOURCE
2
3 #include <errno.h>
4 #include <string.h>
5 #include <strings.h>
6 #include <unistd.h>
7 #include <netinet/in.h>
8 #include <sys/time.h>
9 #include <sys/ioctl.h>
10 #include <time.h>
11 #include <stdarg.h>
12
13 #include <Conn.h>
14
15 #include "priv.h"
16 #include "decode.h"
17 #include "tools.h"
18 #include "stools.h"
19
20 /* Global variables */
21 static unsigned short debug = 70; // 1 recommended for production
22
23 struct Clients
24 {
25 struct Conn *C;
26 struct Clients *next;
27 };
28 static struct Clients *Clients_head, *Clients_tail;
29
30 static void dump_Clients(void)
31 {
32 struct Clients *q;
33
34 Log(10, "Dumping Clients:\n");
35
36 q = Clients_head;
37 while (q) {
38 Log(10, "\tq=%p q->next=%p q->C->id=%llu\n",
39 q, q->next, Conn_get_id(q->C));
40 q = q->next;
41 }
42 }
43
44 static void accept_cb(struct Conn *C)
45 {
46 struct Clients *q;
47 struct priv *priv;
48
49 Log(1, "%llu %s from %s/%d\n", Conn_get_id(C), __func__,
50 Conn_addr_remote(C), Conn_port_remote(C));
51
52 priv = malloc(sizeof(struct priv));
53 if (!priv) {
54 Log(0, "\tCannot alloc memory for private area!\n");
55 Conn_close(C);
56 return;
57 }
58 memset(priv, 0, sizeof(struct priv));
59 Conn_set_private(C, priv);
60
61 priv->fd = -1;
62
63 q = malloc(sizeof(struct Clients));
64 if (!q) {
65 Log(0, "\tCannot alloc memory for Clients!\n");
66 Conn_close(C);
67 return;
68 }
69
70 q->C = C;
71 q->next = NULL;
72
73 if (Clients_head)
74 Clients_tail->next = q;
75 else
76 Clients_head = q;
77 Clients_tail = q;
78
79 dump_Clients();
80 }
81
82 static void close_cb(struct Conn *C)
83 {
84 struct Clients *q, *p;
85 struct priv *priv;
86
87 Log(0, "%llu %s Closing...\n", Conn_get_id(C), __func__);
88
89 priv = Conn_get_private(C);
90
91 if (priv->fd != -1)
92 close(priv->fd);
93
94 if (C == Clients_head->C) {
95 p = Clients_head;
96 Clients_head = Clients_head->next;
97 free(p);
98 return;
99 }
100
101 q = Clients_head;
102 while (q->next) {
103 if (q->next->C == C) {
104 p = q->next;
105 q->next = q->next->next;
106 free(p);
107 if (!q->next)
108 Clients_tail = q;
109 break;
110 }
111
112 q = q->next;
113 }
114
115 dump_Clients();
116 }
117
118 static void process(struct Conn *C, void *buf, const unsigned int size)
119 {
120 struct priv *priv;
121
122 Log(1, "%llu %s size=%u\n", Conn_get_id(C), __func__, size);
123
124 priv = Conn_get_private(C);
125
126 if (priv->sent_ws == 0) {
127 Conn_eatall(C); // TODO: we need to be sure we have the full header
128
129 Conn_printf(C,
130 "HTTP/1.1 101 Switching Protocols\r\n"
131 "Server: ninedogs\r\n"
132 "Upgrade: websocket\r\n"
133 "Connection: Upgrade\r\n"
134 "Sec-WebSocket-Accept: bla\r\n"
135 "\r\n");
136 Conn_kick(C);
137 priv->sent_ws = 1;
138 }
139
140 unsigned int used = decode(C, buf, size);
141 Conn_eat(C, used);
142 }
143
144 static void data(struct Conn *C)
145 {
146 process(C, Conn_ibuf(C), Conn_iqlen(C));
147 }
148
149 int main(void)
150 {
151 int ret;
152 struct Conn *C;
153 char *stats;
154
155 setlinebuf(stdout);
156
157 Conn_debug(0, debug);
158
159 ret = mkdir_recursive("/var/lib/ninedogs", 0700);
160 if (ret == -1) {
161 Log(1, "Cannot create dir /var/lib/ninedogs!\n");
162 exit(1);
163 }
164
165 ret = Conn_init(0);
166 if (ret == -1) {
167 printf("%s", Conn_strerror());
168 return 1;
169 }
170
171 printf("Trying to register IPv4 socket...\n");
172 C = Conn_alloc();
173 if (!C) {
174 printf("Cannot alloc socket [%s].\n", Conn_strerror());
175 return 1;
176 }
177
178 Conn_set_socket_domain(C, PF_INET);
179 Conn_set_socket_type(C, SOCK_STREAM);
180 Conn_set_socket_bind_addr(C, "127.0.0.1");
181 Conn_set_socket_bind_port(C, 6001);
182
183 Conn_set_cb(C, CONN_CB_ACCEPT, accept_cb);
184 Conn_set_cb(C, CONN_CB_CLOSE, close_cb);
185 Conn_set_cb(C, CONN_CB_DATA, data);
186
187 ret = Conn_commit(C);
188 if (ret != 0) {
189 printf("Cannot bind on ipv4 socket [%s].\n",
190 Conn_strerror());
191 return 1;
192 }
193
194 Log(12, "Waiting...\n");
195 while (1) {
196 ret = Conn_poll(-1);
197 if (ret == -1) {
198 printf("Error in poll [%s]!\n",
199 Conn_strerror());
200 break;
201 }
202
203 #if 1
204 if (debug >= 9) {
205 stats = Conn_status(0);
206 printf("%s\n", stats);
207 free(stats);
208 }
209 #endif
210 }
211
212 Conn_shutdown();
213
214 return 0;
215 }
File ingestd/ninedogs-ingestd.service added (mode: 100644) (index 0000000..aacde51)
1 [Unit]
2 Description=Ninedogs ingestion daemon
3
4 [Service]
5 Type=exec
6 ExecStart=/date/sync/no-crypt/sync1/Dev/ninedogs/ingestd/ninedogs-ingestd
7 #User=rocketgit
8 #Group=rocketgit
9 PrivateTmp=true
10 Restart=on-failure
11 RestartSec=10
12 ProtectSystem=full
13 NoNewPrivileges=yes
14
15 [Install]
16 WantedBy=multi-user.target
File ingestd/priv.h added (mode: 100644) (index 0000000..a5379d8)
1 #include <sys/utsname.h>
2
3 // Private data per client
4 struct priv {
5 struct {
6 char id[33];
7 unsigned char pad1[3];
8 unsigned int uid;
9 unsigned long local_conn_time, remote_conn_time;
10 unsigned int pid, tid, pad2;
11 unsigned int client_id;
12 unsigned int minutes_west;
13 unsigned int dsttime;
14 } id;
15
16 struct utsname uname;
17 unsigned char pad3[2];
18
19 unsigned int sent_ws:1;
20 unsigned int pad4:31;
21 int fd;
22 unsigned int fd_ts;
23 unsigned int pad5;
24 };
File ingestd/stools.c added (mode: 100644) (index 0000000..fb1abeb)
1 #include <string.h>
2 #include <endian.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <sys/stat.h>
6 #include <time.h>
7 #include <errno.h>
8 #include <stdio.h>
9 #include <unistd.h>
10
11 #include <Conn.h>
12
13 #include "tools.h"
14 #include "stools.h"
15 #include "priv.h"
16
17
18 static int save_buf(int fd, const unsigned char *buf, const unsigned int len)
19 {
20 unsigned int off;
21
22 off = 0;
23 do {
24 ssize_t n = write(fd, buf + off, len - off);
25 if (n == -1) {
26 if (errno == EAGAIN)
27 continue;
28 Log(1, "Cannot write: %m\n");
29 // TODO: buffer data in memory?
30 return -1;
31 }
32 off += n;
33 } while (off < len);
34
35 return len;
36 }
37
38 /*
39 * This saves a file to be checked ASAP by scheduler.
40 * It is used to check certificates validity, security and other stuff.
41 */
42 int save_data_check(struct Conn *C, const unsigned char *buf, const unsigned int len,
43 const unsigned long long ts)
44 {
45 struct priv *p = Conn_get_private(C);
46 char path[4096];
47 int fd;
48
49 Log(10, "%s: client_id=%u len=%u ts=%llu\n",
50 __func__, p->id.client_id, len, ts);
51
52 snprintf(path, sizeof(path), "/var/lib/ninedogs/check");
53 mkdir_recursive(path, 0700);
54
55 // We do not want to overwrite an existing file
56 do {
57 snprintf(path, sizeof(path), "/var/lib/ninedogs/check/%llu-%u-%s-%08x",
58 ts, p->id.client_id, p->id.id, rand());
59 Log(10, " saving to %s\n", path);
60 fd = open(path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0600);
61 if (fd == -1) {
62 if (errno == EEXIST)
63 continue;
64 Log(1, "Cannot open [%s]: %m\n", path);
65 return -1;
66 }
67 } while (0);
68
69 int r = save_buf(fd, buf, len);
70 close(fd);
71 if (r == -1)
72 return -1;
73
74 return 0;
75 }
76
77 int save_data(struct Conn *C, const unsigned char *buf, const unsigned int len,
78 const unsigned long long ts)
79 {
80 struct priv *p = Conn_get_private(C);
81 unsigned long long hour;
82
83 Log(10, "%s: client_id=%u len=%u ts=%llu\n",
84 __func__, p->id.client_id, len, ts);
85
86 hour = get_hour(ts);
87 if (p->fd != -1) {
88 // we need to check if we need to open another file
89 if (hour > p->fd_ts) {
90 close(p->fd);
91 p->fd = -1;
92 }
93 }
94
95 if (p->fd == -1) {
96 char path[4096], sts[16];
97
98 snprintf(path, sizeof(path), "/var/lib/ninedogs/%02hhx/%02hhx/%02hhx/%02hhx/%c%c/%c%c/%s/t",
99 p->id.client_id >> 24, p->id.client_id >> 16,
100 p->id.client_id >> 8, p->id.client_id,
101 p->id.id[0], p->id.id[1], p->id.id[2], p->id.id[3], p->id.id + 4);
102 mkdir_recursive(path, 0700);
103 strcat(path, "/");
104 snprintf(sts, sizeof(sts), "%llu", hour);
105 strcat(path, sts);
106 Log(10, " saving to %s\n", path);
107 p->fd = open(path, O_CREAT | O_WRONLY | O_APPEND, 0600);
108 if (p->fd == -1) {
109 Log(1, "Cannot open [%s]: %m\n", path);
110 return -1;
111 }
112
113 p->fd_ts = hour;
114 }
115
116 int r = save_buf(p->fd, buf, len);
117 if (r == -1)
118 return -1;
119
120 return 0;
121 }
122
File ingestd/stools.h added (mode: 100644) (index 0000000..8a9560f)
1 enum
2 {
3 DECODE_FLAGS_CHECK = 0x00000001,
4 DECODE_FLAGS_NO_SAVE = 0x00000002
5 };
6
7 int save_data_check(struct Conn *C, const unsigned char *buf,
8 const unsigned int len, const unsigned long long ts);
9
10 int save_data(struct Conn *C, const unsigned char *buf,
11 const unsigned int len, const unsigned long long ts);
12
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/ninedogs

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/ninedogs

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/ninedogs

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main