1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 1997 Peter Wemm.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed for the FreeBSD Project
18 *	by Peter Wemm.
19 * 4. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * so there!
35 */
36
37#pragma once
38
39#include <libifconfig.h>
40#include <stdbool.h>
41#include <net/if_types.h>
42
43#define	__constructor	__attribute__((constructor))
44
45#ifdef WITHOUT_NETLINK
46#define	__netlink_used		__unused
47#define	__netlink_unused
48#else
49#define	__netlink_used
50#define	__netlink_unused	__unused
51#endif
52
53struct afswtch;
54struct cmd;
55struct snl_state;
56struct ifconfig_args;
57struct ifconfig_context {
58	struct ifconfig_args	*args;
59	const struct afswtch	*afp;
60	int			io_s;		/* fd to use for ioctl() */
61	struct snl_state	*io_ss;		/* NETLINK_ROUTE socket */
62	const char		*ifname;	/* Current interface name */
63	char			_ifname_storage_ioctl[IFNAMSIZ];
64};
65typedef struct ifconfig_context if_ctx;
66
67typedef	void c_func(if_ctx *ctx, const char *cmd, int arg);
68typedef	void c_func2(if_ctx *ctx, const char *arg1, const char *arg2);
69typedef	void c_func3(if_ctx *ctx, const char *cmd, const char *arg);
70
71struct cmd {
72	const char *c_name;
73	int	c_parameter;
74#define	NEXTARG		0xffffff	/* has following arg */
75#define	NEXTARG2	0xfffffe	/* has 2 following args */
76#define	OPTARG		0xfffffd	/* has optional following arg */
77#define	SPARAM		0xfffffc	/* parameter is string c_sparameter */
78	const char *c_sparameter;
79	union {
80		c_func	*c_func;
81		c_func2	*c_func2;
82		c_func3	*c_func3;
83	} c_u;
84	int	c_iscloneop;
85	struct cmd *c_next;
86};
87void	cmd_register(struct cmd *);
88
89typedef	void callback_func(if_ctx *, void *);
90void	callback_register(callback_func *, void *);
91
92/*
93 * Macros for initializing command handlers.
94 */
95
96#define	DEF_CMD(name, param, func) {		\
97    .c_name = (name),				\
98    .c_parameter = (param),			\
99    .c_u = { .c_func = (func) },		\
100    .c_iscloneop = 0,				\
101    .c_next = NULL,				\
102}
103#define	DEF_CMD_ARG(name, func) {		\
104    .c_name = (name),				\
105    .c_parameter = NEXTARG,			\
106    .c_u = { .c_func = (func) },		\
107    .c_iscloneop = 0,				\
108    .c_next = NULL,				\
109}
110#define	DEF_CMD_OPTARG(name, func) {		\
111    .c_name = (name),				\
112    .c_parameter = OPTARG,			\
113    .c_u = { .c_func = (func) },		\
114    .c_iscloneop = 0,				\
115    .c_next = NULL,				\
116}
117#define	DEF_CMD_ARG2(name, func) {		\
118    .c_name = (name),				\
119    .c_parameter = NEXTARG2,			\
120    .c_u = { .c_func2 = (func) },		\
121    .c_iscloneop = 0,				\
122    .c_next = NULL,				\
123}
124#define	DEF_CMD_SARG(name, sparam, func) {	\
125    .c_name = (name),				\
126    .c_parameter = SPARAM,			\
127    .c_sparameter = (sparam),			\
128    .c_u = { .c_func3 = (func) },		\
129    .c_iscloneop = 0,				\
130    .c_next = NULL,				\
131}
132#define	DEF_CLONE_CMD(name, param, func) {	\
133    .c_name = (name),				\
134    .c_parameter = (param),			\
135    .c_u = { .c_func = (func) },		\
136    .c_iscloneop = 1,				\
137    .c_next = NULL,				\
138}
139#define	DEF_CLONE_CMD_ARG(name, func) {		\
140    .c_name = (name),				\
141    .c_parameter = NEXTARG,			\
142    .c_u = { .c_func = (func) },		\
143    .c_iscloneop = 1,				\
144    .c_next = NULL,				\
145}
146#define	DEF_CLONE_CMD_ARG2(name, func) {	\
147    .c_name = (name),				\
148    .c_parameter = NEXTARG2,			\
149    .c_u = { .c_func2 = (func) },		\
150    .c_iscloneop = 1,				\
151    .c_next = NULL,				\
152}
153
154#define	ioctl_ctx(ctx, _req, ...)	ioctl((ctx)->io_s, _req, ## __VA_ARGS__)
155int ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr);
156
157struct ifaddrs;
158struct addrinfo;
159
160enum {
161	RIDADDR = 0,
162	ADDR = 1,
163	MASK = 2,
164	DSTADDR = 3,
165#ifdef WITHOUT_NETLINK
166	BRDADDR = 3,
167#else
168	BRDADDR = 4,
169#endif
170};
171
172struct snl_parsed_addr;
173struct snl_parsed_link;
174typedef struct snl_parsed_link if_link_t;
175typedef struct snl_parsed_addr if_addr_t;
176
177typedef void af_setvhid_f(int vhid);
178typedef	void af_status_nl_f(if_ctx *ctx, if_link_t *link, if_addr_t *ifa);
179typedef void af_status_f(if_ctx *ctx, const struct ifaddrs *);
180typedef void af_other_status_f(if_ctx *ctx);
181typedef void af_postproc_f(if_ctx *ctx, int newaddr, int ifflags);
182typedef	int af_exec_f(if_ctx *ctx, unsigned long action, void *data);
183typedef void af_copyaddr_f(if_ctx *ctx, int to, int from);
184typedef void af_status_tunnel_f(if_ctx *ctx);
185typedef void af_settunnel_f(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres);
186
187struct afswtch {
188	const char	*af_name;	/* as given on cmd line, e.g. "inet" */
189	short		af_af;		/* AF_* */
190	/*
191	 * Status is handled one of two ways; if there is an
192	 * address associated with the interface then the
193	 * associated address family af_status method is invoked
194	 * with the appropriate addressin info.  Otherwise, if
195	 * all possible info is to be displayed and af_other_status
196	 * is defined then it is invoked after all address status
197	 * is presented.
198	 */
199#ifndef WITHOUT_NETLINK
200	af_status_nl_f	*af_status;
201#else
202	af_status_f	*af_status;
203#endif
204	af_other_status_f	*af_other_status;
205	void		(*af_getaddr)(const char *, int);
206	af_copyaddr_f	*af_copyaddr;	/* Copy address between <RID|*>ADDR */
207					/* parse prefix method (IPv6) */
208	void		(*af_getprefix)(const char *, int);
209	af_postproc_f	*af_postproc;
210	af_setvhid_f	*af_setvhid;	/* Set CARP vhid for an address */
211	af_exec_f	*af_exec;	/* Handler to interact with kernel */
212	u_long		af_difaddr;	/* set dst if address ioctl */
213	u_long		af_aifaddr;	/* set if address ioctl */
214	void		*af_ridreq;	/* */
215	void		*af_addreq;	/* */
216	struct afswtch	*af_next;
217
218	/* XXX doesn't fit model */
219	af_status_tunnel_f	*af_status_tunnel;
220	af_settunnel_f	*af_settunnel;
221};
222void	af_register(struct afswtch *);
223int	af_exec_ioctl(if_ctx *ctx, unsigned long action, void *data);
224
225struct ifconfig_args {
226	bool all;		/* Match everything */
227	bool downonly;		/* Down-only items */
228	bool uponly;		/* Up-only items */
229	bool namesonly;		/* Output only names */
230	bool noload;		/* Do not load relevant kernel modules */
231	bool supmedia;		/* Supported media */
232	bool printkeys;		/* Print security keys */
233	bool allfamilies;	/* Print all families */
234	bool drivername;	/* Print driver name */
235	int verbose;		/* verbosity level */
236	int argc;
237	char **argv;
238	const char *ifname;	/* Requested interface name */
239	const char *matchgroup;		/* Group name to match */
240	const char *nogroup;		/* Group name to exclude */
241	const struct afswtch *afp;	/* AF we're operating on */
242	const char *jail_name;	/* Jail name or jail id specified */
243};
244
245struct option {
246	const char *opt;
247	const char *opt_usage;
248	void	(*cb)(const char *arg);
249	struct option *next;
250};
251void	opt_register(struct option *);
252
253extern	ifconfig_handle_t *lifh;
254extern	int allmedia;
255extern	int exit_code;
256extern	char *f_inet, *f_inet6, *f_ether, *f_addr;
257
258void	clearifcap(if_ctx *ctx, const char *, int value);
259void	setifcap(if_ctx *ctx, const char *, int value);
260void	setifcapnv(if_ctx *ctx, const char *vname, const char *arg);
261
262void	Perror(const char *cmd);
263void	print_bits(const char *btype, uint32_t *v, const int v_count,
264		const char **names, const int n_count);
265void	printb(const char *s, unsigned value, const char *bits);
266
267void	ifmaybeload(struct ifconfig_args *args, const char *name);
268
269typedef int  clone_match_func(const char *);
270typedef void clone_callback_func(if_ctx *, struct ifreq *);
271void	clone_setdefcallback_prefix(const char *, clone_callback_func *);
272void	clone_setdefcallback_filter(clone_match_func *, clone_callback_func *);
273
274void	sfp_status(if_ctx *ctx);
275
276struct sockaddr_dl;
277bool	match_ether(const struct sockaddr_dl *sdl);
278bool	match_if_flags(struct ifconfig_args *args, int if_flags);
279int	ifconfig_ioctl(if_ctx *ctx, int iscreate, const struct afswtch *uafp);
280bool	group_member(const char *ifname, const char *match, const char *nomatch);
281void	tunnel_status(if_ctx *ctx);
282struct afswtch	*af_getbyfamily(int af);
283void	af_other_status(if_ctx *ctx);
284void	print_ifstatus(if_ctx *ctx);
285void	print_metric(if_ctx *ctx);
286ifType	convert_iftype(ifType iftype);
287
288/* Netlink-related functions */
289void	list_interfaces_nl(struct ifconfig_args *args);
290int	ifconfig_nl(if_ctx *ctx, int iscreate,
291		const struct afswtch *uafp);
292uint32_t if_nametoindex_nl(struct snl_state *ss, const char *ifname);
293
294/*
295 * XXX expose this so modules that need to know of any pending
296 * operations on ifmedia can avoid cmd line ordering confusion.
297 */
298struct ifmediareq *ifmedia_getstate(if_ctx *ctx);
299
300void print_vhid(const struct ifaddrs *);
301
302void ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr);
303
304/* Helpers */
305struct sockaddr_in;
306struct sockaddr_in6;
307struct sockaddr;
308
309static inline struct sockaddr_in6 *
310satosin6(struct sockaddr *sa)
311{
312	return ((struct sockaddr_in6 *)(void *)sa);
313}
314
315static inline struct sockaddr_in *
316satosin(struct sockaddr *sa)
317{
318	return ((struct sockaddr_in *)(void *)sa);
319}
320
321static inline struct sockaddr_dl *
322satosdl(struct sockaddr *sa)
323{
324	return ((struct sockaddr_dl *)(void *)sa);
325}
326
327static inline const struct sockaddr_dl *
328satosdl_c(const struct sockaddr *sa)
329{
330	return ((const struct sockaddr_dl *)(const void *)sa);
331}
332