util_ifname.c revision c7e4935f5b755b4bbeaec416f1ad24337aeac7a4
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <libdlpi.h>
#include <ctype.h>
#include <sys/sysmacros.h>
#include <net/if_types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <stropts.h>
#include <fcntl.h>
#include <iscsitgt_impl.h>
#include "target.h"
#include "queue.h"
#include "utility.h"
#define LOCAL_LOOPBACK "lo0"
/*
* This entire file is all about getting these two variables. To create a
* unique iSCSI IQN string we need information that is unique. What Sun has
* decided is to use a MAC address along with a timestamp. No other machine
* at this given time will have the same MAC address and as time moves along
* well, time will change.
*/
/*
* []----
* | if_find_mac -- Finds a valid MAC address to use for GUID & IQN creation
* |
* | To create both the GUID and the IQN string we need to make them unique
* | and do so without requiring the user to have to register each target
* | creation with Sun. Each machine that's using iSCSI will have a network
* | interface from which we can obtain the MAC address. That guarantees
* | uniqueness within the network, but doesn't guarantee uniqueness with
* []----
*/
{
int n;
char *str;
}
/* ---- grab the first valid MAC address ---- */
break;
}
}
if (first)
}
/*
* []----
* | if_target_address -- setup IP address for SendTargets
* |
* | This routine is called when the iSCSI target is returning SendTargets
* | data during a discovery phase. The target name is returned along
* | with all of the IP address that can access that target. There's one
* | catch, the first address in the list will be the address used by
* | the initiator if it doesn't support multiple connections per session.
* | Therefore, whatever connection the initiator used is the first one
* | that should be in our list. The ramificiations of not doing this are
* | possible performance issues. Take for example a setup where both the
* | initiator and target have 10GbE and 1GbE interfaces. The initiator wants
* | to use the 10GbE interface because of it's speed. If the target returns
* | a list of addresses with the 1GbE listed first, that's the one which
* | the initiator would use. Not good.
* []----
*/
void
{
*first;
int n,
i,
s;
struct sockaddr_in *sin4_cur,
*sin4_pos;
struct sockaddr_in6 *sin6_cur,
*sin6_pos;
char ta[80],
int fromlen;
fromlen = sizeof (struct sockaddr_in);
return;
/*LINTED*/
/*
* Ugh. Would you believe that even though this array
* is defined as zero, we get back non-zero data from
* getsockname().
*/
fromlen = sizeof (struct sockaddr_in6);
return;
/*LINTED*/
} else
return;
continue;
continue;
/*
* Change the possible incoming addresses port number,
* which would be zero, to that of the current incoming
* port number. Otherwise the comparison will not match.
*/
} else
goto clean_up;
}
ip_buf);
ip_buf);
} else
goto clean_up;
/*
* There is possiblity that both IPv4 & IPv6 enabled on
* certain interface, then we will see that interface
* twice identically in the list.
* Of course we need only one of them, not both.
*/
break;
}
}
/*
* We allow for the loopback address to match the discovery
* address above since it's entirely possible to create
* a target on the same machine that you're running the
* initiator. Now, when we provide the list of other
* possible interfaces to use we don't want to include
* the loopback because that's obviously not a valid I/F
* for a remote node.
*/
continue;
ip_buf);
ip_buf);
} else
goto clean_up;
}
}
(void) close(s);
if (first)
}
/*
* []----
* | dump_addr_to_ascii -- Use appropriate translation routine
* []----
*/
static void
{
struct sockaddr_in *sin4;
struct sockaddr_in6 *sin6;
/*LINTED*/
/*LINTED*/
}
}
/*
* []----
* | if_setup -- Load up the interface names
* |
* | If this routine returns NULL, argument 'n' is also guaranteed to
* | be set to 0.
* []----
*/
static struct lifreq *
if_setup(int *n)
{
int numifs;
unsigned bufsize;
char *buf;
int s;
*n = 0;
/*
* If we failed to open an IPv6 socket
* try IPv4 socket instead
*/
return (NULL);
}
return (NULL);
/*
* This call is made so early on that if we're out of memory
* here, just say goodbye.
*/
return (NULL);
}
return (NULL);
}
(void) close(s);
}
static Boolean_t
{
int retval;
return (False);
dlpi_close(dh);
return (retval == DLPI_SUCCESS);
}