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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * selfcheck.c 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <errno.h> 28 #include <syslog.h> 29 30 #include <strings.h> 31 #include <malloc.h> 32 #include <stdio.h> 33 #include <unistd.h> 34 #include <sys/sockio.h> 35 #include <netinet/in.h> 36 #include <sys/socket.h> 37 #include <netdb.h> 38 #include <net/if.h> 39 40 int 41 self_check(char *hostname) 42 { 43 int s, res = 0; 44 struct sioc_addrreq areq; 45 46 struct hostent *hostinfo; 47 int family; 48 int flags; 49 int error_num; 50 char **hostptr; 51 52 struct sockaddr_in6 ipv6addr; 53 54 family = AF_INET6; 55 /* 56 * We cannot specify AI_DEFAULT since it includes AI_ADDRCONFIG. 57 * Localhost name resolution will fail if no IP interfaces other than 58 * loopback are plumbed and AI_ADDRCONFIG is specified, and this 59 * causes localhost mounts to fail. 60 */ 61 flags = AI_V4MAPPED; 62 63 if ((s = socket(family, SOCK_DGRAM, 0)) < 0) { 64 syslog(LOG_ERR, "self_check: socket: %m"); 65 return (0); 66 } 67 68 if ((hostinfo = getipnodebyname(hostname, family, flags, 69 &error_num)) == NULL) { 70 71 if (error_num == TRY_AGAIN) 72 syslog(LOG_DEBUG, 73 "self_check: unknown host: %s (try again later)\n", 74 hostname); 75 else 76 syslog(LOG_DEBUG, 77 "self_check: unknown host: %s\n", hostname); 78 79 (void) close(s); 80 return (0); 81 } 82 83 for (hostptr = hostinfo->h_addr_list; *hostptr; hostptr++) { 84 bzero(&ipv6addr, sizeof (ipv6addr)); 85 ipv6addr.sin6_family = AF_INET6; 86 ipv6addr.sin6_addr = *((struct in6_addr *)(*hostptr)); 87 memcpy(&areq.sa_addr, (void *)&ipv6addr, sizeof (ipv6addr)); 88 areq.sa_res = -1; 89 (void) ioctl(s, SIOCTMYADDR, (caddr_t)&areq); 90 if (areq.sa_res == 1) { 91 res = 1; 92 break; 93 } 94 } 95 96 freehostent(hostinfo); 97 98 (void) close(s); 99 return (res); 100 } 101 102 #define MAXIFS 32 103 104 /* 105 * create an ifconf structure that represents all the interfaces 106 * configured for this host. Two buffers are allcated here: 107 * lifc - the ifconf structure returned 108 * lifc->lifc_buf - the list of ifreq structures 109 * Both of the buffers must be freed by the calling routine. 110 * A NULL pointer is returned upon failure. In this case any 111 * data that was allocated before the failure has already been 112 * freed. 113 */ 114 struct lifconf * 115 getmyaddrs(void) 116 { 117 int sock; 118 struct lifnum lifn; 119 int numifs; 120 char *buf; 121 struct lifconf *lifc; 122 123 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 124 syslog(LOG_ERR, "statd:getmyaddrs socket: %m"); 125 return ((struct lifconf *)NULL); 126 } 127 128 lifn.lifn_family = AF_UNSPEC; 129 lifn.lifn_flags = 0; 130 131 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { 132 syslog(LOG_ERR, 133 "statd:getmyaddrs, get number of interfaces, error: %m"); 134 numifs = MAXIFS; 135 } 136 137 numifs = lifn.lifn_count; 138 139 lifc = (struct lifconf *)malloc(sizeof (struct lifconf)); 140 if (lifc == NULL) { 141 syslog(LOG_ERR, 142 "statd:getmyaddrs, malloc for lifconf failed: %m"); 143 (void) close(sock); 144 return ((struct lifconf *)NULL); 145 } 146 buf = (char *)malloc(numifs * sizeof (struct lifreq)); 147 if (buf == NULL) { 148 syslog(LOG_ERR, 149 "statd:getmyaddrs, malloc for lifreq failed: %m"); 150 (void) close(sock); 151 free(lifc); 152 return ((struct lifconf *)NULL); 153 } 154 155 lifc->lifc_family = AF_UNSPEC; 156 lifc->lifc_flags = 0; 157 lifc->lifc_buf = buf; 158 lifc->lifc_len = numifs * sizeof (struct lifreq); 159 160 if (ioctl(sock, SIOCGLIFCONF, (char *)lifc) < 0) { 161 syslog(LOG_ERR, "statd:getmyaddrs, SIOCGLIFCONF, error: %m"); 162 (void) close(sock); 163 free(buf); 164 free(lifc); 165 return ((struct lifconf *)NULL); 166 } 167 168 (void) close(sock); 169 170 return (lifc); 171 } 172 173 int 174 Is_ipv6present(void) 175 { 176 int sock; 177 struct lifnum lifn; 178 179 sock = socket(AF_INET6, SOCK_DGRAM, 0); 180 if (sock < 0) 181 return (0); 182 183 lifn.lifn_family = AF_INET6; 184 lifn.lifn_flags = 0; 185 if (ioctl(sock, SIOCGLIFNUM, (char *)&lifn) < 0) { 186 close(sock); 187 return (0); 188 } 189 close(sock); 190 if (lifn.lifn_count == 0) 191 return (0); 192 return (1); 193 } 194