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