1/*-
2 * Copyright (c) 2014 Gleb Kurtsou <gleb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <sys/param.h>
33#include <sys/user.h>
34#include <sys/socket.h>
35#include <string.h>
36
37#include "libprocstat.h"
38
39#define	SPECNAMELEN_COMPAT12	63
40
41struct freebsd11_ptsstat {
42	uint32_t	dev;
43	char		devname[SPECNAMELEN_COMPAT12 + 1];
44};
45
46struct freebsd11_vnstat {
47	uint64_t	vn_fileid;
48	uint64_t	vn_size;
49	char		*vn_mntdir;
50	uint32_t	vn_dev;
51	uint32_t	vn_fsid;
52	int		vn_type;
53	uint16_t	vn_mode;
54	char		vn_devname[SPECNAMELEN_COMPAT12 + 1];
55};
56struct freebsd11_semstat {
57	uint32_t	value;
58	uint16_t	mode;
59};
60struct freebsd11_shmstat {
61	uint64_t	size;
62	uint16_t	mode;
63};
64
65struct freebsd11_sockstat {
66	uint64_t	inp_ppcb;
67	uint64_t	so_addr;
68	uint64_t	so_pcb;
69	uint64_t	unp_conn;
70	int		dom_family;
71	int		proto;
72	int		so_rcv_sb_state;
73	int		so_snd_sb_state;
74	struct sockaddr_storage	sa_local;	/* Socket address. */
75	struct sockaddr_storage	sa_peer;	/* Peer address. */
76	int		type;
77	char		dname[32];
78};
79
80struct freebsd12_vnstat {
81	uint64_t	vn_fileid;
82	uint64_t	vn_size;
83	uint64_t	vn_dev;
84	uint64_t	vn_fsid;
85	char		*vn_mntdir;
86	int		vn_type;
87	uint16_t	vn_mode;
88	char		vn_devname[SPECNAMELEN_COMPAT12 + 1];
89};
90struct freebsd12_ptsstat {
91	uint64_t	dev;
92	char		devname[SPECNAMELEN_COMPAT12 + 1];
93};
94
95int	freebsd11_procstat_get_pts_info(struct procstat *procstat,
96    struct filestat *fst, struct freebsd11_ptsstat *pts, char *errbuf);
97int	freebsd12_procstat_get_pts_info(struct procstat *procstat,
98    struct filestat *fst, struct freebsd12_ptsstat *pts_compat, char *errbuf);
99int	freebsd11_procstat_get_sem_info(struct procstat *procstat,
100    struct filestat *fst, struct freebsd11_semstat *sem, char *errbuf);
101int	freebsd11_procstat_get_shm_info(struct procstat *procstat,
102    struct filestat *fst, struct freebsd11_shmstat *shm, char *errbuf);
103int	freebsd11_procstat_get_socket_info(struct procstat *procstat,
104    struct filestat *fst, struct freebsd11_sockstat *sock, char *errbuf);
105int	freebsd11_procstat_get_vnode_info(struct procstat *procstat,
106    struct filestat *fst, struct freebsd11_vnstat *vn, char *errbuf);
107int	freebsd12_procstat_get_vnode_info(struct procstat *procstat,
108    struct filestat *fst, struct freebsd12_vnstat *vn_compat, char *errbuf);
109
110static const char trunc_name[] = "<TRUNCATED>";
111
112int
113freebsd11_procstat_get_pts_info(struct procstat *procstat,
114    struct filestat *fst, struct freebsd11_ptsstat *pts_compat, char *errbuf)
115{
116	struct ptsstat pts;
117	int r;
118
119	r = procstat_get_pts_info(procstat, fst, &pts, errbuf);
120	if (r != 0)
121		return (r);
122	pts_compat->dev = pts.dev;
123	if (strlen(pts.devname) >= sizeof(pts_compat->devname))
124		strcpy(pts_compat->devname, trunc_name);
125	else
126		memcpy(pts_compat->devname, pts.devname,
127		    sizeof(pts_compat->devname));
128	return (0);
129}
130
131int
132freebsd12_procstat_get_pts_info(struct procstat *procstat,
133    struct filestat *fst, struct freebsd12_ptsstat *pts_compat, char *errbuf)
134{
135	struct ptsstat pts;
136	int r;
137
138	r = procstat_get_pts_info(procstat, fst, &pts, errbuf);
139	if (r != 0)
140		return (r);
141	pts_compat->dev = pts.dev;
142	if (strlen(pts.devname) >= sizeof(pts_compat->devname))
143		strcpy(pts_compat->devname, trunc_name);
144	else
145		memcpy(pts_compat->devname, pts.devname,
146		    sizeof(pts_compat->devname));
147	return (0);
148}
149
150int
151freebsd11_procstat_get_sem_info(struct procstat *procstat,
152    struct filestat *fst, struct freebsd11_semstat *sem_compat, char *errbuf)
153{
154	struct semstat sem;
155	int r;
156
157	r = procstat_get_sem_info(procstat, fst, &sem, errbuf);
158	if (r != 0)
159		return (r);
160	sem_compat->value = sem.value;
161	sem_compat->mode = sem.mode;
162	return (0);
163}
164
165int
166freebsd11_procstat_get_shm_info(struct procstat *procstat,
167    struct filestat *fst, struct freebsd11_shmstat *shm_compat, char *errbuf)
168{
169	struct shmstat shm;
170	int r;
171
172	r = procstat_get_shm_info(procstat, fst, &shm, errbuf);
173	if (r != 0)
174		return (r);
175	shm_compat->size = shm.size;
176	shm_compat->mode = shm.mode;
177	return (0);
178}
179
180int
181freebsd11_procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
182    struct freebsd11_sockstat *sock_compat, char *errbuf)
183{
184	struct sockstat sock;
185	int r;
186
187	r = procstat_get_socket_info(procstat, fst, &sock, errbuf);
188	if (r != 0)
189		return (r);
190	sock_compat->inp_ppcb = sock.inp_ppcb;
191	sock_compat->so_addr = sock.so_addr;
192	sock_compat->so_pcb = sock.so_pcb;
193	sock_compat->unp_conn = sock.unp_conn;
194	sock_compat->dom_family = sock.dom_family;
195	sock_compat->proto = sock.proto;
196	sock_compat->so_rcv_sb_state = sock.so_rcv_sb_state;
197	sock_compat->so_snd_sb_state = sock.so_snd_sb_state;
198	sock_compat->sa_local = sock.sa_local;
199	sock_compat->sa_peer = sock.sa_peer;
200	sock_compat->type = sock.type;
201	memcpy(sock_compat->dname, sock.dname, sizeof(sock.dname));
202	return (0);
203}
204
205int
206freebsd11_procstat_get_vnode_info(struct procstat *procstat,
207    struct filestat *fst, struct freebsd11_vnstat *vn_compat, char *errbuf)
208{
209	struct vnstat vn;
210	int r;
211
212	r = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
213	if (r != 0)
214		return (r);
215	vn_compat->vn_fileid = vn.vn_fileid;
216	vn_compat->vn_size = vn.vn_size;
217	vn_compat->vn_mntdir = vn.vn_mntdir;
218	vn_compat->vn_dev = vn.vn_dev;
219	vn_compat->vn_fsid = vn.vn_fsid;
220	vn_compat->vn_type = vn.vn_type;
221	vn_compat->vn_mode = vn.vn_mode;
222	if (strlen(vn.vn_devname) >= sizeof(vn_compat->vn_devname))
223		strcpy(vn_compat->vn_devname, trunc_name);
224	else
225		memcpy(vn_compat->vn_devname, vn.vn_devname,
226		    sizeof(vn_compat->vn_devname));
227	return (0);
228}
229
230int
231freebsd12_procstat_get_vnode_info(struct procstat *procstat,
232    struct filestat *fst, struct freebsd12_vnstat *vn_compat, char *errbuf)
233{
234	struct vnstat vn;
235	int r;
236
237	r = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
238	if (r != 0)
239		return (r);
240	vn_compat->vn_fileid = vn.vn_fileid;
241	vn_compat->vn_size = vn.vn_size;
242	vn_compat->vn_mntdir = vn.vn_mntdir;
243	vn_compat->vn_dev = vn.vn_dev;
244	vn_compat->vn_fsid = vn.vn_fsid;
245	vn_compat->vn_type = vn.vn_type;
246	vn_compat->vn_mode = vn.vn_mode;
247	if (strlen(vn.vn_devname) >= sizeof(vn_compat->vn_devname))
248		strcpy(vn_compat->vn_devname, trunc_name);
249	else
250		memcpy(vn_compat->vn_devname, vn.vn_devname,
251		    sizeof(vn_compat->vn_devname));
252	return (0);
253}
254
255__sym_compat(procstat_get_pts_info, freebsd11_procstat_get_pts_info, FBSD_1.2);
256__sym_compat(procstat_get_socket_info, freebsd11_procstat_get_socket_info,
257    FBSD_1.2);
258__sym_compat(procstat_get_vnode_info, freebsd11_procstat_get_vnode_info,
259    FBSD_1.2);
260__sym_compat(procstat_get_sem_info, freebsd11_procstat_get_sem_info, FBSD_1.3);
261__sym_compat(procstat_get_shm_info, freebsd11_procstat_get_shm_info, FBSD_1.3);
262__sym_compat(procstat_get_pts_info, freebsd12_procstat_get_pts_info, FBSD_1.5);
263__sym_compat(procstat_get_vnode_info, freebsd12_procstat_get_vnode_info,
264    FBSD_1.5);
265