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 53 struct afswtch; 54 struct cmd; 55 struct snl_state; 56 struct ifconfig_args; 57 struct 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 }; 65 typedef struct ifconfig_context if_ctx; 66 67 typedef void c_func(if_ctx *ctx, const char *cmd, int arg); 68 typedef void c_func2(if_ctx *ctx, const char *arg1, const char *arg2); 69 typedef void c_func3(if_ctx *ctx, const char *cmd, const char *arg); 70 typedef int c_funcv(if_ctx *ctx, int argc, const char *const *argv); 71 72 struct cmd { 73 const char *c_name; 74 int c_parameter; 75 #define NEXTARG 0xffffff /* has following arg */ 76 #define NEXTARG2 0xfffffe /* has 2 following args */ 77 #define OPTARG 0xfffffd /* has optional following arg */ 78 #define SPARAM 0xfffffc /* parameter is string c_sparameter */ 79 #define ARGVECTOR 0xfffffb /* takes argument vector */ 80 const char *c_sparameter; 81 union { 82 c_func *c_func; 83 c_func2 *c_func2; 84 c_func3 *c_func3; 85 c_funcv *c_funcv; 86 } c_u; 87 int c_iscloneop; 88 struct cmd *c_next; 89 }; 90 void cmd_register(struct cmd *); 91 92 typedef void callback_func(if_ctx *, void *); 93 void callback_register(callback_func *, void *); 94 95 /* 96 * Macros for initializing command handlers. 97 */ 98 99 #define DEF_CMD(name, param, func) { \ 100 .c_name = (name), \ 101 .c_parameter = (param), \ 102 .c_u = { .c_func = (func) }, \ 103 .c_iscloneop = 0, \ 104 .c_next = NULL, \ 105 } 106 #define DEF_CMD_ARG(name, func) { \ 107 .c_name = (name), \ 108 .c_parameter = NEXTARG, \ 109 .c_u = { .c_func = (func) }, \ 110 .c_iscloneop = 0, \ 111 .c_next = NULL, \ 112 } 113 #define DEF_CMD_OPTARG(name, func) { \ 114 .c_name = (name), \ 115 .c_parameter = OPTARG, \ 116 .c_u = { .c_func = (func) }, \ 117 .c_iscloneop = 0, \ 118 .c_next = NULL, \ 119 } 120 #define DEF_CMD_ARG2(name, func) { \ 121 .c_name = (name), \ 122 .c_parameter = NEXTARG2, \ 123 .c_u = { .c_func2 = (func) }, \ 124 .c_iscloneop = 0, \ 125 .c_next = NULL, \ 126 } 127 #define DEF_CMD_VARG(name, func) { \ 128 .c_name = (name), \ 129 .c_parameter = ARGVECTOR, \ 130 .c_u = { .c_funcv = (func) }, \ 131 .c_iscloneop = 0, \ 132 .c_next = NULL, \ 133 } 134 #define DEF_CMD_SARG(name, sparam, func) { \ 135 .c_name = (name), \ 136 .c_parameter = SPARAM, \ 137 .c_sparameter = (sparam), \ 138 .c_u = { .c_func3 = (func) }, \ 139 .c_iscloneop = 0, \ 140 .c_next = NULL, \ 141 } 142 #define DEF_CLONE_CMD(name, param, func) { \ 143 .c_name = (name), \ 144 .c_parameter = (param), \ 145 .c_u = { .c_func = (func) }, \ 146 .c_iscloneop = 1, \ 147 .c_next = NULL, \ 148 } 149 #define DEF_CLONE_CMD_ARG(name, func) { \ 150 .c_name = (name), \ 151 .c_parameter = NEXTARG, \ 152 .c_u = { .c_func = (func) }, \ 153 .c_iscloneop = 1, \ 154 .c_next = NULL, \ 155 } 156 #define DEF_CLONE_CMD_ARG2(name, func) { \ 157 .c_name = (name), \ 158 .c_parameter = NEXTARG2, \ 159 .c_u = { .c_func2 = (func) }, \ 160 .c_iscloneop = 1, \ 161 .c_next = NULL, \ 162 } 163 164 #define ioctl_ctx(ctx, _req, ...) ioctl((ctx)->io_s, _req, ## __VA_ARGS__) 165 int ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr); 166 167 struct ifaddrs; 168 struct addrinfo; 169 170 enum { 171 RIDADDR = 0, 172 ADDR = 1, 173 MASK = 2, 174 DSTADDR = 3, 175 #ifdef WITHOUT_NETLINK 176 BRDADDR = 3, 177 #else 178 BRDADDR = 4, 179 #endif 180 }; 181 182 struct snl_parsed_addr; 183 struct snl_parsed_link; 184 typedef struct snl_parsed_link if_link_t; 185 typedef struct snl_parsed_addr if_addr_t; 186 187 typedef void af_setvhid_f(int vhid); 188 typedef void af_status_nl_f(if_ctx *ctx, if_link_t *link, if_addr_t *ifa); 189 typedef void af_status_f(if_ctx *ctx, const struct ifaddrs *); 190 typedef void af_other_status_f(if_ctx *ctx); 191 typedef void af_postproc_f(if_ctx *ctx, int newaddr, int ifflags); 192 typedef int af_exec_f(if_ctx *ctx, unsigned long action, void *data); 193 typedef void af_copyaddr_f(if_ctx *ctx, int to, int from); 194 typedef void af_status_tunnel_f(if_ctx *ctx); 195 typedef void af_settunnel_f(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres); 196 197 struct afswtch { 198 const char *af_name; /* as given on cmd line, e.g. "inet" */ 199 short af_af; /* AF_* */ 200 /* 201 * Status is handled one of two ways; if there is an 202 * address associated with the interface then the 203 * associated address family af_status method is invoked 204 * with the appropriate addressin info. Otherwise, if 205 * all possible info is to be displayed and af_other_status 206 * is defined then it is invoked after all address status 207 * is presented. 208 */ 209 #ifndef WITHOUT_NETLINK 210 af_status_nl_f *af_status; 211 #else 212 af_status_f *af_status; 213 #endif 214 af_other_status_f *af_other_status; 215 void (*af_getaddr)(const char *, int); 216 af_copyaddr_f *af_copyaddr; /* Copy address between <RID|*>ADDR */ 217 /* parse prefix method (IPv6) */ 218 void (*af_getprefix)(const char *, int); 219 af_postproc_f *af_postproc; 220 af_setvhid_f *af_setvhid; /* Set CARP vhid for an address */ 221 af_exec_f *af_exec; /* Handler to interact with kernel */ 222 u_long af_difaddr; /* set dst if address ioctl */ 223 u_long af_aifaddr; /* set if address ioctl */ 224 void *af_ridreq; /* */ 225 void *af_addreq; /* */ 226 struct afswtch *af_next; 227 228 /* XXX doesn't fit model */ 229 af_status_tunnel_f *af_status_tunnel; 230 af_settunnel_f *af_settunnel; 231 }; 232 void af_register(struct afswtch *); 233 int af_exec_ioctl(if_ctx *ctx, unsigned long action, void *data); 234 235 struct ifconfig_args { 236 bool all; /* Match everything */ 237 bool downonly; /* Down-only items */ 238 bool uponly; /* Up-only items */ 239 bool namesonly; /* Output only names */ 240 bool noload; /* Do not load relevant kernel modules */ 241 bool supmedia; /* Supported media */ 242 bool printkeys; /* Print security keys */ 243 bool allfamilies; /* Print all families */ 244 bool drivername; /* Print driver name */ 245 int verbose; /* verbosity level */ 246 int argc; 247 char **argv; 248 const char *ifname; /* Requested interface name */ 249 const char *matchgroup; /* Group name to match */ 250 const char *nogroup; /* Group name to exclude */ 251 const struct afswtch *afp; /* AF we're operating on */ 252 const char *jail_name; /* Jail name or jail id specified */ 253 }; 254 255 struct option { 256 const char *opt; 257 const char *opt_usage; 258 void (*cb)(const char *arg); 259 struct option *next; 260 }; 261 void opt_register(struct option *); 262 263 extern ifconfig_handle_t *lifh; 264 extern int allmedia; 265 extern int exit_code; 266 extern char *f_inet, *f_inet6, *f_ether, *f_addr; 267 268 void clearifcap(if_ctx *ctx, const char *, int value); 269 void setifcap(if_ctx *ctx, const char *, int value); 270 void setifcapnv(if_ctx *ctx, const char *vname, const char *arg); 271 272 void Perror(const char *cmd); 273 void print_bits(const char *btype, uint32_t *v, const int v_count, 274 const char **names, const int n_count); 275 void printb(const char *s, unsigned value, const char *bits); 276 277 void ifmaybeload(struct ifconfig_args *args, const char *name); 278 279 typedef int clone_match_func(const char *); 280 typedef void clone_callback_func(if_ctx *, struct ifreq *); 281 void clone_setdefcallback_prefix(const char *, clone_callback_func *); 282 void clone_setdefcallback_filter(clone_match_func *, clone_callback_func *); 283 284 void sfp_status(if_ctx *ctx); 285 286 struct sockaddr_dl; 287 bool match_ether(const struct sockaddr_dl *sdl); 288 bool match_if_flags(struct ifconfig_args *args, int if_flags); 289 int ifconfig_ioctl(if_ctx *ctx, int iscreate, const struct afswtch *uafp); 290 bool group_member(const char *ifname, const char *match, const char *nomatch); 291 void tunnel_status(if_ctx *ctx); 292 struct afswtch *af_getbyfamily(int af); 293 void af_other_status(if_ctx *ctx); 294 void print_ifstatus(if_ctx *ctx); 295 void print_metric(if_ctx *ctx); 296 ifType convert_iftype(ifType iftype); 297 298 /* Netlink-related functions */ 299 void list_interfaces_nl(struct ifconfig_args *args); 300 int ifconfig_nl(if_ctx *ctx, int iscreate, 301 const struct afswtch *uafp); 302 uint32_t if_nametoindex_nl(struct snl_state *ss, const char *ifname); 303 304 /* 305 * XXX expose this so modules that need to know of any pending 306 * operations on ifmedia can avoid cmd line ordering confusion. 307 */ 308 struct ifmediareq *ifmedia_getstate(if_ctx *ctx); 309 310 void print_vhid(const struct ifaddrs *); 311 312 void ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr); 313 314 /* Helpers */ 315 struct sockaddr_in; 316 struct sockaddr_in6; 317 struct sockaddr; 318 319 static inline struct sockaddr_in6 * 320 satosin6(struct sockaddr *sa) 321 { 322 return ((struct sockaddr_in6 *)(void *)sa); 323 } 324 325 static inline struct sockaddr_in * 326 satosin(struct sockaddr *sa) 327 { 328 return ((struct sockaddr_in *)(void *)sa); 329 } 330 331 static inline struct sockaddr_dl * 332 satosdl(struct sockaddr *sa) 333 { 334 return ((struct sockaddr_dl *)(void *)sa); 335 } 336 337 static inline const struct sockaddr_dl * 338 satosdl_c(const struct sockaddr *sa) 339 { 340 return ((const struct sockaddr_dl *)(const void *)sa); 341 } 342