arp_check.c revision 69bb4bb45c98da60d21839c4dc3c01ea1be60585
/*
* 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 (c) 1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%W% %E% SMI"
#include <poll.h>
#include <netinet/if_ether.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <dhcpmsg.h>
#include <stddef.h>
#include "defaults.h"
#include "util.h"
#include "interface.h"
#include "dlpi_io.h"
#include "arp_check.h"
/*
* the struct arp_info is used by arp_reply_filter() to build a filter
* that only receives replies from the ARPed IP address.
*/
struct arp_info {
};
/*
* arp_reply_filter(): builds a filter that permits ARP replies to our request
*
* input: ushort_t *: a place to store the packet filter code
* void *: a struct arp_info containing the requested IP address
* output: ushort_t *: two bytes past the last byte of the filter
*/
static ushort_t *
{
/*
* make sure this ARP reply is from the target IP address,
* which will be the "sender" IP address in the reply (even in
* the case of proxy ARP). the position of sender IP address
* depends on the link layer; so we can be link-layer
* independent, these values are calculated in arp_check().
*
* the byteorder issues here are *really* subtle. suppose
* that the network address is 0x11223344 (as stored in the
* packet read off the wire) by an intel machine. then notice
* that since the packet filter operates 16 bits at a time
* that the high-order word will load as 0x2211 and the
* low-order word will load as 0x4433. so send_addr has the
* register value 0x44332211 on intel since that will store to
* the network address 0x11223344 in memory. thus, to compare
* the low-order word, we must first ntohl() send_addr, which
* changes its register-value to 0x11223344, and then mask
* off the high-order bits, getting 0x3344, and then convert
* that to network order, getting 0x4433, which is what we
* want. the same logic applies to the high-order word. you
* are not expected to understand this.
*/
return (pfp);
}
/*
* arp_check(): checks to see if a given IP address is already in use
*
* input: struct ifslist *: the interface to send the ARP request on
* in_addr_t: the IP address to send from, network order
* in_addr_t: the IP address to check on, network order
* uchar_t *: a scratch buffer that holds the hardware address
* of the machine that replied to our ARP request,
* if there was one.
* uint32_t: the length of the buffer
* uint32_t: how long to wait for an ARP reply, in milliseconds
* output: int: 1 if the IP address is in use, 0 if not in use.
*/
int
{
int fd;
int retval;
unsigned int arp_pkt_len;
if (fd == -1)
goto failure;
/*
* the packet consists of an ARP header, two IP addresses
* and two hardware addresses (each ifsp->if_hwlen bytes long).
*/
goto failure;
/*
* while we're at the appropriate offset for sender IP address,
* store it for use by the packet filter.
*/
/*
* install the packet filter, send our ARP request, and wait
* for a reply. waiting usually isn't a good idea since the
* design of the agent is nonblocking. however, we can
* tolerate short waits (< 5 seconds).
*/
goto failure;
/*
* try to grab the hardware address. if we fail, we'll
* just end up with some misleading diagnostics. the
* hardware address is at the start of the payload.
*/
}
return ((retval == 0) ? 0 : 1);
"assuming address is available");
return (0);
}
"assuming address is unavailable");
return (1);
}