1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This RCM module adds support to the RCM framework for IP managed 31 * interfaces. 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <assert.h> 38 #include <string.h> 39 #include <synch.h> 40 #include <libintl.h> 41 #include <errno.h> 42 #include <fcntl.h> 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <sys/socket.h> 46 #include <sys/sockio.h> 47 #include <net/if.h> 48 #include <netinet/in.h> 49 #include <netinet/tcp.h> 50 #include <arpa/inet.h> 51 #include <sys/dlpi.h> 52 #include <stropts.h> 53 #include <strings.h> 54 #include <libdevinfo.h> 55 #include <sys/systeminfo.h> 56 #include <netdb.h> 57 #include <libdladm.h> 58 #include <libdlpi.h> 59 60 #include <ipmp_mpathd.h> 61 #include "rcm_module.h" 62 63 /* 64 * Definitions 65 */ 66 #ifndef lint 67 #define _(x) gettext(x) 68 #else 69 #define _(x) x 70 #endif 71 72 /* Some generic well-knowns and defaults used in this module */ 73 #define SLASH_DEV "/dev" /* /dev directory */ 74 75 #define IP_DEV_NAME "/dev/ip" /* IPV4 ip device */ 76 #define IP6_DEV_NAME "/dev/ip6" /* IPV6 ip device */ 77 #define IP_MOD_NAME "ip" /* ip module */ 78 #define ARP_MOD_NAME "arp" /* arp module */ 79 #define UDP_DEV_NAME "/dev/udp" /* IPv4 udp device */ 80 #define UDP6_DEV_NAME "/dev/udp6" /* IPv6 udp device */ 81 #define IP_MAX_MODS 9 /* max modules pushed on intr */ 82 #define MAX_RECONFIG_SIZE 1024 /* Max. reconfig string size */ 83 84 #define RCM_NET_PREFIX "SUNW_network" /* RCM network name prefix */ 85 #define RCM_NET_RESOURCE_MAX (13 + LIFNAMSIZ) /* RCM_NET_PREFIX+LIFNAMSIZ */ 86 87 #define RCM_STR_SUNW_IP "SUNW_ip/" /* IP address export prefix */ 88 #define RCM_SIZE_SUNW_IP 9 /* strlen("SUNW_ip/") + 1 */ 89 90 #define MAXINTSTR 11 /* max integer string len */ 91 92 /* ifconfig(1M) */ 93 #define USR_SBIN_IFCONFIG "/usr/sbin/ifconfig" /* ifconfig command */ 94 #define CFGFILE_FMT_IPV4 "/etc/hostname." /* IPV4 config file */ 95 #define CFGFILE_FMT_IPV6 "/etc/hostname6." /* IPV6 config file */ 96 #define CFG_CMDS_STD " netmask + broadcast + up" /* Normal config string */ 97 #define CONFIG_AF_INET 0x1 /* Post-configure IPv4 */ 98 #define CONFIG_AF_INET6 0x2 /* Post-configure IPv6 */ 99 #define MAXLINE 1024 /* Max. line length */ 100 #define MAXARGS 512 /* Max. args in ifconfig cmd */ 101 102 /* Physical interface flags mask */ 103 #define RCM_PIF_FLAGS (IFF_OFFLINE | IFF_INACTIVE | IFF_FAILED | \ 104 IFF_STANDBY) 105 106 /* Some useful macros */ 107 #ifndef MAX 108 #define MAX(a, b) (((a) > (b))?(a):(b)) 109 #endif /* MAX */ 110 111 #ifndef ISSPACE 112 #define ISSPACE(c) ((c) == ' ' || (c) == '\t') 113 #endif 114 115 #ifndef ISEOL 116 #define ISEOL(c) ((c) == '\n' || (c) == '\r' || (c) == '\0') 117 #endif 118 119 #ifndef STREQ 120 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 121 #endif 122 123 #ifndef ADDSPACE 124 #define ADDSPACE(a) ((void) strcat((a), " ")) 125 #endif 126 127 /* Interface Cache state flags */ 128 #define CACHE_IF_STALE 0x1 /* stale cached data */ 129 #define CACHE_IF_NEW 0x2 /* new cached interface */ 130 #define CACHE_IF_OFFLINED 0x4 /* interface offlined */ 131 #define CACHE_IF_UPDATED 0x8 /* interface props. updated */ 132 #define CACHE_IF_IGNORE 0x10 /* state held elsewhere */ 133 134 /* Network Cache lookup options */ 135 #define CACHE_NO_REFRESH 0x1 /* cache refresh not needed */ 136 #define CACHE_REFRESH 0x2 /* refresh cache */ 137 138 /* RCM IPMP Module specific property definitions */ 139 #define RCM_IPMP_MIN_REDUNDANCY 1 /* default min. redundancy */ 140 141 /* in.mpathd(1M) specifics */ 142 #define MPATHD_MAX_RETRIES 5 /* Max. offline retries */ 143 #define MPATHD_OK 0 /* failback success from mpathd */ 144 #define MPATHD_FAILBACK_TIME 180 /* Time in secs. for mpathd failback */ 145 146 /* Stream module operations */ 147 #define MOD_INSERT 0 /* Insert a mid-stream module */ 148 #define MOD_REMOVE 1 /* Remove a mid-stream module */ 149 #define MOD_CHECK 2 /* Check mid-stream module safety */ 150 151 /* VLAN format support */ 152 #define VLAN_MAX_PPA_ALLOWED 1000 153 #define VLAN_GET_VID(ppa) (ppa / VLAN_MAX_PPA_ALLOWED) 154 #define VLAN_GET_PPA(ppa) (ppa % VLAN_MAX_PPA_ALLOWED) 155 156 /* devfsadm attach nvpair values */ 157 #define PROP_NV_DDI_NETWORK "ddi_network" 158 159 /* 160 * in.mpathd(1M) message passing formats 161 */ 162 typedef struct mpathd_cmd { 163 uint32_t cmd_command; /* message command */ 164 char cmd_ifname[LIFNAMSIZ]; /* this interface name */ 165 char cmd_movetoif[LIFNAMSIZ]; /* move to interface */ 166 uint32_t cmd_min_red; /* min. redundancy */ 167 /* Message passing values for MI_SETOINDEX */ 168 #define from_lifname cmd_ifname /* current logical interface */ 169 #define to_pifname cmd_movetoif /* new physical interface */ 170 #define addr_family cmd_min_red /* address family */ 171 } mpathd_cmd_t; 172 173 /* This is needed since mpathd checks message size for offline */ 174 typedef struct mpathd_unoffline { 175 uint32_t cmd_command; /* offline / undo offline */ 176 char cmd_ifname[LIFNAMSIZ]; /* this interface name */ 177 } mpathd_unoffline_t; 178 179 typedef struct mpathd_response { 180 uint32_t resp_sys_errno; /* system errno */ 181 uint32_t resp_mpathd_err; /* mpathd error information */ 182 } mpathd_response_t; 183 184 /* 185 * IP module data types 186 */ 187 188 /* Physical interface representation */ 189 typedef struct ip_pif { 190 char pi_ifname[LIFNAMSIZ+1]; /* interface name */ 191 char pi_ifindex; /* Interface index */ 192 char pi_grpname[LIFNAMSIZ+1]; /* IPMP group name */ 193 int pi_style; /* DLPI provider style */ 194 int pi_ppa; /* Phys. point of attachment */ 195 struct ip_lif *pi_lifs; /* ptr to logical interfaces */ 196 } ip_pif_t; 197 198 /* Logical interface representation */ 199 typedef struct ip_lif 200 { 201 struct ip_lif *li_next; /* ptr to next lif */ 202 struct ip_lif *li_prev; /* previous next ptr */ 203 ip_pif_t *li_pif; /* back ptr to phy int */ 204 ushort_t li_ifnum; /* interface number */ 205 union { 206 sa_family_t family; 207 struct sockaddr_storage storage; 208 struct sockaddr_in ip4; /* IPv4 */ 209 struct sockaddr_in6 ip6; /* IPv6 */ 210 } li_addr; 211 uint64_t li_ifflags; /* current IFF_* flags */ 212 uint64_t li_oldflags; /* flags prior to offline */ 213 int li_modcnt; /* # of modules */ 214 char *li_modules[IP_MAX_MODS]; /* module list pushed */ 215 char *li_reconfig; /* Reconfiguration string */ 216 int32_t li_cachestate; /* cache state flags */ 217 } ip_lif_t; 218 219 /* Cache element */ 220 typedef struct ip_cache 221 { 222 struct ip_cache *ip_next; /* next cached resource */ 223 struct ip_cache *ip_prev; /* prev cached resource */ 224 char *ip_resource; /* resource name */ 225 ip_pif_t *ip_pif; /* ptr to phy int */ 226 int32_t ip_ifred; /* min. redundancy */ 227 int ip_cachestate; /* cache state flags */ 228 } ip_cache_t; 229 230 /* 231 * Global cache for network interfaces 232 */ 233 static ip_cache_t cache_head; 234 static ip_cache_t cache_tail; 235 static mutex_t cache_lock; 236 static int events_registered = 0; 237 238 /* 239 * Global NIC list to be configured after DR-attach 240 */ 241 #define NIL_NULL ((struct ni_list *)0) 242 243 struct net_interface { 244 char *type; /* Name of type of interface (le, ie, etc.) */ 245 char *name; /* Qualified name of interface (le0, ie0, etc.) */ 246 }; 247 248 struct ni_list { 249 struct net_interface *nifp; 250 struct ni_list *next; 251 }; 252 253 static mutex_t nil_lock; /* NIC list lock */ 254 static int num_ni = 0; /* Global new interface count */ 255 static struct ni_list *nil_head = NIL_NULL; /* Global new if list */ 256 257 struct devfs_minor_data { 258 int32_t minor_type; 259 char *minor_name; 260 char *minor_node_type; 261 }; 262 263 /* 264 * RCM module interface prototypes 265 */ 266 static int ip_register(rcm_handle_t *); 267 static int ip_unregister(rcm_handle_t *); 268 static int ip_get_info(rcm_handle_t *, char *, id_t, uint_t, 269 char **, char **, nvlist_t *, rcm_info_t **); 270 static int ip_suspend(rcm_handle_t *, char *, id_t, 271 timespec_t *, uint_t, char **, rcm_info_t **); 272 static int ip_resume(rcm_handle_t *, char *, id_t, uint_t, 273 char **, rcm_info_t **); 274 static int ip_offline(rcm_handle_t *, char *, id_t, uint_t, 275 char **, rcm_info_t **); 276 static int ip_undo_offline(rcm_handle_t *, char *, id_t, uint_t, 277 char **, rcm_info_t **); 278 static int ip_remove(rcm_handle_t *, char *, id_t, uint_t, 279 char **, rcm_info_t **); 280 static int ip_notify_event(rcm_handle_t *, char *, id_t, uint_t, 281 char **, nvlist_t *, rcm_info_t **); 282 283 /* Module private routines */ 284 static void free_cache(); 285 static int update_cache(rcm_handle_t *); 286 static void cache_remove(ip_cache_t *); 287 static ip_cache_t *cache_lookup(rcm_handle_t *, char *, char); 288 static void free_node(ip_cache_t *); 289 static void cache_insert(ip_cache_t *); 290 static char *ip_usage(ip_cache_t *); 291 static int update_pif(rcm_handle_t *, int, int, struct lifreq *); 292 static int ip_ipmp_offline(ip_cache_t *, ip_cache_t *); 293 static int ip_ipmp_undo_offline(ip_cache_t *); 294 static int if_cfginfo(ip_cache_t *, uint_t); 295 static int if_unplumb(ip_cache_t *); 296 static int if_replumb(ip_cache_t *); 297 static void ip_log_err(ip_cache_t *, char **, char *); 298 static int getdlpi_style(char *); 299 static char *get_physical_resource(char *); 300 static int get_ppa(char *); 301 static void clr_cfg_state(ip_pif_t *); 302 /*LINTED*/ 303 static int if_change_flags(ip_pif_t *, uint64_t, boolean_t); 304 static uint64_t if_get_flags(ip_pif_t *); 305 static int mpathd_send_cmd(mpathd_cmd_t *); 306 static int connect_to_mpathd(int); 307 /*LINTED*/ 308 static int get_lun(char *); 309 /*LINTED*/ 310 static void dump_node(ip_cache_t *); 311 static int modop(char *, char *, int, char); 312 static int get_modlist(char *, ip_lif_t *); 313 static int ip_domux2fd(int *, int *, struct lifreq *); 314 static int ip_plink(int, int, struct lifreq *); 315 static int ip_onlinelist(rcm_handle_t *, ip_cache_t *, char **, uint_t, 316 rcm_info_t **); 317 static int ip_offlinelist(rcm_handle_t *, ip_cache_t *, char **, uint_t, 318 rcm_info_t **); 319 static char **ip_get_addrlist(ip_cache_t *); 320 static void ip_free_addrlist(char **); 321 static void ip_consumer_notify(rcm_handle_t *, char *, char **, uint_t, 322 rcm_info_t **); 323 324 static int process_nvlist(nvlist_t *); 325 static void process_minor(char *, char *, int32_t, struct devfs_minor_data *); 326 static int if_configure(char *); 327 static int isgrouped(char *); 328 static int if_ipmp_config(char *, int, int); 329 static int if_mpathd_configure(char *, char *, int, int); 330 static char *get_mpathd_dest(char *, int); 331 static int if_getcount(int); 332 static void tokenize(char *, char **, char *, int *); 333 334 335 /* Module-Private data */ 336 static struct rcm_mod_ops ip_ops = 337 { 338 RCM_MOD_OPS_VERSION, 339 ip_register, 340 ip_unregister, 341 ip_get_info, 342 ip_suspend, 343 ip_resume, 344 ip_offline, 345 ip_undo_offline, 346 ip_remove, 347 NULL, 348 NULL, 349 ip_notify_event 350 }; 351 352 /* 353 * rcm_mod_init() - Update registrations, and return the ops structure. 354 */ 355 struct rcm_mod_ops * 356 rcm_mod_init(void) 357 { 358 rcm_log_message(RCM_TRACE1, "IP: mod_init\n"); 359 360 cache_head.ip_next = &cache_tail; 361 cache_head.ip_prev = NULL; 362 cache_tail.ip_prev = &cache_head; 363 cache_tail.ip_next = NULL; 364 (void) mutex_init(&cache_lock, NULL, NULL); 365 (void) mutex_init(&nil_lock, NULL, NULL); 366 367 /* Return the ops vectors */ 368 return (&ip_ops); 369 } 370 371 /* 372 * rcm_mod_info() - Return a string describing this module. 373 */ 374 const char * 375 rcm_mod_info(void) 376 { 377 rcm_log_message(RCM_TRACE1, "IP: mod_info\n"); 378 379 return ("IP Multipathing module version %I%"); 380 } 381 382 /* 383 * rcm_mod_fini() - Destroy the network interfaces cache. 384 */ 385 int 386 rcm_mod_fini(void) 387 { 388 rcm_log_message(RCM_TRACE1, "IP: mod_fini\n"); 389 390 free_cache(); 391 (void) mutex_destroy(&nil_lock); 392 (void) mutex_destroy(&cache_lock); 393 return (RCM_SUCCESS); 394 } 395 396 /* 397 * ip_register() - Make sure the cache is properly sync'ed, and its 398 * registrations are in order. 399 */ 400 static int 401 ip_register(rcm_handle_t *hd) 402 { 403 rcm_log_message(RCM_TRACE1, "IP: register\n"); 404 405 /* Guard against bad arguments */ 406 assert(hd != NULL); 407 408 if (update_cache(hd) < 0) 409 return (RCM_FAILURE); 410 411 /* 412 * Need to register interest in all new resources 413 * getting attached, so we get attach event notifications 414 */ 415 if (!events_registered) { 416 if (rcm_register_event(hd, RCM_RESOURCE_NETWORK_NEW, 0, NULL) 417 != RCM_SUCCESS) { 418 rcm_log_message(RCM_ERROR, 419 _("IP: failed to register %s\n"), 420 RCM_RESOURCE_NETWORK_NEW); 421 return (RCM_FAILURE); 422 } else { 423 rcm_log_message(RCM_DEBUG, "IP: registered %s\n", 424 RCM_RESOURCE_NETWORK_NEW); 425 events_registered++; 426 } 427 } 428 429 return (RCM_SUCCESS); 430 } 431 432 /* 433 * ip_unregister() - Walk the cache, unregistering all the networks. 434 */ 435 static int 436 ip_unregister(rcm_handle_t *hd) 437 { 438 ip_cache_t *probe; 439 440 rcm_log_message(RCM_TRACE1, "IP: unregister\n"); 441 442 /* Guard against bad arguments */ 443 assert(hd != NULL); 444 445 /* Walk the cache, unregistering everything */ 446 (void) mutex_lock(&cache_lock); 447 probe = cache_head.ip_next; 448 while (probe != &cache_tail) { 449 if (rcm_unregister_interest(hd, probe->ip_resource, 0) 450 != RCM_SUCCESS) { 451 /* unregister failed for whatever reason */ 452 (void) mutex_unlock(&cache_lock); 453 return (RCM_FAILURE); 454 } 455 cache_remove(probe); 456 free_node(probe); 457 probe = cache_head.ip_next; 458 } 459 (void) mutex_unlock(&cache_lock); 460 461 /* 462 * Need to unregister interest in all new resources 463 */ 464 if (events_registered) { 465 if (rcm_unregister_event(hd, RCM_RESOURCE_NETWORK_NEW, 0) 466 != RCM_SUCCESS) { 467 rcm_log_message(RCM_ERROR, 468 _("IP: failed to unregister %s\n"), 469 RCM_RESOURCE_NETWORK_NEW); 470 return (RCM_FAILURE); 471 } else { 472 rcm_log_message(RCM_DEBUG, "IP: unregistered %s\n", 473 RCM_RESOURCE_NETWORK_NEW); 474 events_registered--; 475 } 476 } 477 478 return (RCM_SUCCESS); 479 } 480 481 /* 482 * ip_offline() - Offline an interface. 483 */ 484 static int 485 ip_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 486 char **errorp, rcm_info_t **depend_info) 487 { 488 char *nic; 489 ip_cache_t *node; 490 ip_pif_t *pif; 491 int detachable = 0; 492 int nofailover = 0; 493 int ipmp = 0; 494 495 rcm_log_message(RCM_TRACE1, "IP: offline(%s)\n", rsrc); 496 497 /* Guard against bad arguments */ 498 assert(hd != NULL); 499 assert(rsrc != NULL); 500 assert(id == (id_t)0); 501 assert(errorp != NULL); 502 assert(depend_info != NULL); 503 504 nic = strrchr(rsrc, '/'); 505 nic = nic ? nic + 1 : rsrc; 506 507 /* Lock the cache and lookup the resource */ 508 (void) mutex_lock(&cache_lock); 509 node = cache_lookup(hd, rsrc, CACHE_REFRESH); 510 if (node == NULL) { 511 ip_log_err(node, errorp, "Unrecognized resource"); 512 errno = ENOENT; 513 (void) mutex_unlock(&cache_lock); 514 return (RCM_SUCCESS); 515 } 516 517 pif = node->ip_pif; 518 519 /* Establish default detachability criteria */ 520 if (flags & RCM_FORCE) { 521 detachable++; 522 } 523 524 /* Check if the interface is an IPMP grouped interface */ 525 if (strcmp(pif->pi_grpname, "")) { 526 ipmp++; 527 } 528 529 if (if_get_flags(pif) & IFF_NOFAILOVER) { 530 nofailover++; 531 } 532 533 /* 534 * Even if the interface is not in an IPMP group, it's possible that 535 * it's still okay to offline it as long as there are higher-level 536 * failover mechanisms for the addresses it owns (e.g., clustering). 537 * In this case, ip_offlinelist() will return RCM_SUCCESS, and we 538 * charge on. 539 */ 540 if (!ipmp && !detachable) { 541 /* Inform consumers of IP addresses being offlined */ 542 if (ip_offlinelist(hd, node, errorp, flags, depend_info) == 543 RCM_SUCCESS) { 544 rcm_log_message(RCM_DEBUG, 545 "IP: consumers agree on detach"); 546 } else { 547 ip_log_err(node, errorp, 548 "Device consumers prohibit offline"); 549 (void) mutex_unlock(&cache_lock); 550 return (RCM_FAILURE); 551 } 552 } 553 554 /* 555 * Cannot remove an IPMP interface if IFF_NOFAILOVER is set. 556 */ 557 if (ipmp && nofailover) { 558 /* Interface is part of an IPMP group, and cannot failover */ 559 ip_log_err(node, errorp, "Failover disabled"); 560 errno = EBUSY; 561 (void) mutex_unlock(&cache_lock); 562 return (RCM_FAILURE); 563 } 564 565 /* Check if it's a query */ 566 if (flags & RCM_QUERY) { 567 rcm_log_message(RCM_TRACE1, "IP: offline query success(%s)\n", 568 rsrc); 569 (void) mutex_unlock(&cache_lock); 570 return (RCM_SUCCESS); 571 } 572 573 /* Check detachability, save configuration if detachable */ 574 if (if_cfginfo(node, (flags & RCM_FORCE)) < 0) { 575 node->ip_cachestate |= CACHE_IF_IGNORE; 576 rcm_log_message(RCM_TRACE1, "IP: Ignoring node(%s)\n", rsrc); 577 (void) mutex_unlock(&cache_lock); 578 return (RCM_SUCCESS); 579 } 580 581 /* standalone detachable device */ 582 if (!ipmp) { 583 if (if_unplumb(node) < 0) { 584 ip_log_err(node, errorp, 585 "Failed to unplumb the device"); 586 587 errno = EIO; 588 (void) mutex_unlock(&cache_lock); 589 return (RCM_FAILURE); 590 } 591 592 node->ip_cachestate |= CACHE_IF_OFFLINED; 593 rcm_log_message(RCM_TRACE1, "IP: Offline success(%s)\n", rsrc); 594 (void) mutex_unlock(&cache_lock); 595 return (RCM_SUCCESS); 596 } 597 598 /* 599 * This an IPMP interface that can be failed over. 600 * Request in.mpathd(1M) to failover the physical interface. 601 */ 602 603 /* Failover to "any", let mpathd determine best failover candidate */ 604 if (ip_ipmp_offline(node, NULL) < 0) { 605 ip_log_err(node, errorp, "in.mpathd failover failed"); 606 /* 607 * Odds are that in.mpathd(1M) could not offline the device 608 * because it was the last interface in the group. However, 609 * it's possible that it's still okay to offline it as long as 610 * there are higher-level failover mechanisms for the 611 * addresses it owns (e.g., clustering). In this case, 612 * ip_offlinelist() will return RCM_SUCCESS, and we charge on. 613 * 614 * TODO: change ip_ipmp_offline() to return the actual failure 615 * from in.mpathd so that we can verify that it did indeed 616 * fail with IPMP_EMINRED. 617 */ 618 if (!detachable) { 619 /* Inform consumers of IP addresses being offlined */ 620 if (ip_offlinelist(hd, node, errorp, flags, 621 depend_info) == RCM_SUCCESS) { 622 rcm_log_message(RCM_DEBUG, 623 "IP: consumers agree on detach"); 624 } else { 625 ip_log_err(node, errorp, 626 "Device consumers prohibit offline"); 627 (void) mutex_unlock(&cache_lock); 628 errno = EBUSY; 629 return (RCM_FAILURE); 630 } 631 } 632 } 633 634 if (if_unplumb(node) < 0) { 635 rcm_log_message(RCM_ERROR, 636 _("IP: Unplumb failed (%s)\n"), 637 pif->pi_ifname); 638 639 /* Request mpathd to undo the offline */ 640 if (ip_ipmp_undo_offline(node) < 0) { 641 ip_log_err(node, errorp, "Undo offline failed"); 642 (void) mutex_unlock(&cache_lock); 643 return (RCM_FAILURE); 644 } 645 (void) mutex_unlock(&cache_lock); 646 return (RCM_FAILURE); 647 } 648 649 node->ip_cachestate |= CACHE_IF_OFFLINED; 650 rcm_log_message(RCM_TRACE1, "IP: offline success(%s)\n", rsrc); 651 (void) mutex_unlock(&cache_lock); 652 return (RCM_SUCCESS); 653 } 654 655 /* 656 * ip_undo_offline() - Undo offline of a previously offlined device. 657 */ 658 /*ARGSUSED*/ 659 static int 660 ip_undo_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 661 char **errorp, rcm_info_t **depend_info) 662 { 663 ip_cache_t *node; 664 char *nic; 665 666 rcm_log_message(RCM_TRACE1, "IP: online(%s)\n", rsrc); 667 668 /* Guard against bad arguments */ 669 assert(hd != NULL); 670 assert(rsrc != NULL); 671 assert(id == (id_t)0); 672 assert(errorp != NULL); 673 assert(depend_info != NULL); 674 675 nic = strrchr(rsrc, '/'); 676 nic = nic ? nic + 1 : rsrc; 677 678 (void) mutex_lock(&cache_lock); 679 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 680 681 if (node == NULL) { 682 ip_log_err(node, errorp, "No such device"); 683 (void) mutex_unlock(&cache_lock); 684 errno = ENOENT; 685 return (RCM_FAILURE); 686 } 687 688 /* Check if no attempt should be made to online the device here */ 689 if (node->ip_cachestate & CACHE_IF_IGNORE) { 690 node->ip_cachestate &= ~(CACHE_IF_IGNORE); 691 (void) mutex_unlock(&cache_lock); 692 return (RCM_SUCCESS); 693 } 694 695 /* Check if the interface was previously offlined */ 696 if (!(node->ip_cachestate & CACHE_IF_OFFLINED)) { 697 ip_log_err(node, errorp, "Device not offlined"); 698 (void) mutex_unlock(&cache_lock); 699 errno = ENOTSUP; 700 return (RCM_FAILURE); 701 } 702 703 if (if_replumb(node) == -1) { 704 /* re-plumb failed */ 705 ip_log_err(node, errorp, "Replumb failed"); 706 (void) mutex_unlock(&cache_lock); 707 errno = EIO; 708 return (RCM_FAILURE); 709 710 } 711 712 /* Inform consumers about IP addresses being un-offlined */ 713 (void) ip_onlinelist(hd, node, errorp, flags, depend_info); 714 715 node->ip_cachestate &= ~(CACHE_IF_OFFLINED); 716 rcm_log_message(RCM_TRACE1, "IP: online success(%s)\n", rsrc); 717 (void) mutex_unlock(&cache_lock); 718 return (RCM_SUCCESS); 719 } 720 721 /* 722 * ip_get_info() - Gather usage information for this resource. 723 */ 724 /*ARGSUSED*/ 725 int 726 ip_get_info(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 727 char **usagep, char **errorp, nvlist_t *props, rcm_info_t **depend_info) 728 { 729 ip_cache_t *node; 730 char *infostr; 731 732 /* Guard against bad arguments */ 733 assert(hd != NULL); 734 assert(rsrc != NULL); 735 assert(id == (id_t)0); 736 assert(usagep != NULL); 737 assert(errorp != NULL); 738 assert(depend_info != NULL); 739 740 rcm_log_message(RCM_TRACE1, "IP: get_info(%s)\n", rsrc); 741 742 (void) mutex_lock(&cache_lock); 743 node = cache_lookup(hd, rsrc, CACHE_REFRESH); 744 if (!node) { 745 rcm_log_message(RCM_INFO, 746 _("IP: get_info(%s) unrecognized resource\n"), rsrc); 747 (void) mutex_unlock(&cache_lock); 748 errno = ENOENT; 749 return (RCM_FAILURE); 750 } 751 752 infostr = ip_usage(node); 753 754 if (infostr == NULL) { 755 /* most likely malloc failure */ 756 rcm_log_message(RCM_ERROR, 757 _("IP: get_info(%s) malloc failure\n"), rsrc); 758 (void) mutex_unlock(&cache_lock); 759 errno = ENOMEM; 760 *errorp = NULL; 761 return (RCM_FAILURE); 762 } 763 764 /* Set client/role properties */ 765 (void) nvlist_add_string(props, RCM_CLIENT_NAME, "IP"); 766 767 /* Set usage property, infostr will be freed by caller */ 768 *usagep = infostr; 769 770 rcm_log_message(RCM_TRACE1, "IP: get_info(%s) info = %s \n", 771 rsrc, infostr); 772 773 (void) mutex_unlock(&cache_lock); 774 return (RCM_SUCCESS); 775 } 776 777 /* 778 * ip_suspend() - Nothing to do, always okay 779 */ 780 /*ARGSUSED*/ 781 static int 782 ip_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval, 783 uint_t flags, char **errorp, rcm_info_t **depend_info) 784 { 785 /* Guard against bad arguments */ 786 assert(hd != NULL); 787 assert(rsrc != NULL); 788 assert(id == (id_t)0); 789 assert(interval != NULL); 790 assert(errorp != NULL); 791 assert(depend_info != NULL); 792 793 rcm_log_message(RCM_TRACE1, "IP: suspend(%s)\n", rsrc); 794 return (RCM_SUCCESS); 795 } 796 797 /* 798 * ip_resume() - Nothing to do, always okay 799 */ 800 /*ARGSUSED*/ 801 static int 802 ip_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 803 char **errorp, rcm_info_t ** depend_info) 804 { 805 /* Guard against bad arguments */ 806 assert(hd != NULL); 807 assert(rsrc != NULL); 808 assert(id == (id_t)0); 809 assert(errorp != NULL); 810 assert(depend_info != NULL); 811 812 rcm_log_message(RCM_TRACE1, "IP: resume(%s)\n", rsrc); 813 814 return (RCM_SUCCESS); 815 } 816 817 /* 818 * ip_remove() - remove a resource from cache 819 */ 820 /*ARGSUSED*/ 821 static int 822 ip_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 823 char **errorp, rcm_info_t **depend_info) 824 { 825 ip_cache_t *node; 826 827 /* Guard against bad arguments */ 828 assert(hd != NULL); 829 assert(rsrc != NULL); 830 assert(id == (id_t)0); 831 assert(errorp != NULL); 832 assert(depend_info != NULL); 833 834 rcm_log_message(RCM_TRACE1, "IP: remove(%s)\n", rsrc); 835 836 (void) mutex_lock(&cache_lock); 837 node = cache_lookup(hd, rsrc, CACHE_NO_REFRESH); 838 if (!node) { 839 rcm_log_message(RCM_INFO, 840 _("IP: remove(%s) unrecognized resource\n"), rsrc); 841 (void) mutex_unlock(&cache_lock); 842 errno = ENOENT; 843 return (RCM_FAILURE); 844 } 845 846 /* remove the cached entry for the resource */ 847 cache_remove(node); 848 849 (void) mutex_unlock(&cache_lock); 850 return (RCM_SUCCESS); 851 } 852 853 /* 854 * ip_notify_event - Project private implementation to receive new resource 855 * events. It intercepts all new resource events. If the 856 * new resource is a network resource, pass up a notify 857 * for it too. The new resource need not be cached, since 858 * it is done at register again. 859 */ 860 /*ARGSUSED*/ 861 static int 862 ip_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags, 863 char **errorp, nvlist_t *nvl, rcm_info_t **depend_info) 864 { 865 struct ni_list *nilp, *onilp; 866 struct net_interface *nip; 867 int n; 868 869 assert(hd != NULL); 870 assert(rsrc != NULL); 871 assert(id == (id_t)0); 872 assert(nvl != NULL); 873 874 rcm_log_message(RCM_TRACE1, "IP: notify_event(%s)\n", rsrc); 875 876 if (!STREQ(rsrc, RCM_RESOURCE_NETWORK_NEW)) { 877 rcm_log_message(RCM_INFO, 878 _("IP: unrecognized event for %s\n"), rsrc); 879 ip_log_err(NULL, errorp, "unrecognized event"); 880 errno = EINVAL; 881 return (RCM_FAILURE); 882 } 883 884 /* Update cache to reflect latest interfaces */ 885 if (update_cache(hd) < 0) { 886 rcm_log_message(RCM_ERROR, _("IP: update_cache failed\n")); 887 ip_log_err(NULL, errorp, "Private Cache update failed"); 888 return (RCM_FAILURE); 889 } 890 891 /* Process the nvlist for the event */ 892 if (process_nvlist(nvl) != 0) { 893 rcm_log_message(RCM_WARNING, 894 _("IP: Error processing resource attributes(%s)\n"), rsrc); 895 rcm_log_message(RCM_WARNING, 896 _("IP: One or more devices may not be configured.\n")); 897 ip_log_err(NULL, errorp, "Error processing device properties"); 898 /* Continue processing interfaces that were valid */ 899 } 900 901 (void) mutex_lock(&nil_lock); 902 903 /* Configure all new interfaces found */ 904 for (nilp = nil_head, n = 0; n < num_ni; nilp = nilp->next, n++) { 905 nip = nilp->nifp; 906 if (if_configure(nip->name) != 0) { 907 rcm_log_message(RCM_ERROR, 908 _("IP: Configuration failed (%s)\n"), nip->name); 909 ip_log_err(NULL, errorp, 910 "Failed configuring one or more IP addresses"); 911 /* continue configuring rest of the interfaces */ 912 } 913 } 914 915 /* Notify all IP address consumers and clean up interface list */ 916 for (nilp = nil_head; nilp; ) { 917 nip = nilp->nifp; 918 if (nip != (struct net_interface *)0) { 919 if (nip->name != 0) { 920 ip_consumer_notify(hd, nip->name, errorp, flags, 921 depend_info); 922 free(nip->name); 923 } 924 if (nip->type != 0) 925 free(nip->type); 926 free((char *)nip); 927 } 928 929 onilp = nilp; 930 nilp = nilp->next; 931 free((char *)onilp); 932 } 933 934 num_ni = 0; /* reset new if count */ 935 nil_head = NIL_NULL; /* reset list head */ 936 937 (void) mutex_unlock(&nil_lock); 938 939 rcm_log_message(RCM_TRACE1, 940 "IP: notify_event: device configuration complete\n"); 941 942 return (RCM_SUCCESS); 943 } 944 945 /* 946 * ip_usage - Determine the usage of a device. Call with cache_lock held. 947 * The returned buffer is owned by caller, and the caller 948 * must free it up when done. 949 */ 950 static char * 951 ip_usage(ip_cache_t *node) 952 { 953 ip_lif_t *lif; 954 int numifs; 955 char *buf; 956 char *nic; 957 const char *fmt; 958 char *sep; 959 char addrstr[INET6_ADDRSTRLEN]; 960 int offline = 0; 961 size_t bufsz; 962 963 rcm_log_message(RCM_TRACE2, "IP: usage(%s)\n", node->ip_resource); 964 965 nic = strchr(node->ip_resource, '/'); 966 nic = nic ? nic + 1 : node->ip_resource; 967 968 /* TRANSLATION_NOTE: separator used between IP addresses */ 969 sep = _(", "); 970 971 numifs = 0; 972 for (lif = node->ip_pif->pi_lifs; lif != NULL; lif = lif->li_next) { 973 if (lif->li_ifflags & IFF_UP) { 974 numifs++; 975 } 976 } 977 978 if (node->ip_cachestate & CACHE_IF_OFFLINED) { 979 offline++; 980 } 981 982 if (!offline && numifs) { 983 fmt = _("%1$s hosts IP addresses: "); 984 } else if (offline) { 985 fmt = _("%1$s offlined"); 986 } else { 987 fmt = _("%1$s plumbed but down"); 988 } 989 990 /* space for addresses and separators, plus message */ 991 bufsz = ((numifs * (INET6_ADDRSTRLEN + strlen(sep))) + 992 strlen(fmt) + strlen(nic) + 1); 993 if ((buf = malloc(bufsz)) == NULL) { 994 rcm_log_message(RCM_ERROR, 995 _("IP: usage(%s) malloc failure(%s)\n"), 996 node->ip_resource, strerror(errno)); 997 return (NULL); 998 } 999 bzero(buf, bufsz); 1000 (void) sprintf(buf, fmt, nic); 1001 1002 if (offline || (numifs == 0)) { /* Nothing else to do */ 1003 rcm_log_message(RCM_TRACE2, "IP: usage (%s) info = %s\n", 1004 node->ip_resource, buf); 1005 1006 return (buf); 1007 } 1008 1009 for (lif = node->ip_pif->pi_lifs; lif != NULL; lif = lif->li_next) { 1010 1011 void *addr; 1012 int af; 1013 1014 if (!(lif->li_ifflags & IFF_UP)) { 1015 /* ignore interfaces not up */ 1016 continue; 1017 } 1018 af = lif->li_addr.family; 1019 if (af == AF_INET6) { 1020 addr = &lif->li_addr.ip6.sin6_addr; 1021 } else if (af == AF_INET) { 1022 addr = &lif->li_addr.ip4.sin_addr; 1023 } else { 1024 rcm_log_message(RCM_DEBUG, 1025 "IP: unknown addr family %d, assuming AF_INET\n", 1026 af); 1027 af = AF_INET; 1028 addr = &lif->li_addr.ip4.sin_addr; 1029 } 1030 if (inet_ntop(af, addr, addrstr, INET6_ADDRSTRLEN) == NULL) { 1031 rcm_log_message(RCM_ERROR, 1032 _("IP: inet_ntop: %s\n"), strerror(errno)); 1033 continue; 1034 } 1035 rcm_log_message(RCM_DEBUG, "IP addr := %s\n", addrstr); 1036 1037 (void) strcat(buf, addrstr); 1038 numifs--; 1039 if (numifs > 0) { 1040 (void) strcat(buf, ", "); 1041 } 1042 } 1043 1044 rcm_log_message(RCM_TRACE2, "IP: usage (%s) info = %s\n", 1045 node->ip_resource, buf); 1046 1047 return (buf); 1048 } 1049 1050 /* 1051 * Cache management routines, all cache management functions should be 1052 * be called with cache_lock held. 1053 */ 1054 1055 /* 1056 * cache_lookup() - Get a cache node for a resource. Supports VLAN interfaces. 1057 * Call with cache lock held. 1058 * 1059 * This ensures that the cache is consistent with the system state and 1060 * returns a pointer to the cache element corresponding to the resource. 1061 */ 1062 static ip_cache_t * 1063 cache_lookup(rcm_handle_t *hd, char *rsrc, char options) 1064 { 1065 ip_cache_t *probe; 1066 char *resource; /* physical resource */ 1067 1068 rcm_log_message(RCM_TRACE2, "IP: cache lookup(%s)\n", rsrc); 1069 1070 if ((options & CACHE_REFRESH) && (hd != NULL)) { 1071 /* drop lock since update locks cache again */ 1072 (void) mutex_unlock(&cache_lock); 1073 (void) update_cache(hd); 1074 (void) mutex_lock(&cache_lock); 1075 } 1076 1077 if ((resource = get_physical_resource(rsrc)) == NULL) { 1078 errno = ENOENT; 1079 return (NULL); 1080 } 1081 1082 probe = cache_head.ip_next; 1083 while (probe != &cache_tail) { 1084 if (probe->ip_resource && 1085 STREQ(resource, probe->ip_resource)) { 1086 rcm_log_message(RCM_TRACE2, 1087 "IP: cache lookup success(%s)\n", rsrc); 1088 free(resource); 1089 return (probe); 1090 } 1091 probe = probe->ip_next; 1092 } 1093 free(resource); 1094 return (NULL); 1095 } 1096 1097 /* 1098 * free_node - Free a node from the cache 1099 * Call with cache_lock held. 1100 */ 1101 static void 1102 free_node(ip_cache_t *node) 1103 { 1104 ip_pif_t *pif; 1105 ip_lif_t *lif, *tmplif; 1106 1107 if (node) { 1108 if (node->ip_resource) { 1109 free(node->ip_resource); 1110 } 1111 1112 /* free the pif */ 1113 pif = node->ip_pif; 1114 if (pif) { 1115 /* free logical interfaces */ 1116 lif = pif->pi_lifs; 1117 while (lif) { 1118 tmplif = lif->li_next; 1119 free(lif); 1120 lif = tmplif; 1121 } 1122 free(pif); 1123 } 1124 free(node); 1125 } 1126 } 1127 1128 /* 1129 * cache_insert - Insert a resource node in cache 1130 * Call with the cache_lock held. 1131 */ 1132 static void 1133 cache_insert(ip_cache_t *node) 1134 { 1135 /* insert at the head for best performance */ 1136 node->ip_next = cache_head.ip_next; 1137 node->ip_prev = &cache_head; 1138 1139 node->ip_next->ip_prev = node; 1140 node->ip_prev->ip_next = node; 1141 } 1142 1143 /* 1144 * cache_remove() - Remove a resource node from cache. 1145 * Call with the cache_lock held. 1146 */ 1147 static void 1148 cache_remove(ip_cache_t *node) 1149 { 1150 node->ip_next->ip_prev = node->ip_prev; 1151 node->ip_prev->ip_next = node->ip_next; 1152 node->ip_next = NULL; 1153 node->ip_prev = NULL; 1154 } 1155 1156 /* 1157 * update_pif() - Update physical interface properties 1158 * Call with cache_lock held 1159 */ 1160 /*ARGSUSED*/ 1161 static int 1162 update_pif(rcm_handle_t *hd, int af, int sock, struct lifreq *lifr) 1163 { 1164 char ifname[RCM_NET_RESOURCE_MAX]; 1165 ushort_t ifnumber = 0; 1166 int ppa; 1167 char *cp; 1168 ip_cache_t *probe; 1169 ip_pif_t pif; 1170 ip_pif_t *probepif; 1171 ip_lif_t *probelif; 1172 struct lifreq lifreq; 1173 struct sockaddr_storage ifaddr; 1174 uint64_t ifflags; 1175 int lif_listed = 0; 1176 1177 rcm_log_message(RCM_TRACE1, "IP: update_pif(%s)\n", lifr->lifr_name); 1178 1179 /* Determine the interface name and lun number */ 1180 (void) memcpy(&ifname, lifr->lifr_name, sizeof (ifname)); 1181 ifname[sizeof (ifname) - 1] = '\0'; 1182 1183 /* remove LIF component */ 1184 cp = strchr(ifname, ':'); 1185 if (cp) { 1186 *cp = 0; 1187 cp++; 1188 ifnumber = atoi(cp); 1189 } 1190 1191 (void) memcpy(&pif.pi_ifname, &ifname, sizeof (pif.pi_ifname)); 1192 pif.pi_ifname[sizeof (pif.pi_ifname) - 1] = '\0'; 1193 1194 /* Determine DLPI style */ 1195 if (getdlpi_style(ifname) == DL_STYLE1) { 1196 pif.pi_ppa = 0; 1197 pif.pi_style = DL_STYLE1; 1198 rcm_log_message(RCM_DEBUG, "IP: DLPI style1 (%s)\n", ifname); 1199 } else { /* DLPI style 2 */ 1200 /* Determine the ppa */ 1201 if ((ppa = get_ppa(ifname)) < 0) { 1202 rcm_log_message(RCM_ERROR, 1203 _("IP: get_ppa(%s): %s\n"), 1204 ifname, strerror(ENXIO)); 1205 return (-1); 1206 } 1207 1208 pif.pi_style = DL_STYLE2; 1209 pif.pi_ppa = ppa; 1210 rcm_log_message(RCM_DEBUG, "IP: DLPI style2 (%s)\n", ifname); 1211 } 1212 1213 /* Get the interface flags */ 1214 (void) strcpy(lifreq.lifr_name, lifr->lifr_name); 1215 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifreq) < 0) { 1216 rcm_log_message(RCM_ERROR, 1217 _("IP: SIOCGLIFFLAGS(%s): %s\n"), 1218 ifname, strerror(errno)); 1219 return (-1); 1220 } 1221 (void) memcpy(&ifflags, &lifreq.lifr_flags, sizeof (ifflags)); 1222 1223 /* Ignore loopback and multipoint interfaces */ 1224 if (!(ifflags & IFF_MULTICAST) || 1225 (ifflags & IFF_LOOPBACK)) { 1226 rcm_log_message(RCM_TRACE3, "IP: if ignored (%s)\n", ifname); 1227 return (0); 1228 } 1229 1230 /* Get the interface group name for this interface */ 1231 if (ioctl(sock, SIOCGLIFGROUPNAME, (char *)&lifreq) < 0) { 1232 rcm_log_message(RCM_ERROR, 1233 _("IP: SIOCGLIFGROUPNAME(%s): %s\n"), 1234 lifreq.lifr_name, strerror(errno)); 1235 return (-1); 1236 } 1237 1238 /* copy the group name */ 1239 (void) memcpy(&pif.pi_grpname, &lifreq.lifr_groupname, 1240 sizeof (pif.pi_grpname)); 1241 pif.pi_grpname[sizeof (pif.pi_grpname) - 1] = '\0'; 1242 1243 /* Get the interface address for this interface */ 1244 if (ioctl(sock, SIOCGLIFADDR, (char *)&lifreq) < 0) { 1245 rcm_log_message(RCM_ERROR, 1246 _("IP: SIOCGLIFADDR(%s): %s\n"), 1247 lifreq.lifr_name, strerror(errno)); 1248 return (-1); 1249 } 1250 (void) memcpy(&ifaddr, &lifreq.lifr_addr, sizeof (ifaddr)); 1251 1252 /* Get the interface index */ 1253 if (ioctl(sock, SIOCGLIFINDEX, (char *)&lifreq) < 0) { 1254 rcm_log_message(RCM_ERROR, 1255 _("IP: SIOCGLIFINDEX(%s): %s\n"), 1256 lifreq.lifr_name, strerror(errno)); 1257 return (-1); 1258 } 1259 pif.pi_ifindex = lifreq.lifr_index; 1260 1261 /* Search for the interface in our cache */ 1262 (void) snprintf(ifname, sizeof (ifname), "%s/%s", RCM_NET_PREFIX, 1263 pif.pi_ifname); 1264 1265 probe = cache_lookup(hd, ifname, CACHE_NO_REFRESH); 1266 if (probe != NULL) { 1267 probe->ip_cachestate &= ~(CACHE_IF_STALE); 1268 } else { 1269 if ((probe = calloc(1, sizeof (ip_cache_t))) == NULL) { 1270 /* malloc errors are bad */ 1271 rcm_log_message(RCM_ERROR, _("IP: calloc: %s\n"), 1272 strerror(errno)); 1273 return (-1); 1274 } 1275 1276 probe->ip_resource = get_physical_resource(ifname); 1277 if (!probe->ip_resource) { 1278 rcm_log_message(RCM_ERROR, _("IP: strdup: %s\n"), 1279 strerror(errno)); 1280 free(probe); 1281 return (-1); 1282 } 1283 1284 probe->ip_pif = NULL; 1285 probe->ip_ifred = RCM_IPMP_MIN_REDUNDANCY; 1286 probe->ip_cachestate |= CACHE_IF_NEW; 1287 1288 cache_insert(probe); 1289 } 1290 1291 probepif = probe->ip_pif; 1292 if (probepif != NULL) { 1293 /* Check if lifs need to be updated */ 1294 probelif = probepif->pi_lifs; 1295 while (probelif != NULL) { 1296 if ((probelif->li_ifnum == ifnumber) && 1297 (probelif->li_addr.family == ifaddr.ss_family)) { 1298 1299 rcm_log_message(RCM_TRACE2, 1300 "IP: refreshing lifs for %s, ifnum=%d\n", 1301 pif.pi_ifname, probelif->li_ifnum); 1302 1303 /* refresh lif properties */ 1304 (void) memcpy(&probelif->li_addr, &ifaddr, 1305 sizeof (probelif->li_addr)); 1306 1307 probelif->li_ifflags = ifflags; 1308 1309 lif_listed++; 1310 probe->ip_cachestate |= CACHE_IF_UPDATED; 1311 probelif->li_cachestate &= ~(CACHE_IF_STALE); 1312 break; 1313 } 1314 probelif = probelif->li_next; 1315 } 1316 } 1317 1318 if (probepif == NULL) { 1319 if ((probepif = calloc(1, sizeof (ip_pif_t))) == NULL) { 1320 rcm_log_message(RCM_ERROR, _("IP: malloc: %s\n"), 1321 strerror(errno)); 1322 if (probe->ip_pif == NULL) { 1323 /* we created it, so clean it up */ 1324 free(probe); 1325 } 1326 return (-1); 1327 } 1328 1329 probe->ip_pif = probepif; 1330 1331 probe->ip_cachestate |= CACHE_IF_UPDATED; 1332 1333 /* Save interface name */ 1334 (void) memcpy(&probepif->pi_ifname, &pif.pi_ifname, 1335 sizeof (pif.pi_ifname)); 1336 } 1337 1338 /* save pif properties */ 1339 probepif->pi_ifindex = pif.pi_ifindex; 1340 (void) memcpy(&probepif->pi_grpname, &pif.pi_grpname, 1341 sizeof (pif.pi_grpname)); 1342 probepif->pi_style = pif.pi_style; 1343 probepif->pi_ppa = pif.pi_ppa; 1344 1345 /* add lif, if this is a lif and it is not in cache */ 1346 if (!lif_listed) { 1347 rcm_log_message(RCM_TRACE2, "IP: adding lifs to %s\n", 1348 pif.pi_ifname); 1349 1350 if ((probelif = calloc(1, sizeof (ip_lif_t))) == NULL) { 1351 rcm_log_message(RCM_ERROR, _("IP: malloc: %s\n"), 1352 strerror(errno)); 1353 return (-1); 1354 } 1355 1356 /* save lif properties */ 1357 (void) memcpy(&probelif->li_addr, &ifaddr, 1358 sizeof (probelif->li_addr)); 1359 1360 probelif->li_ifnum = ifnumber; 1361 probelif->li_ifflags = ifflags; 1362 1363 /* insert us at the head of the lif list */ 1364 probelif->li_next = probepif->pi_lifs; 1365 if (probelif->li_next != NULL) { 1366 probelif->li_next->li_prev = probelif; 1367 } 1368 probelif->li_prev = NULL; 1369 probelif->li_pif = probepif; 1370 1371 probepif->pi_lifs = probelif; 1372 probelif->li_cachestate = CACHE_IF_NEW; 1373 1374 probe->ip_cachestate |= CACHE_IF_UPDATED; 1375 } 1376 1377 rcm_log_message(RCM_TRACE3, "IP: update_pif: (%s) success\n", 1378 probe->ip_resource); 1379 1380 return (0); 1381 } 1382 1383 /* 1384 * update_ipifs() - Determine all network interfaces in the system 1385 * Call with cache_lock held 1386 */ 1387 static int 1388 update_ipifs(rcm_handle_t *hd, int af) 1389 { 1390 int sock; 1391 char *buf; 1392 struct lifnum lifn; 1393 struct lifconf lifc; 1394 struct lifreq *lifrp; 1395 int i; 1396 1397 rcm_log_message(RCM_TRACE2, "IP: update_ipifs\n"); 1398 1399 if ((sock = socket(af, SOCK_DGRAM, 0)) == -1) { 1400 rcm_log_message(RCM_ERROR, 1401 _("IP: failure opening %s socket: %s\n"), 1402 af == AF_INET6 ? "IPv6" : "IPv4", strerror(errno)); 1403 return (-1); 1404 } 1405 1406 lifn.lifn_family = af; 1407 lifn.lifn_flags = 0; 1408 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { 1409 rcm_log_message(RCM_ERROR, 1410 _("IP: SIOCLGIFNUM failed: %s\n"), 1411 strerror(errno)); 1412 (void) close(sock); 1413 return (-1); 1414 } 1415 1416 if ((buf = calloc(lifn.lifn_count, sizeof (struct lifreq))) == NULL) { 1417 rcm_log_message(RCM_ERROR, _("IP: calloc: %s\n"), 1418 strerror(errno)); 1419 (void) close(sock); 1420 return (-1); 1421 } 1422 1423 lifc.lifc_family = af; 1424 lifc.lifc_flags = 0; 1425 lifc.lifc_len = sizeof (struct lifreq) * lifn.lifn_count; 1426 lifc.lifc_buf = buf; 1427 1428 if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) { 1429 rcm_log_message(RCM_ERROR, 1430 _("IP: SIOCGLIFCONF failed: %s\n"), 1431 strerror(errno)); 1432 free(buf); 1433 (void) close(sock); 1434 return (-1); 1435 } 1436 1437 /* now we need to search for active interfaces */ 1438 lifrp = lifc.lifc_req; 1439 for (i = 0; i < lifn.lifn_count; i++) { 1440 (void) update_pif(hd, af, sock, lifrp); 1441 lifrp++; 1442 } 1443 1444 free(buf); 1445 (void) close(sock); 1446 return (0); 1447 } 1448 1449 /* 1450 * update_cache() - Update cache with latest interface info 1451 */ 1452 static int 1453 update_cache(rcm_handle_t *hd) 1454 { 1455 ip_cache_t *probe; 1456 struct ip_lif *lif; 1457 struct ip_lif *nextlif; 1458 int rv; 1459 int i; 1460 1461 rcm_log_message(RCM_TRACE2, "IP: update_cache\n"); 1462 1463 (void) mutex_lock(&cache_lock); 1464 1465 /* first we walk the entire cache, marking each entry stale */ 1466 probe = cache_head.ip_next; 1467 while (probe != &cache_tail) { 1468 probe->ip_cachestate |= CACHE_IF_STALE; 1469 if ((probe->ip_pif != NULL) && 1470 ((lif = probe->ip_pif->pi_lifs) != NULL)) { 1471 while (lif != NULL) { 1472 lif->li_cachestate |= CACHE_IF_STALE; 1473 lif = lif->li_next; 1474 } 1475 } 1476 probe = probe->ip_next; 1477 } 1478 1479 rcm_log_message(RCM_TRACE2, "IP: scanning IPv4 interfaces\n"); 1480 if (update_ipifs(hd, AF_INET) < 0) { 1481 (void) mutex_unlock(&cache_lock); 1482 return (-1); 1483 } 1484 1485 rcm_log_message(RCM_TRACE2, "IP: scanning IPv6 interfaces\n"); 1486 if (update_ipifs(hd, AF_INET6) < 0) { 1487 (void) mutex_unlock(&cache_lock); 1488 return (-1); 1489 } 1490 1491 probe = cache_head.ip_next; 1492 /* unregister devices that are not offlined and still in cache */ 1493 while (probe != &cache_tail) { 1494 ip_cache_t *freeit; 1495 if ((probe->ip_pif != NULL) && 1496 ((lif = probe->ip_pif->pi_lifs) != NULL)) { 1497 /* clear stale lifs */ 1498 while (lif != NULL) { 1499 if (lif->li_cachestate & CACHE_IF_STALE) { 1500 nextlif = lif->li_next; 1501 if (lif->li_prev != NULL) 1502 lif->li_prev->li_next = nextlif; 1503 if (nextlif != NULL) 1504 nextlif->li_prev = lif->li_prev; 1505 if (probe->ip_pif->pi_lifs == lif) 1506 probe->ip_pif->pi_lifs = 1507 nextlif; 1508 for (i = 0; i < IP_MAX_MODS; i++) { 1509 free(lif->li_modules[i]); 1510 } 1511 free(lif->li_reconfig); 1512 free(lif); 1513 lif = nextlif; 1514 } else { 1515 lif = lif->li_next; 1516 } 1517 } 1518 } 1519 if ((probe->ip_cachestate & CACHE_IF_STALE) && 1520 !(probe->ip_cachestate & CACHE_IF_OFFLINED)) { 1521 (void) rcm_unregister_interest(hd, probe->ip_resource, 1522 0); 1523 rcm_log_message(RCM_DEBUG, "IP: unregistered %s\n", 1524 probe->ip_resource); 1525 freeit = probe; 1526 probe = probe->ip_next; 1527 cache_remove(freeit); 1528 free_node(freeit); 1529 continue; 1530 } 1531 1532 if (!(probe->ip_cachestate & CACHE_IF_NEW)) { 1533 probe = probe->ip_next; 1534 continue; 1535 } 1536 1537 rv = rcm_register_interest(hd, probe->ip_resource, 0, NULL); 1538 if (rv != RCM_SUCCESS) { 1539 rcm_log_message(RCM_ERROR, 1540 _("IP: failed to register %s\n"), 1541 probe->ip_resource); 1542 (void) mutex_unlock(&cache_lock); 1543 return (-1); 1544 } else { 1545 rcm_log_message(RCM_DEBUG, "IP: registered %s\n", 1546 probe->ip_resource); 1547 probe->ip_cachestate &= ~(CACHE_IF_NEW); 1548 } 1549 probe = probe->ip_next; 1550 } 1551 1552 (void) mutex_unlock(&cache_lock); 1553 return (0); 1554 } 1555 1556 /* 1557 * free_cache() - Empty the cache 1558 */ 1559 static void 1560 free_cache() 1561 { 1562 ip_cache_t *probe; 1563 1564 rcm_log_message(RCM_TRACE2, "IP: free_cache\n"); 1565 1566 (void) mutex_lock(&cache_lock); 1567 probe = cache_head.ip_next; 1568 while (probe != &cache_tail) { 1569 cache_remove(probe); 1570 free_node(probe); 1571 probe = cache_head.ip_next; 1572 } 1573 (void) mutex_unlock(&cache_lock); 1574 } 1575 1576 /* 1577 * ip_log_err() - RCM error log wrapper 1578 */ 1579 static void 1580 ip_log_err(ip_cache_t *node, char **errorp, char *errmsg) 1581 { 1582 char *nic = NULL; 1583 int len; 1584 const char *errfmt; 1585 char *error; 1586 1587 if ((node != NULL) && (node->ip_pif != NULL) && 1588 (node->ip_pif->pi_ifname != NULL)) { 1589 nic = strrchr(node->ip_pif->pi_ifname, '/'); 1590 nic = nic ? nic + 1 : node->ip_pif->pi_ifname; 1591 } 1592 1593 if (errorp != NULL) 1594 *errorp = NULL; 1595 1596 if (nic == NULL) { 1597 rcm_log_message(RCM_ERROR, _("IP: %s\n"), errmsg); 1598 errfmt = _("IP: %s"); 1599 len = strlen(errfmt) + strlen(errmsg) + 1; 1600 if (error = (char *)calloc(1, len)) { 1601 (void) sprintf(error, errfmt, errmsg); 1602 } 1603 } else { 1604 rcm_log_message(RCM_ERROR, _("IP: %s(%s)\n"), errmsg, nic); 1605 errfmt = _("IP: %s(%s)"); 1606 len = strlen(errfmt) + strlen(errmsg) + strlen(nic) + 1; 1607 if (error = (char *)calloc(1, len)) { 1608 (void) sprintf(error, errfmt, errmsg, nic); 1609 } 1610 } 1611 1612 if (errorp != NULL) 1613 *errorp = error; 1614 } 1615 1616 1617 /* 1618 * if_cfginfo() - Save off the config info for all interfaces 1619 */ 1620 static int 1621 if_cfginfo(ip_cache_t *node, uint_t force) 1622 { 1623 ip_lif_t *lif; 1624 ip_pif_t *pif; 1625 int i; 1626 FILE *fp; 1627 char syscmd[MAX_RECONFIG_SIZE + LIFNAMSIZ]; 1628 char buf[MAX_RECONFIG_SIZE]; 1629 1630 rcm_log_message(RCM_TRACE2, "IP: if_cfginfo(%s)\n", node->ip_resource); 1631 1632 pif = node->ip_pif; 1633 lif = pif->pi_lifs; 1634 1635 while (lif != NULL) { 1636 /* Make a list of modules pushed and save */ 1637 if (lif->li_ifnum == 0) { /* physical instance */ 1638 if (get_modlist(pif->pi_ifname, lif) == -1) { 1639 rcm_log_message(RCM_ERROR, 1640 _("IP: get modlist error (%s) %s\n"), 1641 pif->pi_ifname, strerror(errno)); 1642 (void) clr_cfg_state(pif); 1643 return (-1); 1644 } 1645 1646 if (!force) { 1647 /* Look if unknown modules have been inserted */ 1648 for (i = (lif->li_modcnt - 2); i > 0; i--) { 1649 if (modop(pif->pi_ifname, 1650 lif->li_modules[i], 1651 i, MOD_CHECK) == -1) { 1652 rcm_log_message(RCM_ERROR, 1653 _("IP: module %s@%d\n"), 1654 lif->li_modules[i], i); 1655 (void) clr_cfg_state(pif); 1656 return (-1); 1657 } 1658 } 1659 } 1660 1661 /* Last module is the device driver, so ignore that */ 1662 for (i = (lif->li_modcnt - 2); i > 0; i--) { 1663 rcm_log_message(RCM_TRACE2, 1664 "IP: modremove Pos = %d, Module = %s \n", 1665 i, lif->li_modules[i]); 1666 if (modop(pif->pi_ifname, lif->li_modules[i], 1667 i, MOD_REMOVE) == -1) { 1668 while (i != (lif->li_modcnt - 2)) { 1669 if (modop(pif->pi_ifname, 1670 lif->li_modules[i], 1671 i, MOD_INSERT) == -1) { 1672 /* Gross error */ 1673 rcm_log_message( 1674 RCM_ERROR, 1675 _("IP: if_cfginfo" 1676 "(%s) %s\n"), 1677 pif->pi_ifname, 1678 strerror(errno)); 1679 clr_cfg_state(pif); 1680 return (-1); 1681 } 1682 i++; 1683 } 1684 rcm_log_message( 1685 RCM_ERROR, 1686 _("IP: if_cfginfo(%s): modremove " 1687 "%s failed: %s\n"), pif->pi_ifname, 1688 lif->li_modules[i], 1689 strerror(errno)); 1690 clr_cfg_state(pif); 1691 return (-1); 1692 } 1693 } 1694 } 1695 1696 /* Save reconfiguration information */ 1697 if (lif->li_ifflags & IFF_IPV4) { 1698 (void) snprintf(syscmd, sizeof (syscmd), 1699 "%s %s:%d configinfo\n", USR_SBIN_IFCONFIG, 1700 pif->pi_ifname, lif->li_ifnum); 1701 } else if (lif->li_ifflags & IFF_IPV6) { 1702 (void) snprintf(syscmd, sizeof (syscmd), 1703 "%s %s:%d inet6 configinfo\n", USR_SBIN_IFCONFIG, 1704 pif->pi_ifname, lif->li_ifnum); 1705 } 1706 rcm_log_message(RCM_TRACE2, "IP: %s\n", syscmd); 1707 1708 /* open a pipe to retrieve reconfiguration info */ 1709 if ((fp = popen(syscmd, "r")) == NULL) { 1710 rcm_log_message(RCM_ERROR, 1711 _("IP: ifconfig configinfo error (%s:%d) %s\n"), 1712 pif->pi_ifname, lif->li_ifnum, strerror(errno)); 1713 (void) clr_cfg_state(pif); 1714 return (-1); 1715 } 1716 bzero(buf, MAX_RECONFIG_SIZE); 1717 1718 if (fgets(buf, MAX_RECONFIG_SIZE, fp) == NULL) { 1719 rcm_log_message(RCM_ERROR, 1720 _("IP: ifconfig configinfo error (%s:%d) %s\n"), 1721 pif->pi_ifname, lif->li_ifnum, strerror(errno)); 1722 (void) pclose(fp); 1723 (void) clr_cfg_state(pif); 1724 return (-1); 1725 } 1726 (void) pclose(fp); 1727 1728 lif->li_reconfig = malloc(strlen(buf)+1); 1729 if (lif->li_reconfig == NULL) { 1730 rcm_log_message(RCM_ERROR, 1731 _("IP: malloc error (%s) %s\n"), 1732 pif->pi_ifname, strerror(errno)); 1733 (void) clr_cfg_state(pif); 1734 return (-1); 1735 } 1736 (void) strcpy(lif->li_reconfig, buf); 1737 rcm_log_message(RCM_DEBUG, 1738 "IP: if_cfginfo: reconfig string(%s:%d) = %s\n", 1739 pif->pi_ifname, lif->li_ifnum, lif->li_reconfig); 1740 1741 lif = lif->li_next; 1742 } 1743 1744 return (0); 1745 } 1746 1747 /* 1748 * if_unplumb() - Unplumb the interface 1749 * Save off the modlist, ifconfig options and unplumb. 1750 * Fail, if an unknown module lives between IP and driver and 1751 * force is not set 1752 * Call with cache_lock held 1753 */ 1754 static int 1755 if_unplumb(ip_cache_t *node) 1756 { 1757 ip_lif_t *lif; 1758 ip_pif_t *pif; 1759 int ipv4 = 0, ipv6 = 0; 1760 char syscmd[MAX_RECONFIG_SIZE + LIFNAMSIZ]; 1761 1762 rcm_log_message(RCM_TRACE2, "IP: if_unplumb(%s)\n", node->ip_resource); 1763 1764 pif = node->ip_pif; 1765 lif = pif->pi_lifs; 1766 1767 while (lif != NULL) { 1768 if (lif->li_ifflags & IFF_IPV4) { 1769 ipv4++; 1770 } else if (lif->li_ifflags & IFF_IPV6) { 1771 ipv6++; 1772 } else { 1773 /* Unlikely case */ 1774 rcm_log_message(RCM_DEBUG, 1775 _("IP: Unplumb ignored (%s:%d)\n"), 1776 pif->pi_ifname, lif->li_ifnum); 1777 lif = lif->li_next; 1778 continue; 1779 } 1780 lif = lif->li_next; 1781 } 1782 1783 /* Unplumb the physical interface */ 1784 if (ipv4) { 1785 rcm_log_message(RCM_TRACE2, 1786 "IP: if_unplumb: ifconfig %s unplumb\n", pif->pi_ifname); 1787 (void) snprintf(syscmd, sizeof (syscmd), "%s %s unplumb\n", 1788 USR_SBIN_IFCONFIG, pif->pi_ifname); 1789 if (rcm_exec_cmd(syscmd) != 0) { 1790 rcm_log_message(RCM_ERROR, 1791 _("IP: Cannot unplumb (%s) %s\n"), 1792 pif->pi_ifname, strerror(errno)); 1793 return (-1); 1794 } 1795 } 1796 if (ipv6) { 1797 rcm_log_message(RCM_TRACE2, 1798 "IP: if_unplumb: ifconfig %s inet6 unplumb\n", 1799 pif->pi_ifname); 1800 (void) snprintf(syscmd, sizeof (syscmd), 1801 "%s %s inet6 unplumb\n", USR_SBIN_IFCONFIG, pif->pi_ifname); 1802 if (rcm_exec_cmd(syscmd) != 0) { 1803 rcm_log_message(RCM_ERROR, 1804 _("IP: Cannot unplumb (%s) %s\n"), 1805 pif->pi_ifname, strerror(errno)); 1806 return (-1); 1807 } 1808 } 1809 rcm_log_message(RCM_TRACE2, "IP: if_unplumb(%s) success\n", 1810 node->ip_resource); 1811 1812 return (0); 1813 } 1814 1815 /* 1816 * if_replumb() - Undo previous unplumb i.e. plumb back the physical interface 1817 * instances and the logical interfaces in order, restoring 1818 * all ifconfig options 1819 * Call with cache_lock held 1820 */ 1821 static int 1822 if_replumb(ip_cache_t *node) 1823 { 1824 ip_lif_t *lif; 1825 ip_pif_t *pif; 1826 int i; 1827 char syscmd[LIFNAMSIZ+MAXPATHLEN]; /* must be big enough */ 1828 int max_ipv4 = 0, max_ipv6 = 0; 1829 1830 rcm_log_message(RCM_TRACE2, "IP: if_replumb(%s)\n", node->ip_resource); 1831 1832 /* 1833 * Be extra careful about bringing up the interfaces in the 1834 * correct order: 1835 * - First plumb in the physical interface instances 1836 * - modinsert the necessary modules@pos 1837 * - Next, add the logical interfaces being careful about 1838 * the order, (follow the cached interface number li_ifnum order) 1839 */ 1840 1841 pif = node->ip_pif; 1842 lif = pif->pi_lifs; 1843 1844 /* 1845 * Make a first pass to plumb in physical interfaces and get a count 1846 * of the max logical interfaces 1847 */ 1848 while (lif != NULL) { 1849 if (lif->li_ifflags & IFF_IPV4) { 1850 if (lif->li_ifnum > max_ipv4) { 1851 max_ipv4 = lif->li_ifnum; 1852 } 1853 } else if (lif->li_ifflags & IFF_IPV6) { 1854 if (lif->li_ifnum > max_ipv6) { 1855 max_ipv6 = lif->li_ifnum; 1856 } 1857 } else { 1858 /* Unlikely case */ 1859 rcm_log_message(RCM_DEBUG, 1860 _("IP: Re-plumb ignored (%s:%d)\n"), 1861 pif->pi_ifname, lif->li_ifnum); 1862 lif = lif->li_next; 1863 continue; 1864 } 1865 1866 if (lif->li_ifnum == 0) { /* physical interface instance */ 1867 if ((lif->li_ifflags & IFF_NOFAILOVER) || 1868 (strcmp(pif->pi_grpname, "") == 0)) { 1869 (void) snprintf(syscmd, sizeof (syscmd), 1870 "%s %s\n", USR_SBIN_IFCONFIG, 1871 lif->li_reconfig); 1872 } else if (lif->li_ifflags & IFF_IPV4) { 1873 (void) snprintf(syscmd, sizeof (syscmd), 1874 "%s %s inet plumb group %s\n", 1875 USR_SBIN_IFCONFIG, 1876 pif->pi_ifname, pif->pi_grpname); 1877 } else if (lif->li_ifflags & IFF_IPV6) { 1878 (void) snprintf(syscmd, sizeof (syscmd), 1879 "%s %s inet6 plumb group %s\n", 1880 USR_SBIN_IFCONFIG, 1881 pif->pi_ifname, pif->pi_grpname); 1882 } 1883 1884 rcm_log_message(RCM_TRACE2, 1885 "IP: if_replumb: %s\n", syscmd); 1886 if (rcm_exec_cmd(syscmd) != 0) { 1887 rcm_log_message(RCM_ERROR, 1888 _("IP: Cannot plumb (%s) %s\n"), 1889 pif->pi_ifname, strerror(errno)); 1890 return (-1); 1891 } 1892 1893 rcm_log_message(RCM_TRACE2, 1894 "IP: if_replumb: Modcnt = %d\n", lif->li_modcnt); 1895 /* modinsert modules in order, ignore driver(last) */ 1896 for (i = 0; i < (lif->li_modcnt - 1); i++) { 1897 rcm_log_message(RCM_TRACE2, 1898 "IP: modinsert: Pos = %d Mod = %s\n", 1899 i, lif->li_modules[i]); 1900 if (modop(pif->pi_ifname, lif->li_modules[i], i, 1901 MOD_INSERT) == -1) { 1902 rcm_log_message(RCM_ERROR, 1903 _("IP: modinsert error(%s)\n"), 1904 pif->pi_ifname); 1905 return (-1); 1906 } 1907 } 1908 } 1909 1910 lif = lif->li_next; 1911 } 1912 1913 /* Now, add all the logical interfaces in the correct order */ 1914 for (i = 1; i <= MAX(max_ipv6, max_ipv4); i++) { 1915 /* reset lif through every iteration */ 1916 lif = pif->pi_lifs; 1917 while (lif != NULL) { 1918 if (((lif->li_ifflags & IFF_NOFAILOVER) || 1919 (strcmp(pif->pi_grpname, "") == 0)) && 1920 (lif->li_ifnum == i)) { 1921 /* Plumb in the logical interface */ 1922 (void) snprintf(syscmd, sizeof (syscmd), 1923 "%s %s\n", USR_SBIN_IFCONFIG, 1924 lif->li_reconfig); 1925 rcm_log_message(RCM_TRACE2, 1926 "IP: if_replumb: %s\n", syscmd); 1927 if (rcm_exec_cmd(syscmd) != 0) { 1928 rcm_log_message(RCM_ERROR, 1929 _("IP: Cannot addif (%s:%d) " 1930 "%s\n"), 1931 pif->pi_ifname, i, strerror(errno)); 1932 return (-1); 1933 } 1934 } 1935 lif = lif->li_next; 1936 } 1937 } 1938 1939 rcm_log_message(RCM_TRACE2, "IP: if_replumb(%s) success \n", 1940 node->ip_resource); 1941 1942 return (0); 1943 } 1944 1945 /* 1946 * clr_cfg_state() - Cleanup after errors in unplumb 1947 */ 1948 static void 1949 clr_cfg_state(ip_pif_t *pif) 1950 { 1951 ip_lif_t *lif; 1952 int i; 1953 1954 lif = pif->pi_lifs; 1955 1956 while (lif != NULL) { 1957 lif->li_modcnt = 0; 1958 free(lif->li_reconfig); 1959 lif->li_reconfig = NULL; 1960 for (i = 0; i < IP_MAX_MODS; i++) { 1961 free(lif->li_modules[i]); 1962 lif->li_modules[i] = NULL; 1963 } 1964 lif = lif->li_next; 1965 } 1966 } 1967 1968 /* 1969 * ip_ipmp_offline() - Failover from if_from to if_to using a 1970 * minimum redudancy of min_red. This uses IPMPs 1971 * "offline" mechanism to achieve the failover. 1972 */ 1973 static int 1974 ip_ipmp_offline(ip_cache_t *if_from, ip_cache_t *if_to) 1975 { 1976 mpathd_cmd_t mpdcmd; 1977 1978 if ((if_from == NULL) || (if_from->ip_pif == NULL) || 1979 (if_from->ip_pif->pi_ifname == NULL)) { 1980 return (-1); 1981 } 1982 1983 rcm_log_message(RCM_TRACE1, "IP: ip_ipmp_offline\n"); 1984 1985 mpdcmd.cmd_command = MI_OFFLINE; 1986 (void) strcpy(mpdcmd.cmd_ifname, if_from->ip_pif->pi_ifname); 1987 1988 if ((if_to != NULL) && (if_to->ip_pif != NULL) && 1989 (if_to->ip_pif->pi_ifname != NULL)) { 1990 rcm_log_message(RCM_TRACE1, "IP: ip_ipmp_offline (%s)->(%s)\n", 1991 if_from->ip_pif->pi_ifname, if_to->ip_pif->pi_ifname); 1992 (void) strncpy(mpdcmd.cmd_movetoif, if_to->ip_pif->pi_ifname, 1993 sizeof (mpdcmd.cmd_movetoif)); 1994 mpdcmd.cmd_movetoif[sizeof (mpdcmd.cmd_movetoif) - 1] = '\0'; 1995 } else { 1996 rcm_log_message(RCM_TRACE1, "IP: ip_ipmp_offline (%s)->(any)\n", 1997 if_from->ip_pif->pi_ifname); 1998 (void) strcpy(mpdcmd.cmd_movetoif, ""); /* signifies any */ 1999 } 2000 mpdcmd.cmd_min_red = if_from->ip_ifred; 2001 2002 if (mpathd_send_cmd(&mpdcmd) < 0) { 2003 rcm_log_message(RCM_ERROR, 2004 _("IP: mpathd offline error: %s\n"), 2005 strerror(errno)); 2006 return (-1); 2007 } 2008 2009 rcm_log_message(RCM_TRACE1, "IP: ipmp offline success\n"); 2010 return (0); 2011 } 2012 2013 /* 2014 * ip_ipmp_undo_offline() - Undo prior offline of the interface. 2015 * This uses IPMPs "undo offline" feature. 2016 */ 2017 static int 2018 ip_ipmp_undo_offline(ip_cache_t *node) 2019 { 2020 mpathd_cmd_t mpdcmd; 2021 2022 mpdcmd.cmd_command = MI_UNDO_OFFLINE; 2023 (void) strcpy(mpdcmd.cmd_ifname, node->ip_pif->pi_ifname); 2024 2025 if (mpathd_send_cmd(&mpdcmd) < 0) { 2026 rcm_log_message(RCM_ERROR, 2027 _("IP: mpathd error: %s\n"), 2028 strerror(errno)); 2029 return (-1); 2030 } 2031 2032 rcm_log_message(RCM_TRACE1, "IP: ipmp undo offline success\n"); 2033 return (0); 2034 } 2035 2036 /* 2037 * is_virtual() - Determine whether the specified device is a virtual 2038 * device managed by dld. 2039 */ 2040 static boolean_t 2041 is_virtual(char *ifname) 2042 { 2043 dladm_attr_t attr; 2044 2045 return (dladm_info(ifname, &attr) == 0); 2046 } 2047 2048 /* 2049 * getdlpi_style() - Determine the DLPI provider style of the interface 2050 */ 2051 static int 2052 getdlpi_style(char *ifname) 2053 { 2054 int local_fd; 2055 char devname[RCM_NET_RESOURCE_MAX]; 2056 2057 (void) snprintf(devname, sizeof (devname), "%s/%s", SLASH_DEV, ifname); 2058 2059 /* First try DLPI style 1 */ 2060 if ((local_fd = open(devname, O_RDWR)) != -1) { 2061 (void) close(local_fd); 2062 return (DL_STYLE1); 2063 } 2064 2065 return (DL_STYLE2); 2066 } 2067 2068 /* 2069 * get_ppa() - Determine the ppa for an interface, DLPI style 2 only 2070 */ 2071 static int 2072 get_ppa(char *rsrc) 2073 { 2074 int i; 2075 uint_t p = 0; 2076 unsigned int m = 1; 2077 2078 i = strlen(rsrc) - 1; 2079 while (i >= 0 && '0' <= rsrc[i] && rsrc[i] <= '9') { 2080 p += (rsrc[i] - '0')*m; 2081 m *= 10; 2082 i--; 2083 } 2084 if (m == 1) { 2085 return (-1); 2086 } 2087 return (is_virtual(rsrc) ? p : VLAN_GET_PPA(p)); /* VLAN support */ 2088 } 2089 2090 /* 2091 * get_lun() - Determine the logical interface number 2092 */ 2093 static int 2094 get_lun(char *rsrc) 2095 { 2096 char resource[RCM_NET_RESOURCE_MAX]; 2097 char *cp; 2098 2099 (void) strcpy(resource, rsrc); 2100 2101 /* remove LIF component */ 2102 cp = strchr(resource, ':'); 2103 if (cp) { 2104 cp++; 2105 return (atoi(cp)); 2106 } 2107 2108 return (0); 2109 } 2110 2111 /* 2112 * get_physical_resource() - Determine the actual physical interface name. 2113 * Supports VLAN interfaces. 2114 * Caller must free the malloced space for the string. 2115 */ 2116 static char * 2117 get_physical_resource(char *rsrc) 2118 { 2119 char *resource; 2120 char *ifname; 2121 char *nic; 2122 int ppa; 2123 2124 resource = (char *)malloc(strlen(rsrc) + 1); 2125 if (resource == NULL) { 2126 rcm_log_message(RCM_ERROR, 2127 _("IP: malloc error(%s): %s\n"), strerror(errno), rsrc); 2128 return (NULL); 2129 } 2130 (void) strcpy(resource, rsrc); 2131 2132 /* remove LIF component if any */ 2133 nic = strchr(resource, ':'); 2134 if (nic) { 2135 *nic = 0; 2136 } 2137 2138 ppa = get_ppa(resource); 2139 2140 /* Determine device name */ 2141 nic = resource; 2142 while (nic++) { 2143 if (('0' <= *nic) && (*nic <= '9')) { 2144 *nic = 0; 2145 break; 2146 } 2147 } 2148 2149 ifname = (char *)malloc(RCM_NET_RESOURCE_MAX); 2150 if (ifname == NULL) { 2151 rcm_log_message(RCM_ERROR, 2152 _("IP: malloc error(%s): %s\n"), strerror(errno), rsrc); 2153 free(resource); 2154 return (NULL); 2155 } 2156 2157 if (ppa < 0) { 2158 /* This could be a network group */ 2159 (void) snprintf(ifname, RCM_NET_RESOURCE_MAX, "%s", resource); 2160 } else { 2161 (void) snprintf(ifname, RCM_NET_RESOURCE_MAX, "%s%d", 2162 resource, ppa); 2163 } 2164 2165 free(resource); 2166 return (ifname); 2167 } 2168 2169 /* 2170 * if_change_flags() - set/clear the flag specified for the physical interface 2171 * Call with cache_lock held 2172 */ 2173 static int 2174 if_change_flags(ip_pif_t *pif, uint64_t flags, boolean_t set) 2175 { 2176 int sock; 2177 struct lifreq lifr; 2178 ip_lif_t *lif; 2179 2180 if (!(flags & RCM_PIF_FLAGS)) { 2181 rcm_log_message(RCM_DEBUG, 2182 "IP: if_change_flags: Not a physical interface flag\n"); 2183 return (-1); 2184 } 2185 2186 /* IPv4 is ok, since we only manipulate physical interface flags */ 2187 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { 2188 rcm_log_message(RCM_ERROR, 2189 _("IPv4 socket open: %s\n"), strerror(errno)); 2190 return (-1); 2191 } 2192 2193 /* 2194 * Get the current flags from the kernel, and set/clear the 2195 * desired phyint flags. 2196 */ 2197 (void) strncpy(lifr.lifr_name, pif->pi_ifname, sizeof (lifr.lifr_name)); 2198 lifr.lifr_name[sizeof (lifr.lifr_name) - 1] = '\0'; 2199 if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 2200 rcm_log_message(RCM_DEBUG, 2201 "ioctl SIOCGLIFFLAGS: %s\n", strerror(errno)); 2202 (void) close(sock); 2203 return (-1); 2204 } 2205 if (set) 2206 lifr.lifr_flags |= flags; 2207 else 2208 lifr.lifr_flags &= ~flags; 2209 if (ioctl(sock, SIOCSLIFFLAGS, (char *)&lifr) < 0) { 2210 rcm_log_message(RCM_DEBUG, 2211 "ioctl SIOCSLIFFLAGS: %s\n", strerror(errno)); 2212 (void) close(sock); 2213 return (-1); 2214 } 2215 2216 (void) close(sock); 2217 2218 /* Keep cached flags consistent. */ 2219 for (lif = pif->pi_lifs; lif != NULL; lif = lif->li_next) { 2220 if (lif->li_ifnum == 0) { 2221 if (set) 2222 lif->li_ifflags |= flags; 2223 else 2224 lif->li_ifflags &= ~flags; 2225 } 2226 } 2227 2228 return (0); 2229 } 2230 2231 /* 2232 * if_get_flags() - Return the cached physical interface flags 2233 * Call with cache_lock held 2234 */ 2235 static uint64_t 2236 if_get_flags(ip_pif_t *pif) 2237 { 2238 ip_lif_t *lif; 2239 2240 for (lif = pif->pi_lifs; lif != NULL; lif = lif->li_next) { 2241 if (lif->li_ifnum == 0) { 2242 return (lif->li_ifflags & RCM_PIF_FLAGS); 2243 } 2244 } 2245 return (0); 2246 } 2247 2248 /* 2249 * mpathd_send_cmd() - Sends the command to in.mpathd. 2250 */ 2251 static int 2252 mpathd_send_cmd(mpathd_cmd_t *mpd) 2253 { 2254 mpathd_unoffline_t mpc; 2255 struct mpathd_response mpr; 2256 int i; 2257 int s; 2258 2259 rcm_log_message(RCM_TRACE1, "IP: mpathd_send_cmd \n"); 2260 2261 for (i = 0; i < MPATHD_MAX_RETRIES; i++) { 2262 s = connect_to_mpathd(AF_INET); 2263 if (s == -1) { 2264 s = connect_to_mpathd(AF_INET6); 2265 if (s == -1) { 2266 rcm_log_message(RCM_ERROR, 2267 _("IP: Cannot talk to mpathd\n")); 2268 return (-1); 2269 } 2270 } 2271 switch (mpd->cmd_command) { 2272 case MI_OFFLINE : 2273 rcm_log_message(RCM_TRACE1, "IP: MI_OFFLINE: " 2274 "(%s)->(%s) redundancy = %d\n", mpd->cmd_ifname, 2275 mpd->cmd_movetoif, mpd->cmd_min_red); 2276 2277 if (write(s, mpd, sizeof (mpathd_cmd_t)) != 2278 sizeof (mpathd_cmd_t)) { 2279 rcm_log_message(RCM_ERROR, 2280 _("IP: mpathd write: %s\n"), 2281 strerror(errno)); 2282 (void) close(s); 2283 return (-1); 2284 } 2285 break; 2286 2287 case MI_SETOINDEX : 2288 rcm_log_message(RCM_TRACE1, "IP: MI_SETOINDEX: " 2289 "(%s)->(%s) family = %d\n", mpd->from_lifname, 2290 mpd->to_pifname, mpd->addr_family); 2291 2292 if (write(s, mpd, sizeof (mpathd_cmd_t)) != 2293 sizeof (mpathd_cmd_t)) { 2294 rcm_log_message(RCM_ERROR, 2295 _("IP: mpathd write: %s\n"), 2296 strerror(errno)); 2297 (void) close(s); 2298 return (-1); 2299 } 2300 break; 2301 2302 case MI_UNDO_OFFLINE: 2303 /* mpathd checks for exact size of the message */ 2304 mpc.cmd_command = mpd->cmd_command; 2305 (void) strcpy(mpc.cmd_ifname, mpd->cmd_ifname); 2306 2307 rcm_log_message(RCM_TRACE1, "IP: MI_UNDO_OFFLINE: " 2308 "(%s)\n", mpd->cmd_ifname); 2309 2310 if (write(s, &mpc, sizeof (mpathd_unoffline_t)) != 2311 sizeof (mpathd_unoffline_t)) { 2312 rcm_log_message(RCM_ERROR, 2313 _("IP: mpathd write: %s\n"), 2314 strerror(errno)); 2315 (void) close(s); 2316 return (-1); 2317 } 2318 break; 2319 default : 2320 rcm_log_message(RCM_ERROR, 2321 _("IP: unsupported mpathd command\n")); 2322 (void) close(s); 2323 return (-1); 2324 } 2325 2326 bzero(&mpr, sizeof (struct mpathd_response)); 2327 /* Read the result from mpathd */ 2328 if (read(s, &mpr, sizeof (struct mpathd_response)) != 2329 sizeof (struct mpathd_response)) { 2330 rcm_log_message(RCM_ERROR, 2331 _("IP: mpathd read : %s\n"), strerror(errno)); 2332 (void) close(s); 2333 return (-1); 2334 } 2335 2336 (void) close(s); 2337 if (mpr.resp_mpathd_err == 0) { 2338 rcm_log_message(RCM_TRACE1, 2339 "IP: mpathd_send_cmd success\n"); 2340 return (0); /* Successful */ 2341 } 2342 2343 if (mpr.resp_mpathd_err == MPATHD_SYS_ERROR) { 2344 if (mpr.resp_sys_errno == EAGAIN) { 2345 (void) sleep(1); 2346 rcm_log_message(RCM_DEBUG, 2347 _("IP: mpathd retrying\n")); 2348 continue; /* Retry */ 2349 } 2350 errno = mpr.resp_sys_errno; 2351 rcm_log_message(RCM_WARNING, 2352 _("IP: mpathd_send_cmd error: %s\n"), 2353 strerror(errno)); 2354 } else if (mpr.resp_mpathd_err == MPATHD_MIN_RED_ERROR) { 2355 errno = EIO; 2356 rcm_log_message(RCM_ERROR, _("IP: in.mpathd(1M): " 2357 "Minimum redundancy not met\n")); 2358 } else { 2359 rcm_log_message(RCM_ERROR, 2360 _("IP: mpathd_send_cmd error\n")); 2361 } 2362 /* retry */ 2363 } 2364 2365 rcm_log_message(RCM_ERROR, 2366 _("IP: mpathd_send_cmd failed %d retries\n"), MPATHD_MAX_RETRIES); 2367 return (-1); 2368 } 2369 2370 /* 2371 * Returns -1 on failure. Returns the socket file descriptor on 2372 * success. 2373 */ 2374 static int 2375 connect_to_mpathd(int family) 2376 { 2377 int s; 2378 struct sockaddr_storage ss; 2379 struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 2380 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 2381 struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; 2382 int addrlen; 2383 int ret; 2384 int on; 2385 2386 rcm_log_message(RCM_TRACE1, "IP: connect_to_mpathd\n"); 2387 2388 s = socket(family, SOCK_STREAM, 0); 2389 if (s < 0) { 2390 rcm_log_message(RCM_ERROR, 2391 _("IP: mpathd socket: %s\n"), strerror(errno)); 2392 return (-1); 2393 } 2394 bzero((char *)&ss, sizeof (ss)); 2395 ss.ss_family = family; 2396 /* 2397 * Need to bind to a privelged port. For non-root, this 2398 * will fail. in.mpathd verifies that only commands coming 2399 * from priveleged ports succeed so that the ordinary user 2400 * can't issue offline commands. 2401 */ 2402 on = 1; 2403 if (setsockopt(s, IPPROTO_TCP, TCP_ANONPRIVBIND, &on, 2404 sizeof (on)) < 0) { 2405 rcm_log_message(RCM_ERROR, 2406 _("IP: mpathd setsockopt: TCP_ANONPRIVBIND: %s\n"), 2407 strerror(errno)); 2408 return (-1); 2409 } 2410 switch (family) { 2411 case AF_INET: 2412 sin->sin_port = 0; 2413 sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 2414 addrlen = sizeof (struct sockaddr_in); 2415 break; 2416 case AF_INET6: 2417 sin6->sin6_port = 0; 2418 sin6->sin6_addr = loopback_addr; 2419 addrlen = sizeof (struct sockaddr_in6); 2420 break; 2421 } 2422 ret = bind(s, (struct sockaddr *)&ss, addrlen); 2423 if (ret != 0) { 2424 rcm_log_message(RCM_ERROR, 2425 _("IP: mpathd bind: %s\n"), strerror(errno)); 2426 return (-1); 2427 } 2428 switch (family) { 2429 case AF_INET: 2430 sin->sin_port = htons(MPATHD_PORT); 2431 break; 2432 case AF_INET6: 2433 sin6->sin6_port = htons(MPATHD_PORT); 2434 break; 2435 } 2436 ret = connect(s, (struct sockaddr *)&ss, addrlen); 2437 if (ret != 0) { 2438 if (errno == ECONNREFUSED) { 2439 /* in.mpathd is not running, start it */ 2440 if (rcm_exec_cmd(MPATHD_PATH) == -1) { 2441 rcm_log_message(RCM_ERROR, 2442 _("IP: mpathd exec: %s\n"), 2443 strerror(errno)); 2444 return (-1); 2445 } 2446 ret = connect(s, (struct sockaddr *)&ss, addrlen); 2447 } 2448 if (ret != 0) { 2449 rcm_log_message(RCM_ERROR, 2450 _("IP: mpathd connect: %s\n"), strerror(errno)); 2451 return (-1); 2452 } 2453 } 2454 on = 0; 2455 if (setsockopt(s, IPPROTO_TCP, TCP_ANONPRIVBIND, &on, 2456 sizeof (on)) < 0) { 2457 rcm_log_message(RCM_ERROR, 2458 _("IP: mpathd setsockopt TCP_ANONPRIVBIND: %s\n"), 2459 strerror(errno)); 2460 return (-1); 2461 } 2462 2463 rcm_log_message(RCM_TRACE1, "IP: connect_to_mpathd success\n"); 2464 2465 return (s); 2466 } 2467 2468 /* 2469 * modop() - Remove/insert a module 2470 */ 2471 static int 2472 modop(char *name, char *arg, int pos, char op) 2473 { 2474 char syscmd[LIFNAMSIZ+MAXPATHLEN]; /* must be big enough */ 2475 2476 rcm_log_message(RCM_TRACE1, "IP: modop(%s)\n", name); 2477 2478 /* Nothing to do with "ip", "arp" */ 2479 if ((arg == NULL) || (strcmp(arg, "") == 0) || 2480 STREQ(arg, IP_MOD_NAME) || STREQ(arg, ARP_MOD_NAME)) { 2481 rcm_log_message(RCM_TRACE1, "IP: modop success\n"); 2482 return (0); 2483 } 2484 2485 if (op == MOD_CHECK) { 2486 /* 2487 * No known good modules (yet) apart from ip and arp 2488 * which are handled above 2489 */ 2490 return (-1); 2491 } 2492 2493 if (op == MOD_REMOVE) { 2494 (void) snprintf(syscmd, sizeof (syscmd), 2495 "%s %s modremove %s@%d\n", USR_SBIN_IFCONFIG, name, arg, 2496 pos); 2497 } else if (op == MOD_INSERT) { 2498 (void) snprintf(syscmd, sizeof (syscmd), 2499 "%s %s modinsert %s@%d\n", USR_SBIN_IFCONFIG, name, arg, 2500 pos); 2501 } else { 2502 rcm_log_message(RCM_ERROR, 2503 _("IP: modop(%s): unknown operation\n"), name); 2504 return (-1); 2505 } 2506 2507 rcm_log_message(RCM_TRACE1, "IP: modop(%s): %s\n", name, syscmd); 2508 if (rcm_exec_cmd(syscmd) == -1) { 2509 rcm_log_message(RCM_ERROR, 2510 _("IP: modop(%s): %s\n"), name, strerror(errno)); 2511 return (-1); 2512 } 2513 2514 rcm_log_message(RCM_TRACE1, "IP: modop success\n"); 2515 return (0); 2516 } 2517 2518 /* 2519 * get_modlist() - return a list of pushed mid-stream modules 2520 * Required memory is malloced to construct the list, 2521 * Caller must free this memory list 2522 * Call with cache_lock held 2523 */ 2524 static int 2525 get_modlist(char *name, ip_lif_t *lif) 2526 { 2527 int udp_fd; 2528 int fd; 2529 int i; 2530 int num_mods; 2531 struct lifreq lifr; 2532 struct str_list strlist; 2533 2534 rcm_log_message(RCM_TRACE1, "IP: getmodlist(%s)\n", name); 2535 2536 (void) strncpy(lifr.lifr_name, name, sizeof (lifr.lifr_name)); 2537 lifr.lifr_flags = lif->li_ifflags; 2538 if (ip_domux2fd(&udp_fd, &fd, &lifr) < 0) { 2539 rcm_log_message(RCM_ERROR, _("IP: ip_domux2fd(%s)\n"), name); 2540 return (-1); 2541 } 2542 2543 if ((num_mods = ioctl(fd, I_LIST, NULL)) < 0) { 2544 rcm_log_message(RCM_ERROR, 2545 _("IP: get_modlist(%s): I_LIST(%s) \n"), 2546 name, strerror(errno)); 2547 (void) ip_plink(udp_fd, fd, &lifr); 2548 return (-1); 2549 } 2550 2551 strlist.sl_nmods = num_mods; 2552 strlist.sl_modlist = malloc(sizeof (struct str_mlist) * num_mods); 2553 2554 if (strlist.sl_modlist == NULL) { 2555 rcm_log_message(RCM_ERROR, _("IP: get_modlist(%s): %s\n"), 2556 name, strerror(errno)); 2557 (void) ip_plink(udp_fd, fd, &lifr); 2558 return (-1); 2559 } 2560 2561 if (ioctl(fd, I_LIST, (caddr_t)&strlist) < 0) { 2562 rcm_log_message(RCM_ERROR, 2563 _("IP: get_modlist(%s): I_LIST error: %s\n"), 2564 name, strerror(errno)); 2565 (void) ip_plink(udp_fd, fd, &lifr); 2566 return (-1); 2567 } 2568 2569 for (i = 0; i < strlist.sl_nmods; i++) { 2570 lif->li_modules[i] = 2571 malloc(strlen(strlist.sl_modlist[i].l_name)+1); 2572 if (lif->li_modules[i] == NULL) { 2573 rcm_log_message(RCM_ERROR, 2574 _("IP: get_modlist(%s): %s\n"), 2575 name, strerror(errno)); 2576 (void) ip_plink(udp_fd, fd, &lifr); 2577 return (-1); 2578 } 2579 (void) strcpy(lif->li_modules[i], strlist.sl_modlist[i].l_name); 2580 } 2581 2582 lif->li_modcnt = strlist.sl_nmods; 2583 free(strlist.sl_modlist); 2584 2585 rcm_log_message(RCM_TRACE1, "IP: getmodlist(%s) success\n", name); 2586 return (ip_plink(udp_fd, fd, &lifr)); 2587 } 2588 2589 /* 2590 * ip_domux2fd() - Helper function for mod*() functions 2591 * Stolen from ifconfig.c 2592 */ 2593 static int 2594 ip_domux2fd(int *udp_fd, int *fd, struct lifreq *lifr) 2595 { 2596 int ip_fd; 2597 char *udp_dev_name; 2598 char *ip_dev_name; 2599 2600 if (lifr->lifr_flags & IFF_IPV6) { 2601 udp_dev_name = UDP6_DEV_NAME; 2602 ip_dev_name = IP6_DEV_NAME; 2603 } else { 2604 udp_dev_name = UDP_DEV_NAME; 2605 ip_dev_name = IP_DEV_NAME; 2606 } 2607 2608 if ((ip_fd = open(ip_dev_name, O_RDWR)) < 0) { 2609 rcm_log_message(RCM_ERROR, _("IP: ip_domux2fd: open(%s) %s\n"), 2610 ip_dev_name, strerror(errno)); 2611 return (-1); 2612 } 2613 if ((*udp_fd = open(udp_dev_name, O_RDWR)) < 0) { 2614 rcm_log_message(RCM_ERROR, _("IP: ip_domux2fd: open(%s) %s\n"), 2615 udp_dev_name, strerror(errno)); 2616 (void) close(ip_fd); 2617 return (-1); 2618 } 2619 if (ioctl(ip_fd, SIOCGLIFMUXID, (caddr_t)lifr) < 0) { 2620 rcm_log_message(RCM_ERROR, 2621 _("IP: ip_domux2fd: SIOCGLIFMUXID(%s): %s\n"), 2622 ip_dev_name, strerror(errno)); 2623 (void) close(*udp_fd); 2624 (void) close(ip_fd); 2625 return (-1); 2626 } 2627 2628 rcm_log_message(RCM_TRACE2, 2629 "IP: ip_domux2fd: ARP_muxid %d IP_muxid %d\n", 2630 lifr->lifr_arp_muxid, lifr->lifr_ip_muxid); 2631 2632 if ((*fd = ioctl(*udp_fd, _I_MUXID2FD, lifr->lifr_ip_muxid)) < 0) { 2633 rcm_log_message(RCM_ERROR, 2634 _("IP: ip_domux2fd: _I_MUXID2FD(%s): %s\n"), 2635 udp_dev_name, strerror(errno)); 2636 (void) close(*udp_fd); 2637 (void) close(ip_fd); 2638 return (-1); 2639 } 2640 if (ioctl(*udp_fd, I_PUNLINK, lifr->lifr_ip_muxid) < 0) { 2641 rcm_log_message(RCM_ERROR, 2642 _("IP: ip_domux2fd: I_PUNLINK(%s): %s\n"), 2643 udp_dev_name, strerror(errno)); 2644 (void) close(*udp_fd); 2645 (void) close(ip_fd); 2646 return (-1); 2647 } 2648 2649 /* Note: udp_fd is closed in ip_plink below */ 2650 (void) close(ip_fd); 2651 return (0); 2652 } 2653 2654 /* 2655 * ip_plink() - Helper function for mod*() functions. 2656 * Stolen from ifconfig.c 2657 */ 2658 static int 2659 ip_plink(int udp_fd, int fd, struct lifreq *lifr) 2660 { 2661 int mux_id; 2662 2663 if ((mux_id = ioctl(udp_fd, I_PLINK, fd)) < 0) { 2664 rcm_log_message(RCM_ERROR, _("IP: ip_plink I_PLINK(%s): %s\n"), 2665 UDP_DEV_NAME, strerror(errno)); 2666 (void) close(udp_fd); 2667 (void) close(fd); 2668 return (-1); 2669 } 2670 2671 lifr->lifr_ip_muxid = mux_id; 2672 if (ioctl(udp_fd, SIOCSLIFMUXID, (caddr_t)lifr) < 0) { 2673 rcm_log_message(RCM_ERROR, 2674 _("IP: ip_plink SIOCSLIFMUXID(%s): %s\n"), 2675 UDP_DEV_NAME, strerror(errno)); 2676 (void) close(udp_fd); 2677 (void) close(fd); 2678 return (-1); 2679 } 2680 2681 (void) close(udp_fd); 2682 (void) close(fd); 2683 return (0); 2684 } 2685 2686 /* 2687 * ip_onlinelist() 2688 * 2689 * Notify online to IP address consumers. 2690 */ 2691 static int 2692 ip_onlinelist(rcm_handle_t *hd, ip_cache_t *node, char **errorp, uint_t flags, 2693 rcm_info_t **depend_info) 2694 { 2695 char **addrlist; 2696 int ret = RCM_SUCCESS; 2697 2698 rcm_log_message(RCM_TRACE2, "IP: ip_onlinelist\n"); 2699 2700 addrlist = ip_get_addrlist(node); 2701 if (addrlist == NULL || addrlist[0] == NULL) { 2702 rcm_log_message(RCM_TRACE2, "IP: ip_onlinelist none\n"); 2703 ip_free_addrlist(addrlist); 2704 return (ret); 2705 } 2706 2707 ret = rcm_notify_online_list(hd, addrlist, 0, depend_info); 2708 2709 ip_free_addrlist(addrlist); 2710 rcm_log_message(RCM_TRACE2, "IP: ip_onlinelist done\n"); 2711 return (ret); 2712 } 2713 2714 /* 2715 * ip_offlinelist() 2716 * 2717 * Offline IP address consumers. 2718 */ 2719 static int 2720 ip_offlinelist(rcm_handle_t *hd, ip_cache_t *node, char **errorp, uint_t flags, 2721 rcm_info_t **depend_info) 2722 { 2723 char **addrlist; 2724 int ret = RCM_SUCCESS; 2725 2726 rcm_log_message(RCM_TRACE2, "IP: ip_offlinelist\n"); 2727 2728 addrlist = ip_get_addrlist(node); 2729 if (addrlist == NULL || addrlist[0] == NULL) { 2730 rcm_log_message(RCM_TRACE2, "IP: ip_offlinelist none\n"); 2731 ip_free_addrlist(addrlist); 2732 return (RCM_SUCCESS); 2733 } 2734 2735 if ((ret = rcm_request_offline_list(hd, addrlist, flags, depend_info)) 2736 != RCM_SUCCESS) { 2737 if (ret == RCM_FAILURE) 2738 (void) rcm_notify_online_list(hd, addrlist, 0, NULL); 2739 2740 ret = RCM_FAILURE; 2741 } 2742 2743 ip_free_addrlist(addrlist); 2744 rcm_log_message(RCM_TRACE2, "IP: ip_offlinelist done\n"); 2745 return (ret); 2746 } 2747 2748 /* 2749 * ip_get_addrlist() - Compile list of IP addresses hosted on this NIC (node) 2750 * This routine malloc() required memeory for the list 2751 * Returns list on success, NULL if failed 2752 * Call with cache_lock held. 2753 */ 2754 static char ** 2755 ip_get_addrlist(ip_cache_t *node) 2756 { 2757 ip_lif_t *lif; 2758 char **addrlist = NULL; 2759 int numifs; 2760 char addrstr[INET6_ADDRSTRLEN]; 2761 void *addr; 2762 int af; 2763 int i; 2764 2765 rcm_log_message(RCM_TRACE2, "IP: ip_get_addrlist(%s)\n", 2766 node->ip_resource); 2767 2768 numifs = 0; 2769 for (lif = node->ip_pif->pi_lifs; lif != NULL; lif = lif->li_next) { 2770 numifs++; 2771 } 2772 2773 /* 2774 * Allocate space for resource names list; add 1 and use calloc() 2775 * so that the list is NULL-terminated. 2776 */ 2777 if ((addrlist = calloc(numifs + 1, sizeof (char *))) == NULL) { 2778 rcm_log_message(RCM_ERROR, 2779 _("IP: ip_get_addrlist(%s) malloc failure(%s)\n"), 2780 node->ip_resource, strerror(errno)); 2781 return (NULL); 2782 } 2783 2784 for (lif = node->ip_pif->pi_lifs, i = 0; lif != NULL; 2785 lif = lif->li_next, i++) { 2786 2787 af = lif->li_addr.family; 2788 if (af == AF_INET6) { 2789 addr = &lif->li_addr.ip6.sin6_addr; 2790 } else if (af == AF_INET) { 2791 addr = &lif->li_addr.ip4.sin_addr; 2792 } else { 2793 rcm_log_message(RCM_DEBUG, 2794 "IP: unknown addr family %d, assuming AF_INET\n", 2795 af); 2796 af = AF_INET; 2797 addr = &lif->li_addr.ip4.sin_addr; 2798 } 2799 if (inet_ntop(af, addr, addrstr, INET6_ADDRSTRLEN) == NULL) { 2800 rcm_log_message(RCM_ERROR, 2801 _("IP: inet_ntop: %s\n"), strerror(errno)); 2802 ip_free_addrlist(addrlist); 2803 return (NULL); 2804 } 2805 2806 if ((addrlist[i] = malloc(strlen(addrstr) + RCM_SIZE_SUNW_IP)) 2807 == NULL) { 2808 rcm_log_message(RCM_ERROR, 2809 _("IP: ip_get_addrlist(%s) malloc failure(%s)\n"), 2810 node->ip_resource, strerror(errno)); 2811 ip_free_addrlist(addrlist); 2812 return (NULL); 2813 } 2814 (void) strcpy(addrlist[i], RCM_STR_SUNW_IP); /* SUNW_ip/ */ 2815 (void) strcat(addrlist[i], addrstr); /* SUNW_ip/<address> */ 2816 2817 rcm_log_message(RCM_DEBUG, "Anon Address: %s\n", addrlist[i]); 2818 } 2819 2820 rcm_log_message(RCM_TRACE2, "IP: get_addrlist (%s) done\n", 2821 node->ip_resource); 2822 2823 return (addrlist); 2824 } 2825 2826 static void 2827 ip_free_addrlist(char **addrlist) 2828 { 2829 int i; 2830 2831 if (addrlist == NULL) 2832 return; 2833 2834 for (i = 0; addrlist[i] != NULL; i++) 2835 free(addrlist[i]); 2836 free(addrlist); 2837 } 2838 2839 /* 2840 * ip_consumer_notify() - Notify consumers of IP addresses coming back online. 2841 */ 2842 2843 static void 2844 ip_consumer_notify(rcm_handle_t *hd, char *ifinst, char **errorp, uint_t flags, 2845 rcm_info_t **depend_info) 2846 { 2847 char ifname[LIFNAMSIZ + 1]; 2848 char cached_name[RCM_NET_RESOURCE_MAX]; 2849 ip_cache_t *node; 2850 char *cp; 2851 2852 rcm_log_message(RCM_TRACE1, "IP: ip_consumer_notify(%s)\n", ifinst); 2853 2854 if (ifinst == NULL) 2855 return; 2856 2857 (void) memcpy(&ifname, ifinst, sizeof (ifname)); 2858 ifname[sizeof (ifname) - 1] = '\0'; 2859 2860 /* remove LIF component */ 2861 cp = strchr(ifname, ':'); 2862 if (cp) { 2863 *cp = 0; 2864 } 2865 2866 /* Check for the interface in the cache */ 2867 (void) snprintf(cached_name, sizeof (cached_name), "%s/%s", 2868 RCM_NET_PREFIX, ifname); 2869 2870 (void) mutex_lock(&cache_lock); 2871 if ((node = cache_lookup(hd, cached_name, CACHE_REFRESH)) == NULL) { 2872 rcm_log_message(RCM_TRACE1, "IP: Skipping interface(%s) \n", 2873 ifname); 2874 (void) mutex_unlock(&cache_lock); 2875 return; 2876 } 2877 /* 2878 * Inform anonymous consumers about IP addresses being 2879 * onlined 2880 */ 2881 (void) ip_onlinelist(hd, node, errorp, flags, depend_info); 2882 2883 (void) mutex_unlock(&cache_lock); 2884 2885 rcm_log_message(RCM_TRACE2, "IP: ip_consumer_notify success\n"); 2886 return; 2887 2888 } 2889 /* 2890 * process_nvlist() - Determine network interfaces on a new attach by 2891 * processing the nvlist 2892 */ 2893 /*ARGSUSED*/ 2894 static int 2895 process_nvlist(nvlist_t *nvl) 2896 { 2897 nvpair_t *nvp = NULL; 2898 char *driver_name; 2899 char *devfs_path; 2900 int32_t instance; 2901 char *minor_byte_array; /* packed nvlist of minor_data */ 2902 uint_t nminor; /* # of minor nodes */ 2903 struct devfs_minor_data *mdata; 2904 nvlist_t *mnvl; 2905 nvpair_t *mnvp = NULL; 2906 2907 rcm_log_message(RCM_TRACE1, "IP: process_nvlist\n"); 2908 2909 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { 2910 /* Get driver name */ 2911 if (STREQ(nvpair_name(nvp), RCM_NV_DRIVER_NAME)) { 2912 if (nvpair_value_string(nvp, &driver_name) != 0) { 2913 rcm_log_message(RCM_WARNING, 2914 _("IP: cannot get driver name\n")); 2915 return (-1); 2916 } 2917 } 2918 /* Get instance */ 2919 if (STREQ(nvpair_name(nvp), RCM_NV_INSTANCE)) { 2920 if (nvpair_value_int32(nvp, &instance) != 0) { 2921 rcm_log_message(RCM_WARNING, 2922 _("IP: cannot get device instance\n")); 2923 return (-1); 2924 } 2925 } 2926 /* Get devfs_path */ 2927 if (STREQ(nvpair_name(nvp), RCM_NV_DEVFS_PATH)) { 2928 if (nvpair_value_string(nvp, &devfs_path) != 0) { 2929 rcm_log_message(RCM_WARNING, 2930 _("IP: cannot get device path\n")); 2931 return (-1); 2932 } 2933 } 2934 /* Get minor data */ 2935 if (STREQ(nvpair_name(nvp), RCM_NV_MINOR_DATA)) { 2936 if (nvpair_value_byte_array(nvp, 2937 (uchar_t **)&minor_byte_array, &nminor) != 0) { 2938 rcm_log_message(RCM_WARNING, 2939 _("IP: cannot get device minor data\n")); 2940 return (-1); 2941 } 2942 if (nvlist_unpack(minor_byte_array, 2943 nminor, &mnvl, 0) != 0) { 2944 rcm_log_message(RCM_WARNING, 2945 _("IP: cannot get minor node data\n")); 2946 return (-1); 2947 } 2948 mdata = (struct devfs_minor_data *)calloc(1, 2949 sizeof (struct devfs_minor_data)); 2950 if (mdata == NULL) { 2951 rcm_log_message(RCM_WARNING, 2952 _("IP: calloc error(%s)\n"), 2953 strerror(errno)); 2954 nvlist_free(mnvl); 2955 return (-1); 2956 } 2957 /* Enumerate minor node data */ 2958 while ((mnvp = nvlist_next_nvpair(mnvl, mnvp)) != 2959 NULL) { 2960 /* Get minor type */ 2961 if (STREQ(nvpair_name(mnvp), 2962 RCM_NV_MINOR_TYPE)) { 2963 if (nvpair_value_int32(mnvp, 2964 &mdata->minor_type) != 0) { 2965 rcm_log_message(RCM_WARNING, 2966 _("IP: cannot get minor " 2967 "type \n")); 2968 nvlist_free(mnvl); 2969 return (-1); 2970 } 2971 } 2972 /* Get minor name */ 2973 if (STREQ(nvpair_name(mnvp), 2974 RCM_NV_MINOR_NAME)) { 2975 if (nvpair_value_string(mnvp, 2976 &mdata->minor_name) != 0) { 2977 rcm_log_message(RCM_WARNING, 2978 _("IP: cannot get minor " 2979 "name \n")); 2980 nvlist_free(mnvl); 2981 return (-1); 2982 } 2983 } 2984 /* Get minor node type */ 2985 if (STREQ(nvpair_name(mnvp), 2986 RCM_NV_MINOR_NODE_TYPE)) { 2987 if (nvpair_value_string(mnvp, 2988 &mdata->minor_node_type) != 0) { 2989 rcm_log_message(RCM_WARNING, 2990 _("IP: cannot get minor " 2991 "node type \n")); 2992 nvlist_free(mnvl); 2993 return (-1); 2994 } 2995 } 2996 } 2997 (void) process_minor(devfs_path, driver_name, instance, 2998 mdata); 2999 nvlist_free(mnvl); 3000 } 3001 } 3002 3003 rcm_log_message(RCM_TRACE1, "IP: process_nvlist success\n"); 3004 return (0); 3005 } 3006 3007 static void 3008 process_minor(char *devfs_path, char *name, int instance, 3009 struct devfs_minor_data *mdata) 3010 { 3011 struct net_interface *nip; 3012 struct ni_list *nilp; 3013 struct ni_list *p; 3014 struct ni_list **pp; 3015 char *cname; 3016 size_t cnamelen; 3017 char dev_name[MAXPATHLEN]; 3018 boolean_t virtual = B_FALSE; 3019 3020 rcm_log_message(RCM_TRACE1, "IP: process_minor\n"); 3021 3022 if ((mdata->minor_node_type != NULL) && 3023 !STREQ(mdata->minor_node_type, PROP_NV_DDI_NETWORK)) { 3024 /* Process network devices only */ 3025 return; 3026 } 3027 3028 rcm_log_message(RCM_TRACE1, "IP: Examining %s (%s)\n", 3029 devfs_path, mdata->minor_name); 3030 3031 /* 3032 * Virtual DDI_NT_NET nodes created by dld are exposed by devfs 3033 * for non-VLAN as well as VLANs. Determine if we're dealing 3034 * with a virtual device. 3035 */ 3036 if (strncmp("/pseudo", devfs_path, strlen("/pseudo")) == 0) { 3037 rcm_log_message(RCM_TRACE1, "IP: pseudo node %s (%s)\n", 3038 devfs_path, mdata->minor_name); 3039 if (strcmp(name, "dld") == 0) { 3040 if (dlpi_if_parse(mdata->minor_name, dev_name, 3041 &instance) < 0 || instance < 0) { 3042 /* dld always also creates a style-2 */ 3043 rcm_log_message(RCM_DEBUG, "IP: ignoring " 3044 "\"%s\" (style 1)\n", devfs_path); 3045 return; 3046 } 3047 name = dev_name; 3048 virtual = B_TRUE; 3049 rcm_log_message(RCM_TRACE1, "IP: virtual datalink " 3050 "%s%d\n", name, instance); 3051 } 3052 } 3053 3054 /* Sanity check, instances > 999 are illegal */ 3055 if (!virtual && instance > 999) { 3056 errno = EINVAL; 3057 rcm_log_message(RCM_ERROR, _("IP: invalid instance %d(%s)\n"), 3058 instance, strerror(errno)); 3059 return; 3060 } 3061 3062 /* Now, let's add the node to the interface list */ 3063 if ((nip = malloc(sizeof (struct net_interface))) == NULL) { 3064 rcm_log_message(RCM_ERROR, _("IP: malloc failure(%s)\n"), 3065 strerror(errno)); 3066 return; 3067 } 3068 (void) memset(nip, 0, sizeof (struct net_interface)); 3069 3070 cnamelen = strlen(name) + 1; 3071 /* Set NIC type */ 3072 if ((nip->type = (char *)malloc(cnamelen)) == NULL) { 3073 free(nip); 3074 rcm_log_message(RCM_ERROR, _("IP: malloc failure(%s)\n"), 3075 strerror(errno)); 3076 return; 3077 } 3078 (void) memcpy(nip->type, name, cnamelen); 3079 3080 cnamelen += MAXINTSTR; 3081 if ((cname = (char *)malloc(cnamelen)) == NULL) { 3082 free(nip->type); 3083 free(nip); 3084 rcm_log_message(RCM_ERROR, _("IP: malloc failure(%s)\n"), 3085 strerror(errno)); 3086 return; 3087 } 3088 (void) snprintf(cname, cnamelen, "%s%d", name, instance); 3089 3090 rcm_log_message(RCM_TRACE1, "IP: Found SUNW_network/%s%d\n", name, 3091 instance); 3092 3093 /* Set NIC name */ 3094 if ((nip->name = strdup(cname)) == NULL) { 3095 free(nip->type); 3096 free(nip); 3097 free(cname); 3098 rcm_log_message(RCM_ERROR, _("IP: strdup failure(%s)\n"), 3099 strerror(errno)); 3100 return; 3101 } 3102 free(cname); 3103 3104 /* Add new interface to the list */ 3105 (void) mutex_lock(&nil_lock); 3106 for (pp = &nil_head; (p = *pp) != NULL; pp = &(p->next)) { 3107 cname = p->nifp->name; 3108 if (strcmp(cname, nip->name) == 0) 3109 break; 3110 } 3111 3112 if (p != NULL) { 3113 (void) mutex_unlock(&nil_lock); 3114 free(nip->name); 3115 free(nip->type); 3116 free(nip); 3117 rcm_log_message(RCM_TRACE1, "IP: secondary node - ignoring\n"); 3118 return; 3119 } 3120 3121 if ((nilp = malloc(sizeof (struct ni_list))) == NULL) { 3122 (void) mutex_unlock(&nil_lock); 3123 free(nip->name); 3124 free(nip->type); 3125 free(nip); 3126 rcm_log_message(RCM_ERROR, _("IP: malloc failure(%s)\n"), 3127 strerror(errno)); 3128 return; 3129 } 3130 3131 nilp->nifp = nip; 3132 nilp->next = NULL; 3133 *pp = nilp; 3134 3135 num_ni++; /* Increment interface count */ 3136 3137 (void) mutex_unlock(&nil_lock); 3138 rcm_log_message(RCM_TRACE1, "IP: added new node\n"); 3139 } 3140 3141 /* 3142 * if_configure() - Configure a physical interface after attach 3143 */ 3144 static int 3145 if_configure(char *ifinst) 3146 { 3147 char cfgfile[MAXPATHLEN]; 3148 char ifname[LIFNAMSIZ + 1]; 3149 char cached_name[RCM_NET_RESOURCE_MAX]; 3150 struct stat statbuf; 3151 ip_cache_t *node; 3152 char *cp; 3153 int af = 0; 3154 int ipmp = 0; 3155 3156 if (ifinst == NULL) 3157 return (0); 3158 3159 rcm_log_message(RCM_TRACE1, "IP: if_configure(%s)\n", ifinst); 3160 3161 /* 3162 * Check if the interface is already configured 3163 */ 3164 3165 (void) memcpy(&ifname, ifinst, sizeof (ifname)); 3166 ifname[sizeof (ifname) - 1] = '\0'; 3167 3168 /* remove LIF component */ 3169 cp = strchr(ifname, ':'); 3170 if (cp) { 3171 *cp = 0; 3172 } 3173 3174 /* Check for the interface in the cache */ 3175 (void) snprintf(cached_name, sizeof (cached_name), "%s/%s", 3176 RCM_NET_PREFIX, ifname); 3177 3178 /* Check if the interface is new or was previously offlined */ 3179 (void) mutex_lock(&cache_lock); 3180 if (((node = cache_lookup(NULL, cached_name, CACHE_REFRESH)) != NULL) && 3181 (!(node->ip_cachestate & CACHE_IF_OFFLINED))) { 3182 rcm_log_message(RCM_TRACE1, 3183 "IP: Skipping configured interface(%s) \n", ifname); 3184 (void) mutex_unlock(&cache_lock); 3185 return (0); 3186 } 3187 (void) mutex_unlock(&cache_lock); 3188 3189 /* Scan IPv4 configuration first */ 3190 (void) snprintf(cfgfile, MAXPATHLEN, "%s%s", CFGFILE_FMT_IPV4, ifinst); 3191 cfgfile[MAXPATHLEN - 1] = '\0'; 3192 3193 rcm_log_message(RCM_TRACE1, "IP: Scanning %s\n", cfgfile); 3194 if (stat(cfgfile, &statbuf) == 0) { 3195 af |= CONFIG_AF_INET; 3196 if (isgrouped(cfgfile)) { 3197 ipmp++; 3198 } 3199 } 3200 3201 /* Scan IPv6 configuration details */ 3202 (void) snprintf(cfgfile, MAXPATHLEN, "%s%s", CFGFILE_FMT_IPV6, ifinst); 3203 cfgfile[MAXPATHLEN - 1] = '\0'; 3204 rcm_log_message(RCM_TRACE1, "IP: Scanning %s\n", cfgfile); 3205 if (stat(cfgfile, &statbuf) == 0) { 3206 af |= CONFIG_AF_INET6; 3207 if ((ipmp == 0) && isgrouped(cfgfile)) { 3208 ipmp++; 3209 } 3210 } 3211 3212 if (af & CONFIG_AF_INET) { 3213 if (if_ipmp_config(ifinst, CONFIG_AF_INET, ipmp) == -1) { 3214 rcm_log_message(RCM_ERROR, 3215 _("IP: IPv4 Post-attach failed (%s)\n"), ifinst); 3216 return (-1); 3217 } 3218 } 3219 3220 if (af & CONFIG_AF_INET6) { 3221 if (if_ipmp_config(ifinst, CONFIG_AF_INET6, ipmp) == -1) { 3222 rcm_log_message(RCM_ERROR, 3223 _("IP: IPv6 Post-attach failed(%s)\n"), ifinst); 3224 return (-1); 3225 } 3226 } 3227 3228 rcm_log_message(RCM_TRACE1, "IP: if_configure(%s) success\n", ifinst); 3229 3230 return (0); 3231 3232 } 3233 3234 /* 3235 * isgrouped() - Scans the given config file to see if this is a grouped 3236 * interface 3237 * Returns non-zero if true; 0 if false 3238 */ 3239 static int 3240 isgrouped(char *cfgfile) 3241 { 3242 FILE *fp; 3243 struct stat statb; 3244 char *buf = NULL; 3245 char *tokens[MAXARGS]; /* token pointers */ 3246 char tspace[MAXLINE]; /* token space */ 3247 int ntok; 3248 int group = 0; 3249 3250 if (cfgfile == NULL) 3251 return (0); 3252 3253 rcm_log_message(RCM_TRACE1, "IP: isgrouped(%s)\n", cfgfile); 3254 3255 if (stat(cfgfile, &statb) != 0) { 3256 rcm_log_message(RCM_TRACE1, 3257 _("IP: No config file(%s)\n"), cfgfile); 3258 return (0); 3259 } 3260 3261 /* 3262 * We also ignore single-byte config files because the file should 3263 * always be newline-terminated, so we know there's nothing of 3264 * interest. Further, a single-byte file would cause the fgets() loop 3265 * below to spin forever. 3266 */ 3267 if (statb.st_size <= 1) { 3268 rcm_log_message(RCM_TRACE1, 3269 _("IP: Empty config file(%s)\n"), cfgfile); 3270 return (0); 3271 } 3272 3273 if ((fp = fopen(cfgfile, "r")) == NULL) { 3274 rcm_log_message(RCM_ERROR, 3275 _("IP: Cannot open configuration file(%s): %s\n"), cfgfile, 3276 strerror(errno)); 3277 return (0); 3278 } 3279 3280 if ((buf = calloc(1, statb.st_size)) == NULL) { 3281 rcm_log_message(RCM_ERROR, 3282 _("IP: calloc failure(%s): %s\n"), cfgfile, 3283 strerror(errno)); 3284 (void) fclose(fp); 3285 return (0); 3286 } 3287 3288 while (fgets(buf, statb.st_size, fp) != NULL) { 3289 if (*buf == '\0') 3290 continue; 3291 3292 tokenize(buf, tokens, tspace, &ntok); 3293 while (ntok) { 3294 if (STREQ("group", tokens[ntok - 1])) { 3295 if (tokens[ntok] != NULL) { 3296 group++; 3297 } 3298 } 3299 ntok--; 3300 } 3301 } 3302 3303 free(buf); 3304 3305 (void) fclose(fp); 3306 3307 if (group <= 0) { 3308 rcm_log_message(RCM_TRACE1, "IP: isgrouped(%s) non-grouped\n", 3309 cfgfile); 3310 return (0); 3311 } else { 3312 rcm_log_message(RCM_TRACE1, "IP: isgrouped(%s) grouped\n", 3313 cfgfile); 3314 return (1); 3315 } 3316 } 3317 3318 3319 /* 3320 * if_ipmp_config() - Configure an interface instance as specified by the 3321 * address family af and if it is grouped (ipmp). 3322 */ 3323 static int 3324 if_ipmp_config(char *ifinst, int af, int ipmp) 3325 { 3326 char cfgfile[MAXPATHLEN]; /* configuration file */ 3327 FILE *fp; 3328 struct stat statb; 3329 char *buf; 3330 char *tokens[MAXARGS]; /* list of config attributes */ 3331 char tspace[MAXLINE]; /* token space */ 3332 char syscmd[MAX_RECONFIG_SIZE + MAXPATHLEN + 1]; 3333 char grpcmd[MAX_RECONFIG_SIZE + MAXPATHLEN + 1]; 3334 char fstr[8]; /* address family string inet or inet6 */ 3335 int nofailover = 0; 3336 int newattach = 0; 3337 int cmdvalid = 0; 3338 int ntok; 3339 int n; 3340 int stdif = 0; 3341 3342 if (ifinst == NULL) 3343 return (0); 3344 3345 rcm_log_message(RCM_TRACE1, "IP: if_ipmp_config(%s) ipmp = %d\n", 3346 ifinst, ipmp); 3347 3348 if (af & CONFIG_AF_INET) { 3349 (void) snprintf(cfgfile, MAXPATHLEN, "%s%s", CFGFILE_FMT_IPV4, 3350 ifinst); 3351 (void) strcpy(fstr, "inet"); 3352 } else if (af & CONFIG_AF_INET6) { 3353 (void) snprintf(cfgfile, MAXPATHLEN, "%s%s", CFGFILE_FMT_IPV6, 3354 ifinst); 3355 (void) strcpy(fstr, "inet6"); 3356 } else { 3357 return (0); /* nothing to do */ 3358 } 3359 3360 cfgfile[MAXPATHLEN - 1] = '\0'; 3361 grpcmd[0] = '\0'; 3362 3363 if (stat(cfgfile, &statb) != 0) { 3364 rcm_log_message(RCM_TRACE1, 3365 _("IP: No config file(%s)\n"), ifinst); 3366 return (0); 3367 } 3368 3369 /* Config file exists, plumb in the physical interface */ 3370 if (af & CONFIG_AF_INET6) { 3371 if (if_getcount(AF_INET6) == 0) { 3372 /* 3373 * Configure software loopback driver if this is the 3374 * first IPv6 interface plumbed 3375 */ 3376 newattach++; 3377 (void) snprintf(syscmd, sizeof (syscmd), 3378 "%s lo0 %s plumb ::1 up", USR_SBIN_IFCONFIG, fstr); 3379 if (rcm_exec_cmd(syscmd) != 0) { 3380 rcm_log_message(RCM_ERROR, 3381 _("IP: Cannot plumb (%s) %s\n"), 3382 ifinst, strerror(errno)); 3383 return (-1); 3384 } 3385 } 3386 (void) snprintf(syscmd, sizeof (syscmd), "%s %s %s plumb up", 3387 USR_SBIN_IFCONFIG, ifinst, fstr); 3388 } else { 3389 (void) snprintf(syscmd, sizeof (syscmd), "%s %s %s plumb ", 3390 USR_SBIN_IFCONFIG, ifinst, fstr); 3391 if (if_getcount(AF_INET) == 0) { 3392 newattach++; 3393 } 3394 } 3395 rcm_log_message(RCM_TRACE1, "IP: Exec: %s\n", syscmd); 3396 3397 if (rcm_exec_cmd(syscmd) != 0) { 3398 rcm_log_message(RCM_ERROR, 3399 _("IP: Cannot plumb (%s) %s\n"), ifinst, strerror(errno)); 3400 return (-1); 3401 } 3402 3403 /* Check if config file is empty, if so, nothing else to do */ 3404 if (statb.st_size == 0) { 3405 rcm_log_message(RCM_TRACE1, 3406 _("IP: Zero size config file(%s)\n"), ifinst); 3407 return (0); 3408 } 3409 3410 if ((fp = fopen(cfgfile, "r")) == NULL) { 3411 rcm_log_message(RCM_ERROR, 3412 _("IP: Open error(%s): %s\n"), cfgfile, strerror(errno)); 3413 return (-1); 3414 } 3415 3416 if ((buf = calloc(1, statb.st_size)) == NULL) { 3417 rcm_log_message(RCM_ERROR, 3418 _("IP: calloc(%s): %s\n"), ifinst, strerror(errno)); 3419 (void) fclose(fp); 3420 return (-1); 3421 } 3422 3423 /* a single line with one token implies a classical if */ 3424 if (fgets(buf, statb.st_size, fp) != NULL) { 3425 tokenize(buf, tokens, tspace, &ntok); 3426 if (ntok == 1) { 3427 rcm_log_message(RCM_TRACE1, "IP: Standard interface\n"); 3428 stdif++; 3429 } 3430 } 3431 if (fseek(fp, 0L, SEEK_SET) == -1) { 3432 rcm_log_message(RCM_ERROR, _("IP: fseek: %s\n"), 3433 strerror(errno)); 3434 return (-1); 3435 } 3436 3437 /* 3438 * Process the config command 3439 * This loop also handles multiple logical interfaces that may 3440 * be configured on a single line 3441 */ 3442 while (fgets(buf, statb.st_size, fp) != NULL) { 3443 nofailover = 0; 3444 cmdvalid = 0; 3445 3446 if (*buf == '\0') 3447 continue; 3448 3449 tokenize(buf, tokens, tspace, &ntok); 3450 if (ntok <= 0) 3451 continue; 3452 3453 /* Reset the config command */ 3454 (void) snprintf(syscmd, sizeof (syscmd), "%s %s %s ", 3455 USR_SBIN_IFCONFIG, ifinst, fstr); 3456 3457 /* No parsing if this is first interface of its kind */ 3458 if (newattach) { 3459 (void) strcat(syscmd, buf); 3460 /* Classic if */ 3461 if ((af & CONFIG_AF_INET) && (stdif == 1)) { 3462 (void) strcat(syscmd, CFG_CMDS_STD); 3463 } 3464 rcm_log_message(RCM_TRACE1, "IP: New: %s\n", syscmd); 3465 if (rcm_exec_cmd(syscmd) != 0) { 3466 rcm_log_message(RCM_ERROR, 3467 _("IP: Error: %s (%s): %s\n"), 3468 syscmd, ifinst, strerror(errno)); 3469 } 3470 continue; 3471 } 3472 3473 /* Parse the tokens to determine nature of the interface */ 3474 for (n = 0; n < ntok; n++) { 3475 /* Handle pathological failover cases */ 3476 if (STREQ("-failover", tokens[n])) 3477 nofailover++; 3478 if (STREQ("failover", tokens[n])) 3479 nofailover--; 3480 3481 /* group attribute requires special processing */ 3482 if (STREQ("group", tokens[n])) { 3483 if (tokens[n + 1] != NULL) { 3484 (void) snprintf(grpcmd, sizeof (grpcmd), 3485 "%s %s %s %s %s", USR_SBIN_IFCONFIG, 3486 ifinst, fstr, 3487 tokens[n], tokens[n + 1]); 3488 n++; /* skip next token */ 3489 continue; 3490 } 3491 } 3492 3493 /* Execute buffered command ? */ 3494 if (STREQ("set", tokens[n]) || 3495 STREQ("addif", tokens[n]) || 3496 STREQ("removeif", tokens[n]) || 3497 (n == (ntok -1))) { 3498 3499 /* config command complete ? */ 3500 if (n == (ntok -1)) { 3501 ADDSPACE(syscmd); 3502 (void) strcat(syscmd, tokens[n]); 3503 cmdvalid++; 3504 } 3505 3506 if (!cmdvalid) { 3507 ADDSPACE(syscmd); 3508 (void) strcat(syscmd, tokens[n]); 3509 cmdvalid++; 3510 continue; 3511 } 3512 /* Classic if ? */ 3513 if ((af & CONFIG_AF_INET) && (stdif == 1)) { 3514 (void) strcat(syscmd, CFG_CMDS_STD); 3515 } 3516 3517 if (nofailover > 0) { 3518 rcm_log_message(RCM_TRACE1, 3519 "IP: Interim exec: %s\n", syscmd); 3520 if (rcm_exec_cmd(syscmd) != 0) { 3521 rcm_log_message(RCM_ERROR, 3522 _("IP: %s fail(%s): %s\n"), 3523 syscmd, ifinst, 3524 strerror(errno)); 3525 } 3526 } else { 3527 /* Have mpathd configure the address */ 3528 if (if_mpathd_configure(syscmd, ifinst, 3529 af, ipmp) != 0) { 3530 rcm_log_message(RCM_ERROR, 3531 _("IP: %s fail(%s): %s\n"), 3532 syscmd, ifinst, 3533 strerror(errno)); 3534 } 3535 } 3536 3537 /* Reset config command */ 3538 (void) snprintf(syscmd, sizeof (syscmd), 3539 "%s %s %s ", USR_SBIN_IFCONFIG, ifinst, 3540 fstr); 3541 nofailover = 0; 3542 cmdvalid = 0; 3543 } 3544 /* 3545 * Note: No explicit command validation is required 3546 * since ifconfig to does it for us 3547 */ 3548 ADDSPACE(syscmd); 3549 (void) strcat(syscmd, tokens[n]); 3550 cmdvalid++; 3551 } 3552 } 3553 3554 free(buf); 3555 (void) fclose(fp); 3556 3557 /* 3558 * The group name needs to be set after all the test/nofailover 3559 * addresses have been configured. Otherwise, if IPMP detects that the 3560 * interface is failed, the addresses will be moved to a working 3561 * interface before the '-failover' flag can be set. 3562 */ 3563 if (grpcmd[0] != '\0') { 3564 rcm_log_message(RCM_TRACE1, "IP: set group name: %s\n", grpcmd); 3565 if (rcm_exec_cmd(grpcmd) != 0) { 3566 rcm_log_message(RCM_ERROR, _("IP: %s fail(%s): %s\n"), 3567 grpcmd, ifinst, strerror(errno)); 3568 } 3569 } 3570 3571 rcm_log_message(RCM_TRACE1, "IP: if_ipmp_config(%s) success\n", ifinst); 3572 3573 return (0); 3574 } 3575 3576 /* 3577 * if_mpathd_configure() - Determine configuration disposition of the interface 3578 */ 3579 static int 3580 if_mpathd_configure(char *syscmd, char *ifinst, int af, int ipmp) 3581 { 3582 char *tokens[MAXARGS]; 3583 char tspace[MAXLINE]; 3584 int ntok; 3585 char *addr; 3586 char *from_lifname; 3587 mpathd_cmd_t mpdcmd; 3588 int n; 3589 3590 rcm_log_message(RCM_TRACE1, "IP: if_mpathd_configure(%s): %s\n", 3591 ifinst, syscmd); 3592 3593 tokenize(syscmd, tokens, tspace, &ntok); 3594 if (ntok <= 0) 3595 return (0); 3596 3597 addr = tokens[3]; /* by default, third token is valid address */ 3598 for (n = 0; n < ntok; n++) { 3599 if (STREQ("set", tokens[n]) || 3600 STREQ("addif", tokens[n])) { 3601 addr = tokens[n+1]; 3602 if (addr == NULL) { /* invalid format */ 3603 return (-1); 3604 } else 3605 break; 3606 } 3607 } 3608 3609 /* Check std. commands or no failed over address */ 3610 if (STREQ("removeif", addr) || STREQ("group", addr) || 3611 ((from_lifname = get_mpathd_dest(addr, af)) == NULL)) { 3612 rcm_log_message(RCM_TRACE1, 3613 "IP: No failed-over host, exec %s\n", syscmd); 3614 if (rcm_exec_cmd(syscmd) != 0) { 3615 rcm_log_message(RCM_ERROR, 3616 _("IP: %s failed(%s): %s\n"), 3617 syscmd, ifinst, strerror(errno)); 3618 return (-1); 3619 } 3620 return (0); 3621 } 3622 3623 /* Check for non-IPMP failover scenarios */ 3624 if ((ipmp <= 0) && (from_lifname != NULL)) { 3625 /* Address already hosted on another NIC, return */ 3626 rcm_log_message(RCM_TRACE1, 3627 "IP: Non-IPMP failed-over host(%s): %s\n", 3628 ifinst, addr); 3629 return (0); 3630 } 3631 3632 /* 3633 * Valid failed-over host; have mpathd set the original index 3634 */ 3635 mpdcmd.cmd_command = MI_SETOINDEX; 3636 (void) strcpy(mpdcmd.from_lifname, from_lifname); 3637 (void) strcpy(mpdcmd.to_pifname, ifinst); 3638 if (af & CONFIG_AF_INET6) { 3639 mpdcmd.addr_family = AF_INET6; 3640 } else { 3641 mpdcmd.addr_family = AF_INET; 3642 } 3643 3644 /* Send command to in.mpathd(1M) */ 3645 rcm_log_message(RCM_TRACE1, 3646 "IP: Attempting setoindex from (%s) to (%s) ....\n", 3647 from_lifname, ifinst); 3648 3649 if (mpathd_send_cmd(&mpdcmd) < 0) { 3650 rcm_log_message(RCM_TRACE1, 3651 _("IP: mpathd set original index unsuccessful: %s\n"), 3652 strerror(errno)); 3653 return (-1); 3654 } 3655 3656 rcm_log_message(RCM_TRACE1, 3657 "IP: setoindex success (%s) to (%s)\n", 3658 from_lifname, ifinst); 3659 3660 return (0); 3661 } 3662 3663 /* 3664 * get_mpathd_addr() - Return current destination for lif; caller is 3665 * responsible to free memory allocated for address 3666 */ 3667 static char * 3668 get_mpathd_dest(char *addr, int family) 3669 { 3670 int sock; 3671 char *buf; 3672 struct lifnum lifn; 3673 struct lifconf lifc; 3674 struct lifreq *lifrp; 3675 sa_family_t af = AF_INET; /* IPv4 by default */ 3676 int i; 3677 struct lifreq lifreq; 3678 struct sockaddr_in *sin; 3679 struct sockaddr_in6 *sin6; 3680 struct hostent *hp; 3681 char *ifname = NULL; 3682 char *prefix = NULL; 3683 char addrstr[INET6_ADDRSTRLEN]; 3684 char ifaddr[INET6_ADDRSTRLEN]; 3685 int err; 3686 3687 if (addr == NULL) { 3688 return (NULL); 3689 } 3690 3691 rcm_log_message(RCM_TRACE2, "IP: get_mpathd_dest(%s)\n", addr); 3692 3693 if (family & CONFIG_AF_INET6) { 3694 af = AF_INET6; 3695 } else { 3696 af = AF_INET; 3697 } 3698 3699 if ((sock = socket(af, SOCK_DGRAM, 0)) == -1) { 3700 rcm_log_message(RCM_ERROR, 3701 _("IP: failure opening %s socket: %s\n"), 3702 af == AF_INET6 ? "IPv6" : "IPv4", strerror(errno)); 3703 return (NULL); 3704 } 3705 3706 lifn.lifn_family = af; 3707 lifn.lifn_flags = 0; 3708 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { 3709 rcm_log_message(RCM_ERROR, 3710 _("IP: SIOCLGIFNUM failed: %s\n"), 3711 strerror(errno)); 3712 (void) close(sock); 3713 return (NULL); 3714 } 3715 3716 if ((buf = calloc(lifn.lifn_count, sizeof (struct lifreq))) == NULL) { 3717 rcm_log_message(RCM_ERROR, _("IP: calloc: %s\n"), 3718 strerror(errno)); 3719 (void) close(sock); 3720 return (NULL); 3721 } 3722 3723 lifc.lifc_family = af; 3724 lifc.lifc_flags = 0; 3725 lifc.lifc_len = sizeof (struct lifreq) * lifn.lifn_count; 3726 lifc.lifc_buf = buf; 3727 3728 if (ioctl(sock, SIOCGLIFCONF, (char *)&lifc) < 0) { 3729 rcm_log_message(RCM_ERROR, 3730 _("IP: SIOCGLIFCONF failed: %s\n"), 3731 strerror(errno)); 3732 free(buf); 3733 (void) close(sock); 3734 return (NULL); 3735 } 3736 3737 /* Filter out prefix address from netmask */ 3738 (void) strcpy(ifaddr, addr); 3739 if ((prefix = strchr(ifaddr, '/')) != NULL) { 3740 *prefix = '\0'; /* We care about the address part only */ 3741 } 3742 3743 /* Check for aliases */ 3744 hp = getipnodebyname(ifaddr, af, AI_DEFAULT, &err); 3745 if (hp) { 3746 if (inet_ntop(af, (void *)hp->h_addr_list[0], 3747 ifaddr, sizeof (ifaddr)) == NULL) { 3748 /* Restore original address and use it */ 3749 (void) strcpy(ifaddr, addr); 3750 if ((prefix = strchr(ifaddr, '/')) != NULL) { 3751 *prefix = '\0'; 3752 } 3753 } 3754 freehostent(hp); 3755 } 3756 rcm_log_message(RCM_TRACE2, "IP: ifaddr(%s) = %s\n", 3757 addr, ifaddr); 3758 3759 /* now search the interfaces */ 3760 lifrp = lifc.lifc_req; 3761 for (i = 0; i < lifn.lifn_count; i++, lifrp++) { 3762 (void) strcpy(lifreq.lifr_name, lifrp->lifr_name); 3763 /* Get the interface address for this interface */ 3764 if (ioctl(sock, SIOCGLIFADDR, (char *)&lifreq) < 0) { 3765 rcm_log_message(RCM_ERROR, 3766 _("IP: SIOCGLIFADDR: %s\n"), strerror(errno)); 3767 free(buf); 3768 (void) close(sock); 3769 return (NULL); 3770 } 3771 3772 if (af == AF_INET6) { 3773 sin6 = (struct sockaddr_in6 *)&lifreq.lifr_addr; 3774 if (inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, 3775 addrstr, sizeof (addrstr)) == NULL) { 3776 continue; 3777 } 3778 } else { 3779 sin = (struct sockaddr_in *)&lifreq.lifr_addr; 3780 if (inet_ntop(AF_INET, (void *)&sin->sin_addr, 3781 addrstr, sizeof (addrstr)) == NULL) { 3782 continue; 3783 } 3784 } 3785 3786 if (STREQ(addrstr, ifaddr)) { 3787 /* Allocate memory to hold interface name */ 3788 if ((ifname = (char *)malloc(LIFNAMSIZ)) == NULL) { 3789 rcm_log_message(RCM_ERROR, 3790 _("IP: malloc: %s\n"), strerror(errno)); 3791 free(buf); 3792 (void) close(sock); 3793 return (NULL); 3794 } 3795 3796 /* Copy the interface name */ 3797 /* 3798 * (void) memcpy(ifname, lifrp->lifr_name, 3799 * sizeof (ifname)); 3800 * ifname[sizeof (ifname) - 1] = '\0'; 3801 */ 3802 (void) strcpy(ifname, lifrp->lifr_name); 3803 break; 3804 } 3805 } 3806 3807 (void) close(sock); 3808 free(buf); 3809 3810 if (ifname == NULL) 3811 rcm_log_message(RCM_TRACE2, "IP: get_mpathd_dest(%s): none\n", 3812 addr); 3813 else 3814 rcm_log_message(RCM_TRACE2, "IP: get_mpathd_dest(%s): %s\n", 3815 addr, ifname); 3816 3817 return (ifname); 3818 } 3819 3820 static int 3821 if_getcount(int af) 3822 { 3823 int sock; 3824 struct lifnum lifn; 3825 3826 rcm_log_message(RCM_TRACE1, "IP: if_getcount\n"); 3827 3828 if ((sock = socket(af, SOCK_DGRAM, 0)) == -1) { 3829 rcm_log_message(RCM_ERROR, 3830 _("IP: failure opening %s socket: %s\n"), 3831 af == AF_INET6 ? "IPv6" : "IPv4", strerror(errno)); 3832 return (-1); 3833 } 3834 3835 lifn.lifn_family = af; 3836 lifn.lifn_flags = 0; 3837 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { 3838 rcm_log_message(RCM_ERROR, 3839 _("IP: SIOCLGIFNUM failed: %s\n"), 3840 strerror(errno)); 3841 (void) close(sock); 3842 return (-1); 3843 } 3844 (void) close(sock); 3845 3846 rcm_log_message(RCM_TRACE1, "IP: if_getcount success: %d\n", 3847 lifn.lifn_count); 3848 3849 return (lifn.lifn_count); 3850 } 3851 3852 /* 3853 * tokenize() - turn a command line into tokens; caller is responsible to 3854 * provide enough memory to hold all tokens 3855 */ 3856 static void 3857 tokenize(char *line, char **tokens, char *tspace, int *ntok) 3858 { 3859 char *cp; 3860 char *sp; 3861 3862 sp = tspace; 3863 cp = line; 3864 for (*ntok = 0; *ntok < MAXARGS; (*ntok)++) { 3865 tokens[*ntok] = sp; 3866 while (ISSPACE(*cp)) 3867 cp++; 3868 if (ISEOL(*cp)) 3869 break; 3870 do { 3871 *sp++ = *cp++; 3872 } while (!ISSPACE(*cp) && !ISEOL(*cp)); 3873 3874 *sp++ = '\0'; 3875 } 3876 } 3877 3878 #ifdef RCM_IPMP_DEBUG 3879 3880 static void 3881 dump_node(ip_cache_t *node) 3882 { 3883 ip_pif_t *pif; 3884 ip_lif_t *lif; 3885 3886 pif = node->ip_pif; 3887 3888 rcm_log_message(RCM_TRACE1, "Node dump:\n"); 3889 rcm_log_message(RCM_TRACE1, "resource = %s\t cache flags = 0x%x\n", 3890 node->ip_resource, node->ip_cachestate); 3891 rcm_log_message(RCM_TRACE1, "ifname = %s\t ifindex = %d\n", 3892 pif->pi_ifname, pif->pi_ifindex); 3893 rcm_log_message(RCM_TRACE1, "groupname = %s\t PPA = %d\n", 3894 pif->pi_grpname, pif->pi_ppa); 3895 if (pif->pi_style == DL_STYLE1) { 3896 rcm_log_message(RCM_TRACE1, "Provider = DLPI style 1\n"); 3897 } 3898 if (pif->pi_style == DL_STYLE2) { 3899 rcm_log_message(RCM_TRACE1, "Provider = DLPI style 2\n"); 3900 }; 3901 3902 lif = pif->pi_lifs; 3903 3904 if (lif == NULL) { 3905 rcm_log_message(RCM_TRACE1, "No lifs hosted on this device.\n"); 3906 return; 3907 } 3908 3909 rcm_log_message(RCM_TRACE1, 3910 "Logical interfaces hosted on this device - \n"); 3911 while (lif != NULL) { 3912 rcm_log_message(RCM_TRACE1, "\t ifnum = %d \t ifflags = 0x%x", 3913 lif->li_ifnum, lif->li_ifflags); 3914 if (lif->li_addr.family == AF_INET) 3915 rcm_log_message(RCM_TRACE1, "\t Family = IPv4"); 3916 else if (lif->li_addr.family == AF_INET6) 3917 rcm_log_message(RCM_TRACE1, "\t Family = IPv6"); 3918 else rcm_log_message(RCM_TRACE1, "\t Family = <Unknown>"); 3919 rcm_log_message(RCM_TRACE1, "\n"); 3920 3921 lif = lif->li_next; 3922 } 3923 } 3924 3925 #else /* !RCM_IPMP_DEBUG */ 3926 3927 /*ARGSUSED*/ 3928 static void 3929 dump_node(ip_cache_t *node) 3930 { 3931 /* do nothing */ 3932 } 3933 3934 #endif /* RCM_IPMP_DEBUG */ 3935