Files
openflow/tests/test-dhcp-client.c
T

207 lines
6.2 KiB
C

/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
* (Software) available for public use and benefit with the expectation
* that others will use, modify and enhance the Software and contribute
* those enhancements back to the community. However, since we would
* like to make the Software available for broadest use, with as few
* restrictions as possible permission is hereby granted, free of
* charge, to any person obtaining a copy of this Software to deal in
* the Software under the copyrights without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* The name and trademarks of copyright holder(s) may NOT be used in
* advertising or publicity pertaining to the Software or any
* derivatives without specific, written prior permission.
*/
#include <config.h>
#include "dhcp-client.h"
#include <arpa/inet.h>
#include <getopt.h>
#include <stdlib.h>
#include <limits.h>
#include "command-line.h"
#include "dhcp.h"
#include "fatal-signal.h"
#include "fault.h"
#include "poll-loop.h"
#include "util.h"
#include "vlog.h"
/* --request-ip: IP address to request from server. If zero, then do not
* request a specific IP address. */
static struct in_addr request_ip;
/* --vendor-class: Vendor class string to include in request. If null, no
* vendor class string is included. */
static const char *vendor_class;
/* --no-resolv-conf: Update /etc/resolv.conf to match DHCP reply? */
static bool update_resolv_conf = true;
static void parse_options(int argc, char *argv[]);
static void usage(void);
static void release(void *cli_);
static void modify_dhcp_request(struct dhcp_msg *, void *aux);
int
main(int argc, char *argv[])
{
struct dhclient *cli;
int error;
set_program_name(argv[0]);
register_fault_handlers();
vlog_init();
parse_options(argc, argv);
argc -= optind;
argv += optind;
if (argc != 1) {
ofp_fatal(0, "exactly one non-option argument required; "
"use --help for help");
}
error = dhclient_create(argv[0], modify_dhcp_request, NULL, NULL, &cli);
if (error) {
ofp_fatal(error, "dhclient_create failed");
}
dhclient_init(cli, request_ip.s_addr);
fatal_signal_add_hook(release, cli, true);
for (;;) {
fatal_signal_block();
dhclient_run(cli);
if (dhclient_changed(cli)) {
dhclient_configure_netdev(cli);
if (update_resolv_conf) {
dhclient_update_resolv_conf(cli);
}
}
dhclient_wait(cli);
fatal_signal_unblock();
poll_block();
}
}
static void
release(void *cli_)
{
struct dhclient *cli = cli_;
dhclient_release(cli);
if (dhclient_changed(cli)) {
dhclient_configure_netdev(cli);
}
}
static void
modify_dhcp_request(struct dhcp_msg *msg, void *aux UNUSED)
{
if (vendor_class) {
dhcp_msg_put_string(msg, DHCP_CODE_VENDOR_CLASS, vendor_class);
}
}
static void
parse_options(int argc, char *argv[])
{
enum {
OPT_REQUEST_IP = UCHAR_MAX + 1,
OPT_VENDOR_CLASS,
OPT_NO_RESOLV_CONF
};
static struct option long_options[] = {
{"request-ip", required_argument, 0, OPT_REQUEST_IP },
{"vendor-class", required_argument, 0, OPT_VENDOR_CLASS },
{"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF},
{"verbose", optional_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
};
char *short_options = long_options_to_short_options(long_options);
for (;;) {
int c;
c = getopt_long(argc, argv, short_options, long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
case OPT_REQUEST_IP:
if (!inet_aton(optarg, &request_ip)) {
ofp_fatal(0,
"--request-ip argument is not a valid IP address");
}
break;
case OPT_VENDOR_CLASS:
vendor_class = optarg;
break;
case OPT_NO_RESOLV_CONF:
update_resolv_conf = false;
break;
case 'h':
usage();
case 'V':
printf("%s %s compiled "__DATE__" "__TIME__"\n",
program_name, VERSION BUILDNR);
exit(EXIT_SUCCESS);
case 'v':
vlog_set_verbosity(optarg);
break;
case '?':
exit(EXIT_FAILURE);
default:
abort();
}
}
free(short_options);
}
static void
usage(void)
{
printf("%s: standalone program for testing OpenFlow DHCP client.\n"
"usage: %s [OPTIONS] NETDEV\n"
"where NETDEV is a network device (e.g. eth0).\n"
"\nDHCP options:\n"
" --request-ip=IP request specified IP address (default:\n"
" do not request a specific IP)\n"
" --vendor-class=STRING use STRING as vendor class (default:\n"
" none); use OpenFlow to imitate secchan\n"
" --no-resolv-conf do not update /etc/resolv.conf\n",
program_name, program_name);
vlog_usage();
printf("\nOther options:\n"
" -h, --help display this help message\n"
" -V, --version display version information\n");
exit(EXIT_SUCCESS);
}