ipmp_mpathd.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Low-level interfaces for communicating with in.mpathd(1M).
*
* These routines are not intended for use outside of libipmp.
*/
#include <alloca.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include "ipmp.h"
#include "ipmp_mpathd.h"
/*
* Connect to the multipathing daemon. Returns an IPMP error code; upon
* success, `fdp' points to the newly opened socket.
*/
int
ipmp_connect(int *fdp)
{
int fd;
int error;
int on = 1;
int flags;
struct sockaddr_in sin;
if (fd == -1)
return (IPMP_FAILURE);
/*
* Enable TCP_ANONPRIVBIND so the kernel will choose our source port.
* Since we're using loopback sockets, requiring use of privileged
* source ports is sufficient for security.
*/
sizeof (on)) == -1)
goto fail;
/*
* Bind to a privileged port chosen by the kernel.
*/
goto fail;
/*
* Attempt to connect to in.mpathd.
*/
if (errno == ECONNREFUSED) {
return (IPMP_ENOMPATHD);
}
goto fail;
}
/*
* Kick the socket into nonblocking mode.
*/
if (flags != -1)
return (IPMP_SUCCESS);
fail:
return (IPMP_FAILURE);
}
/*
* Read the TLV triplet from descriptor `fd' and store its type, length and
* value in `*typep', `*lenp', and `*valuep' respectively, before the current
* time becomes `endtp'. The buffer pointed to by `*valuep' will be
* dynamically allocated. Returns an IPMP error code.
*/
int
{
int retval;
void *value;
if (retval != IPMP_SUCCESS)
return (retval);
if (retval != IPMP_SUCCESS)
return (retval);
/*
* Even though we cannot allocate space for the value, we
* still slurp it off so the input stream doesn't get left
* in a weird place.
*/
return (IPMP_ENOMEM);
}
if (retval != IPMP_SUCCESS) {
return (retval);
}
return (IPMP_SUCCESS);
}
/*
* Write `buflen' bytes from `buffer' to open file `fd'. Returns IPMP_SUCCESS
* if all requested bytes were written, or an error code if not.
*/
int
{
if (nbytes == -1)
return (IPMP_FAILURE);
if (nbytes == 0) {
return (IPMP_FAILURE);
}
}
return (IPMP_SUCCESS);
}
/*
* Write the TLV triplet named by `type', `len' and `value' to file descriptor
* `fd'. Returns an IPMP error code.
*/
int
{
int retval;
if (retval != IPMP_SUCCESS)
return (retval);
if (retval != IPMP_SUCCESS)
return (retval);
}
/*
* Attempt to read `buflen' worth of bytes from `fd' into the buffer pointed
* to by `buf' before the current time becomes `endtp'; a `endtp' of NULL
* means forever. Returns an IPMP error code.
*/
int
{
int retval;
int timeleft = -1;
/*
* If a timeout was specified, then compute the amount of time
* left before timing out.
*/
break;
/*
* If we should've already timed out, then just
* have poll() return immediately.
*/
if (timeleft < 0)
timeleft = 0;
}
/*
* Wait for data to come in or for the timeout to fire.
*/
if (retval <= 0) {
if (retval == 0)
break;
}
/*
* Descriptor is ready; have at it.
*/
if (prbytes <= 0) {
continue;
break;
}
}
}