]>
Commit | Line | Data |
---|---|---|
2da06d3c MY |
1 | /* |
2 | * lsfd-sock.c - handle associations opening socket objects | |
3 | * | |
4 | * Copyright (C) 2021 Red Hat, Inc. All rights reserved. | |
5 | * Written by Masatake YAMATO <yamato@redhat.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it would be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software Foundation, | |
19 | * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | */ | |
21 | ||
2dfe2e4d MY |
22 | #include <sys/types.h> |
23 | #include <sys/xattr.h> | |
24 | ||
2da06d3c | 25 | #include "lsfd.h" |
ac8be186 | 26 | #include "sock.h" |
2da06d3c | 27 | |
0ee16e43 MY |
28 | static void attach_sock_xinfo(struct file *file) |
29 | { | |
30 | struct sock *sock = (struct sock *)file; | |
046c5d5a | 31 | |
0ee16e43 | 32 | sock->xinfo = get_sock_xinfo(file->stat.st_ino); |
046c5d5a MY |
33 | if (sock->xinfo) { |
34 | struct ipc *ipc = get_ipc(file); | |
35 | if (ipc) | |
36 | add_endpoint(&sock->endpoint, ipc); | |
37 | } | |
38 | } | |
39 | ||
40 | static const struct ipc_class *sock_get_ipc_class(struct file *file) | |
41 | { | |
42 | struct sock *sock = (struct sock *)file; | |
43 | ||
44 | if (sock->xinfo && sock->xinfo->class->get_ipc_class) | |
45 | return sock->xinfo->class->get_ipc_class(sock->xinfo, sock); | |
46 | ||
47 | return NULL; | |
0ee16e43 MY |
48 | } |
49 | ||
2da06d3c | 50 | static bool sock_fill_column(struct proc *proc __attribute__((__unused__)), |
2dfe2e4d | 51 | struct file *file, |
2da06d3c MY |
52 | struct libscols_line *ln, |
53 | int column_id, | |
54 | size_t column_index) | |
55 | { | |
cb6a617d | 56 | char *str = NULL; |
2dfe2e4d | 57 | struct sock *sock = (struct sock *)file; |
f4479119 MY |
58 | |
59 | if (sock->xinfo && sock->xinfo->class | |
60 | && sock->xinfo->class->fill_column) { | |
61 | if (sock->xinfo->class->fill_column(proc, sock->xinfo, sock, ln, | |
62 | column_id, column_index, | |
63 | &str)) | |
64 | goto out; | |
65 | } | |
66 | ||
2da06d3c MY |
67 | switch(column_id) { |
68 | case COL_TYPE: | |
be019f66 MY |
69 | if (!sock->protoname) |
70 | return false; | |
71 | /* FALL THROUGH */ | |
e193602a | 72 | case COL_SOCK_PROTONAME: |
2dfe2e4d MY |
73 | if (sock->protoname) |
74 | if (scols_line_set_data(ln, column_index, sock->protoname)) | |
75 | err(EXIT_FAILURE, _("failed to add output data")); | |
76 | return true; | |
7b50bd25 MY |
77 | case COL_NAME: |
78 | if (sock->xinfo | |
79 | && sock->xinfo->class && sock->xinfo->class->get_name) { | |
b3649945 | 80 | str = sock->xinfo->class->get_name(sock->xinfo, sock); |
7b50bd25 MY |
81 | if (str) |
82 | break; | |
83 | } | |
84 | return false; | |
618db964 | 85 | case COL_SOURCE: |
a500de34 MY |
86 | if (major(file->stat.st_dev) == 0 |
87 | && strncmp(file->name, "socket:", 7) == 0) { | |
e0dc84da | 88 | str = xstrdup("sockfs"); |
a500de34 MY |
89 | break; |
90 | } | |
91 | return false; | |
86a7e471 | 92 | case COL_SOCK_NETNS: |
7b50bd25 MY |
93 | if (sock->xinfo) { |
94 | xasprintf(&str, "%llu", | |
95 | (unsigned long long)sock->xinfo->netns_inode); | |
96 | break; | |
97 | } | |
98 | return false; | |
86a7e471 | 99 | case COL_SOCK_TYPE: |
7b50bd25 MY |
100 | if (sock->xinfo |
101 | && sock->xinfo->class && sock->xinfo->class->get_type) { | |
102 | str = sock->xinfo->class->get_type(sock->xinfo, sock); | |
103 | if (str) | |
104 | break; | |
105 | } | |
106 | return false; | |
86a7e471 | 107 | case COL_SOCK_STATE: |
7b50bd25 MY |
108 | if (sock->xinfo |
109 | && sock->xinfo->class && sock->xinfo->class->get_state) { | |
110 | str = sock->xinfo->class->get_state(sock->xinfo, sock); | |
111 | if (str) | |
112 | break; | |
113 | } | |
114 | return false; | |
86a7e471 | 115 | case COL_SOCK_LISTENING: |
45d61bff MY |
116 | str = xstrdup((sock->xinfo |
117 | && sock->xinfo->class | |
118 | && sock->xinfo->class->get_listening | |
119 | && sock->xinfo->class->get_listening(sock->xinfo, sock)) | |
120 | ? "1" | |
121 | : "0"); | |
122 | break; | |
426ff07f MY |
123 | case COL_SOCK_SHUTDOWN: |
124 | str = xstrdup("??"); | |
125 | break; | |
2da06d3c MY |
126 | default: |
127 | return false; | |
128 | } | |
cb6a617d | 129 | |
f4479119 | 130 | out: |
cb6a617d MY |
131 | if (!str) |
132 | err(EXIT_FAILURE, _("failed to add output data")); | |
133 | if (scols_line_refer_data(ln, column_index, str)) | |
134 | err(EXIT_FAILURE, _("failed to add output data")); | |
135 | return true; | |
2da06d3c MY |
136 | } |
137 | ||
99ce4250 | 138 | static void init_sock_content(struct file *file) |
2dfe2e4d | 139 | { |
f9fa97d3 | 140 | int fd; |
046c5d5a | 141 | struct sock *sock = (struct sock *)file; |
f9fa97d3 KZ |
142 | |
143 | assert(file); | |
f9fa97d3 KZ |
144 | |
145 | fd = file->association; | |
146 | ||
1e9880a8 | 147 | if (fd >= 0 || fd == -ASSOC_MEM || fd == -ASSOC_SHM) { |
34f3fd1a | 148 | char path[PATH_MAX] = {'\0'}; |
2dfe2e4d MY |
149 | char buf[256]; |
150 | ssize_t len; | |
f9fa97d3 | 151 | |
34f3fd1a | 152 | assert(file->proc); |
2dfe2e4d | 153 | |
c0f84bd1 | 154 | if (is_opened_file(file)) |
34f3fd1a | 155 | sprintf(path, "/proc/%d/fd/%d", file->proc->pid, fd); |
99ce4250 | 156 | else |
174ab64a | 157 | sprintf(path, "/proc/%d/map_files/%"PRIx64 "-%" PRIx64, |
34f3fd1a | 158 | file->proc->pid, |
99ce4250 KZ |
159 | file->map_start, |
160 | file->map_end); | |
161 | ||
2dfe2e4d MY |
162 | len = getxattr(path, "system.sockprotoname", buf, sizeof(buf) - 1); |
163 | if (len > 0) { | |
164 | buf[len] = '\0'; | |
165 | sock->protoname = xstrdup(buf); | |
166 | } | |
167 | } | |
046c5d5a MY |
168 | |
169 | init_endpoint(&sock->endpoint); | |
2dfe2e4d MY |
170 | } |
171 | ||
172 | static void free_sock_content(struct file *file) | |
2da06d3c | 173 | { |
2dfe2e4d MY |
174 | struct sock *sock = (struct sock *)file; |
175 | if (sock->protoname) { | |
176 | free(sock->protoname); | |
177 | sock->protoname = NULL; | |
178 | } | |
2da06d3c | 179 | } |
14e16696 | 180 | |
0ee16e43 MY |
181 | static void initialize_sock_class(void) |
182 | { | |
183 | initialize_sock_xinfos(); | |
184 | } | |
185 | ||
186 | static void finalize_sock_class(void) | |
187 | { | |
188 | finalize_sock_xinfos(); | |
189 | } | |
190 | ||
14e16696 MY |
191 | const struct file_class sock_class = { |
192 | .super = &file_class, | |
2dfe2e4d | 193 | .size = sizeof(struct sock), |
14e16696 | 194 | .fill_column = sock_fill_column, |
0ee16e43 | 195 | .attach_xinfo = attach_sock_xinfo, |
f9fa97d3 | 196 | .initialize_content = init_sock_content, |
2dfe2e4d | 197 | .free_content = free_sock_content, |
0ee16e43 MY |
198 | .initialize_class = initialize_sock_class, |
199 | .finalize_class = finalize_sock_class, | |
046c5d5a | 200 | .get_ipc_class = sock_get_ipc_class, |
14e16696 | 201 | }; |