Files
NetworkManager/dhcpcd/buildmsg.c
Dan Williams e26e7e9983 2004-12-15 Dan Williams <dcbw@redhat.com>
* Rework the DHCP code again to revert to sending full ethernet frames
		rather then relying on the kernel to do the right thing with our
		packets.


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@340 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2004-12-15 17:58:59 +00:00

356 lines
12 KiB
C

/*
* dhcpcd - DHCP client daemon -
* Copyright (C) 1996 - 1997 Yoichi Hariguchi <yoichi@fore.com>
* Copyright (C) January, 1998 Sergei Viznyuk <sv@phystech.com>
*
* dhcpcd is an RFC2131 and RFC1541 compliant DHCP client daemon.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Softwarme
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <net/if_arp.h>
#include "client.h"
#include "buildmsg.h"
#include "udpipgen.h"
extern int DebugFlag;
/*****************************************************************************/
void fill_common_fields (dhcp_interface *iface, udpipMessage *msg, unsigned char dhost_addr[6], int bcast_resp)
{
dhcpMessage *dhcp_msg = (dhcpMessage *)&(msg->udpipmsg[sizeof(udpiphdr)]);
int magic_cookie = htonl (MAGIC_COOKIE);
/* build Ethernet header */
memcpy (msg->ethhdr.ether_dhost, dhost_addr, ETH_ALEN);
memcpy (msg->ethhdr.ether_shost, iface->chaddr, ETH_ALEN);
msg->ethhdr.ether_type = htons (ETHERTYPE_IP);
dhcp_msg->op = DHCP_BOOTREQUEST;
dhcp_msg->htype = ARPHRD_ETHER;
dhcp_msg->hlen = ETH_ALEN;
dhcp_msg->xid = iface->xid;
dhcp_msg->secs = htons (10);
if (bcast_resp && iface->client_options->do_broadcast_response)
dhcp_msg->flags = htons (BROADCAST_FLAG);
memcpy (dhcp_msg->chaddr, iface->chaddr, ETH_ALEN);
memcpy (dhcp_msg->options, &magic_cookie, 4);
}
/*****************************************************************************/
unsigned char *fill_host_and_class_id (dhcp_interface *iface, unsigned char *p)
{
const char *host_name = iface->client_options->host_name;
int host_name_len = strlen (host_name);
if ( host_name_len )
{
*p++ = hostName;
*p++ = host_name_len;
memcpy (p, host_name, host_name_len);
p += host_name_len;
}
*p++ = dhcpClassIdentifier;
*p++ = iface->cls_id_len;
memcpy (p, iface->cls_id, iface->cls_id_len);
p += iface->cls_id_len;
*p++ = dhcpClientIdentifier;
*p++ = iface->cli_id_len;
memcpy (p, iface->cli_id, iface->cli_id_len);
p += iface->cli_id_len;
return p;
}
/*****************************************************************************/
unsigned char *fill_param_request (unsigned char *p)
{
*p++ = dhcpParamRequest;
*p++ = 9;
*p++ = subnetMask;
*p++ = routersOnSubnet;
*p++ = dns;
*p++ = hostName;
*p++ = domainName;
*p++ = broadcastAddr;
*p++ = nisDomainName;
*p++ = nisServers;
*p++ = ntpServers;
return p;
}
/*****************************************************************************/
unsigned char *fill_requested_ipaddr (dhcp_interface *iface, unsigned char *p)
{
*p++ = dhcpRequestedIPaddr;
*p++ = 4;
memcpy (p, &(iface->ciaddr), 4);
p += 4;
return p;
}
/*****************************************************************************/
unsigned char *fill_lease_time (unsigned int *lease_time, unsigned char *p)
{
*p++ = dhcpIPaddrLeaseTime;
*p++ = 4;
memcpy (p, lease_time, 4);
p += 4;
return p;
}
/*****************************************************************************/
unsigned char *fill_server_id (unsigned int *server_id, unsigned char *p)
{
*p++ = dhcpServerIdentifier;
*p++ = 4;
memcpy (p, server_id, 4);
p += 4;
return p;
}
/*****************************************************************************/
unsigned char *fill_message_type (unsigned char request, unsigned char *p)
{
const unsigned short dhcpMsgSize = htons (sizeof (dhcpMessage));
*p++ = dhcpMessageType;
*p++ = 1;
*p++ = request;
*p++ = dhcpMaxMsgSize;
*p++ = 2;
memcpy (p, &dhcpMsgSize, 2);
p += 2;
return p;
}
/*****************************************************************************/
udpipMessage *build_dhcp_discover (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
unsigned int lease_time = htonl (iface->default_lease_time);
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, MAC_BCAST_ADDR, 1);
p = fill_message_type (DHCP_DISCOVER, p);
if ( iface->ciaddr )
{
if ( iface->client_options->do_rfc1541 )
dhcp_msg->ciaddr = iface->ciaddr;
else
p = fill_requested_ipaddr (iface, p);
}
p = fill_lease_time (&lease_time, p);
p = fill_param_request (p);
p = fill_host_and_class_id (iface, p);
*p++ = endOption;
/* build UDP/IP header */
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen ((udpiphdr *)(udp_msg->udpipmsg), 0, INADDR_BROADCAST, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)p - (char *)udp_msg;
return (udp_msg);
}
/*****************************************************************************/
udpipMessage *build_dhcp_request (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, MAC_BCAST_ADDR, 1);
p = fill_message_type (DHCP_REQUEST, p);
p = fill_server_id (iface->dhcp_options.val[dhcpServerIdentifier], p);
if ( iface->client_options->do_rfc1541 )
dhcp_msg->ciaddr = iface->ciaddr;
else
p = fill_requested_ipaddr (iface, p);
if ( iface->dhcp_options.val[dhcpIPaddrLeaseTime] )
p = fill_lease_time (iface->dhcp_options.val[dhcpIPaddrLeaseTime], p);
p = fill_param_request (p);
p = fill_host_and_class_id (iface, p);
*p = endOption;
/* build UDP/IP header */
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen ((udpiphdr *)(udp_msg->udpipmsg), 0, INADDR_BROADCAST, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)(p++) - (char *)udp_msg;
return udp_msg;
}
/*****************************************************************************/
udpipMessage *build_dhcp_renew (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, iface->shaddr, 1);
dhcp_msg->ciaddr = iface->ciaddr;
p = fill_message_type (DHCP_REQUEST, p);
#if 0
if ( iface->dhcp_options.val[dhcpIPaddrLeaseTime] )
p = fill_lease_time (iface->dhcp_options.val[dhcpIPaddrLeaseTime], p);
#endif
p = fill_param_request (p);
p = fill_host_and_class_id (iface, p);
*p = endOption;
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen ((udpiphdr *)(udp_msg->udpipmsg), iface->ciaddr, iface->siaddr, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)(p++) - (char *)udp_msg;
return (udp_msg);
}
/*****************************************************************************/
udpipMessage *build_dhcp_rebind (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, MAC_BCAST_ADDR, 1);
dhcp_msg->ciaddr = iface->ciaddr;
p = fill_message_type (DHCP_REQUEST, p);
if ( iface->dhcp_options.val[dhcpIPaddrLeaseTime] )
p = fill_lease_time (iface->dhcp_options.val[dhcpIPaddrLeaseTime], p);
p = fill_param_request (p);
p = fill_host_and_class_id (iface, p);
*p = endOption;
/* build UDP/IP header */
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen ((udpiphdr *)(udp_msg->udpipmsg), iface->ciaddr, INADDR_BROADCAST, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)(p++) - (char *)udp_msg;
return udp_msg;
}
/*****************************************************************************/
udpipMessage *build_dhcp_reboot (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
unsigned int lease_time = htonl (iface->default_lease_time);
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, MAC_BCAST_ADDR, 1);
p = fill_message_type (DHCP_REQUEST, p);
if ( iface->client_options->do_rfc1541 )
dhcp_msg->ciaddr = iface->ciaddr;
else
p = fill_requested_ipaddr (iface, p);
p = fill_lease_time (&lease_time, p);
p = fill_param_request (p);
p = fill_host_and_class_id (iface, p);
*p = endOption;
/* build UDP/IP header */
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen ((udpiphdr *)(udp_msg->udpipmsg), 0, INADDR_BROADCAST, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)(p++) - (char *)udp_msg;
return (udp_msg);
}
/*****************************************************************************/
udpipMessage *build_dhcp_release (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, iface->shaddr, 1);
dhcp_msg->ciaddr = iface->ciaddr;
*p++ = dhcpMessageType;
*p++ = 1;
*p++ = DHCP_RELEASE;
p = fill_server_id (iface->dhcp_options.val[dhcpServerIdentifier], p);
memcpy(p, iface->cli_id, iface->cli_id_len);
p += iface->cli_id_len;
*p = endOption;
/* build UDP/IP header */
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen ((udpiphdr *)(udp_msg->udpipmsg), iface->ciaddr, iface->siaddr, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)(p++) - (char *)udp_msg;
return (udp_msg);
}
/*****************************************************************************/
#ifdef ARPCHECK
udpipMessage *build_dhcp_decline (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, iface->shaddr, 1);
*p++ = dhcpMessageType;
*p++ = 1;
*p++ = DHCP_DECLINE;
p = fill_server_id (iface->dhcp_options.val[dhcpServerIdentifier], p);
if ( iface->client_options->do_rfc1541 )
dhcp_msg->ciaddr = iface->ciaddr;
else
p = fill_requested_ipaddr (iface, p);
memcpy (p, iface->cli_id, iface->cli_id_len);
p += iface->cli_id_len;
*p = endOption;
/* build UDP/IP header */
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen ((udpiphdr *)(udp_msg->udpipmsg), 0, iface->siaddr, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)(p++) - (char *)udp_msg;
return (udp_msg);
}
#endif
/*****************************************************************************/
udpipMessage *build_dhcp_inform (dhcp_interface *iface, int *msg_len)
{
udpipMessage *udp_msg = calloc (1, sizeof (udpipMessage));
dhcpMessage *dhcp_msg = (dhcpMessage *)&(udp_msg->udpipmsg[sizeof(udpiphdr)]);
register unsigned char *p = dhcp_msg->options + 4;
int dhcp_msg_len;
fill_common_fields (iface, udp_msg, iface->shaddr, 1);
dhcp_msg->ciaddr = iface->ciaddr;
p = fill_message_type (DHCP_INFORM, p);
p = fill_param_request (p);
p = fill_host_and_class_id (iface, p);
*p = endOption;
/* build UDP/IP header */
p++;
dhcp_msg_len = (char *)p - (char *)dhcp_msg;
udpipgen((udpiphdr *)(udp_msg->udpipmsg), 0, INADDR_BROADCAST, &iface->ip_id, dhcp_msg_len);
*msg_len = (char *)(p++) - (char *)udp_msg;
return (udp_msg);
}