smb_nic.c revision c8ec8eea9849cac239663c46be8a7f5d2ba7ca00
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "@(#)smb_nic.c 1.6 08/07/24 SMI"
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <libintl.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <synch.h>
#include <stropts.h>
#include <errno.h>
#include <pthread.h>
#include <netdb.h>
#include <sys/systeminfo.h>
#define SMB_NIC_DB_NAME "/var/smb/smbhosts.db"
#define SMB_NIC_DB_VERMAJOR 1
#define SMB_NIC_DB_VERMINOR 0
#define SMB_NIC_DB_SQL \
"CREATE TABLE db_info (" \
" ver_major INTEGER," \
" ver_minor INTEGER," \
" magic INTEGER" \
");" \
"" \
"CREATE TABLE hosts (" \
" hostname TEXT PRIMARY KEY," \
" comment TEXT," \
" ifnames TEXT" \
");"
#define SMB_NIC_HTBL_NCOL 3
#define SMB_NIC_HTBL_HOST 0
#define SMB_NIC_HTBL_CMNT 1
#define SMB_NIC_HTBL_IFS 2
#define SMB_NIC_MAXIFS 256
typedef struct smb_hostifs {
char if_host[MAXHOSTNAMELEN];
char if_cmnt[SMB_PI_MAX_COMMENT];
char *if_names[SMB_NIC_MAXIFS];
int if_num;
typedef struct smb_hosts {
int h_num;
int h_ifnum;
} smb_hosts_t;
typedef struct {
int nl_cnt; /* number of smb_nic_t structures */
int nl_hcnt; /* number of host names */
long nl_seqnum; /* a random sequence number */
static int smb_nic_list_create(void);
static void smb_nic_list_destroy(void);
static int smb_nic_hlist_create(smb_hosts_t *);
static void smb_nic_hlist_destroy(smb_hosts_t *);
static int smb_nic_hlist_dbget(smb_hosts_t *);
static int smb_nic_hlist_sysget(smb_hosts_t *);
static void smb_nic_iflist_destroy(smb_hostifs_t *);
static smb_hostifs_t *smb_nic_iflist_decode(const char **);
static int smb_nic_dbcreate(void);
static sqlite *smb_nic_dbopen(int);
static void smb_nic_dbclose(sqlite *);
static boolean_t smb_nic_dbexists(void);
static boolean_t smb_nic_dbvalidate(void);
static int smb_nic_dbaddhost(const char *, const char *, char *);
static int smb_nic_dbdelhost(const char *);
static int smb_nic_dbsetinfo(sqlite *);
static int smb_nic_getinfo(char *, smb_nic_t *);
/* This is the list we will monitor */
static smb_niclist_t smb_niclist;
/*
* smb_nic_init
*
* Initializes the interface list.
*/
int
smb_nic_init(void)
{
int rc;
rc = smb_nic_list_create();
return (rc);
}
/*
* smb_nic_fini
*
* Destroys the interface list.
*/
void
smb_nic_fini(void)
{
}
/*
* smb_nic_getnum
*
* Gets the number of interfaces for the specified host.
* if host is NULL then total number of interfaces
* is returned. It's assumed that given name is a NetBIOS
* encoded name.
*/
int
smb_nic_getnum(char *nb_hostname)
{
int n = 0, i;
if (nb_hostname != NULL) {
for (i = 0; i < smb_niclist.nl_cnt; i++) {
/* ignore the suffix */
n++;
}
} else {
n = smb_niclist.nl_cnt;
}
return (n);
}
/*
* smb_nic_getfirst
*
* Returns the first NIC in the interface list and
* initializes the given iterator. To get the rest of
* NICs smb_nic_getnext() must be called.
*
* Returns 0 upon success and -1 if there's no interface
* available or if 'ni' is NULL.
*/
int
{
int rc = 0;
return (-1);
if (smb_niclist.nl_cnt > 0) {
} else {
rc = -1;
}
return (rc);
}
/*
* smb_nic_getnext
*
* Returns the next NIC information based on the passed
* iterator (ni). The iterator must have previously been
* initialized by calling smb_nic_getfirst().
*
* Returns 0 upon successfully finding the specified NIC.
* Returns -1 if:
* - the specified iterator is invalid
* - reaches the end of the NIC list
* - sequence number in the iterator is different from
* the sequence number in the NIC list which means
* calls.
*/
int
{
int rc = 0;
return (-1);
} else {
rc = -1;
}
return (rc);
}
/*
* smb_nic_exists
*
* Check to see if there's a NIC with the given IP address
* in the list. Subnet mask will be applied when comparing the
* IPs if the use_mask arg is true.
*/
{
int i;
for (i = 0; i < smb_niclist.nl_cnt; i++) {
if (use_mask)
return (B_TRUE);
}
}
return (B_FALSE);
}
/*
* smb_nic_addhost
*
* Adds an association between the given host and the specified interface
* list (if_names). This function can be called as many times as needed,
* the associations will be stored in /var/smb/smbhosts.db, which is sqlite
* database. If this file exists and it's not empty NIC list is generated
* based on the information stored in this file.
*
* host: actual system's name (not Netbios name)
* cmnt: an optional description for the CIFS server running on
* the specified host. Can be NULL.
* if_num: number of interface names in if_names arg
* if_names: array of interface names in string format
*
* Returns 0 upon success and -1 when fails
*/
int
{
char *if_list;
char *ifname;
int buflen = 0;
int rc, i;
return (-1);
if (!smb_nic_dbexists() || !smb_nic_dbvalidate()) {
if (smb_nic_dbcreate() != SQLITE_OK)
return (-1);
}
return (-1);
}
return (-1);
for (i = 0; i < if_num - 1; i++)
}
/*
* smb_nic_delhost
*
* Removes the stored interface association for the specified host
*/
int
smb_nic_delhost(const char *host)
{
return (-1);
if (!smb_nic_dbexists())
return (0);
if (!smb_nic_dbvalidate()) {
(void) unlink(SMB_NIC_DB_NAME);
return (0);
}
return (-1);
return (0);
}
/*
* smb_nic_list_create
*
* Creates a NIC list either based on /var/smb/smbhosts.db or
* by getting the information from OS.
*
* Note that the caller of this function should grab the
* list lock.
*/
static int
smb_nic_list_create(void)
{
char *ifname;
char excludestr[MAX_EXCLUDE_LIST_LEN];
int nexclude;
int i;
if (smb_nic_hlist_create(&hlist) < 0)
return (-1);
smb_niclist.nl_cnt = 0;
return (-1);
}
sizeof (excludestr));
do {
continue;
nc++;
}
return (0);
}
static void
smb_nic_list_destroy(void)
{
smb_niclist.nl_cnt = 0;
}
/*
* smb_nic_getinfo
*
* Get IP info and more for the given interface
*/
static int
{
struct sockaddr_in *sa;
int s;
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
return (0);
}
/*
* smb_nic_hlist_create
*
* Creates a list of hosts and their associated interfaces.
* If host database exists the information is retrieved from
* the database, otherwise it's retrieved from OS.
*
* The allocated memories for the returned list should be freed
* by calling smb_nic_hlist_destroy()
*/
static int
{
int rc;
if (smb_nic_dbexists() && smb_nic_dbvalidate()) {
} else {
}
if (rc != 0)
return (rc);
}
static void
{
return;
}
}
/*
* smb_nic_hlist_sysget
*
* Get the list of currently plumbed and up interface names. The loopback (lo0)
* port is ignored
*/
static int
{
char *ifname;
int ifnum;
int i;
int s;
return (-1);
return (-1);
}
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
return (-1);
}
(void) close(s);
return (-1);
}
/*
* Get the flags so that we can skip the loopback interface
*/
(void) close(s);
return (-1);
}
continue;
continue;
(void) close(s);
return (-1);
}
}
(void) close(s);
return (0);
}
static int
{
const char **values;
char *sql;
return (-1);
return (-1);
}
return (-1);
}
do {
if (rc == SQLITE_ROW) {
if (ncol != SMB_NIC_HTBL_NCOL) {
break;
}
break;
}
}
} while (rc == SQLITE_ROW);
if (rc != SQLITE_DONE)
}
return ((error) ? -1 : 0);
}
static smb_hostifs_t *
smb_nic_iflist_decode(const char **values)
{
char *host;
char *cmnt;
char *ifnames;
char *lasts;
char *ifname;
int if_num = 0;
return (NULL);
return (NULL);
return (NULL);
return (NULL);
}
}
return (iflist);
}
/*
* smb_nic_iflist_destroy
*
* Frees allocated memory for the given IF names lists.
*/
static void
{
int i;
return;
}
/*
*
* Each entry in the hosts table associates a hostname with a
* be added by calling smb_nic_addhost() and could be removed by
* calling smb_nic_delhost(). If the database exists and it contains
* valid information then the inteface list wouldn't be obtained
* from system using ioctl.
*/
/*
* smb_nic_dbcreate
*
* Creates the host database based on the defined SQL statement.
* It also initializes db_info table.
*/
static int
smb_nic_dbcreate(void)
{
int rc;
(void) unlink(SMB_NIC_DB_NAME);
return (SQLITE_CANTOPEN);
}
return (rc);
}
&errmsg);
&errmsg);
} else {
errmsg);
&errmsg);
}
/* this is bad - database may be left in a locked state */
}
(void) sqlite_close(db);
return (rc);
}
/*
* smb_nic_dbopen
*
* Opens host database with the given mode.
*/
static sqlite *
smb_nic_dbopen(int mode)
{
}
return (db);
}
/*
* smb_nic_dbclose
*
* Closes the given database handle
*/
static void
{
if (db) {
}
}
static boolean_t
smb_nic_dbexists(void)
{
}
static boolean_t
smb_nic_dbvalidate(void)
{
char *sql;
char **result;
int rc;
return (B_FALSE);
return (B_FALSE);
}
return (B_FALSE);
}
return (B_FALSE);
}
return (B_FALSE);
}
return (B_FALSE);
}
return (B_FALSE);
}
if (nrow == 0)
/* No hosts in the database */
return (check);
}
static int
{
char *sql;
char *errmsg;
int rc;
return (SQLITE_NOMEM);
return (SQLITE_CANTOPEN);
}
}
return (rc);
}
static int
smb_nic_dbdelhost(const char *host)
{
char *sql;
char *errmsg;
int rc;
return (SQLITE_NOMEM);
return (SQLITE_CANTOPEN);
}
}
return (rc);
}
/*
* smb_nic_dbsetinfo
*
* Initializes the db_info table upon database creation.
*/
static int
{
char *sql;
int rc;
" magic) VALUES (%d, %d, %d)", SMB_NIC_DB_VERMAJOR,
return (SQLITE_NOMEM);
}
return (rc);
}