llp.c revision d71dbb732372504daff1f1783bc0d8864ce9bd50
/*
* 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"
/*
* This file contains the routines that manipulate Link Layer Profiles
* (aka LLPs) and various support functions. This includes parsing and
*
* The daemon maintains a list of llp_t structures that represent the
* provided configuration information for a link. After the llp file
* is read, entries are added to the LLP list for any known links
* (identified by checking the interface list, which is based on the
* v4 interfaces present after 'ifconfig -a plumb') which were not
* represented in the llp file. These entries contain the default
* "automatic" settings: plumb both IPv4 and IPv6, use DHCP on the
* v4 interface, and accept router- and DHCPv6-assigned addresses on
* the v6 interface. The default entries created by the daemon are
* also added to the llp file.
*
* LLP priority is assigned based on two factors: the order within
* the llp file, with earlier entries having higher priority; and
* a preference for wired interfaces before wireless. Entries that
* are added to the file by the daemon are added *after* any existing
* entries; within the added block, wired entries are added before
* wireless. Thus if the llp file is never modified externally, wired
* will generally be ordered before wireless. However, if the
* administrator creates the file with wireless entries before wired,
* that priority order will be respected.
*
* The llp list (pointed to by the global llp_head) is protected by
* the global llp_lock, which should be pthread_mutex_lock()'d before
* reading or writing the list.
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <syslog.h>
#include <atomic.h>
#include <pthread.h>
#include <signal.h>
#include "defines.h"
#include "structures.h"
#include "functions.h"
#include "variables.h"
/* Lock to protect the llp list. */
/*
* Global variable to hold the highest priority. Need to use the atomic
* integer arithmetic functions to update it.
*/
static uint32_t llp_highest_pri = 0;
static void print_llp_list(void);
char *
{
return ("null_llp");
return ("null_lname");
else
}
static void
{
if (pthread_mutex_lock(&llp_lock) != 0) {
/* Something very serious is wrong... */
return;
}
}
(void) pthread_mutex_unlock(&llp_lock);
}
llp_t *
llp_lookup(const char *link)
{
return (NULL);
/* The name may change. Better hold the lock. */
if (pthread_mutex_lock(&llp_lock) != 0) {
/* Something very serious is wrong... */
return (NULL);
}
break;
}
(void) pthread_mutex_unlock(&llp_lock);
return (llp);
}
/*
* Choose the higher priority llp of the two passed in. If one is
* NULL, the other will be higher priority. If both are NULL, NULL
* is returned.
*
* Assumes that both are available (i.e. doesn't check IFF_RUNNING
* or IF_DHCPFAILED flag values).
*/
llp_t *
{
if (a == NULL)
return (b);
else if (b == NULL)
return (a);
/*
* Higher priority is represented by a lower number. This seems a
* bit backwards, but for now it makes assigning priorities very easy.
*
* We shouldn't have ties right now, but just in case, tie goes to a.
*/
}
/*
* Chooses the highest priority link that corresponds to an
* available interface.
*/
llp_t *
llp_best_avail(void)
{
/* The priority may change. Better hold the lock. */
if (pthread_mutex_lock(&llp_lock) != 0) {
/* Something very serious is wrong... */
return (NULL);
}
continue;
}
(void) pthread_mutex_unlock(&llp_lock);
return (rtnllp);
}
/*
* Returns B_TRUE if llp is successfully activated;
* B_FALSE if activation fails.
*/
{
char *host;
/*
* Choosing "dhcp" as a hostname is unsupported right now.
* We use hostname="dhcp" as a keyword telling bringupinterface()
* to use dhcp on the interface.
*/
char *dhcpstr = "dhcp";
llp->llp_ipv6onlink)) {
} else {
}
return (rtn);
}
/*
* Deactivate the current active llp (link_layer_profile)
*/
void
llp_deactivate(void)
{
if (link_layer_profile == NULL)
return;
dprintf("llp_deactivate: setting link_layer_profile(%p) to NULL",
(void *)link_layer_profile);
}
/*
* Replace the currently active link layer profile with the one
* specified. And since we're changing the lower layer stuff,
* we need to first deactivate the current upper layer profile.
* An upper layer profile will be reactivated later, when we get
* confirmation that the new llp is fully up (has an address
* assigned).
*
* If the new llp is the same as the currently active one, don't
* do anything.
*
* If the new llp is NULL, just take down the currently active one.
*/
void
{
char *upifname;
if (newllp == link_layer_profile)
return;
if (link_layer_profile == NULL) {
/*
* there shouldn't be anything else running;
* make sure that's the case!
*/
} else {
dprintf("taking down current link layer profile (%s)",
}
dprintf("bringing up new link layer profile (%s)",
(void) llp_activate(newllp);
}
}
/*
*
* ifp->if_family == AF_INET, addr_src == DHCP ==> addr == NULL
* ifp->if_family == AF_INET, addr_src == STATIC ==> addr non null sockaddr_in
* ifp->if_family == AF_INET6, ipv6onlink == FALSE ==> addr == NULL
* ifp->if_family == AF_INET6, ipv6onlink == TRUE,
* if addr non NULL then it is the textual representation of the address
* and prefix.
*
* The above set of conditions describe what the inputs to this fuction are
* expected to be. Given input which meets those conditions this functions
* then outputs a line of configuration describing the inputs.
*
* Note that it is assumed only one thread can call this function at
* any time. So there is no lock to protect the file writing. This
* is true as the only caller of this function should originate from
* llp_parse_config(), which is done at program initialization time.
*/
static void
{
char addr_buf[INET6_ADDRSTRLEN];
case AF_INET:
switch (addr_src) {
case IPV4SRC_STATIC:
/* This is not supposed to happen... */
break;
}
addr_buf);
break;
case IPV4SRC_DHCP:
/* Default is DHCP for now. */
default:
break;
}
break;
case AF_INET6:
if (ipv6onlink)
break;
default:
break;
}
}
/*
* Walker function to pass to walk_interface() to add a default
* interface description to the LLPFILE.
*
* Regarding IF_TUN interfaces: see comments before find_and_add_llp()
* for an explanation of why we skip them.
*/
static void
{
}
/* Create the LLPFILE using info from the interface list. */
static void
create_llp_file(void)
{
/* Create the NWAM directory in case it does not exist. */
return;
}
}
return;
}
}
/*
* Append an llp struct to the end of the llp list.
*/
static void
{
/*
* should be a no-op, but for now, make sure we only
* create llps for wired and wireless interfaces.
*/
return;
if (pthread_mutex_lock(&llp_lock) != 0) {
/* Something very serious is wrong... */
return;
}
(void) pthread_mutex_unlock(&llp_lock);
}
/*
* Create a llp given the parameters and add it to the global list.
*/
static void
{
int lnamelen;
if (ipv6addrstr != NULL) {
"address for %s", name);
}
}
return;
return;
}
return;
}
if (ipv4src == IPV4SRC_STATIC) {
return;
}
} else {
}
} else {
}
}
/*
* Walker function to pass to walk_interface() to find out if
* an interface description is missing from LLPFILE. If it is,
* add it.
*
* Currently, IF_TUN type interfaces are special-cased: they are
* only handled as user-enabled, layered links (which may be created
* as part of a higher-layer profile, for example). Thus, they
* shouldn't be considered when looking at the llp list, so don't
* add them here.
*/
static void
{
/* If we run out of memory, ignore this interface for now. */
}
}
/*
* This is a very "slow" function. It uses walk_interface() to find
* out if any of the interface is missing from the LLPFILE. For the
* missing ones, add them to the LLPFILE.
*/
static void
{
}
static void
print_llp_list(void)
{
dprintf("Walking llp list");
}
/*
* profile. The file is line oriented with each line containing tab or space
* delimited fields. Each address family (IPv4, IPv6) is described on a
* separate line.
* The first field is a link name.
* The second field can be either static, dhcp, ipv6, or noipv6.
* If the second field is static then the next field is an ipv4 address which
* can contain a prefix. Previous versions of this file could contain a
* hostname in this field which is no longer supported.
* If the second field is dhcp then dhcp will be used on the interface.
* If the second field is ipv6 then an ipv6 interface is plumbed up. The
* outcome of this is that if offered by the network in.ndpd and dhcp
* will conspire to put addresses on additional ipv6 logical interfaces.
* If the next field is non-null then it is taken to be an IPv6 address
* and possible prefix which are applied to the interface.
* If the second field is noipv6 then no ipv6 interfaces will be put on that
* link.
*/
void
llp_parse_config(void)
{
static const char STATICSTR[] = "static";
static const char DHCP[] = "dhcp";
static const char IPV6[] = "ipv6";
static const char NOIPV6[] = "noipv6";
int lnum;
/*
* XXX See comment before create_llp_file() re
* better error handling.
*/
return;
}
/*
* If there is none, we should create one instead.
* For now, we will use the order of the interface list
* for the priority. We should have a priority field
* in the llp file eventually...
*/
/* Now we can try to reopen the file for processing. */
return;
}
}
cp++;
continue;
"ignoring entry", lnum);
continue;
}
"for static config; ignoring entry",
lnum);
continue;
}
ipv6onlink = B_TRUE;
"static address %s for %s",
}
} else {
}
} else {
"field; ignoring entry", lnum);
continue;
}
}
/*
* So we have read in the llp file, is there an interface which
* it does not describe? If yes, we'd better add it to the
* file for future reference. Again, since we don't have a
* priority field yet, we will add the interface in the order
* in the interface list.
*/
}