in.rarpd.c revision 2b24ab6b3865caeede9eeb9db6b83e1d89dcd1ea
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley 4.3 BSD
* under license from the Regents of the University of California.
*/
/*
* rarpd.c Reverse-ARP server.
* Refer to RFC 903 "A Reverse Address Resolution Protocol".
*/
#define _REENTRANT
#include <thread.h>
#include <synch.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <dirent.h>
#include <syslog.h>
#include <netdb.h>
#include <errno.h>
#include <netinet/if_ether.h>
#include <stropts.h>
#include <libinetutil.h>
#include <libdlpi.h>
#include <net/if_types.h>
#define MAXIFS 256
/*
* Logical network devices
*/
struct ifdev {
int lunit;
};
/*
* Physical network device
*/
struct rarpdev {
char device[DLPI_LINKNAME_MAX];
/* mac address of interface */
int ifrarplen; /* size of rarp data packet */
};
struct rarpreply {
};
static struct rarpreply *delay_list;
static sema_t delay_sema;
static mutex_t delay_mutex;
static mutex_t debug_mutex;
static struct rarpdev *rarpdev_head;
/*
* Globals initialized before multi-threading
*/
static char *cmdname; /* command name from argv[0] */
static int dflag = 0; /* enable diagnostics */
static int aflag = 0; /* start rarpd on all interfaces */
static void getintf(void);
static void init_rarpdev(struct rarpdev *);
static void do_rarp(void *);
uchar_t *);
static void do_delay_write(void *);
static int strioctl(int, int, int, int, char *);
static void usage();
static void syserr(const char *);
/*PRINTFLIKE1*/
static void error(const char *, ...);
static void debug(char *, ...);
extern int optind;
extern char *optarg;
int
{
int c;
int i;
switch (c) {
case 'a':
aflag = 1;
break;
case 'd':
dflag = 1;
break;
default:
usage();
}
}
usage();
/* NOTREACHED */
}
if (!dflag) {
/*
* Background
*/
switch (fork()) {
case -1: /* error */
syserr("fork");
/*NOTREACHED*/
case 0: /* child */
break;
default: /* parent */
return (0);
}
for (i = 0; i < 3; i++) {
(void) close(i);
}
(void) dup2(0, 1);
(void) dup2(0, 2);
/*
* Detach terminal
*/
if (setsid() < 0)
syserr("setsid");
}
syserr("setrlimit");
if (aflag) {
/*
* Get each interface name and load rarpdev list.
*/
getintf();
} else {
/*
* Load specified device as only element of the list.
*/
sizeof (struct rarpdev));
if (rarpdev_head == NULL) {
error("out of memory");
}
error("out of memory");
}
error("invalid interface specification");
if (ifsp.ifsp_lunvalid) {
} else {
}
sizeof (rarpdev_head->device));
}
/*
* Initialize each rarpdev.
*/
}
/*
* Start delayed processing thread.
*/
THR_NEW_LWP, NULL);
/*
* Start RARP processing for each device.
*/
THR_NEW_LWP, NULL);
}
}
/*
* Exit main() thread
*/
return (0);
}
static void
getintf(void)
{
int fd;
int numifs;
unsigned bufsize;
/*
* Open the IP provider.
*/
/*
* Ask IP for the list of configured interfaces.
*/
}
error("out of memory");
}
syserr("SIOCGIFCONF");
/*
* Initialize a rarpdev for each interface.
*/
syserr("ioctl SIOCGIFFLAGS");
exit(1);
}
continue;
error("ifparse_ifspec failed");
/*
* Look for an existing device for logical interfaces.
*/
error("out of memory");
rarpdev_head = rdev;
}
error("out of memory");
if (ifsp.ifsp_lunvalid) {
} else
}
}
static struct rarpdev *
{
return (rdev);
}
return (NULL);
}
static void
{
char *dev;
int unit;
int retval;
char linkname[DLPI_LINKNAME_MAX];
/*
* Open datalink provider and get our mac address.
*/
}
dlpi_close(dh);
}
/*
* Save our mac address.
*/
&physaddrlen)) != DLPI_SUCCESS) {
dlpi_close(dh);
}
(2 * physaddrlen);
if (dflag) {
}
}
/*
* Assign dlpi handle to rdev.
*/
/*
* Get the IP address and netmask from directory service for
* each logical interface.
*/
/*
* If lunit == -1 then this is the primary interface name.
*/
} else {
}
/*
* Use IP address of the interface.
*/
}
}
static void
{
char *cause;
int retval;
syserr("malloc");
if (dflag) {
debug("starting rarp service on device %s%d physical"
}
}
/*
* Read RARP packets and respond to them.
*/
for (;;) {
if (retval == DLPI_ETIMEDOUT) {
continue;
} else if (retval != DLPI_SUCCESS) {
}
cause = "short packet";
cause = "hardware type not Ethernet";
cause = "protocol type not IP";
cause = "unexpected hardware address length";
cause = "unexpected protocol address length";
if (dflag)
debug("RARP packet received but "
"discarded: %s", cause);
continue;
}
/*
* Handle the request.
*/
case REVARP_REQUEST:
break;
case ARPOP_REQUEST:
break;
case REVARP_REPLY:
if (dflag)
debug("REVARP_REPLY ignored");
break;
case ARPOP_REPLY:
if (dflag)
debug("ARPOP_REPLY ignored");
break;
default:
if (dflag)
break;
}
}
}
/*
* Reverse address determination and allocation code.
*/
static void
{
int retval;
if (dflag) {
}
}
/*
* Third party lookups are rare and wonderful.
*/
if (dflag)
debug("weird (3rd party lookup)");
}
/*
* Fill in given parts of reply packet.
*/
/*
* If a good address is stored in our lookup tables, return it
* immediately or after a delay. Store it in our kernel's ARP cache.
*/
return;
if (dflag) {
}
error("out of memory");
/*
* Create rarpreply structure.
*/
/*
* If this is diskless and we're not its bootserver, let the
* bootserver reply first by delaying a while.
*/
if (retval != DLPI_SUCCESS) {
} else if (dflag) {
debug("immediate reply sent");
}
} else {
}
}
/*
* Download an ARP entry into our kernel.
*/
static void
{
struct sockaddr_in *sin;
int fd;
/*
* Common part of query or set.
*/
/*
* Open the IP provider.
*/
/*
* Set the entry.
*/
(char *)&ar);
(char *)&ar) < 0)
syserr("SIOCSXARP");
}
/*
* The RARP spec says we must be able to process ARP requests,
* even through the packet type is RARP. Let's hope this feature
* is not heavily used.
*/
static void
{
int retval;
if (dflag)
debug("ARPOP_REQUEST");
break;
}
return;
/*
* Create rarp reply structure.
*/
error("out of memory");
if (retval != DLPI_SUCCESS)
}
/* ARGSUSED */
static void
do_delay_write(void *buf)
{
int err;
for (;;) {
continue;
error("do_delay_write: sema_wait failed");
}
(void) mutex_lock(&delay_mutex);
rrp = delay_list;
(void) mutex_unlock(&delay_mutex);
if (err != DLPI_SUCCESS)
}
}
/* ARGSUSED */
static void
{
(void) mutex_lock(&delay_mutex);
if (delay_list == NULL) {
delay_list = rrp;
} else {
trp = delay_list;
}
(void) mutex_unlock(&delay_mutex);
(void) sema_post(&delay_sema);
}
/*
* See if we have a TFTP boot file for this guy. Filenames in TFTP
* boot requests are of the form <ipaddr> for Sun-3's and of the form
* <ipaddr>.<arch> for all other architectures. Since we don't know
* the client's architecture, either format will do.
*/
static int
{
/*
* Try a quick access() first.
*/
return (1);
/*
* Not there, do it the slow way by
* reading through the directory.
*/
return (0);
continue;
continue;
break;
}
}
/*
* Get our IP address and local netmask.
*/
static void
{
int fd;
struct sockaddr_in *sin;
/* LINTED pointer */
/*
* Open the IP provider.
*/
/*
* Ask IP for our IP address.
*/
(char *)&ifr) < 0)
syserr("SIOCGIFADDR");
if (dflag)
/*
* Ask IP for our netmask.
*/
(char *)&ifr) < 0)
syserr("SIOCGIFNETMASK");
if (dflag)
/*
* Thankyou ip.
*/
}
/*
* Translate mac address to IP address.
* Return 0 on success, nonzero on failure.
*/
static int
{
int herror;
char **p;
if (dflag)
"address to IP address");
return (1);
}
/*
* Translate mac address to hostname and IP address.
*/
&herror)) ||
if (dflag)
debug("could not map hardware address to IP address");
return (1);
}
/*
* Find the IP address on the right net.
*/
for (p = hp->h_addr_list; *p; p++) {
if (dflag) {
sizeof (ipaddr_t));
debug("trying physical netnum %s"
ifdev->if_netmask);
else
debug("trying logical %d netnum %s"
ifdev->if_netmask);
}
/*
* Return the correct IP address.
*/
/*
* Return the interface's ipaddr
*/
sizeof (ipaddr_t));
return (0);
}
}
}
if (dflag)
debug("got host entry but no IP address on this net");
return (1);
}
static int
{
}
static void
usage(void)
{
}
static void
syserr(const char *s)
{
char buf[256];
int status = 1;
}
static void
{
char buf[256];
int status = 1;
}
/*PRINTFLIKE1*/
static void
{
(void) mutex_lock(&debug_mutex);
(void) mutex_unlock(&debug_mutex);
}