components/visual-panels/core/src/cmd/rad/mod/network/mod_network.c
changeset 827 0944d8c0158b
child 901 19b502ccabc8
equal deleted inserted replaced
826:c6aad84d2493 827:0944d8c0158b
       
     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 /*
       
    23  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 #include <sys/types.h>
       
    27 #include <stropts.h>
       
    28 #include <sys/conf.h>
       
    29 #include <net/if.h>
       
    30 #include <sys/sockio.h>
       
    31 #include <string.h>
       
    32 #include <stdio.h>
       
    33 #include <stdlib.h>
       
    34 #include <unistd.h>
       
    35 #include <netdb.h>
       
    36 #include <arpa/inet.h>
       
    37 
       
    38 #include <rad/adr.h>
       
    39 #include <rad/rad_modapi.h>
       
    40 
       
    41 #include "api_network.h"
       
    42 
       
    43 #include <sys/socket.h>
       
    44 #include <sys/ioctl.h>
       
    45 #include <netinet/in.h>
       
    46 #include <net/if.h>
       
    47 #include <ifaddrs.h>
       
    48 
       
    49 static int
       
    50 if_count(int fd, int *count)
       
    51 {
       
    52 	struct lifnum ifnum;
       
    53 
       
    54 	ifnum.lifn_family = AF_INET;
       
    55 	ifnum.lifn_flags = 0;
       
    56 	if (ioctl(fd, SIOCGLIFNUM, &ifnum) == -1) {
       
    57 		(void) close(fd);
       
    58 		return (-1);
       
    59 	}
       
    60 
       
    61 	*count = ifnum.lifn_count;
       
    62 	return (0);
       
    63 }
       
    64 
       
    65 /* ARGSUSED */
       
    66 conerr_t
       
    67 interface_Network_read_networkInterfaces(rad_instance_t *inst,
       
    68     adr_attribute_t *attr, data_t **data, data_t **error)
       
    69 {
       
    70 	int fd;
       
    71 	int count, rcount;
       
    72 	int reqsize;
       
    73 	struct lifreq *reqs = NULL;
       
    74 	struct lifconf ifconf;
       
    75 	data_t *result;
       
    76 
       
    77 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
       
    78 		return (ce_object);
       
    79 
       
    80 	do {
       
    81 		if (reqs != NULL)
       
    82 			free(reqs);
       
    83 
       
    84 		if (if_count(fd, &count) == -1)
       
    85 			return (ce_object);
       
    86 
       
    87 		if (count == 0) {
       
    88 			(void) close(fd);
       
    89 			*data = data_new_array(&t_array_string, 0);
       
    90 			return (ce_ok);
       
    91 		}
       
    92 
       
    93 		count += 5;
       
    94 		reqsize = count * sizeof (struct lifreq);
       
    95 		if ((reqs = malloc(reqsize)) == NULL) {
       
    96 			(void) close(fd);
       
    97 			return (ce_object);
       
    98 		}
       
    99 
       
   100 		ifconf.lifc_family = AF_INET;
       
   101 		ifconf.lifc_len = reqsize;
       
   102 		ifconf.lifc_buf = (char *)reqs;
       
   103 		ifconf.lifc_flags = 0;
       
   104 		if (ioctl(fd, SIOCGLIFCONF, &ifconf) == -1) {
       
   105 			(void) close(fd);
       
   106 			free(reqs);
       
   107 			return (ce_object);
       
   108 		}
       
   109 		rcount = ifconf.lifc_len / sizeof (struct lifreq);
       
   110 	} while (rcount >= count);
       
   111 
       
   112 	result = data_new_array(&t_array_string, rcount);
       
   113 	for (int i = 0; i < rcount; i++) {
       
   114 		struct lifreq *r = &ifconf.lifc_req[i];
       
   115 		if (strchr(r->lifr_name, ':') != NULL)
       
   116 			continue;
       
   117 		if (ioctl(fd, SIOCGLIFFLAGS, r) == -1)
       
   118 			continue;
       
   119 		if ((r->lifr_flags & (IFF_LOOPBACK | IFF_VIRTUAL)) != 0)
       
   120 			continue;
       
   121 		(void) array_add(result, data_new_string(r->lifr_name,
       
   122 		    lt_copy));
       
   123 	}
       
   124 	(void) close(fd);
       
   125 	free(reqs);
       
   126 
       
   127 	*data = data_purify_deep(result);
       
   128 	return (ce_ok);
       
   129 }
       
   130 
       
   131 /* ARGSUSED */
       
   132 conerr_t
       
   133 interface_Network_invoke_getHostNameForIP(rad_instance_t *inst,
       
   134     adr_method_t *meth, data_t **ret, data_t **args, int count, data_t **error)
       
   135 {
       
   136 	int errnum;
       
   137 	struct hostent *he;
       
   138 	ipaddr_t addr;
       
   139 
       
   140 	if (inet_pton(AF_INET, data_to_string(args[0]), &addr) != 1)
       
   141 		return (ce_object);
       
   142 
       
   143 	if ((he = getipnodebyaddr(&addr, sizeof (addr), AF_INET, &errnum))
       
   144 	    == NULL) {
       
   145 		/* Not found?  Bounce it back. */
       
   146 		(void) data_ref(args[0]);
       
   147 		*ret = args[0];
       
   148 		return (ce_ok);
       
   149 	}
       
   150 
       
   151 	data_t *result = data_new_string(he->h_name, lt_copy);
       
   152 	freehostent(he);
       
   153 	*ret = result;
       
   154 
       
   155 	return (ce_ok);
       
   156 }
       
   157 
       
   158 /* ARGSUSED */
       
   159 conerr_t
       
   160 interface_Network_invoke_hostGetIPs(rad_instance_t *inst, adr_method_t *meth,
       
   161     data_t **ret, data_t **args, int count, data_t **error)
       
   162 {
       
   163 	int errnum;
       
   164 	struct hostent *he;
       
   165 
       
   166 	if ((he = getipnodebyname(data_to_string(args[0]), AF_INET, AI_DEFAULT,
       
   167 	    &errnum)) == NULL) {
       
   168 		*ret = NULL;
       
   169 		return (ce_object);
       
   170 	}
       
   171 
       
   172 	int n = 0;
       
   173 	for (char **aptr = he->h_addr_list; *aptr != NULL; aptr++)
       
   174 		n++;
       
   175 	data_t *result = data_new_array(&t_array_string, n);
       
   176 	for (int i = 0; i < n; i++) {
       
   177 		char abuf[INET_ADDRSTRLEN];
       
   178 		if (inet_ntop(AF_INET, he->h_addr_list[i], abuf,
       
   179 		    sizeof (abuf)) != NULL)
       
   180 			(void) array_add(result, data_new_string(abuf,
       
   181 			    lt_copy));
       
   182 	}
       
   183 
       
   184 	*ret = data_purify_deep(result);
       
   185 	freehostent(he);
       
   186 
       
   187 	return (ce_ok);
       
   188 }
       
   189 
       
   190 /* ARGSUSED */
       
   191 conerr_t
       
   192 interface_Network_invoke_isLocalAddress(rad_instance_t *inst,
       
   193     adr_method_t *meth, data_t **ret, data_t **args, int count, data_t **error)
       
   194 {
       
   195 	struct ifaddrs *ifaddr;
       
   196 	struct ifaddrs *ifa;
       
   197 	struct sockaddr_in *sin;
       
   198 	struct sockaddr_in6 *sin6;
       
   199 
       
   200 	char buf[1024];
       
   201 	(void) memset(buf, 0, sizeof (buf));
       
   202 
       
   203 	/* Set default return value */
       
   204 	*ret = data_new_boolean(B_FALSE);
       
   205 
       
   206 	// Get IP addresses of each network interface.
       
   207 	//
       
   208 	// ifa_name	ifa_addr->sin_addr.s_addr
       
   209 	//
       
   210 	// lo0		0.0.0.0
       
   211 	// lo0		::1 (AF_INET6)
       
   212 	// lo0		127.0.0.1 (AF_INET)
       
   213 	// e1000g0	129.XXX.XXX.XXX (AF_INET)
       
   214 	//
       
   215 	// See: man -s3 socket getifaddrs
       
   216 	if (getifaddrs(&ifaddr) == -1) {
       
   217 		return (ce_object);
       
   218 	}
       
   219 
       
   220 	/* Iterate over linked list of IP addresses */
       
   221 	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
       
   222 		if (ifa->ifa_flags & IFF_IPV4) {
       
   223 			/* LINTED */
       
   224 			sin = (struct sockaddr_in *)ifa->ifa_addr;
       
   225 
       
   226 			/* Match given IP address */
       
   227 			if (strcmp(data_to_string(args[0]), inet_ntop(AF_INET,
       
   228 			    &sin->sin_addr.s_addr, buf, 1024)) == 0) {
       
   229 				*ret = data_new_boolean(B_TRUE);
       
   230 				break;
       
   231 			}
       
   232 		} else {
       
   233 			/* LINTED */
       
   234 			sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
       
   235 
       
   236 			/* Match given IP address */
       
   237 			if (strcmp(data_to_string(args[0]), inet_ntop(AF_INET6,
       
   238 			    &sin6->sin6_addr.s6_addr, buf, 1024)) == 0) {
       
   239 				*ret = data_new_boolean(B_TRUE);
       
   240 				break;
       
   241 			}
       
   242 		}
       
   243 	}
       
   244 	freeifaddrs(ifaddr);
       
   245 	return (ce_ok);
       
   246 }
       
   247 
       
   248 static rad_modinfo_t modinfo = { "network", "Network panel support" };
       
   249 
       
   250 int
       
   251 _rad_init(void *handle)
       
   252 {
       
   253 	if (rad_module_register(handle, RAD_MODVERSION, &modinfo) == -1)
       
   254 		return (-1);
       
   255 
       
   256 	if (rad_isproxy)
       
   257 		return (0);
       
   258 
       
   259 	(void) cont_insert_singleton(rad_container, adr_name_fromstr(
       
   260 	    "com.oracle.solaris.vp.panel.common.api.network:type=Network"),
       
   261 	    &interface_Network_svr);
       
   262 
       
   263 	return (0);
       
   264 }