summaryrefslogtreecommitdiffstats
path: root/cpukit/libnetworking/rtems/rtems_dhcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libnetworking/rtems/rtems_dhcp.c')
-rw-r--r--cpukit/libnetworking/rtems/rtems_dhcp.c1287
1 files changed, 0 insertions, 1287 deletions
diff --git a/cpukit/libnetworking/rtems/rtems_dhcp.c b/cpukit/libnetworking/rtems/rtems_dhcp.c
deleted file mode 100644
index 6a153a4a40..0000000000
--- a/cpukit/libnetworking/rtems/rtems_dhcp.c
+++ /dev/null
@@ -1,1287 +0,0 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
-/*
- * DCHP client for RTEMS
- * Andrew Bythell, <abythell@nortelnetworks.com>
- * based on and uses subroutines from c/src/libnetworking/nfs/bootp_subr.c
- */
-
-/*
- * DHCP task added.
- * Brendan Gannon, <bgannon@cybertec.com.au>
- */
-
-/*
- * Added interface to terminate DHCP task, and removed panics.
- * Arnout Vandecappelle <arnout@mind.be>, Essensium/Mind
- * Maarten Van Es <maarten@mind.be>, Essensium/Mind
- */
-
-/*
- * Copyright (c) 1995 Gordon Ross, Adam Glass
- * Copyright (c) 1992 Regents of the University of California.
- * All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <machine/rtems-bsd-kernel-space.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems.h>
-#include <rtems/error.h>
-#include <rtems/rtems_bsdnet.h>
-#include <rtems/bsdnet/servers.h>
-
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <sys/sockio.h>
-#include <sys/param.h> /* for MAXHOSTNAMELEN */
-#include <sys/systm.h>
-#include <sys/socketvar.h> /* for socreat() soclose() */
-#include <sys/socket.h>
-
-#include <net/if.h>
-#include <net/if_var.h>
-#include <netinet/in.h> /* for NBO-HBO conversions */
-#include <net/if_types.h> /* for IFT_ETHER */
-#include <net/if_dl.h> /* for LLADDR */
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <rtems/mkrootfs.h>
-
-#include "rtems/dhcp.h"
-#include "rtems/bootp.h"
-
-#ifndef EALEN
-#define EALEN 6
-#endif
-
-/*
- *DHCP flags
- */
-#define DHCP_BROADCAST 0x8000
-#define DHCP_UNICAST 0x0000
-
-/*
- * DHCP Op Codes
- */
-#define DHCP_BOOTREQUEST 1
-#define DHCP_BOOTREPLY 2
-
-/*
- * DHCP Messages
- */
-#define DHCP_DISCOVER 1
-#define DHCP_OFFER 2
-#define DHCP_REQUEST 3
-#define DHCP_DECLINE 4
-#define DHCP_ACK 5
-#define DHCP_NACK 6
-#define DHCP_RELEASE 7
-
-/*
- * DHCP Options
- */
-#define DHCP_OPTION_PAD 0
-#define DHCP_SUBNET 1
-#define DHCP_GATEWAY 3
-#define DHCP_DNS 6
-#define DHCP_HOST 12
-#define DHCP_DOMAIN_NAME 15
-#define DHCP_NETMASK 28
-#define DHCP_REQUESTED_IP 50
-#define DHCP_LEASE 51
-#define DHCP_MESSAGE 53
-#define DHCP_SERVER 54
-#define DHCP_PARAMETERS 55
-#define DHCP_OPTION_END 255
-
-/*
- * Definitions from RFC
- */
-struct dhcp_packet
-{
- u_int8_t op;
- u_int8_t htype;
- u_int8_t hlen;
- u_int8_t hops;
- u_int32_t xid;
- u_int16_t secs;
- u_int16_t flags;
- struct in_addr ciaddr;
- struct in_addr yiaddr;
- struct in_addr siaddr;
- struct in_addr giaddr;
- unsigned char chaddr[16];
- char sname[64];
- char file[128];
- unsigned char vend[312];
-};
-
-/*
- * Variables
- */
-static int dhcp_option_overload = 0;
-static char dhcp_gotgw = 0;
-static char dhcp_gotnetmask = 0;
-static char dhcp_gotserver = 0;
-static char dhcp_gotlogserver = 0;
-static struct sockaddr_in dhcp_netmask;
-static struct sockaddr_in dhcp_gw;
-static char *dhcp_hostname;
-static int dhcp_message_type = 0;
-static unsigned long dhcp_lease_time;
-static unsigned long dhcp_elapsed_time = 0;
-static const char dhcp_magic_cookie[4] = { 99, 130, 83, 99 };
-static const char dhcp_request_parameters[5] = { DHCP_SUBNET,
- DHCP_GATEWAY,
- DHCP_DNS,
- DHCP_HOST,
- DHCP_DOMAIN_NAME };
-#define NUM_NAMESERVERS \
- (sizeof rtems_bsdnet_config.name_server / sizeof rtems_bsdnet_config.name_server[0])
-static struct in_addr rtems_dhcpd_nameserver[NUM_NAMESERVERS];
-static int rtems_dhcpd_nameserver_count = 0;
-
-/*
- * Clean any DNS entries add by a DHCP request.
- */
-static void
-clean_dns_entries (void)
-{
- int e;
- for (e = 0; e < rtems_dhcpd_nameserver_count; ++e)
- {
- int n;
- for (n = 0; n < rtems_bsdnet_nameserver_count; ++ n)
- {
- if (memcmp (&rtems_dhcpd_nameserver[e], &rtems_bsdnet_nameserver[n], 4) == 0)
- {
- if (n < (NUM_NAMESERVERS - 1))
- memmove (&rtems_bsdnet_nameserver[n],
- &rtems_bsdnet_nameserver[n + 1],
- (NUM_NAMESERVERS - n - 1) * 4);
- --rtems_bsdnet_nameserver_count;
- }
- }
- }
- rtems_dhcpd_nameserver_count = 0;
-}
-
-/*
- * Format an IP address in dotted decimal.
- */
-static void
-format_ip (unsigned long ip, char* buffer)
-{
- sprintf (buffer,
- "%lu.%lu.%lu.%lu",
- (ip >> 24),
- (ip >> 16) & 0xff,
- (ip >> 8) & 0xff,
- (ip & 0xff));
-
- return;
-}
-
-/*
- * Print the IP setup
- */
-static void
-printsetup (const char *iface,
- struct in_addr ip_addr,
- struct in_addr mask_addr,
- struct in_addr srv_addr,
- struct in_addr gw_addr)
-{
- unsigned long ip;
- char ip_str[15];
-
- printf ("dhcpc: %s: ", iface);
-
- ip = ntohl (ip_addr.s_addr);
- format_ip (ip, ip_str);
- printf ("inet: %-15s ", ip_str);
-
- ip = ntohl (mask_addr.s_addr);
- format_ip (ip, ip_str);
- printf ("mask: %-15s\n", ip_str);
-
- ip = ntohl (srv_addr.s_addr);
- format_ip (ip, ip_str);
- printf (" srv: %-15s ", ip_str);
-
- ip = ntohl (gw_addr.s_addr);
- format_ip (ip, ip_str);
- printf (" gw: %-15s\n", ip_str);
-
- return;
-}
-
-/*
- * Process options from the DHCP packet.
- * Based on BOOTP routine.
- */
-static void
-process_options (unsigned char *optbuf, int optbufSize)
-{
- int j = 0;
- int len;
- int code, ncode;
- char *p;
-
- dhcp_message_type = 0;
-
- ncode = optbuf[0];
- while (j < optbufSize)
- {
- code = optbuf[j] = ncode;
- if (code == 255)
- return;
- if (code == 0)
- {
- j++;
- continue;
- }
- len = optbuf[j + 1];
- j += 2;
-
- if ((len + j) >= optbufSize)
- {
- printf ("Truncated field for code %d", code);
- return;
- }
-
- ncode = optbuf[j + len];
- optbuf[j + len] = '\0';
- p = (char*) &optbuf[j];
- j += len;
-
- /*
- * Process the option
- */
- switch (code)
- {
- case 1:
- /* Subnet mask */
- if (len != 4) {
- printf ("dhcpc: subnet mask len is %d\n", len);
- continue;
- }
- memcpy (&dhcp_netmask.sin_addr, p, 4);
- dhcp_gotnetmask = 1;
- break;
-
- case 2:
- /* Time offset */
- if (len != 4) {
- printf ("dhcpc: time offset len is %d\n", len);
- continue;
- }
- memcpy (&rtems_bsdnet_timeoffset, p, 4);
- rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset);
- break;
-
- case 3:
- /* Routers */
- if (len % 4) {
- printf ("dhcpc: Router Len is %d\n", len);
- continue;
- }
- if (len > 0)
- {
- memcpy (&dhcp_gw.sin_addr, p, 4);
- dhcp_gotgw = 1;
- }
- break;
-
- case 42:
- /* NTP servers */
- if (len % 4) {
- printf ("dhcpc: time server Len is %d\n", len);
- continue;
- }
- {
- int tlen = 0;
- while ((tlen < len) &&
- (rtems_bsdnet_ntpserver_count <
- sizeof rtems_bsdnet_config.ntp_server /
- sizeof rtems_bsdnet_config.ntp_server[0]))
- {
- memcpy (&rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count],
- p + tlen, 4);
- rtems_bsdnet_ntpserver_count++;
- tlen += 4;
- }
- }
- break;
-
- case 6:
- /* Domain Name servers */
- if (len % 4) {
- printf ("dhcpc: DNS Len is %d\n", len);
- continue;
- }
- {
- int dlen = 0;
- while ((dlen < len) &&
- (rtems_dhcpd_nameserver_count < NUM_NAMESERVERS) &&
- (rtems_bsdnet_nameserver_count < NUM_NAMESERVERS))
- {
- memcpy (&rtems_dhcpd_nameserver
- [rtems_dhcpd_nameserver_count], p + dlen, 4);
- rtems_dhcpd_nameserver_count++;
- memcpy (&rtems_bsdnet_nameserver
- [rtems_bsdnet_nameserver_count], p + dlen, 4);
- rtems_bsdnet_nameserver_count++;
- dlen += 4;
- }
- }
- break;
-
- case 12:
- /* Host name */
- if (len >= MAXHOSTNAMELEN) {
- printf ("dhcpc: hostname >= %d bytes\n", MAXHOSTNAMELEN);
- len = MAXHOSTNAMELEN-1;
- }
- if (sethostname (p, len) < 0) {
- printf ("dhcpc: can't set host name");
- }
- if (dhcp_hostname != NULL)
- {
- char *tmp = realloc (dhcp_hostname, len);
- if (tmp != NULL) {
- dhcp_hostname = tmp;
- strncpy (dhcp_hostname, p, len);
- } else { /* realloc failed */
- printf ("dhcpc: realloc failed (%s:%d)", __FILE__, __LINE__);
- free (dhcp_hostname, 0);
- dhcp_hostname = NULL;
- }
- } else { /* dhcp_hostname == NULL */
- dhcp_hostname = strndup (p, len);
- }
- break;
-
- case 7:
- /* Log servers */
- if (len % 4) {
- printf ("dhcpc: Log server Len is %d\n", len);
- continue;
- }
- if (len > 0)
- {
- memcpy (&rtems_bsdnet_log_host_address, p, 4);
- dhcp_gotlogserver = 1;
- }
- break;
-
- case 15:
- /* Domain name */
- if (p[0])
- {
- rtems_bsdnet_domain_name = strdup (p);
- }
- break;
-
- case 16: /* Swap server IP address. unused */
- break;
-
- case 50:
- /* DHCP Requested IP Address */
- if (len != 4)
- printf ("dhcpc: DHCP option requested IP len is %d", len);
- /*
- * although nothing happens here, this case keeps the client
- * from complaining about unknown options. The Requested IP
- * is necessary to return to the server for a DHCP REQUEST
- */
- break;
-
- case 51:
- /* DHCP Lease Length */
- if (len != 4) {
- printf ("dhcpc: DHCP option lease-length len is %d", len);
- continue;
- }
- memcpy (&dhcp_lease_time, &p[0], 4);
- dhcp_lease_time = ntohl (dhcp_lease_time);
- break;
-
- case 52:
- /* DHCP option override */
- if (len != 1) {
- printf ("dhcpc: DHCP option overload len is %d", len);
- continue;
- }
- dhcp_option_overload = p[0];
- break;
-
- case 53:
- /* DHCP message */
- if (len != 1) {
- printf ("dhcpc: DHCP message len is %d", len);
- continue;
- }
- dhcp_message_type = p[0];
- break;
-
- case 128: /* Site-specific option for DHCP servers that
- * a) don't supply tag 54
- * and
- * b) don't supply the server address in siaddr
- * For example, on Solaris 2.6 in.dhcpd, include in the dhcptab:
- * Bootsrv s Site,128,IP,1,1
- * and use that symbol in the macro that defines the client:
- * Bootsrv=<tftp-server-ip-address>
- */
- case 54:
- /* DHCP server */
- if (len != 4) {
- printf ("dhcpc: DHCP server len is %d", len);
- continue;
- }
- memcpy (&rtems_bsdnet_bootp_server_address, p, 4);
- dhcp_gotserver = 1;
- break;
-
- case 66:
- /* DHCP server name option */
- if (p[0])
- rtems_bsdnet_bootp_server_name = strdup (p);
- break;
-
- case 67:
- /* DHCP bootfile option */
- if (p[0])
- rtems_bsdnet_bootp_boot_file_name = strdup (p);
- break;
-
- default:
- break;
- }
- }
-}
-
-/*
- * Generate the packet for a DHCP DISCOVER.
- */
-static int
-dhcp_discover_req (struct dhcp_packet* call,
- struct sockaddr_dl *sdl,
- unsigned long *xid)
-{
- int len = 0;
-
- memset (call, 0, sizeof (struct dhcp_packet));
-
- /*
- * Send a DHCP DISCOVER Message
- */
- call->op = DHCP_BOOTREQUEST;
- call->htype = 1; /* 10mb ethernet */
- call->hlen = sdl->sdl_alen; /* Hardware address length */
- call->hops = 0;
- (*xid)++;
- call->xid = htonl (*xid);
- call->flags = htons (DHCP_BROADCAST);
-
- memcpy (&call->chaddr, LLADDR (sdl), sdl->sdl_alen);
-
- /*
- * Magic cookie.
- */
- memcpy (&call->vend[len], dhcp_magic_cookie, sizeof (dhcp_magic_cookie));
- len += sizeof (dhcp_magic_cookie);
-
- /*
- * DHCP Message type.
- */
- call->vend[len++] = DHCP_MESSAGE;
- call->vend[len++] = 1;
- call->vend[len++] = DHCP_DISCOVER;
-
- /*
- * If a host name is set add it to the request.
- */
- if (rtems_bsdnet_config.hostname && \
- (strlen (rtems_bsdnet_config.hostname) > 1) &&
- (strlen (rtems_bsdnet_config.hostname) < 32)) {
- call->vend[len++] = DHCP_HOST;
- call->vend[len++] = strlen (rtems_bsdnet_config.hostname);
- memcpy (&call->vend[len],
- rtems_bsdnet_config.hostname,
- strlen (rtems_bsdnet_config.hostname));
- len += strlen (rtems_bsdnet_config.hostname);
- }
-
- /*
- * DHCP Parameter request list
- */
- call->vend[len++] = DHCP_PARAMETERS;
- call->vend[len++] = sizeof (dhcp_request_parameters);
- memcpy (&call->vend[len], &dhcp_request_parameters, sizeof (dhcp_request_parameters));
- len += sizeof (dhcp_request_parameters);
-
- /*
- * Lease time.
- */
- call->vend[len++] = DHCP_LEASE;
- call->vend[len++] = 4;
- memset (&call->vend[len], 0xFF, 4); /* request infinite lease time */
- len += 4;
-
- /*
- * End.
- */
- call->vend[len++] = DHCP_OPTION_END;
- call->secs = 0;
-
- return len;
-}
-
-/*
- * Generate the packet for a DHCP REQUEST.
- */
-static int
-dhcp_request_req (struct dhcp_packet* call,
- struct dhcp_packet* reply,
- struct sockaddr_dl *sdl,
- int broadcast)
-{
- int len = 0;
- unsigned long temp;
- char *hostname;
-
- memset (call, 0, sizeof (struct dhcp_packet));
-
- /*
- * Send a DHCP REQUEST Message
- */
- call->op = DHCP_BOOTREQUEST;
- call->htype = 1; /* 10mb ethernet */
- call->hlen = sdl->sdl_alen; /* Hardware address length */
- call->hops = 0;
- call->xid = reply->xid;
- if (broadcast)
- call->flags = htons (DHCP_BROADCAST);
- else
- {
- call->flags = htons (DHCP_UNICAST);
- call->ciaddr = reply->yiaddr;
- }
- memcpy (&call->chaddr, LLADDR (sdl), sdl->sdl_alen);
-
- /*
- * Magic cookie.
- */
- memcpy (&call->vend[len], dhcp_magic_cookie, sizeof (dhcp_magic_cookie));
- len += sizeof (dhcp_magic_cookie);
-
- /*
- * DHCP Message type.
- */
- call->vend[len++] = DHCP_MESSAGE;
- call->vend[len++] = 1;
- call->vend[len++] = DHCP_REQUEST;
-
- /*
- * DHCP server
- */
- if (broadcast)
- {
- call->vend[len++] = DHCP_SERVER;
- call->vend[len++] = sizeof (rtems_bsdnet_bootp_server_address);
- memcpy (&call->vend[len], &rtems_bsdnet_bootp_server_address,
- sizeof (rtems_bsdnet_bootp_server_address));
- len += sizeof (rtems_bsdnet_bootp_server_address);
- }
-
- /*
- * Requested IP
- */
- call->vend[len++] = DHCP_REQUESTED_IP;
- call->vend[len++] = sizeof (reply->yiaddr);
- memcpy (&call->vend[len], &reply->yiaddr, sizeof (reply->yiaddr));
- len += sizeof (reply->yiaddr);
-
- /*
- * DHCP Parameter request list
- */
- call->vend[len++] = DHCP_PARAMETERS;
- call->vend[len++] = sizeof (dhcp_request_parameters);
- memcpy (&call->vend[len], &dhcp_request_parameters, sizeof (dhcp_request_parameters));
- len += sizeof (dhcp_request_parameters);
-
- /*
- * Lease time.
- * For the REQUEST, return the lease time the server offered.
- */
- call->vend[len++] = DHCP_LEASE;
- call->vend[len++] = 4;
- temp = htonl (dhcp_lease_time);
- memcpy (&call->vend[len], &temp, sizeof (unsigned long));
- len += 4;
-
- /*
- * Host name.
- */
- hostname = malloc (MAXHOSTNAMELEN, 0, M_NOWAIT);
- if (hostname != NULL)
- {
- if (gethostname (hostname, MAXHOSTNAMELEN) == 0)
- {
- call->vend[len++] = DHCP_HOST;
- call->vend[len++] = strlen (hostname);
- strcpy ((char*) &call->vend[len], hostname);
- len += strlen (hostname);
- }
- free (hostname, 0);
- }
-
- /*
- * End.
- */
- call->vend[len++] = DHCP_OPTION_END;
- call->secs = 0;
-
- return len;
-}
-
-/*
- * Variables for the DHCP task.
- */
-static struct dhcp_packet dhcp_req;
-static rtems_id dhcp_task_id;
-
-/*
- * The DHCP task counts until half the lease time has expired.
- * When this period is up, it sends a DHCP REQUEST packet to the
- * server again to renew the lease.
- * If the lease is renewed, the task starts counting again.
- * If the lease is not renewed, the task retries until it is.
- *
- * The task will not rebind if the lease is not renewed.
- */
-static void
-dhcp_task (rtems_task_argument _sdl)
-{
- unsigned long count;
- struct dhcp_packet call;
- struct sockaddr_dl *sdl;
- rtems_event_set event_out;
- unsigned int timeout = 0;
- int error;
- struct proc *procp = NULL;
- rtems_status_code ev_st;
-
- sdl = (struct sockaddr_dl *) _sdl;
-
- count = dhcp_elapsed_time;
-
- while (true)
- {
- /*
- * Sleep until the next poll
- */
- timeout = RTEMS_MILLISECONDS_TO_TICKS (1000);
- ev_st = rtems_event_receive (RTEMS_EVENT_0,
- RTEMS_WAIT | RTEMS_EVENT_ANY,
- timeout, &event_out);
-
- /*
- * Check if not a poll timeout. So when ANY event received, exit task.
- * Actually, only event RTEMS_EVENT_0 sent from rtem_dhcp_failsafe.c
- * if "failsafe" dhcp enabled when interface down. Otherwise, no
- * event should occur, just timeout.
- */
- if(ev_st != RTEMS_TIMEOUT)
- break;
-
- count++;
-
- if (count >= (dhcp_lease_time / 2))
- {
- rtems_bsdnet_semaphore_obtain ();
-
- dhcp_request_req (&call, &dhcp_req, sdl, true);
-
- /*
- * Send the Request.
- */
- error = bootpc_call ((struct bootp_packet *)&call,
- (struct bootp_packet *)&dhcp_req, procp, NULL, 0);
- if (error) {
- rtems_bsdnet_semaphore_release ();
- printf ("DHCP call failed -- error %d", error);
- continue;
- }
-
- /*
- * Check for DHCP ACK/NACK
- */
- if (memcmp (&dhcp_req.vend[0],
- dhcp_magic_cookie,
- sizeof (dhcp_magic_cookie)) != 0)
- {
- rtems_bsdnet_semaphore_release ();
- printf ("DHCP server did not send Magic Cookie.\n");
- continue;
- }
-
- /*
- * We have an ack. Clear the DNS entries that have been assigned by a previous
- * DHCP request.
- */
- clean_dns_entries ();
-
- /*
- * Process this requests options.
- */
- process_options (&dhcp_req.vend[4], sizeof (dhcp_req.vend) - 4);
-
- if (dhcp_message_type != DHCP_ACK)
- {
- rtems_bsdnet_semaphore_release ();
- printf ("DHCP server did not accept the DHCP request");
- continue;
- }
-
- rtems_bsdnet_semaphore_release ();
-
- count = 0;
- }
- }
-
-
- dhcp_task_id = 0;
- printf ("dhcpc: exiting lease renewal task.\n");
- rtems_task_exit();
-
-}
-
-/*
- * Start the DHCP task.
- */
-static rtems_status_code
-dhcp_start_task (struct sockaddr_dl *sdl,
- struct dhcp_packet *reply,
- int priority)
-{
- rtems_status_code sc;
-
- memcpy (&dhcp_req, reply, sizeof (struct dhcp_packet));
-
- sc = rtems_task_create (rtems_build_name ('d','h','c','p'),
- priority,
- 2048,
- RTEMS_PREEMPT |
- RTEMS_NO_TIMESLICE |
- RTEMS_NO_ASR |
- RTEMS_INTERRUPT_LEVEL (0),
- RTEMS_LOCAL,
- &dhcp_task_id);
-
- if (sc != RTEMS_SUCCESSFUL)
- return sc;
-
- sc = rtems_task_start (dhcp_task_id,
- dhcp_task,
- (rtems_task_argument) sdl);
-
- if (sc != RTEMS_SUCCESSFUL)
- return sc;
-
- return RTEMS_SUCCESSFUL;
-}
-
-/*
- * Check if the chosen interface already has an IP.
- */
-static int
-dhcp_interface_has_ip (struct ifreq *ireq, struct socket *so, struct proc *procp)
-{
- struct sockaddr_in* sin;
- int error;
-
- /*
- * Check if the interface is already up.
- */
- error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
- if (error)
- return 0;
-
- if ((ireq->ifr_flags & IFF_UP) == 0)
- return 0;
-
- sin = (struct sockaddr_in *)&ireq->ifr_addr;
- bzero ((caddr_t)sin, sizeof (struct sockaddr_in));
- sin->sin_len = sizeof (struct sockaddr_in);
- sin->sin_family = AF_INET;
- error = ifioctl (so, SIOCGIFADDR, (caddr_t)ireq, procp);
- if (error)
- return 0;
-
- if (sin->sin_addr.s_addr != 0)
- return 1;
-
- return 0;
-}
-
-/*
- * DCHP Client Routine
- * - The first DHCP offer is always accepted
- * - No DHCP DECLINE message is sent if ARPing fails
- *
- * return value:
- * 0: ok
- * < 0: failed to startup or configure interface
- */
-static int
-dhcp_init (int update_files)
-{
- struct dhcp_packet call;
- struct dhcp_packet reply;
- static unsigned long xid = ~0xFF;
- struct ifreq ireq;
- struct ifnet *ifp;
- struct socket *so;
- int error;
- struct sockaddr_in myaddr;
- struct ifaddr *ifa;
- struct sockaddr_dl *sdl = NULL;
- struct proc *procp = NULL;
- char expected_dhcp_payload[7];
-
- clean_dns_entries();
-
- /*
- * If we are to update the files create the root
- * file structure.
- */
- if (update_files)
- if (rtems_create_root_fs () < 0) {
- printf("Error creating the root filesystem.\nFile not created.\n");
- update_files = 0;
- }
-
- /*
- * Find a network interface.
- */
- for (ifp = ifnet; ifp != 0; ifp = ifp->if_next)
- if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
- break;
- if (ifp == NULL){
- printf ("dhcpc_init: no suitable interface\n");
- return -1;
- }
-
- memset (&ireq, 0, sizeof (ireq));
- sprintf (ireq.ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
-
- if ((error = socreate (AF_INET, &so, SOCK_DGRAM, 0, procp)) != 0) {
- printf ("dhcpc_init: socreate, error: %s\n", strerror(error));
- return -1;
- }
-
- if (!dhcp_interface_has_ip (&ireq, so, procp))
- bootpc_fakeup_interface (&ireq, so, procp);
-
- /*
- * Get HW address
- */
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
- if (ifa->ifa_addr->sa_family == AF_LINK &&
- (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) &&
- sdl->sdl_type == IFT_ETHER)
- break;
-
- if (!sdl){
- printf ("dhcpc_init: Unable to find HW address\n");
- soclose (so);
- return -1;
- }
- if (sdl->sdl_alen != EALEN) {
- printf ("dhcpc_init: HW address len is %d, expected value is %d\n",
- sdl->sdl_alen, EALEN);
- soclose (so);
- return -1;
- }
-
-
- /*
- * Build the DHCP Discover
- */
- dhcp_discover_req (&call, sdl, &xid);
-
- /*
- * Expect a DHCP offer as response to DHCP discover
- */
- memcpy(expected_dhcp_payload, dhcp_magic_cookie, sizeof(dhcp_magic_cookie));
- expected_dhcp_payload[sizeof(dhcp_magic_cookie) ]=0x35; /* DHCP */
- expected_dhcp_payload[sizeof(dhcp_magic_cookie)+1]=0x01; /* Length : 1 */
- expected_dhcp_payload[sizeof(dhcp_magic_cookie)+2]=0x02; /* DHCP_OFFER */
-
- /*
- * Send the Discover.
- */
- error = bootpc_call ((struct bootp_packet *)&call,
- (struct bootp_packet *)&reply, procp,
- expected_dhcp_payload, sizeof(expected_dhcp_payload));
- if (error) {
- printf ("BOOTP call failed -- %s\n", strerror(error));
- soclose (so);
- return -1;
- }
-
- /*
- * Check for DHCP OFFER
- */
- if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
- printf ("DHCP server did not send Magic Cookie.\n");
- soclose (so);
- return -1;
- }
-
- process_options (&reply.vend[4], sizeof (reply.vend) - 4);
-
- if (dhcp_message_type != DHCP_OFFER) {
- printf ("DHCP server did not send a DHCP Offer.\n");
- soclose (so);
- return -1;
- }
-
- /*
- * Expect a DHCP_ACK as response to the DHCP REQUEST
- * No need to reinitialize the whole expected_dhcp_payload variable,
- * header and first two bytes of the payload are filled from DHCP offer
- */
- expected_dhcp_payload[sizeof(dhcp_magic_cookie)+2]=0x05; /* DHCP_ACK */
-
- /*
- * Send a DHCP REQUEST
- */
- dhcp_request_req (&call, &reply, sdl, true);
-
- error = bootpc_call ((struct bootp_packet *)&call,
- (struct bootp_packet *)&reply, procp,
- expected_dhcp_payload, sizeof(expected_dhcp_payload));
- if (error) {
- printf ("BOOTP call failed -- %s\n", strerror(error));
- soclose (so);
- return -1;
- }
-
- /*
- * Check for DHCP ACK/NACK
- */
- if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) != 0) {
- printf ("DHCP server did not send Magic Cookie.\n");
- soclose (so);
- return -1;
- }
-
- process_options (&reply.vend[4], sizeof (reply.vend) - 4);
-
- if (dhcp_message_type != DHCP_ACK) {
- printf ("DHCP server did not accept the DHCP request\n");
- soclose (so);
- return -1;
- }
-
- /*
- * Initialize network address structures
- */
- memset (&myaddr, 0, sizeof (myaddr));
- memset (&dhcp_netmask, 0, sizeof (dhcp_netmask));
- memset (&dhcp_gw, 0, sizeof (dhcp_gw));
- myaddr.sin_len = sizeof (myaddr);
- myaddr.sin_family = AF_INET;
- dhcp_netmask.sin_len = sizeof (dhcp_netmask);
- dhcp_netmask.sin_family = AF_INET;
- dhcp_gw.sin_len = sizeof (dhcp_gw);
- dhcp_gw.sin_family = AF_INET;
-
- /*
- * Set our address
- */
- myaddr.sin_addr = reply.yiaddr;
-
- /*
- * Process BOOTP/DHCP options
- */
- if (memcmp (&reply.vend[0], dhcp_magic_cookie, sizeof (dhcp_magic_cookie)) == 0)
- process_options (&reply.vend[4], sizeof (reply.vend) - 4);
-
- if (dhcp_option_overload & 1)
- process_options ((unsigned char*) reply.file, sizeof reply.file);
- else
- if (reply.file[0])
- rtems_bsdnet_bootp_boot_file_name = strdup (reply.file);
-
- if (dhcp_option_overload & 2)
- process_options ((unsigned char*) reply.sname, sizeof reply.sname);
- else
- if (reply.sname[0])
- rtems_bsdnet_bootp_server_name = strdup (reply.sname);
-
- /*
- * Use defaults if values were not supplied by BOOTP/DHCP options
- */
- if (!dhcp_gotnetmask)
- {
- if (IN_CLASSA (ntohl (myaddr.sin_addr.s_addr)))
- dhcp_netmask.sin_addr.s_addr = htonl (IN_CLASSA_NET);
- else if (IN_CLASSB (ntohl (myaddr.sin_addr.s_addr)))
- dhcp_netmask.sin_addr.s_addr = htonl (IN_CLASSB_NET);
- else
- dhcp_netmask.sin_addr.s_addr = htonl (IN_CLASSC_NET);
- }
-
- if (!dhcp_gotserver)
- rtems_bsdnet_bootp_server_address = reply.siaddr;
-
- if (!dhcp_gotgw)
- dhcp_gw.sin_addr = reply.giaddr;
-
- if (!dhcp_gotlogserver)
- rtems_bsdnet_log_host_address = rtems_bsdnet_bootp_server_address;
-
- printsetup (ifp->if_name, myaddr.sin_addr, dhcp_netmask.sin_addr,
- rtems_bsdnet_bootp_server_address, dhcp_gw.sin_addr);
-
- /*
- * Update the files if we are asked too.
- */
- if (update_files) {
- char *dn = rtems_bsdnet_domain_name;
- char *hn = dhcp_hostname;
- if (!dn)
- dn = "mydomain";
- if (!hn)
- {
- hn = "me";
- sethostname (hn, strlen (hn));
- }
- rtems_rootfs_append_host_rec(myaddr.sin_addr.s_addr, hn, dn);
-
- /*
- * Should the given domainname be used here ?
- */
- if (dhcp_gotserver) {
- if (rtems_bsdnet_bootp_server_name)
- hn = rtems_bsdnet_bootp_server_name;
- else
- hn = "bootps";
- rtems_rootfs_append_host_rec(rtems_bsdnet_bootp_server_address.s_addr,
- hn, dn);
- }
-
- if (dhcp_gotlogserver) {
- rtems_rootfs_append_host_rec(rtems_bsdnet_log_host_address.s_addr,
- "logs", dn);
- }
-
- /*
- * Setup the DNS configuration file /etc/resolv.conf.
- */
- if (rtems_bsdnet_nameserver_count) {
- int i;
- char buf[64];
- const char *bufl[1];
-
- bufl[0] = buf;
-
-#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH)
-
- if (rtems_bsdnet_domain_name &&
- (strlen(rtems_bsdnet_domain_name) < (sizeof(buf) - 1))) {
- strcpy(buf, "search ");
- strcat(buf, rtems_bsdnet_domain_name);
- strcat(buf, "\n");
- rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl);
- }
-
- for (i = 0; i < rtems_bsdnet_nameserver_count; i++) {
- char addrbuf[INET_ADDRSTRLEN];
- strcpy(buf, "nameserver ");
- strcat(buf, inet_ntoa_r(rtems_bsdnet_ntpserver[i], addrbuf));
- strcat(buf, "\n");
- if (rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl))
- break;
- }
- }
- }
-
- /*
- * Configure the interface with the new settings
- */
- error = bootpc_adjust_interface (&ireq, so,
- &myaddr, &dhcp_netmask, &dhcp_gw, procp);
-
- /*
- * Start the DHCP task if the lease isn't infinite.
- */
- if (dhcp_lease_time != 0xffffffff)
- dhcp_start_task (sdl, &reply, 150);
-
- soclose (so);
-
- return 0;
-}
-
-/*
- *
- * RTEMS Entry point to DHCP client
- *
- */
-void rtems_bsdnet_do_dhcp (void)
-{
- bool update = true;
- rtems_bsdnet_semaphore_obtain ();
- while( dhcp_init (update) < 0 ) {
- update = false;
- rtems_bsdnet_semaphore_release();
- rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000));
- rtems_bsdnet_semaphore_obtain ();
- }
- rtems_bsdnet_semaphore_release ();
-}
-
-int rtems_bsdnet_do_dhcp_timeout( void )
-{
- int return_value;
-
- rtems_bsdnet_semaphore_obtain ();
- return_value = dhcp_init (false);
- rtems_bsdnet_semaphore_release ();
-
- return return_value;
-}
-
-void rtems_bsdnet_dhcp_down (void)
-{
- if(dhcp_task_id != 0) {
- rtems_event_send (dhcp_task_id, RTEMS_EVENT_0);
- }
-}
-
-void
-rtems_bsdnet_do_dhcp_refresh_only (unsigned long xid,
- unsigned long lease_time,
- unsigned long elapsed_time,
- unsigned long ip_address,
- unsigned long srv_address,
- const char* hostname)
-{
- struct dhcp_packet reply;
- struct ifnet *ifp = NULL;
- struct ifaddr *ifa = NULL;
- struct sockaddr_dl *sdl = NULL;
- struct sockaddr_in *sin = NULL;
- int match = 0;
- struct ifnet *mtif = NULL;
-
- /*
- * If an infinite lease has been granted, no task is needed.
- */
- if (lease_time == 0xffffffff)
- return;
-
- /*
- * Find a network interface.
- */
- for (ifp = ifnet; (ifp != NULL) && !match; ifp = ifp->if_next)
- if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
- for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
- if (ifa->ifa_addr->sa_family == AF_INET)
- {
- sin = (struct sockaddr_in *) ifa->ifa_addr;
- if (sin->sin_addr.s_addr == htonl (ip_address))
- {
- mtif = ifp;
- match = 1;
- break;
- }
- }
-
- if (!match) {
- printf ("dhcpc: no matching interface\n");
- return;
- }
-
- for (ifa = mtif->if_addrlist; ifa != NULL; ifa = ifa->ifa_next)
- if (ifa->ifa_addr->sa_family == AF_LINK &&
- (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) &&
- sdl->sdl_type == IFT_ETHER)
- break;
-
- if (!match) {
- printf ("dhcpc: no matching interface address\n");
- return;
- }
-
- /*
- * Set up given values in a simulated DHCP reply.
- */
- memset (&reply, 0x00, sizeof (reply));
- reply.xid = htonl (xid);
- reply.yiaddr.s_addr = htonl (ip_address);
- reply.siaddr.s_addr = htonl (srv_address);
- if (reply.siaddr.s_addr != rtems_bsdnet_bootp_server_address.s_addr)
- {
- memcpy (&rtems_bsdnet_bootp_server_address, &reply.siaddr,
- sizeof (reply.siaddr));
- }
-
- dhcp_lease_time = lease_time;
- dhcp_elapsed_time = elapsed_time;
-
- if (hostname)
- {
- sethostname ((char *) hostname, strlen (hostname));
- dhcp_hostname = bootp_strdup_realloc (dhcp_hostname, hostname);
- }
-
- dhcp_start_task (sdl, &reply, 150);
-}