2 * Samba Unix/Linux SMB client library
4 * Copyright (C) Jule Anger 2022
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "smbprofile.h"
22 #include "lib/util/time_basic.h"
25 #include "librpc/gen_ndr/smbXsrv.h"
26 #include "librpc/gen_ndr/open_files.h"
27 #include "status_json.h"
28 #include "../libcli/security/security.h"
30 #include "lib/util/server_id.h"
31 #include "lib/util/string_wrappers.h"
34 #include "audit_logging.h" /* various JSON helpers */
35 #include "auth/common_auth.h"
37 int add_general_information_to_json(struct traverse_state
*state
)
41 result
= json_add_timestamp(&state
->root_json
);
46 result
= json_add_string(&state
->root_json
, "version", samba_version_string());
51 result
= json_add_string(&state
->root_json
, "smb_conf", get_dyn_CONFIGFILE());
59 static int add_server_id_to_json(struct json_object
*parent_json
,
60 const struct server_id server_id
)
62 struct json_object sub_json
;
64 char *task_id_str
= NULL
;
66 char *unique_id_str
= NULL
;
69 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
70 if (tmp_ctx
== NULL
) {
74 sub_json
= json_new_object();
75 if (json_is_invalid(&sub_json
)) {
79 pid_str
= talloc_asprintf(
80 tmp_ctx
, "%lu", (unsigned long)server_id
.pid
);
81 result
= json_add_string(&sub_json
, "pid", pid_str
);
85 task_id_str
= talloc_asprintf(tmp_ctx
, "%u", server_id
.task_id
);
86 result
= json_add_string(&sub_json
, "task_id", task_id_str
);
90 vnn_str
= talloc_asprintf(tmp_ctx
, "%u", server_id
.vnn
);
91 result
= json_add_string(&sub_json
, "vnn", vnn_str
);
95 unique_id_str
= talloc_asprintf(
96 tmp_ctx
, "%"PRIu64
, server_id
.unique_id
);
97 result
= json_add_string(&sub_json
, "unique_id", unique_id_str
);
102 result
= json_add_object(parent_json
, "server_id", &sub_json
);
107 TALLOC_FREE(tmp_ctx
);
110 json_free(&sub_json
);
111 TALLOC_FREE(tmp_ctx
);
117 const char *string_desc
;
121 * Convert a mask of some sort (access, oplock, leases),
122 * to key/value pairs in a JSON object.
124 static int map_mask_to_json(struct json_object
*root_json
,
126 const struct mask2txt
*table
)
128 const struct mask2txt
*a
= NULL
;
131 for (a
= table
; a
->string_desc
!= 0; a
++) {
132 result
= json_add_bool(root_json
, a
->string_desc
,
133 (tomap
& a
->mask
) ? true : false);
141 /* Assert we know about all requested "tomap" values */
142 SMB_ASSERT(tomap
== 0);
147 static const struct mask2txt access_mask
[] = {
148 {FILE_READ_DATA
, "READ_DATA"},
149 {FILE_WRITE_DATA
, "WRITE_DATA"},
150 {FILE_APPEND_DATA
, "APPEND_DATA"},
151 {FILE_READ_EA
, "READ_EA"},
152 {FILE_WRITE_EA
, "WRITE_EA"},
153 {FILE_EXECUTE
, "EXECUTE"},
154 {FILE_READ_ATTRIBUTES
, "READ_ATTRIBUTES"},
155 {FILE_WRITE_ATTRIBUTES
, "WRITE_ATTRIBUTES"},
156 {FILE_DELETE_CHILD
, "DELETE_CHILD"},
157 {SEC_STD_DELETE
, "DELETE"},
158 {SEC_STD_READ_CONTROL
, "READ_CONTROL"},
159 {SEC_STD_WRITE_DAC
, "WRITE_DAC"},
160 {SEC_STD_SYNCHRONIZE
, "SYNCHRONIZE"},
161 {SEC_FLAG_SYSTEM_SECURITY
, "ACCESS_SYSTEM_SECURITY"},
165 static const struct mask2txt oplock_mask
[] = {
166 {EXCLUSIVE_OPLOCK
, "EXCLUSIVE"},
167 {BATCH_OPLOCK
, "BATCH"},
168 {LEVEL_II_OPLOCK
, "LEVEL_II"},
169 {LEASE_OPLOCK
, "LEASE"},
173 static const struct mask2txt sharemode_mask
[] = {
174 {FILE_SHARE_READ
, "READ"},
175 {FILE_SHARE_WRITE
, "WRITE"},
176 {FILE_SHARE_DELETE
, "DELETE"},
180 static const struct mask2txt lease_mask
[] = {
181 {SMB2_LEASE_READ
, "READ"},
182 {SMB2_LEASE_WRITE
, "WRITE"},
183 {SMB2_LEASE_HANDLE
, "HANDLE"},
187 int add_profile_item_to_json(struct traverse_state
*state
,
189 const char *subsection
,
193 struct json_object section_json
= {
196 struct json_object subsection_json
= {
201 section_json
= json_get_object(&state
->root_json
, section
);
202 if (json_is_invalid(§ion_json
)) {
205 subsection_json
= json_get_object(§ion_json
, subsection
);
206 if (json_is_invalid(&subsection_json
)) {
210 result
= json_add_int(&subsection_json
, key
, value
);
215 result
= json_update_object(§ion_json
, subsection
, &subsection_json
);
219 result
= json_update_object(&state
->root_json
, section
, §ion_json
);
226 json_free(§ion_json
);
227 json_free(&subsection_json
);
231 int add_section_to_json(struct traverse_state
*state
,
234 struct json_object empty_json
;
237 empty_json
= json_new_object();
238 if (json_is_invalid(&empty_json
)) {
242 result
= json_add_object(&state
->root_json
, key
, &empty_json
);
250 static int add_crypto_to_json(struct json_object
*parent_json
,
253 enum crypto_degree degree
)
255 struct json_object sub_json
;
256 const char *degree_str
;
259 if (degree
== CRYPTO_DEGREE_NONE
) {
261 } else if (degree
== CRYPTO_DEGREE_ANONYMOUS
) {
262 degree_str
= "anonymous";
263 } else if (degree
== CRYPTO_DEGREE_PARTIAL
) {
264 degree_str
= "partial";
269 sub_json
= json_new_object();
270 if (json_is_invalid(&sub_json
)) {
274 result
= json_add_string(&sub_json
, "cipher", cipher
);
278 result
= json_add_string(&sub_json
, "degree", degree_str
);
282 result
= json_add_object(parent_json
, key
, &sub_json
);
289 json_free(&sub_json
);
293 static int add_channel_to_json(struct json_object
*parent_json
,
294 const struct smbXsrv_channel_global0
*channel
)
296 TALLOC_CTX
*frame
= talloc_stackframe();
297 struct json_object sub_json
;
300 struct timeval_buf tv_buf
;
301 char *time_str
= NULL
;
304 sub_json
= json_new_object();
305 if (json_is_invalid(&sub_json
)) {
309 id_str
= talloc_asprintf(frame
, "%"PRIu64
"", channel
->channel_id
);
310 if (id_str
== NULL
) {
313 result
= json_add_string(&sub_json
, "channel_id", id_str
);
317 nttime_to_timeval(&tv
, channel
->creation_time
);
318 time_str
= timeval_str_buf(&tv
, true, true, &tv_buf
);
319 if (time_str
== NULL
) {
322 result
= json_add_string(&sub_json
, "creation_time", time_str
);
326 result
= json_add_string(&sub_json
, "local_address", channel
->local_address
);
330 result
= json_add_string(&sub_json
, "remote_address", channel
->remote_address
);
335 result
= json_add_object(parent_json
, id_str
, &sub_json
);
343 json_free(&sub_json
);
348 static int add_channels_to_json(struct json_object
*parent_json
,
349 const struct smbXsrv_session_global0
*global
)
351 struct json_object sub_json
;
355 sub_json
= json_new_object();
356 if (json_is_invalid(&sub_json
)) {
360 for (i
= 0; i
< global
->num_channels
; i
++) {
361 const struct smbXsrv_channel_global0
*c
= &global
->channels
[i
];
363 result
= add_channel_to_json(&sub_json
, c
);
369 result
= json_add_object(parent_json
, "channels", &sub_json
);
376 json_free(&sub_json
);
380 int traverse_connections_json(struct traverse_state
*state
,
381 const struct connections_data
*crec
,
382 const char *encryption_cipher
,
383 enum crypto_degree encryption_degree
,
384 const char *signing_cipher
,
385 enum crypto_degree signing_degree
)
387 struct json_object sub_json
;
388 struct json_object connections_json
;
390 struct timeval_buf tv_buf
;
393 char *sess_id_str
= NULL
;
394 char *tcon_id_str
= NULL
;
396 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
397 if (tmp_ctx
== NULL
) {
401 sub_json
= json_new_object();
402 if (json_is_invalid(&sub_json
)) {
405 connections_json
= json_get_object(&state
->root_json
, "tcons");
406 if (json_is_invalid(&connections_json
)) {
410 result
= json_add_string(&sub_json
, "service", crec
->servicename
);
414 result
= add_server_id_to_json(&sub_json
, crec
->pid
);
418 tcon_id_str
= talloc_asprintf(tmp_ctx
, "%u", crec
->cnum
);
419 if (tcon_id_str
== NULL
) {
422 result
= json_add_string(&sub_json
, "tcon_id", tcon_id_str
);
426 sess_id_str
= talloc_asprintf(tmp_ctx
, "%u", crec
->sess_id
);
427 if (sess_id_str
== NULL
) {
430 result
= json_add_string(&sub_json
, "session_id", sess_id_str
);
434 result
= json_add_string(&sub_json
, "machine", crec
->machine
);
438 nttime_to_timeval(&tv
, crec
->start
);
439 time
= timeval_str_buf(&tv
, true, true, &tv_buf
);
443 result
= json_add_string(&sub_json
, "connected_at", time
);
447 result
= add_crypto_to_json(&sub_json
, "encryption",
448 encryption_cipher
, encryption_degree
);
452 result
= add_crypto_to_json(&sub_json
, "signing",
453 signing_cipher
, signing_degree
);
458 result
= json_add_object(&connections_json
, tcon_id_str
, &sub_json
);
463 result
= json_update_object(&state
->root_json
, "tcons", &connections_json
);
468 TALLOC_FREE(tmp_ctx
);
471 json_free(&sub_json
);
472 TALLOC_FREE(tmp_ctx
);
476 int traverse_sessionid_json(struct traverse_state
*state
,
477 struct sessionid
*session
,
480 const char *encryption_cipher
,
481 enum crypto_degree encryption_degree
,
482 const char *signing_cipher
,
483 enum crypto_degree signing_degree
,
484 const char *connection_dialect
)
486 struct json_object sub_json
;
487 struct json_object session_json
;
491 struct timeval_buf tv_buf
;
492 char *time_str
= NULL
;
494 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
495 if (tmp_ctx
== NULL
) {
499 sub_json
= json_new_object();
500 if (json_is_invalid(&sub_json
)) {
504 session_json
= json_get_object(&state
->root_json
, "sessions");
505 if (json_is_invalid(&session_json
)) {
509 id_str
= talloc_asprintf(tmp_ctx
, "%u", session
->id_num
);
510 result
= json_add_string(&sub_json
, "session_id", id_str
);
514 result
= add_server_id_to_json(&sub_json
, session
->pid
);
518 result
= json_add_int(&sub_json
, "uid", session
->uid
);
522 result
= json_add_int(&sub_json
, "gid", session
->gid
);
526 result
= json_add_string(&sub_json
, "username", uid_str
);
530 result
= json_add_string(&sub_json
, "groupname", gid_str
);
535 nttime_to_timeval(&tv
, session
->global
->creation_time
);
536 time_str
= timeval_str_buf(&tv
, true, true, &tv_buf
);
537 if (time_str
== NULL
) {
540 result
= json_add_string(&sub_json
, "creation_time", time_str
);
545 nttime_to_timeval(&tv
, session
->global
->expiration_time
);
546 time_str
= timeval_str_buf(&tv
, true, true, &tv_buf
);
547 if (time_str
== NULL
) {
550 result
= json_add_string(&sub_json
, "expiration_time", time_str
);
555 nttime_to_timeval(&tv
, session
->global
->auth_time
);
556 time_str
= timeval_str_buf(&tv
, true, true, &tv_buf
);
557 if (time_str
== NULL
) {
560 result
= json_add_string(&sub_json
, "auth_time", time_str
);
565 result
= json_add_string(&sub_json
, "remote_machine", session
->remote_machine
);
569 result
= json_add_string(&sub_json
, "hostname", session
->hostname
);
573 result
= json_add_string(&sub_json
, "session_dialect", connection_dialect
);
577 result
= json_add_guid(&sub_json
,
579 &session
->global
->client_guid
);
583 result
= add_crypto_to_json(&sub_json
, "encryption",
584 encryption_cipher
, encryption_degree
);
588 result
= add_crypto_to_json(&sub_json
, "signing",
589 signing_cipher
, signing_degree
);
594 result
= add_channels_to_json(&sub_json
, session
->global
);
599 result
= json_add_object(&session_json
, id_str
, &sub_json
);
604 result
= json_update_object(&state
->root_json
, "sessions", &session_json
);
609 TALLOC_FREE(tmp_ctx
);
612 json_free(&sub_json
);
613 TALLOC_FREE(tmp_ctx
);
617 static int add_access_mode_to_json(struct json_object
*parent_json
,
620 struct json_object access_json
;
621 char *access_hex
= NULL
;
622 const char *access_str
= NULL
;
625 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
626 if (tmp_ctx
== NULL
) {
630 access_json
= json_new_object();
631 if (json_is_invalid(&access_json
)) {
635 access_hex
= talloc_asprintf(tmp_ctx
, "0x%08x", access_int
);
636 result
= json_add_string(&access_json
, "hex", access_hex
);
640 result
= map_mask_to_json(&access_json
, access_int
, access_mask
);
645 access_str
= talloc_asprintf(tmp_ctx
, "%s%s",
646 (access_int
& FILE_READ_DATA
)?"R":"",
647 (access_int
& (FILE_WRITE_DATA
|FILE_APPEND_DATA
))?"W":"");
648 result
= json_add_string(&access_json
, "text", access_str
);
653 result
= json_add_object(parent_json
, "access_mask", &access_json
);
658 TALLOC_FREE(tmp_ctx
);
661 json_free(&access_json
);
662 TALLOC_FREE(tmp_ctx
);
666 static int add_caching_to_json(struct json_object
*parent_json
,
670 struct json_object caching_json
;
672 char *caching_text
= NULL
;
673 int caching_type
= 0;
676 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
677 if (tmp_ctx
== NULL
) {
681 caching_json
= json_new_object();
682 if (json_is_invalid(&caching_json
)) {
686 if (op_type
& LEASE_OPLOCK
) {
687 caching_type
= lease_type
;
689 if (op_type
& LEVEL_II_OPLOCK
) {
690 caching_type
= SMB2_LEASE_READ
;
691 } else if (op_type
& EXCLUSIVE_OPLOCK
) {
692 caching_type
= SMB2_LEASE_READ
+ SMB2_LEASE_WRITE
;
693 } else if (op_type
& BATCH_OPLOCK
) {
694 caching_type
= SMB2_LEASE_READ
+ SMB2_LEASE_WRITE
+ SMB2_LEASE_HANDLE
;
697 result
= map_mask_to_json(&caching_json
, caching_type
, lease_mask
);
702 hex
= talloc_asprintf(tmp_ctx
, "0x%08x", caching_type
);
706 result
= json_add_string(&caching_json
, "hex", hex
);
711 caching_text
= talloc_asprintf(tmp_ctx
, "%s%s%s",
712 (caching_type
& SMB2_LEASE_READ
)?"R":"",
713 (caching_type
& SMB2_LEASE_WRITE
)?"W":"",
714 (caching_type
& SMB2_LEASE_HANDLE
)?"H":"");
715 if (caching_text
== NULL
) {
719 result
= json_add_string(&caching_json
, "text", caching_text
);
724 result
= json_add_object(parent_json
, "caching", &caching_json
);
729 TALLOC_FREE(tmp_ctx
);
732 json_free(&caching_json
);
733 TALLOC_FREE(tmp_ctx
);
737 static int add_oplock_to_json(struct json_object
*parent_json
,
741 struct json_object oplock_json
;
744 oplock_json
= json_new_object();
745 if (json_is_invalid(&oplock_json
)) {
750 result
= map_mask_to_json(&oplock_json
, op_type
, oplock_mask
);
754 result
= json_add_string(&oplock_json
, "text", op_str
);
760 result
= json_add_object(parent_json
, "oplock", &oplock_json
);
767 json_free(&oplock_json
);
771 static int lease_key_to_str(struct smb2_lease_key lease_key
,
774 uint8_t _buf
[16] = {0};
775 DATA_BLOB blob
= data_blob_const(_buf
, sizeof(_buf
));
780 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
781 if (tmp_ctx
== NULL
) {
785 PUSH_LE_U64(_buf
, 0, lease_key
.data
[0]);
786 PUSH_LE_U64(_buf
, 8, lease_key
.data
[1]);
788 status
= GUID_from_ndr_blob(&blob
, &guid
);
789 if (!NT_STATUS_IS_OK(status
)) {
792 tmp
= GUID_string(tmp_ctx
, &guid
);
796 fstrcpy(lease_str
, tmp
);
798 TALLOC_FREE(tmp_ctx
);
801 TALLOC_FREE(tmp_ctx
);
805 static int add_lease_to_json(struct json_object
*parent_json
,
807 struct smb2_lease_key lease_key
,
810 struct json_object lease_json
;
811 char *lease_hex
= NULL
;
812 char *lease_text
= NULL
;
813 fstring lease_key_str
;
816 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
817 if (tmp_ctx
== NULL
) {
821 lease_json
= json_new_object();
822 if (json_is_invalid(&lease_json
)) {
828 result
= lease_key_to_str(lease_key
, lease_key_str
);
832 result
= json_add_string(&lease_json
, "lease_key", lease_key_str
);
836 lease_hex
= talloc_asprintf(tmp_ctx
, "0x%08x", lease_type
);
837 result
= json_add_string(&lease_json
, "hex", lease_hex
);
841 if (lease_type
> (SMB2_LEASE_WRITE
+ SMB2_LEASE_HANDLE
+ SMB2_LEASE_READ
)) {
842 result
= json_add_bool(&lease_json
, "UNKNOWN", true);
847 result
= map_mask_to_json(&lease_json
, lease_type
, lease_mask
);
852 lease_text
= talloc_asprintf(tmp_ctx
, "%s%s%s",
853 (lease_type
& SMB2_LEASE_READ
)?"R":"",
854 (lease_type
& SMB2_LEASE_WRITE
)?"W":"",
855 (lease_type
& SMB2_LEASE_HANDLE
)?"H":"");
857 result
= json_add_string(&lease_json
, "text", lease_text
);
863 result
= json_add_object(parent_json
, "lease", &lease_json
);
868 TALLOC_FREE(tmp_ctx
);
871 json_free(&lease_json
);
872 TALLOC_FREE(tmp_ctx
);
876 static int add_sharemode_to_json(struct json_object
*parent_json
,
879 struct json_object sharemode_json
;
884 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
885 if (tmp_ctx
== NULL
) {
889 sharemode_json
= json_new_object();
890 if (json_is_invalid(&sharemode_json
)) {
894 hex
= talloc_asprintf(tmp_ctx
, "0x%08x", sharemode
);
898 result
= json_add_string(&sharemode_json
, "hex", hex
);
902 result
= map_mask_to_json(&sharemode_json
, sharemode
, sharemode_mask
);
907 text
= talloc_asprintf(tmp_ctx
, "%s%s%s",
908 (sharemode
& FILE_SHARE_READ
)?"R":"",
909 (sharemode
& FILE_SHARE_WRITE
)?"W":"",
910 (sharemode
& FILE_SHARE_DELETE
)?"D":"");
914 result
= json_add_string(&sharemode_json
, "text", text
);
919 result
= json_add_object(parent_json
, "sharemode", &sharemode_json
);
924 TALLOC_FREE(tmp_ctx
);
927 json_free(&sharemode_json
);
928 TALLOC_FREE(tmp_ctx
);
932 static int add_open_to_json(struct json_object
*parent_json
,
933 const struct share_mode_entry
*e
,
939 struct json_object sub_json
= {
942 struct json_object opens_json
= {
945 struct timeval_buf tv_buf
;
948 bool add_lease
= false;
950 char *share_file_id
= NULL
;
952 struct server_id_buf tmp
;
954 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
955 if (tmp_ctx
== NULL
) {
959 opens_json
= json_get_object(parent_json
, "opens");
960 if (json_is_invalid(&opens_json
)) {
963 sub_json
= json_new_object();
964 if (json_is_invalid(&sub_json
)) {
969 result
= add_server_id_to_json(&sub_json
, e
->pid
);
974 result
= json_add_string(&sub_json
, "username", uid_str
);
979 result
= json_add_int(&sub_json
, "uid", e
->uid
);
983 share_file_id
= talloc_asprintf(tmp_ctx
, "%"PRIu64
, e
->share_file_id
);
984 result
= json_add_string(&sub_json
, "share_file_id", share_file_id
);
988 result
= add_sharemode_to_json(&sub_json
, e
->share_access
);
992 result
= add_access_mode_to_json(&sub_json
, e
->access_mask
);
996 result
= add_caching_to_json(&sub_json
, e
->op_type
, lease_type
);
1000 result
= add_oplock_to_json(&sub_json
, e
->op_type
, op_str
);
1004 add_lease
= e
->op_type
& LEASE_OPLOCK
;
1005 result
= add_lease_to_json(&sub_json
, lease_type
, e
->lease_key
, add_lease
);
1010 timestr
= timeval_str_buf(&e
->time
, true, true, &tv_buf
);
1011 if (timestr
== NULL
) {
1014 result
= json_add_string(&sub_json
, "opened_at", timestr
);
1019 pid
= server_id_str_buf(e
->pid
, &tmp
);
1020 key
= talloc_asprintf(tmp_ctx
, "%s/%"PRIu64
, pid
, e
->share_file_id
);
1021 result
= json_add_object(&opens_json
, key
, &sub_json
);
1025 result
= json_update_object(parent_json
, "opens", &opens_json
);
1030 TALLOC_FREE(tmp_ctx
);
1033 json_free(&opens_json
);
1034 json_free(&sub_json
);
1035 TALLOC_FREE(tmp_ctx
);
1039 static int add_fileid_to_json(struct json_object
*parent_json
,
1042 struct json_object fid_json
;
1045 fid_json
= json_new_object();
1046 if (json_is_invalid(&fid_json
)) {
1050 result
= json_add_int(&fid_json
, "devid", fid
.devid
);
1054 result
= json_add_int(&fid_json
, "inode", fid
.inode
);
1058 result
= json_add_int(&fid_json
, "extid", fid
.extid
);
1063 result
= json_add_object(parent_json
, "fileid", &fid_json
);
1070 json_free(&fid_json
);
1074 int print_share_mode_json(struct traverse_state
*state
,
1075 const struct share_mode_data
*d
,
1076 const struct share_mode_entry
*e
,
1078 const char *uid_str
,
1080 uint32_t lease_type
,
1081 const char *filename
)
1083 struct json_object locks_json
= {
1086 struct json_object file_json
= {
1092 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1093 if (tmp_ctx
== NULL
) {
1097 if (d
->servicepath
[strlen(d
->servicepath
)-1] == '/') {
1098 key
= talloc_asprintf(tmp_ctx
, "%s%s", d
->servicepath
, filename
);
1100 key
= talloc_asprintf(tmp_ctx
, "%s/%s", d
->servicepath
, filename
);
1103 locks_json
= json_get_object(&state
->root_json
, "open_files");
1104 if (json_is_invalid(&locks_json
)) {
1107 file_json
= json_get_object(&locks_json
, key
);
1108 if (json_is_invalid(&file_json
)) {
1112 result
= json_add_string(&file_json
, "service_path", d
->servicepath
);
1116 result
= json_add_string(&file_json
, "filename", filename
);
1120 result
= add_fileid_to_json(&file_json
, fid
);
1124 result
= json_add_int(&file_json
, "num_pending_deletes", d
->num_delete_tokens
);
1129 result
= add_open_to_json(&file_json
,
1131 state
->resolve_uids
,
1139 result
= json_update_object(&locks_json
, key
, &file_json
);
1143 result
= json_update_object(&state
->root_json
, "open_files", &locks_json
);
1148 TALLOC_FREE(tmp_ctx
);
1151 json_free(&file_json
);
1152 json_free(&locks_json
);
1153 TALLOC_FREE(tmp_ctx
);
1157 static int add_lock_to_json(struct json_object
*parent_json
,
1158 struct server_id server_id
,
1160 enum brl_flavour flavour
,
1164 struct json_object sub_json
= {
1167 struct json_object locks_json
= {
1170 const char *flavour_str
;
1173 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1174 if (tmp_ctx
== NULL
) {
1178 locks_json
= json_get_array(parent_json
, "locks");
1179 if (json_is_invalid(&locks_json
)) {
1182 sub_json
= json_new_object();
1183 if (json_is_invalid(&sub_json
)) {
1187 result
= add_server_id_to_json(&sub_json
, server_id
);
1191 result
= json_add_string(&sub_json
, "type", type
);
1195 flavour_str
= talloc_asprintf(tmp_ctx
, "%s%s",
1196 (flavour
== WINDOWS_LOCK
)?"Windows":"",
1197 (flavour
== POSIX_LOCK
)?"Posix":"");
1198 result
= json_add_string(&sub_json
, "flavour", flavour_str
);
1202 result
= json_add_int(&sub_json
, "start", start
);
1206 result
= json_add_int(&sub_json
, "size", size
);
1211 result
= json_add_object(&locks_json
, NULL
, &sub_json
);
1215 result
= json_update_object(parent_json
, "locks", &locks_json
);
1220 TALLOC_FREE(tmp_ctx
);
1223 json_free(&locks_json
);
1224 json_free(&sub_json
);
1225 TALLOC_FREE(tmp_ctx
);
1229 int print_brl_json(struct traverse_state
*state
,
1230 const struct server_id server_id
,
1233 enum brl_flavour flavour
,
1236 const char *sharepath
,
1237 const char *filename
)
1239 struct json_object file_json
= {
1242 struct json_object brl_json
= {
1248 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1249 if (tmp_ctx
== NULL
) {
1253 if (sharepath
[strlen(sharepath
)-1] == '/') {
1254 key
= talloc_asprintf(tmp_ctx
, "%s%s", sharepath
, filename
);
1256 key
= talloc_asprintf(tmp_ctx
, "%s/%s", sharepath
, filename
);
1262 brl_json
= json_get_object(&state
->root_json
, "byte_range_locks");
1263 if (json_is_invalid(&brl_json
)) {
1266 file_json
= json_get_object(&brl_json
, key
);
1267 if (json_is_invalid(&file_json
)) {
1271 result
= add_fileid_to_json(&file_json
, fid
);
1275 result
= json_add_string(&file_json
, "file_name", filename
);
1279 result
= json_add_string(&file_json
, "share_path", sharepath
);
1283 result
= add_server_id_to_json(&file_json
, server_id
);
1287 result
= add_lock_to_json(&file_json
, server_id
, type
, flavour
, start
, size
);
1292 result
= json_add_object(&brl_json
, key
, &file_json
);
1296 result
= json_update_object(&state
->root_json
, "byte_range_locks", &brl_json
);
1301 TALLOC_FREE(tmp_ctx
);
1304 json_free(&file_json
);
1305 json_free(&brl_json
);
1306 TALLOC_FREE(tmp_ctx
);
1310 bool print_notify_rec_json(struct traverse_state
*state
,
1311 const struct notify_instance
*instance
,
1312 const struct server_id server_id
,
1315 struct json_object sub_json
;
1316 struct json_object notify_json
;
1317 char *filter
= NULL
;
1318 char *subdir_filter
= NULL
;
1319 struct timeval_buf tv_buf
;
1323 struct server_id_buf tmp
;
1326 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1327 if (tmp_ctx
== NULL
) {
1331 sub_json
= json_new_object();
1332 if (json_is_invalid(&sub_json
)) {
1335 notify_json
= json_get_object(&state
->root_json
, "notifies");
1336 if (json_is_invalid(¬ify_json
)) {
1340 result
= add_server_id_to_json(&sub_json
, server_id
);
1344 result
= json_add_string(&sub_json
, "path", path
);
1348 filter
= talloc_asprintf(tmp_ctx
, "%u", instance
->filter
);
1349 if (filter
== NULL
) {
1352 result
= json_add_string(&sub_json
, "filter", filter
);
1356 subdir_filter
= talloc_asprintf(tmp_ctx
, "%u", instance
->subdir_filter
);
1357 if (subdir_filter
== NULL
) {
1360 result
= json_add_string(&sub_json
, "subdir_filter", subdir_filter
);
1364 val
= convert_timespec_to_timeval(instance
->creation_time
);
1365 time
= timeval_str_buf(&val
, true, true, &tv_buf
);
1366 result
= json_add_string(&sub_json
, "creation_time", time
);
1371 pid
= server_id_str_buf(server_id
, &tmp
);
1372 result
= json_add_object(¬ify_json
, pid
, &sub_json
);
1377 result
= json_update_object(&state
->root_json
, "notifies", ¬ify_json
);
1382 TALLOC_FREE(tmp_ctx
);
1385 json_free(&sub_json
);
1386 TALLOC_FREE(tmp_ctx
);