1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. 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 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 #include <sys/param.h> 32 #include <sys/ioctl.h> 33 #include <sys/socket.h> 34 #include <sys/sysctl.h> 35 #include <sys/time.h> 36 37 #include <net/if.h> 38 #include <net/if_dl.h> 39 #include <net/if_types.h> 40 #include <net/if_media.h> 41 #include <net/route.h> 42 43 #include <assert.h> 44 #include <ctype.h> 45 #include <err.h> 46 #include <errno.h> 47 #include <fcntl.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 53 #include "libifconfig.h" 54 #include "libifconfig_internal.h" 55 56 57 static struct ifmedia_description *get_toptype_desc(int); 58 static struct ifmedia_type_to_subtype *get_toptype_ttos(int); 59 static struct ifmedia_description *get_subtype_desc(int, 60 struct ifmedia_type_to_subtype *ttos); 61 62 #define IFM_OPMODE(x) \ 63 ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \ 64 IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \ 65 IFM_IEEE80211_MBSS)) 66 #define IFM_IEEE80211_STA 0 67 68 static struct ifmedia_description ifm_type_descriptions[] = 69 IFM_TYPE_DESCRIPTIONS; 70 71 static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = 72 IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; 73 74 static struct ifmedia_description ifm_subtype_ethernet_aliases[] = 75 IFM_SUBTYPE_ETHERNET_ALIASES; 76 77 static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = 78 IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; 79 80 static struct ifmedia_description ifm_subtype_tokenring_descriptions[] = 81 IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; 82 83 static struct ifmedia_description ifm_subtype_tokenring_aliases[] = 84 IFM_SUBTYPE_TOKENRING_ALIASES; 85 86 static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = 87 IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; 88 89 static struct ifmedia_description ifm_subtype_fddi_descriptions[] = 90 IFM_SUBTYPE_FDDI_DESCRIPTIONS; 91 92 static struct ifmedia_description ifm_subtype_fddi_aliases[] = 93 IFM_SUBTYPE_FDDI_ALIASES; 94 95 static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = 96 IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; 97 98 static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = 99 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; 100 101 static struct ifmedia_description ifm_subtype_ieee80211_aliases[] = 102 IFM_SUBTYPE_IEEE80211_ALIASES; 103 104 static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = 105 IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; 106 107 static struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] = 108 IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS; 109 110 static struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] = 111 IFM_SUBTYPE_IEEE80211_MODE_ALIASES; 112 113 static struct ifmedia_description ifm_subtype_atm_descriptions[] = 114 IFM_SUBTYPE_ATM_DESCRIPTIONS; 115 116 static struct ifmedia_description ifm_subtype_atm_aliases[] = 117 IFM_SUBTYPE_ATM_ALIASES; 118 119 static struct ifmedia_description ifm_subtype_atm_option_descriptions[] = 120 IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS; 121 122 static struct ifmedia_description ifm_subtype_shared_descriptions[] = 123 IFM_SUBTYPE_SHARED_DESCRIPTIONS; 124 125 static struct ifmedia_description ifm_subtype_shared_aliases[] = 126 IFM_SUBTYPE_SHARED_ALIASES; 127 128 static struct ifmedia_description ifm_shared_option_descriptions[] = 129 IFM_SHARED_OPTION_DESCRIPTIONS; 130 131 static struct ifmedia_description ifm_shared_option_aliases[] = 132 IFM_SHARED_OPTION_ALIASES; 133 134 struct ifmedia_type_to_subtype { 135 struct { 136 struct ifmedia_description *desc; 137 int alias; 138 } 139 subtypes[5]; 140 struct { 141 struct ifmedia_description *desc; 142 int alias; 143 } 144 options[4]; 145 struct { 146 struct ifmedia_description *desc; 147 int alias; 148 } 149 modes[3]; 150 }; 151 152 /* must be in the same order as IFM_TYPE_DESCRIPTIONS */ 153 static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = 154 { 155 { 156 { 157 { &ifm_subtype_shared_descriptions[0], 0 }, 158 { &ifm_subtype_shared_aliases[0], 1 }, 159 { &ifm_subtype_ethernet_descriptions[0], 0 }, 160 { &ifm_subtype_ethernet_aliases[0], 1 }, 161 { NULL, 0 }, 162 }, 163 { 164 { &ifm_shared_option_descriptions[0], 0 }, 165 { &ifm_shared_option_aliases[0], 1 }, 166 { &ifm_subtype_ethernet_option_descriptions[0], 0 }, 167 { NULL, 0 }, 168 }, 169 { 170 { NULL, 0 }, 171 }, 172 }, 173 { 174 { 175 { &ifm_subtype_shared_descriptions[0], 0 }, 176 { &ifm_subtype_shared_aliases[0], 1 }, 177 { &ifm_subtype_tokenring_descriptions[0], 0 }, 178 { &ifm_subtype_tokenring_aliases[0], 1 }, 179 { NULL, 0 }, 180 }, 181 { 182 { &ifm_shared_option_descriptions[0], 0 }, 183 { &ifm_shared_option_aliases[0], 1 }, 184 { &ifm_subtype_tokenring_option_descriptions[0], 0 }, 185 { NULL, 0 }, 186 }, 187 { 188 { NULL, 0 }, 189 }, 190 }, 191 { 192 { 193 { &ifm_subtype_shared_descriptions[0], 0 }, 194 { &ifm_subtype_shared_aliases[0], 1 }, 195 { &ifm_subtype_fddi_descriptions[0], 0 }, 196 { &ifm_subtype_fddi_aliases[0], 1 }, 197 { NULL, 0 }, 198 }, 199 { 200 { &ifm_shared_option_descriptions[0], 0 }, 201 { &ifm_shared_option_aliases[0], 1 }, 202 { &ifm_subtype_fddi_option_descriptions[0], 0 }, 203 { NULL, 0 }, 204 }, 205 { 206 { NULL, 0 }, 207 }, 208 }, 209 { 210 { 211 { &ifm_subtype_shared_descriptions[0], 0 }, 212 { &ifm_subtype_shared_aliases[0], 1 }, 213 { &ifm_subtype_ieee80211_descriptions[0], 0 }, 214 { &ifm_subtype_ieee80211_aliases[0], 1 }, 215 { NULL, 0 }, 216 }, 217 { 218 { &ifm_shared_option_descriptions[0], 0 }, 219 { &ifm_shared_option_aliases[0], 1 }, 220 { &ifm_subtype_ieee80211_option_descriptions[0], 0 }, 221 { NULL, 0 }, 222 }, 223 { 224 { &ifm_subtype_ieee80211_mode_descriptions[0], 0 }, 225 { &ifm_subtype_ieee80211_mode_aliases[0], 0 }, 226 { NULL, 0 }, 227 }, 228 }, 229 { 230 { 231 { &ifm_subtype_shared_descriptions[0], 0 }, 232 { &ifm_subtype_shared_aliases[0], 1 }, 233 { &ifm_subtype_atm_descriptions[0], 0 }, 234 { &ifm_subtype_atm_aliases[0], 1 }, 235 { NULL, 0 }, 236 }, 237 { 238 { &ifm_shared_option_descriptions[0], 0 }, 239 { &ifm_shared_option_aliases[0], 1 }, 240 { &ifm_subtype_atm_option_descriptions[0], 0 }, 241 { NULL, 0 }, 242 }, 243 { 244 { NULL, 0 }, 245 }, 246 }, 247 }; 248 249 static struct ifmedia_description * 250 get_toptype_desc(int ifmw) 251 { 252 struct ifmedia_description *desc; 253 254 for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++) { 255 if (IFM_TYPE(ifmw) == desc->ifmt_word) { 256 break; 257 } 258 } 259 260 return (desc); 261 } 262 263 static struct ifmedia_type_to_subtype * 264 get_toptype_ttos(int ifmw) 265 { 266 struct ifmedia_description *desc; 267 struct ifmedia_type_to_subtype *ttos; 268 269 for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; 270 desc->ifmt_string != NULL; desc++, ttos++) { 271 if (IFM_TYPE(ifmw) == desc->ifmt_word) { 272 break; 273 } 274 } 275 276 return (ttos); 277 } 278 279 static struct ifmedia_description * 280 get_subtype_desc(int ifmw, 281 struct ifmedia_type_to_subtype *ttos) 282 { 283 int i; 284 struct ifmedia_description *desc; 285 286 for (i = 0; ttos->subtypes[i].desc != NULL; i++) { 287 if (ttos->subtypes[i].alias) { 288 continue; 289 } 290 for (desc = ttos->subtypes[i].desc; 291 desc->ifmt_string != NULL; desc++) { 292 if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) { 293 return (desc); 294 } 295 } 296 } 297 298 return (NULL); 299 } 300 301 const char * 302 ifconfig_media_get_type(int ifmw) 303 { 304 struct ifmedia_description *desc; 305 306 /*int seen_option = 0, i;*/ 307 308 /* Find the top-level interface type. */ 309 desc = get_toptype_desc(ifmw); 310 if (desc->ifmt_string == NULL) { 311 return ("<unknown type>"); 312 } else { 313 return (desc->ifmt_string); 314 } 315 } 316 317 const char * 318 ifconfig_media_get_subtype(int ifmw) 319 { 320 struct ifmedia_description *desc; 321 struct ifmedia_type_to_subtype *ttos; 322 323 ttos = get_toptype_ttos(ifmw); 324 desc = get_subtype_desc(ifmw, ttos); 325 return (desc->ifmt_string); 326 } 327 328 /*************************************************************************** 329 * Above this point, this file is mostly copied from sbin/ifconfig/ifmedia.c 330 ***************************************************************************/ 331 332 /* Internal structure used for allocations and frees */ 333 struct _ifconfig_media_status { 334 struct ifmediareq ifmr; 335 int medialist[0]; 336 }; 337 338 int 339 ifconfig_media_get_mediareq(ifconfig_handle_t *h, const char *name, 340 struct ifmediareq **ifmr) 341 { 342 struct _ifconfig_media_status *ms, *ms2; 343 unsigned long cmd = SIOCGIFXMEDIA; 344 345 *ifmr = NULL; 346 ms = calloc(1, sizeof(*ms)); 347 if (ms == NULL) { 348 h->error.errtype = OTHER; 349 h->error.errcode = ENOMEM; 350 return (-1); 351 } 352 (void)memset(ms, 0, sizeof(*ms)); 353 (void)strlcpy(ms->ifmr.ifm_name, name, sizeof(ms->ifmr.ifm_name)); 354 355 /* 356 * Check if interface supports extended media types. 357 */ 358 if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { 359 cmd = SIOCGIFMEDIA; 360 if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms->ifmr) < 0) { 361 /* Interface doesn't support SIOC{G,S}IFMEDIA. */ 362 h->error.errtype = OK; 363 free(ms); 364 return (-1); 365 } 366 } 367 if (ms->ifmr.ifm_count == 0) { 368 *ifmr = &ms->ifmr; 369 return (0); /* Interface has no media types ?*/ 370 } 371 372 ms2 = realloc(ms, sizeof(*ms) + sizeof(int) * ms->ifmr.ifm_count); 373 if (ms2 == NULL) { 374 h->error.errtype = OTHER; 375 h->error.errcode = ENOMEM; 376 free(ms); 377 return (-1); 378 } 379 ms2->ifmr.ifm_ulist = &ms2->medialist[0]; 380 381 if (ifconfig_ioctlwrap(h, AF_LOCAL, cmd, &ms2->ifmr) < 0) { 382 free(ms2); 383 return (-1); 384 } 385 386 *ifmr = &ms2->ifmr; 387 return (0); 388 } 389 390 const char * 391 ifconfig_media_get_status(const struct ifmediareq *ifmr) 392 { 393 switch (IFM_TYPE(ifmr->ifm_active)) { 394 case IFM_ETHER: 395 case IFM_ATM: 396 if (ifmr->ifm_status & IFM_ACTIVE) { 397 return ("active"); 398 } else { 399 return ("no carrier"); 400 } 401 break; 402 403 case IFM_FDDI: 404 case IFM_TOKEN: 405 if (ifmr->ifm_status & IFM_ACTIVE) { 406 return ("inserted"); 407 } else { 408 return ("no ring"); 409 } 410 break; 411 412 case IFM_IEEE80211: 413 if (ifmr->ifm_status & IFM_ACTIVE) { 414 /* NB: only sta mode associates */ 415 if (IFM_OPMODE(ifmr->ifm_active) == IFM_IEEE80211_STA) { 416 return ("associated"); 417 } else { 418 return ("running"); 419 } 420 } else { 421 return ("no carrier"); 422 } 423 break; 424 default: 425 return (""); 426 } 427 } 428 429 void 430 ifconfig_media_get_options_string(int ifmw, char *buf, size_t buflen) 431 { 432 struct ifmedia_type_to_subtype *ttos; 433 struct ifmedia_description *desc; 434 int i, seen_option = 0; 435 size_t len; 436 437 assert(buflen > 0); 438 buf[0] = '\0'; 439 ttos = get_toptype_ttos(ifmw); 440 for (i = 0; ttos->options[i].desc != NULL; i++) { 441 if (ttos->options[i].alias) { 442 continue; 443 } 444 for (desc = ttos->options[i].desc; 445 desc->ifmt_string != NULL; desc++) { 446 if (ifmw & desc->ifmt_word) { 447 if (seen_option++) { 448 strlcat(buf, ",", buflen); 449 } 450 len = strlcat(buf, desc->ifmt_string, buflen); 451 assert(len < buflen); 452 buf += len; 453 buflen -= len; 454 } 455 } 456 } 457 } 458