2004-11-16 02:41:53 +00:00
|
|
|
/*
|
|
|
|
|
* 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 Software
|
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
|
#include <net/if.h>
|
|
|
|
|
#include <net/if_arp.h>
|
|
|
|
|
#include <net/if_packet.h>
|
|
|
|
|
#include <net/route.h>
|
2004-12-05 21:28:42 +00:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
#include <netinet/udp.h>
|
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
|
#include <netpacket/packet.h>
|
2004-11-16 02:41:53 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <syslog.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include "client.h"
|
|
|
|
|
#include "buildmsg.h"
|
|
|
|
|
#include "arp.h"
|
2004-12-15 17:58:59 +00:00
|
|
|
#include "udpipgen.h"
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-16 04:24:20 +00:00
|
|
|
#ifdef DEBUG
|
2004-11-16 02:41:53 +00:00
|
|
|
int DebugFlag = 1;
|
2004-12-16 04:24:20 +00:00
|
|
|
#else
|
|
|
|
|
int DebugFlag = 0;
|
|
|
|
|
#endif
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
typedef struct dhcp_response_return
|
|
|
|
|
{
|
|
|
|
|
unsigned int server_ip_addr;
|
|
|
|
|
char server_hw_addr[ETH_ALEN];
|
|
|
|
|
dhcpMessage dhcp_msg;
|
|
|
|
|
} dhcp_response_return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void debug_dump_dhcp_options (struct sockaddr_ll *saddr, dhcpMessage *dhcp_msg, dhcpOptions *options);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2004-12-05 21:28:42 +00:00
|
|
|
int parse_dhcp_reply (struct iphdr *iphdr, struct sockaddr_ll *saddr, dhcpMessage *dhcp_msg, dhcpOptions *options)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
register u_char *p = dhcp_msg->options+4;
|
2004-12-05 21:28:42 +00:00
|
|
|
unsigned char *end = dhcp_msg->options + sizeof (dhcp_msg->options);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/* Force T1 and T2 to 0: either new values will be in message, or they
|
|
|
|
|
will need to be recalculated from lease time */
|
|
|
|
|
if ( options->val[dhcpT1value] && options->len[dhcpT1value] > 0 )
|
|
|
|
|
memset (options->val[dhcpT1value], 0, options->len[dhcpT1value]);
|
|
|
|
|
if ( options->val[dhcpT2value] && options->len[dhcpT2value] > 0 )
|
|
|
|
|
memset (options->val[dhcpT2value], 0, options->len[dhcpT2value]);
|
|
|
|
|
|
|
|
|
|
while ( p < end )
|
|
|
|
|
{
|
|
|
|
|
switch ( *p )
|
|
|
|
|
{
|
|
|
|
|
case endOption:
|
|
|
|
|
goto swend;
|
|
|
|
|
case padOption:
|
|
|
|
|
p++;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if ( p[1] )
|
|
|
|
|
{
|
|
|
|
|
if ( options->len[*p] == p[1] )
|
|
|
|
|
memcpy (options->val[*p], p+2, p[1]);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
options->len[*p] = p[1];
|
|
|
|
|
if ( options->val[*p] )
|
|
|
|
|
free (options->val[*p]);
|
|
|
|
|
else
|
|
|
|
|
options->num++;
|
|
|
|
|
options->val[*p] = malloc (p[1]+1);
|
|
|
|
|
memset (options->val[*p], 0, p[1]+1);
|
|
|
|
|
memcpy (options->val[*p], p+2, p[1]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p+=p[1]+2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
swend:
|
|
|
|
|
#ifdef DEBUG
|
2004-12-05 21:28:42 +00:00
|
|
|
debug_dump_dhcp_options (saddr, dhcp_msg, options);
|
2004-11-16 02:41:53 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 0
|
2004-12-05 21:28:42 +00:00
|
|
|
if ( !dhcp_msg->yiaddr )
|
2004-11-16 02:41:53 +00:00
|
|
|
dhcp_msg->yiaddr = DhcpMsgSend->ciaddr;
|
|
|
|
|
#endif
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (!options->val[dhcpServerIdentifier]) /* did not get dhcpServerIdentifier */
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
/* make it the same as IP address of the sender */
|
2004-12-05 21:28:42 +00:00
|
|
|
options->val[dhcpServerIdentifier] = malloc (4);
|
|
|
|
|
memcpy (options->val[dhcpServerIdentifier], &(iphdr->saddr), 4);
|
2004-11-16 02:41:53 +00:00
|
|
|
options->len[dhcpServerIdentifier] = 4;
|
|
|
|
|
options->num++;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "dhcpServerIdentifier option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)options->val[dhcpServerIdentifier])[0],
|
|
|
|
|
((unsigned char *)options->val[dhcpServerIdentifier])[1],
|
|
|
|
|
((unsigned char *)options->val[dhcpServerIdentifier])[2],
|
|
|
|
|
((unsigned char *)options->val[dhcpServerIdentifier])[3]);
|
|
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (!options->val[dns]) /* did not get DNS */
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
/* make it the same as dhcpServerIdentifier */
|
2004-12-05 21:28:42 +00:00
|
|
|
options->val[dns] = malloc (4);
|
2004-11-16 02:41:53 +00:00
|
|
|
memcpy (options->val[dns], options->val[dhcpServerIdentifier], 4);
|
|
|
|
|
options->len[dns] = 4;
|
|
|
|
|
options->num++;
|
|
|
|
|
if ( DebugFlag )
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_DEBUG, "dns option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
|
|
|
|
|
((unsigned char *)options->val[dns])[0], ((unsigned char *)options->val[dns])[1],
|
|
|
|
|
((unsigned char *)options->val[dns])[2], ((unsigned char *)options->val[dns])[3]);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (!options->val[subnetMask]) /* did not get subnetMask */
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
options->val[subnetMask] = malloc (4);
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)options->val[subnetMask])[0] = 255;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (IN_CLASSA (ntohl (dhcp_msg->yiaddr)))
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[1] = 0; /* class A */
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[2] = 0;
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[3] = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[1] = 255;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (IN_CLASSB (ntohl (dhcp_msg->yiaddr)))
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
((unsigned char *)(options->val[subnetMask]))[2] = 0;/* class B */
|
|
|
|
|
((unsigned char *)(options->val[subnetMask]))[3] = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[2] = 255;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (IN_CLASSC (ntohl (dhcp_msg->yiaddr)))
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)options->val[subnetMask])[3] = 0; /* class C */
|
|
|
|
|
else
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[3] = 255;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
options->len[subnetMask] = 4;
|
|
|
|
|
options->num++;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "subnetMask option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[0], ((unsigned char *)options->val[subnetMask])[1],
|
|
|
|
|
((unsigned char *)options->val[subnetMask])[2], ((unsigned char *)options->val[subnetMask])[3]);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (!options->val[broadcastAddr]) /* did not get broadcastAddr */
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
int br = dhcp_msg->yiaddr | ~*((int *)options->val[subnetMask]);
|
2004-12-05 21:28:42 +00:00
|
|
|
options->val[broadcastAddr] = malloc (4);
|
2004-11-16 02:41:53 +00:00
|
|
|
memcpy (options->val[broadcastAddr], &br, 4);
|
|
|
|
|
options->len[broadcastAddr] = 4;
|
|
|
|
|
options->num++;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
syslog(LOG_DEBUG, "broadcastAddr option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
|
2004-12-05 21:28:42 +00:00
|
|
|
((unsigned char *)options->val[broadcastAddr])[0], ((unsigned char *)options->val[broadcastAddr])[1],
|
|
|
|
|
((unsigned char *)options->val[broadcastAddr])[2], ((unsigned char *)options->val[broadcastAddr])[3]);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (!options->val[routersOnSubnet])
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
options->val[routersOnSubnet] = malloc (4);
|
|
|
|
|
if (options->val[dhcpServerIdentifier])
|
|
|
|
|
memcpy (options->val[routersOnSubnet], options->val[dhcpServerIdentifier], 4);
|
2004-11-16 02:41:53 +00:00
|
|
|
else
|
2004-12-05 21:28:42 +00:00
|
|
|
memcpy (options->val[routersOnSubnet], &dhcp_msg->giaddr, 4);
|
2004-11-16 02:41:53 +00:00
|
|
|
options->len[routersOnSubnet] = 4;
|
|
|
|
|
options->num++;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "routersOnSubnet option is missing in DHCP server response. Assuming %u.%u.%u.%u (DHCP server)\n",
|
|
|
|
|
((unsigned char *)options->val[routersOnSubnet])[0], ((unsigned char *)options->val[routersOnSubnet])[1],
|
|
|
|
|
((unsigned char *)options->val[routersOnSubnet])[2], ((unsigned char *)options->val[routersOnSubnet])[3]);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (options->val[dhcpIPaddrLeaseTime] && options->len[dhcpIPaddrLeaseTime] == 4)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
if ( *(unsigned int *)options->val[dhcpIPaddrLeaseTime] == 0 )
|
|
|
|
|
{
|
|
|
|
|
unsigned int lease_time = htonl (DHCP_DEFAULT_LEASETIME);
|
|
|
|
|
memcpy (options->val[dhcpIPaddrLeaseTime], &lease_time, 4);
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "dhcpIPaddrLeaseTime=0 in DHCP server response. Assuming %u sec\n", lease_time);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "dhcpIPaddrLeaseTime = %u in DHCP server response.\n",
|
|
|
|
|
ntohl (*(unsigned int *)options->val[dhcpIPaddrLeaseTime]));
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else /* did not get dhcpIPaddrLeaseTime */
|
|
|
|
|
{
|
|
|
|
|
unsigned int lease_time = htonl (DHCP_DEFAULT_LEASETIME);
|
|
|
|
|
options->val[dhcpIPaddrLeaseTime] = malloc(4);
|
|
|
|
|
memcpy (options->val[dhcpIPaddrLeaseTime], &lease_time, 4);
|
|
|
|
|
options->len[dhcpIPaddrLeaseTime] = 4;
|
|
|
|
|
options->num++;
|
|
|
|
|
if ( DebugFlag )
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_DEBUG, "dhcpIPaddrLeaseTime option is missing in DHCP server response. Assuming %u sec\n", lease_time);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (options->val[dhcpT1value] && options->len[dhcpT1value] == 4)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
if (*(unsigned int *)options->val[dhcpT1value] == 0)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
unsigned t2 = 0.5 * ntohl (*(unsigned int *)options->val[dhcpIPaddrLeaseTime]);
|
|
|
|
|
int t1 = htonl (t2);
|
2004-11-16 02:41:53 +00:00
|
|
|
memcpy (options->val[dhcpT1value],&t1,4);
|
|
|
|
|
options->len[dhcpT1value] = 4;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "dhcpT1value is missing in DHCP server response. Assuming %u sec\n", t2);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else /* did not get T1 */
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
unsigned t2 = 0.5 * ntohl (*(unsigned int *)options->val[dhcpIPaddrLeaseTime]);
|
|
|
|
|
int t1 = htonl (t2);
|
2004-11-16 02:41:53 +00:00
|
|
|
options->val[dhcpT1value] = malloc(4);
|
|
|
|
|
memcpy (options->val[dhcpT1value],&t1,4);
|
|
|
|
|
options->len[dhcpT1value] = 4;
|
|
|
|
|
options->num++;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "dhcpT1value is missing in DHCP server response. Assuming %u sec\n", t2);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (options->val[dhcpT2value] && options->len[dhcpT2value] == 4)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
if (*(unsigned int *)options->val[dhcpT2value] == 0)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
unsigned t2 = 0.875 * ntohl (*(unsigned int *)options->val[dhcpIPaddrLeaseTime]);
|
|
|
|
|
int t1 = htonl (t2);
|
|
|
|
|
memcpy (options->val[dhcpT2value],&t1,4);
|
2004-11-16 02:41:53 +00:00
|
|
|
options->len[dhcpT2value] = 4;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "dhcpT2value is missing in DHCP server response. Assuming %u sec\n", t2);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else /* did not get T2 */
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
unsigned t2 = 0.875 * ntohl (*(unsigned int *)options->val[dhcpIPaddrLeaseTime]);
|
|
|
|
|
int t1 = htonl (t2);
|
2004-11-16 02:41:53 +00:00
|
|
|
options->val[dhcpT2value] = malloc(4);
|
2004-12-05 21:28:42 +00:00
|
|
|
memcpy (options->val[dhcpT2value],&t1,4);
|
2004-11-16 02:41:53 +00:00
|
|
|
options->len[dhcpT2value] = 4;
|
|
|
|
|
options->num++;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "dhcpT2value is missing in DHCP server response. Assuming %u sec\n", t2);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (options->val[dhcpMessageType])
|
2004-11-16 02:41:53 +00:00
|
|
|
return *(unsigned char *)options->val[dhcpMessageType];
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
2004-12-05 21:28:42 +00:00
|
|
|
void class_id_setup (dhcp_interface *iface, const char *g_cls_id)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
unsigned int g_cls_id_len = 0;
|
|
|
|
|
|
|
|
|
|
if (!iface) return;
|
|
|
|
|
|
2004-12-15 17:58:59 +00:00
|
|
|
memset (iface->cls_id, 0, DHCP_CLASS_ID_MAX_LEN);
|
|
|
|
|
|
2004-11-16 02:41:53 +00:00
|
|
|
if (g_cls_id)
|
|
|
|
|
g_cls_id_len = strlen (g_cls_id);
|
|
|
|
|
|
|
|
|
|
if (g_cls_id_len)
|
|
|
|
|
{
|
|
|
|
|
memcpy (iface->cls_id, g_cls_id, g_cls_id_len);
|
|
|
|
|
iface->cls_id_len = g_cls_id_len;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
struct utsname sname;
|
|
|
|
|
if ( uname(&sname) )
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_ERR,"classIDsetup: uname: %m\n");
|
2004-11-16 02:41:53 +00:00
|
|
|
snprintf (iface->cls_id, DHCP_CLASS_ID_MAX_LEN, "%s %s %s",
|
|
|
|
|
sname.sysname, sname.release, sname.machine);
|
2004-12-15 17:58:59 +00:00
|
|
|
iface->cls_id_len = strlen (iface->cls_id);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
2004-12-05 21:28:42 +00:00
|
|
|
void client_id_setup (dhcp_interface *iface, const char *g_cli_id)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
unsigned int g_cli_id_len = 0;
|
2004-12-15 17:58:59 +00:00
|
|
|
char *c;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
if (!iface) return;
|
|
|
|
|
|
2004-12-15 17:58:59 +00:00
|
|
|
memset (iface->cli_id, 0, DHCP_CLIENT_ID_MAX_LEN);
|
|
|
|
|
c = iface->cli_id;
|
|
|
|
|
|
2004-11-16 02:41:53 +00:00
|
|
|
if (g_cli_id)
|
|
|
|
|
g_cli_id_len = strlen (g_cli_id);
|
|
|
|
|
|
|
|
|
|
if ( g_cli_id_len )
|
|
|
|
|
{
|
2004-12-15 17:58:59 +00:00
|
|
|
*c++ = 0; /* type: string */
|
2004-11-16 02:41:53 +00:00
|
|
|
memcpy (c, g_cli_id, g_cli_id_len);
|
2004-12-15 17:58:59 +00:00
|
|
|
iface->cli_id_len = g_cli_id_len + 1;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
*c++ = ARPHRD_ETHER; /* type: Ethernet address */
|
2004-11-16 02:41:53 +00:00
|
|
|
memcpy (c, iface->chaddr, ETH_ALEN);
|
2004-12-15 17:58:59 +00:00
|
|
|
iface->cli_id_len = ETH_ALEN + 1;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
2004-12-05 21:28:42 +00:00
|
|
|
void release_dhcp_options (dhcp_interface *iface)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
register int i;
|
|
|
|
|
for ( i = 1; i < 256; i++ )
|
|
|
|
|
{
|
|
|
|
|
if ( iface->dhcp_options.val[i] )
|
|
|
|
|
free(iface->dhcp_options.val[i]);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
memset (&(iface->dhcp_options), 0, sizeof (dhcpOptions));
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/* Subtract the `struct timeval' values X and Y,
|
|
|
|
|
storing the result in RESULT.
|
|
|
|
|
Return 1 if the difference is negative, otherwise 0. */
|
2004-12-05 21:28:42 +00:00
|
|
|
static int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
/* Perform the carry for the later subtraction by updating Y. */
|
|
|
|
|
if (x->tv_usec < y->tv_usec)
|
|
|
|
|
{
|
|
|
|
|
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
|
|
|
|
|
y->tv_usec -= 1000000 * nsec;
|
|
|
|
|
y->tv_sec += nsec;
|
|
|
|
|
}
|
|
|
|
|
if (x->tv_usec - y->tv_usec > 1000000)
|
|
|
|
|
{
|
|
|
|
|
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
|
|
|
|
|
y->tv_usec += 1000000 * nsec;
|
|
|
|
|
y->tv_sec -= nsec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Compute the time remaining to wait.
|
|
|
|
|
`tv_usec' is certainly positive. */
|
|
|
|
|
result->tv_sec = x->tv_sec - y->tv_sec;
|
|
|
|
|
result->tv_usec = x->tv_usec - y->tv_usec;
|
|
|
|
|
|
|
|
|
|
/* Return 1 if result is negative. */
|
|
|
|
|
return x->tv_sec < y->tv_sec;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
2004-12-05 21:28:42 +00:00
|
|
|
/* Ripped from pump.
|
|
|
|
|
*/
|
|
|
|
|
int verify_checksum(void * buf, int length, void * buf2, int length2)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
unsigned int csum;
|
|
|
|
|
unsigned short * sp;
|
|
|
|
|
|
|
|
|
|
csum = 0;
|
|
|
|
|
for (sp = (unsigned short *) buf; length > 0; (length -= 2), sp++)
|
|
|
|
|
csum += *sp;
|
|
|
|
|
|
|
|
|
|
/* this matches rfc 1071, but not Steven's */
|
|
|
|
|
if (length)
|
|
|
|
|
csum += *((unsigned char *) sp);
|
|
|
|
|
|
|
|
|
|
for (sp = (unsigned short *) buf2; length2 > 0; (length2 -= 2), sp++)
|
|
|
|
|
csum += *sp;
|
|
|
|
|
|
|
|
|
|
/* this matches rfc 1071, but not Steven's */
|
|
|
|
|
if (length)
|
|
|
|
|
csum += *((unsigned char *) sp);
|
|
|
|
|
|
|
|
|
|
while (csum >> 16)
|
|
|
|
|
csum = (csum & 0xffff) + (csum >> 16);
|
|
|
|
|
|
|
|
|
|
if (csum!=0x0000 && csum != 0xffff)
|
|
|
|
|
return 0;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/* "timeout" should be the future point in time when we wish to stop
|
|
|
|
|
* checking for data on the socket.
|
|
|
|
|
*/
|
2005-01-07 18:07:06 +00:00
|
|
|
int peekfd (dhcp_interface *iface, int sk, int min_data, struct timeval *end_time)
|
2004-12-05 21:28:42 +00:00
|
|
|
{
|
|
|
|
|
struct timeval diff;
|
|
|
|
|
struct timeval now;
|
2005-01-07 18:07:06 +00:00
|
|
|
int recv_data_len = 0;
|
|
|
|
|
char ethPacket[ETH_FRAME_LEN];
|
|
|
|
|
|
|
|
|
|
if (min_data < 1)
|
|
|
|
|
return RET_DHCP_ERROR;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/* Wake up each second to check whether or not we've been told
|
2005-01-07 18:07:06 +00:00
|
|
|
* to stop with iface->cease and check our end time.
|
2004-11-16 02:41:53 +00:00
|
|
|
*/
|
2004-12-05 21:28:42 +00:00
|
|
|
gettimeofday (&now, NULL);
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
/* syslog (LOG_INFO, "DHCP waiting for data, overall end_time = {%ds, %dus}\n", (int)end_time->tv_sec, (int)end_time->tv_usec);*/
|
2005-01-07 18:07:06 +00:00
|
|
|
while ((timeval_subtract (&diff, end_time, &now) == 0) && !iface->cease && (recv_data_len < min_data))
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
fd_set fs;
|
2004-11-16 02:41:53 +00:00
|
|
|
struct timeval wait = {1, 0};
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
/* syslog (LOG_INFO, "DHCP waiting for data of minimum size %d, remaining timeout = {%ds, %dus}\n", min_data, (int)diff.tv_sec, (int)diff.tv_usec);*/
|
2004-12-05 21:28:42 +00:00
|
|
|
|
|
|
|
|
FD_ZERO (&fs);
|
|
|
|
|
FD_SET (sk, &fs);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (select (sk+1, &fs, NULL, NULL, &wait) == -1)
|
2004-11-16 02:41:53 +00:00
|
|
|
return RET_DHCP_ERROR;
|
2004-12-05 21:28:42 +00:00
|
|
|
if (FD_ISSET(sk, &fs))
|
2005-01-07 18:07:06 +00:00
|
|
|
{
|
|
|
|
|
/* Get length of data waiting on the socket */
|
|
|
|
|
recv_data_len = recvfrom (sk, ethPacket, sizeof (ethPacket), MSG_DONTWAIT | MSG_PEEK, 0, NULL);
|
|
|
|
|
if ((recv_data_len == -1) && (errno != EAGAIN))
|
|
|
|
|
return RET_DHCP_ERROR; /* Return on fatal errors */
|
|
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
gettimeofday (&now, NULL);
|
|
|
|
|
};
|
2005-01-07 18:07:06 +00:00
|
|
|
|
|
|
|
|
if (iface->cease)
|
|
|
|
|
return RET_DHCP_CEASED;
|
|
|
|
|
else if (recv_data_len >= min_data)
|
|
|
|
|
return RET_DHCP_SUCCESS;
|
|
|
|
|
|
2004-11-16 02:41:53 +00:00
|
|
|
return RET_DHCP_TIMEOUT;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
2004-12-05 21:28:42 +00:00
|
|
|
int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_type,
|
|
|
|
|
dhcp_msg_build_proc build_dhcp_msg, dhcp_response_return *dhcp_return)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
char *pkt_recv = NULL;
|
|
|
|
|
int recv_sk = -1;
|
|
|
|
|
struct sockaddr_in addr;
|
2004-12-06 21:19:41 +00:00
|
|
|
int tries = 0;
|
2004-12-15 17:58:59 +00:00
|
|
|
int err = RET_DHCP_TIMEOUT;
|
2005-01-07 18:07:06 +00:00
|
|
|
struct timeval recv_end, overall_end, diff, current;
|
2004-12-15 17:58:59 +00:00
|
|
|
udpipMessage *udp_send = NULL;
|
2004-12-05 21:28:42 +00:00
|
|
|
|
|
|
|
|
if (!dhcp_return)
|
|
|
|
|
return RET_DHCP_ERROR;
|
|
|
|
|
memset (dhcp_return, 0, sizeof (dhcp_response_return));
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
pkt_recv = malloc (sizeof (char) * ETH_FRAME_LEN);
|
|
|
|
|
if (!pkt_recv)
|
|
|
|
|
return RET_DHCP_ERROR;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
recv_sk = socket (AF_PACKET, SOCK_DGRAM, ntohs (ETH_P_IP));
|
|
|
|
|
if (recv_sk < 0)
|
|
|
|
|
{
|
|
|
|
|
err = RET_DHCP_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2004-11-22 14:42:34 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
/* Setup the time in the future to quit doing DHCP stuff. If we reach this time,
|
|
|
|
|
* we return RET_DHCP_TIMEOUT.
|
|
|
|
|
*/
|
|
|
|
|
gettimeofday (&overall_end, NULL);
|
|
|
|
|
overall_end.tv_sec += iface->client_options->base_timeout;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
/* Send the request, then wait for the reply for a certain period of time
|
|
|
|
|
* that increases with each failed request. Quit when we reach our end time though.
|
|
|
|
|
*/
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_INFO, "DHCP: Starting request loop");
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#endif
|
2004-11-16 02:41:53 +00:00
|
|
|
do
|
|
|
|
|
{
|
2004-12-15 17:58:59 +00:00
|
|
|
udpipMessage *udp_msg_recv = NULL;
|
2005-01-07 18:07:06 +00:00
|
|
|
struct iphdr *ip_hdr = NULL;
|
2004-12-05 21:28:42 +00:00
|
|
|
struct udphdr *udp_hdr;
|
2004-11-16 02:41:53 +00:00
|
|
|
char *tmp_ip;
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcpMessage *dhcp_msg_recv = NULL;
|
2004-11-16 02:41:53 +00:00
|
|
|
int reply_type = -1;
|
|
|
|
|
char foobuf[512];
|
2004-12-05 21:28:42 +00:00
|
|
|
struct sockaddr_ll server_hw_addr;
|
2005-01-07 18:07:06 +00:00
|
|
|
int data_good = 0;
|
|
|
|
|
int min_data_len = (sizeof (struct iphdr) + sizeof (struct udphdr));
|
|
|
|
|
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-06 21:19:41 +00:00
|
|
|
if (iface->cease)
|
|
|
|
|
goto out;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
/* Send the DHCP request */
|
2004-11-22 14:42:34 +00:00
|
|
|
do
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-15 17:58:59 +00:00
|
|
|
int udp_send_len = 0;
|
|
|
|
|
struct sockaddr addr;
|
|
|
|
|
|
|
|
|
|
/* Call the specific DHCP message building routine for this request */
|
|
|
|
|
if (!(udp_send = build_dhcp_msg (iface, &udp_send_len)))
|
|
|
|
|
{
|
|
|
|
|
err = RET_DHCP_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset (&addr, 0, sizeof (struct sockaddr));
|
|
|
|
|
memcpy (addr.sa_data, iface->iface, strlen (iface->iface));
|
|
|
|
|
err = sendto (iface->sk, udp_send, udp_send_len, MSG_DONTWAIT, (struct sockaddr *)&addr, sizeof (struct sockaddr));
|
2004-12-05 21:28:42 +00:00
|
|
|
if (iface->cease || ((err == -1) && (errno != EAGAIN)))
|
2004-11-22 14:42:34 +00:00
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_INFO, "DHCP: error sending, cease = %d, err = %d, errno = %d", iface->cease, err, errno);
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#endif
|
2004-12-05 21:28:42 +00:00
|
|
|
err = iface->cease ? RET_DHCP_CEASED : RET_DHCP_ERROR;
|
|
|
|
|
goto out;
|
2004-11-22 14:42:34 +00:00
|
|
|
}
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
/* Return if we've exceeded our timeout */
|
|
|
|
|
gettimeofday (¤t, NULL);
|
|
|
|
|
if (timeval_subtract (&diff, &overall_end, ¤t) != 0)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
err = RET_DHCP_TIMEOUT;
|
|
|
|
|
goto out;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
} while ((err == -1) && (errno == EAGAIN));
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
/* Set up the future time at which point to stop waiting for data
|
|
|
|
|
* on our socket and try the request again. If that future point is
|
|
|
|
|
* later than our overall DHCP operation timeout (overall_end) then
|
|
|
|
|
* clamp the receive timeout to overall_end.
|
2004-11-16 02:41:53 +00:00
|
|
|
*/
|
2004-12-05 21:28:42 +00:00
|
|
|
tries++;
|
2005-01-07 18:07:06 +00:00
|
|
|
gettimeofday (&recv_end, NULL);
|
|
|
|
|
recv_end.tv_sec += (tries * DHCP_INITIAL_RTO);
|
|
|
|
|
recv_end.tv_usec += (random () % 200000);
|
|
|
|
|
/* Clamp recv_end to overall_end if its greater than overall_end */
|
|
|
|
|
if (timeval_subtract (&diff, &overall_end, &recv_end) != 0)
|
|
|
|
|
memcpy (&recv_end, &overall_end, sizeof (struct timeval));
|
|
|
|
|
|
2005-01-21 17:56:19 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Request sent, waiting for reply...");
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
/* Packet receive loop */
|
|
|
|
|
data_good = 0;
|
2005-01-09 23:15:36 +00:00
|
|
|
gettimeofday (¤t, NULL);
|
|
|
|
|
while ((timeval_subtract (&diff, &recv_end, ¤t) == 0) && !data_good)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2005-01-07 18:07:06 +00:00
|
|
|
int len;
|
|
|
|
|
int o;
|
|
|
|
|
char ethPacket[ETH_FRAME_LEN];
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
/* Wait for some kind of data to appear on the socket */
|
|
|
|
|
if ((err = peekfd (iface, recv_sk, min_data_len, &recv_end)) != RET_DHCP_SUCCESS)
|
2004-12-05 21:28:42 +00:00
|
|
|
{
|
2005-01-07 18:07:06 +00:00
|
|
|
if (err == RET_DHCP_TIMEOUT)
|
|
|
|
|
break;
|
2004-12-05 21:28:42 +00:00
|
|
|
goto out;
|
|
|
|
|
}
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2005-01-09 23:15:36 +00:00
|
|
|
gettimeofday (¤t, NULL);
|
|
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
/* Ok, we allegedly have the data we need, so grab it from the queue */
|
|
|
|
|
o = sizeof (struct sockaddr_ll);
|
|
|
|
|
len = recvfrom (recv_sk, pkt_recv, ETH_FRAME_LEN, 0, (struct sockaddr *)&server_hw_addr, &o);
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Got some data of length %d.", len);
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
if (len < (sizeof (struct iphdr) + sizeof (struct udphdr)))
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Data length failed minimum length check (should be %d, got %d)", (sizeof (struct iphdr) + sizeof (struct udphdr)), len);
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
continue;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
ip_hdr = (struct iphdr *) pkt_recv;
|
|
|
|
|
if (!verify_checksum (NULL, 0, ip_hdr, sizeof (struct iphdr)))
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Reply message had bad IP checksum, won't use it.");
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
if (ntohs (ip_hdr->tot_len) > len)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Reply message had mismatch in length (IP header said %d, packet was really %d), won't use it.", ntohs (ip_hdr->tot_len), len);
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
len = ntohs (ip_hdr->tot_len);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
if (ip_hdr->protocol != IPPROTO_UDP)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "DHCP: Reply message was not UDP (ip_hdr->protocol = %d, IPPROTO_UDP = %d), won't use it.", ip_hdr->protocol, IPPROTO_UDP);
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
udp_hdr = (struct udphdr *) (pkt_recv + sizeof (struct iphdr));
|
|
|
|
|
if (ntohs (udp_hdr->source) != DHCP_SERVER_PORT)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Reply message's source port was not the DHCP server port number, won't use it.");
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (ntohs (udp_hdr->dest) != DHCP_CLIENT_PORT)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Reply message's destination port was not the DHCP client port number, won't use it.");
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
/* Ok, packet appears to be OK */
|
|
|
|
|
/* Ensure DHCP packet is 0xFF terminated, which isn't the case on Cisco 800 series ISDN router */
|
|
|
|
|
dhcp_msg_recv = malloc (sizeof (dhcpMessage));
|
|
|
|
|
memset (dhcp_msg_recv, 0xFF, sizeof (dhcpMessage));
|
|
|
|
|
memcpy (dhcp_msg_recv, (char *) udp_hdr + sizeof (struct udphdr), len - sizeof (struct iphdr) - sizeof (struct udphdr));
|
2004-12-05 21:28:42 +00:00
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
if (dhcp_msg_recv->xid != iface->xid)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Reply message's XID does not match expected XID (message %d, expected %d), won't use it.", dhcp_msg_recv->xid, iface->xid);
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
free (dhcp_msg_recv);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
if (dhcp_msg_recv->htype != ARPHRD_ETHER)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
if (DebugFlag)
|
|
|
|
|
syslog (LOG_DEBUG, "DHCP: Reply message's header type was not ARPHRD_ETHER (messgae %d, expected %d), won't use it.", dhcp_msg_recv->htype, ARPHRD_ETHER);
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
free (dhcp_msg_recv);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dhcp_msg_recv->op != DHCP_BOOTREPLY)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
syslog (LOG_INFO, "DHCP: Reply message was not a bootp/DHCP reply, won't use it.");
|
|
|
|
|
#endif
|
2005-01-07 18:07:06 +00:00
|
|
|
free (dhcp_msg_recv);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data_good = 1;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
2005-01-07 18:07:06 +00:00
|
|
|
if (!data_good)
|
2004-11-16 02:41:53 +00:00
|
|
|
continue;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
/* Clear out all data remaining on the interface in preparation for another broadcast if needed */
|
|
|
|
|
while ((iface->foo_sk > 0) && recvfrom (iface->foo_sk, (void *)foobuf, sizeof (foobuf), 0, NULL, NULL) != -1);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/* Copy DHCP response options from received packet into local options list */
|
2004-12-05 21:28:42 +00:00
|
|
|
reply_type = parse_dhcp_reply (ip_hdr, &server_hw_addr, dhcp_msg_recv, &(iface->dhcp_options));
|
|
|
|
|
if (expected_reply_type == reply_type)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
memcpy (&dhcp_return->server_ip_addr, &(ip_hdr->saddr), 4);
|
|
|
|
|
memcpy (&dhcp_return->server_hw_addr, &server_hw_addr, ETH_ALEN);
|
|
|
|
|
memcpy (&dhcp_return->dhcp_msg, dhcp_msg_recv, sizeof (dhcpMessage));
|
|
|
|
|
free (dhcp_msg_recv);
|
|
|
|
|
err = RET_DHCP_SUCCESS;
|
|
|
|
|
goto out;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
free (dhcp_msg_recv);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
if (reply_type == DHCP_NAK)
|
|
|
|
|
{
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
if (iface->dhcp_options.val[dhcpMsg])
|
|
|
|
|
syslog (LOG_ERR, "DHCP: DHCP_NAK response received: %s.", (char *)iface->dhcp_options.val[dhcpMsg]);
|
|
|
|
|
else
|
|
|
|
|
syslog (LOG_ERR, "DHCP: DHCP_NAK response received.");
|
|
|
|
|
#endif
|
2004-12-05 21:28:42 +00:00
|
|
|
err = RET_DHCP_NAK;
|
|
|
|
|
goto out;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
gettimeofday (¤t, NULL);
|
|
|
|
|
} while (timeval_subtract (&diff, &overall_end, ¤t) == 0);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
out:
|
2004-12-15 17:58:59 +00:00
|
|
|
free (udp_send);
|
2004-12-05 21:28:42 +00:00
|
|
|
if (err != RET_DHCP_SUCCESS)
|
|
|
|
|
free (pkt_recv);
|
|
|
|
|
if (recv_sk >= 0)
|
|
|
|
|
close (recv_sk);
|
|
|
|
|
return err;
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
int dhcp_reboot (dhcp_interface *iface)
|
|
|
|
|
{
|
|
|
|
|
/* Client has a cached IP and wants to request it again from the server
|
|
|
|
|
* if possible. DHCP state INIT-REBOOT.
|
|
|
|
|
*
|
|
|
|
|
* If no response from the server is received, we assume that we can still
|
|
|
|
|
* use the cached IP address.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* FIXME: get the IP address to renew from somewhere */
|
|
|
|
|
|
|
|
|
|
if (!iface) return RET_DHCP_ERROR;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
release_dhcp_options (iface);
|
|
|
|
|
return dhcp_request (iface, &build_dhcp_reboot);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
int dhcp_init (dhcp_interface *iface)
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcp_response_return dhcp_resp;
|
|
|
|
|
int err;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
if (!iface) return RET_DHCP_ERROR;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
release_dhcp_options (iface);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
- Remove some debug messages
- Wrap others in #ifdef DEBUG/#endif
* src/NetworkManager.c
- Remove some debug messages
- Clarify some debug messages
- Remove code related to old single-thread wireless scanning
* src/NetworkManagerAP.[ch]
- New AP property "last_seen" to track how recently an AP was
found in a scan
- Start using 'const' more in function arguments
* src/NetworkManagerAPList.[ch]
- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
of an AP found in an AP list from a source AP, or if not found
in the list add the source AP
- (nm_ap_list_combine): remove, no longer needed
* src/NetworkManagerDevice.c
- Each device now has a "worker" thread from start to end of its life.
Scanning for wireless devices now happens in that thread,
not in a single "wireless scanning thread" for all devices as
previously. Activation consists of adding an idle handler to the
thread's main loop/context, which gets run at the next available
opportunity.
- Wireless scanning is also simplified, there is now only one list of
access points per wireless device, and APs older than 60s are
removed from the list. Previously, we kept results for the last
3 scans and merged whole lists, which was complicated.
- Cleaned up activation debug messages.
- Wireless activation and access-point search routines now use Open System
authentication before trying Shared Key.
- Removed some code in nm_device_update_best_ap() that could cause cards
to loose their link to the access point.
- Scanning now uses a backoff algorithm, where the inverval becomes
progressively longer between scans when the list of scanned access
points doesn't change. A change will revert to the shortest scan
interval (20s).
* src/NetworkManagerWireless.[ch]
- Remove code related to old single-thread wireless scanning
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00
|
|
|
syslog (LOG_DEBUG, "ClassID = \"%s\"", iface->cls_id);
|
|
|
|
|
syslog (LOG_DEBUG, "ClientID = \"%u.%u.%u.%02X.%02X.%02X.%02X.%02X.%02X\"\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
iface->cli_id[0], iface->cli_id[1], iface->cli_id[2],
|
|
|
|
|
iface->cli_id[3], iface->cli_id[4], iface->cli_id[5],
|
|
|
|
|
iface->cli_id[6], iface->cli_id[7], iface->cli_id[8]);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ( DebugFlag )
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Broadcasting DHCP_DISCOVER\n");
|
2004-11-16 02:41:53 +00:00
|
|
|
iface->xid = random ();
|
2004-12-05 21:28:42 +00:00
|
|
|
err = dhcp_handle_transaction (iface, DHCP_OFFER, &build_dhcp_discover, &dhcp_resp);
|
2004-11-16 02:41:53 +00:00
|
|
|
if (err != RET_DHCP_SUCCESS)
|
|
|
|
|
return err;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (iface->client_options->send_second_discover)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcp_response_return dhcp_resp2;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
if (DebugFlag)
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Broadcasting second DHCP_DISCOVER\n");
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
iface->xid = dhcp_resp.dhcp_msg.xid;
|
|
|
|
|
err = dhcp_handle_transaction (iface, DHCP_OFFER, &build_dhcp_discover, &dhcp_resp2);
|
2004-11-16 02:41:53 +00:00
|
|
|
if (err == RET_DHCP_SUCCESS)
|
2004-12-05 21:28:42 +00:00
|
|
|
memcpy (&dhcp_resp, &dhcp_resp2, sizeof (dhcp_response_return));
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
iface->ciaddr = dhcp_resp.dhcp_msg.yiaddr;
|
2004-11-16 02:41:53 +00:00
|
|
|
memcpy (&(iface->siaddr), iface->dhcp_options.val[dhcpServerIdentifier], 4);
|
2004-12-05 21:28:42 +00:00
|
|
|
memcpy (iface->shaddr, dhcp_resp.server_hw_addr, ETH_ALEN);
|
|
|
|
|
iface->xid = dhcp_resp.dhcp_msg.xid;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/* DHCP_OFFER received */
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_INFO, "DHCP_OFFER received from %s (%u.%u.%u.%u)\n", dhcp_resp.dhcp_msg.sname,
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
return dhcp_request (iface, &build_dhcp_request);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
int dhcp_request(dhcp_interface *iface, dhcp_msg_build_proc buildDhcpMsg)
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcp_response_return dhcp_resp;
|
|
|
|
|
int err;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/* DHCP state REQUEST: request an address from a _particular_ DHCP server */
|
|
|
|
|
|
|
|
|
|
if (!iface) return RET_DHCP_ERROR;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Broadcasting DHCP_REQUEST for %u.%u.%u.%u\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
err = dhcp_handle_transaction (iface, DHCP_ACK, buildDhcpMsg, &dhcp_resp);
|
2004-11-16 02:41:53 +00:00
|
|
|
if (err != RET_DHCP_SUCCESS)
|
|
|
|
|
return err;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_resp.dhcp_msg.sname,
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef ARPCHECK
|
|
|
|
|
/* check if the offered IP address already in use */
|
2004-12-05 21:28:42 +00:00
|
|
|
if (arpCheck(iface))
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "requested %u.%u.%u.%u address is in use\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]);
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcpDecline ();
|
2004-11-16 02:41:53 +00:00
|
|
|
iface->ciaddr = 0;
|
|
|
|
|
return RET_DHCP_ADDRESS_IN_USE;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "verified %u.%u.%u.%u address is not in use\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Successfull ACK: Use the fields obtained for future requests */
|
|
|
|
|
memcpy (&(iface->siaddr), iface->dhcp_options.val[dhcpServerIdentifier], 4);
|
2004-12-05 21:28:42 +00:00
|
|
|
memcpy (iface->shaddr, dhcp_resp.server_hw_addr, ETH_ALEN);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
return RET_DHCP_BOUND;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
int dhcp_renew(dhcp_interface *iface)
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcp_response_return dhcp_resp;
|
|
|
|
|
int err;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/* DHCP state RENEW: request renewal of our lease from the original DHCP server */
|
|
|
|
|
if (!iface) return RET_DHCP_ERROR;
|
|
|
|
|
|
|
|
|
|
if ( DebugFlag )
|
|
|
|
|
{
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO,"Sending DHCP_REQUEST for %u.%u.%u.%u to %u.%u.%u.%u\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3],
|
|
|
|
|
((unsigned char *)&(iface->siaddr))[0], ((unsigned char *)&(iface->siaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->siaddr))[2], ((unsigned char *)&(iface->siaddr))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iface->xid = random();
|
2004-12-05 21:28:42 +00:00
|
|
|
err = dhcp_handle_transaction (iface, DHCP_ACK, &build_dhcp_renew, &dhcp_resp);
|
2004-11-16 02:41:53 +00:00
|
|
|
if (err != RET_DHCP_SUCCESS);
|
|
|
|
|
return err;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_resp.dhcp_msg.sname,
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RET_DHCP_BOUND;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
int dhcp_rebind(dhcp_interface *iface)
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcp_response_return dhcp_resp;
|
|
|
|
|
int err;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
/* DHCP state REBIND: request renewal of our lease from _any_ DHCP server */
|
|
|
|
|
if (!iface) return RET_DHCP_ERROR;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO,"Broadcasting DHCP_REQUEST for %u.%u.%u.%u\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iface->xid = random ();
|
2004-12-05 21:28:42 +00:00
|
|
|
err = dhcp_handle_transaction(iface, DHCP_ACK, &build_dhcp_rebind, &dhcp_resp);
|
2004-11-16 02:41:53 +00:00
|
|
|
if (err != RET_DHCP_SUCCESS)
|
|
|
|
|
return err;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_resp.dhcp_msg.sname,
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Successfull ACK: Use the fields obtained for future requests */
|
|
|
|
|
memcpy (&(iface->siaddr), iface->dhcp_options.val[dhcpServerIdentifier], 4);
|
2004-12-05 21:28:42 +00:00
|
|
|
memcpy (iface->shaddr, dhcp_resp.server_hw_addr, ETH_ALEN);
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
return RET_DHCP_BOUND;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
int dhcp_release(dhcp_interface *iface)
|
|
|
|
|
{
|
2004-12-15 17:58:59 +00:00
|
|
|
udpipMessage *msg;
|
|
|
|
|
struct sockaddr addr;
|
|
|
|
|
socklen_t addr_len = sizeof (struct sockaddr);
|
|
|
|
|
int len;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
if ( iface->ciaddr == 0 )
|
|
|
|
|
return RET_DHCP_ERROR;
|
|
|
|
|
|
|
|
|
|
iface->xid = random();
|
2004-12-15 17:58:59 +00:00
|
|
|
if (!(msg = build_dhcp_release (iface, &len)))
|
2004-11-16 02:41:53 +00:00
|
|
|
return RET_DHCP_ERROR;
|
|
|
|
|
|
|
|
|
|
if (DebugFlag)
|
|
|
|
|
{
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Sending DHCP_RELEASE for %u.%u.%u.%u to %u.%u.%u.%u\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3],
|
|
|
|
|
((unsigned char *)&(iface->siaddr))[0], ((unsigned char *)&(iface->siaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->siaddr))[2], ((unsigned char *)&(iface->siaddr))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-15 17:58:59 +00:00
|
|
|
memset (&addr, 0, sizeof (struct sockaddr));
|
|
|
|
|
memcpy (addr.sa_data, iface->iface, strlen (iface->iface));
|
|
|
|
|
if (sendto (iface->sk, msg, len, 0, (struct sockaddr *)&addr, addr_len))
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_ERR, "dhcpRelease: sendto: %m\n");
|
2004-11-16 02:41:53 +00:00
|
|
|
free (msg);
|
|
|
|
|
|
|
|
|
|
arpRelease (iface); /* clear ARP cache entries for client IP addr */
|
|
|
|
|
iface->ciaddr = 0;
|
|
|
|
|
|
|
|
|
|
return RET_DHCP_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
#ifdef ARPCHECK
|
|
|
|
|
int dhcp_decline(dhcp_interface *iface)
|
|
|
|
|
{
|
2004-12-15 17:58:59 +00:00
|
|
|
udpipMessage *msg;
|
|
|
|
|
struct sockaddr addr;
|
|
|
|
|
socklen_t addr_len = sizeof (struct sockaddr);
|
|
|
|
|
int len;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
|
|
|
|
iface->xid = random ();
|
2004-12-15 17:58:59 +00:00
|
|
|
if (!(msg = build_dhcp_decline (iface, &len)))
|
2004-11-16 02:41:53 +00:00
|
|
|
return RET_DHCP_ERROR;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Broadcasting DHCP_DECLINE\n");
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-15 17:58:59 +00:00
|
|
|
memset (&addr, 0, sizeof (struct sockaddr));
|
|
|
|
|
memcpy (addr.sa_data, iface->iface, strlen (iface->iface));
|
|
|
|
|
if (sendto (iface->sk, msg, len, 0, &addr, addr_len))
|
2004-11-16 02:41:53 +00:00
|
|
|
syslog (LOG_ERR,"dhcpDecline: sendto: %m\n");
|
|
|
|
|
free (msg);
|
|
|
|
|
|
|
|
|
|
return RET_DHCP_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
int dhcp_inform(dhcp_interface *iface)
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
dhcp_response_return dhcp_resp;
|
|
|
|
|
int err;
|
2004-11-16 02:41:53 +00:00
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Broadcasting DHCP_INFORM for %u.%u.%u.%u\n",
|
2004-12-05 21:28:42 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iface->xid = random ();
|
2004-12-05 21:28:42 +00:00
|
|
|
err = dhcp_handle_transaction (iface, DHCP_ACK, build_dhcp_inform, &dhcp_resp);
|
2004-11-16 02:41:53 +00:00
|
|
|
if (err != RET_DHCP_SUCCESS)
|
|
|
|
|
return err;
|
|
|
|
|
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
syslog (LOG_INFO, "DHCP_ACK received from %s (%u.%u.%u.%u)\n", dhcp_resp.dhcp_msg.sname,
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[0],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[1],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[2],
|
|
|
|
|
((unsigned char *)(iface->dhcp_options.val[dhcpServerIdentifier]))[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef ARPCHECK
|
|
|
|
|
/* check if the offered IP address already in use */
|
2004-12-05 21:28:42 +00:00
|
|
|
if (arpCheck(iface))
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Requested %u.%u.%u.%u address is in use\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]);
|
|
|
|
|
dhcpDecline (iface);
|
|
|
|
|
return RET_DHCP_SUCCESS;
|
|
|
|
|
}
|
2004-12-05 21:28:42 +00:00
|
|
|
if (DebugFlag)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-11-22 14:42:34 +00:00
|
|
|
syslog (LOG_INFO, "Verified %u.%u.%u.%u address is not in use\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&(iface->ciaddr))[0], ((unsigned char *)&(iface->ciaddr))[1],
|
|
|
|
|
((unsigned char *)&(iface->ciaddr))[2], ((unsigned char *)&(iface->ciaddr))[3]);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return RET_DHCP_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2004-12-16 04:24:20 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
2004-11-16 02:41:53 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
char *get_dhcp_option_name (int i)
|
|
|
|
|
{
|
|
|
|
|
char *buf = NULL;
|
|
|
|
|
if (i <= dhcpClientIdentifier)
|
|
|
|
|
buf = strdup (dhcp_opt_table [i].name);
|
|
|
|
|
else
|
|
|
|
|
buf = strdup ("unknown");
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2004-12-05 21:28:42 +00:00
|
|
|
void debug_dump_dhcp_options (struct sockaddr_ll *saddr, dhcpMessage *dhcp_msg, dhcpOptions *options)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
int i,j;
|
|
|
|
|
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "Server replied with %d DHCP options:\n", options->num);
|
2004-11-16 02:41:53 +00:00
|
|
|
for (i = 1; i < 255; i++)
|
|
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
if (options->val[i])
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
2004-12-05 21:28:42 +00:00
|
|
|
switch (i)
|
2004-11-16 02:41:53 +00:00
|
|
|
{
|
|
|
|
|
case 1: /* subnet mask */
|
|
|
|
|
case 3: /* routers on subnet */
|
|
|
|
|
case 4: /* time servers */
|
|
|
|
|
case 5: /* name servers */
|
|
|
|
|
case 6: /* dns servers */
|
|
|
|
|
case 28:/* broadcast addr */
|
|
|
|
|
case 33:/* staticRoute */
|
|
|
|
|
case 41:/* NIS servers */
|
|
|
|
|
case 42:/* NTP servers */
|
|
|
|
|
case 50:/* dhcpRequestdIPaddr */
|
|
|
|
|
case 54:/* dhcpServerIdentifier */
|
|
|
|
|
for (j = 0; j < options->len[i]; j += 4)
|
|
|
|
|
{
|
|
|
|
|
char *opt_name = get_dhcp_option_name (i);
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\ti=%-2d (%s) len=%-2d option = %u.%u.%u.%u\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
i, opt_name, options->len[i],
|
|
|
|
|
((unsigned char *)options->val[i])[0+j],
|
|
|
|
|
((unsigned char *)options->val[i])[1+j],
|
|
|
|
|
((unsigned char *)options->val[i])[2+j],
|
|
|
|
|
((unsigned char *)options->val[i])[3+j]);
|
|
|
|
|
free (opt_name);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2: /* time offset */
|
|
|
|
|
case 51:/* dhcpAddrLeaseTime */
|
|
|
|
|
case 57:/* dhcpMaxMsgSize */
|
|
|
|
|
case 58:/* dhcpT1value */
|
|
|
|
|
case 59:/* dhcpT2value */
|
|
|
|
|
{
|
|
|
|
|
char *opt_name = get_dhcp_option_name (i);
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\ti=%-2d (%s) len=%-2d option = %d\n", i, opt_name,
|
2004-11-16 02:41:53 +00:00
|
|
|
options->len[i], ntohl(*(int *)options->val[i]));
|
|
|
|
|
free (opt_name);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 23:/* defaultIPTTL */
|
|
|
|
|
case 29:/* performMaskdiscovery */
|
|
|
|
|
case 31:/* performRouterdiscovery */
|
|
|
|
|
case 53:/* dhcpMessageType */
|
|
|
|
|
{
|
|
|
|
|
char *opt_name = get_dhcp_option_name (i);
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\ti=%-2d (%s) len=%-2d option = %u\n", i, opt_name,
|
2004-11-16 02:41:53 +00:00
|
|
|
options->len[i],*(unsigned char *)options->val[i]);
|
|
|
|
|
free (opt_name);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
char *opt_name = get_dhcp_option_name (i);
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\ti=%-2d (%s) len=%-2d option = \"%s\"\n",
|
2004-11-16 02:41:53 +00:00
|
|
|
i, opt_name, options->len[i], (char *)options->val[i]);
|
|
|
|
|
free (opt_name);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\tdhcp_msg->yiaddr = %u.%u.%u.%u",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&dhcp_msg->yiaddr)[0], ((unsigned char *)&dhcp_msg->yiaddr)[1],
|
2004-12-05 21:28:42 +00:00
|
|
|
((unsigned char *)&dhcp_msg->yiaddr)[2], ((unsigned char *)&dhcp_msg->yiaddr)[3]);
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\tdhcp_msg->siaddr = %u.%u.%u.%u",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&dhcp_msg->siaddr)[0], ((unsigned char *)&dhcp_msg->siaddr)[1],
|
2004-12-05 21:28:42 +00:00
|
|
|
((unsigned char *)&dhcp_msg->siaddr)[2], ((unsigned char *)&dhcp_msg->siaddr)[3]);
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\tdhcp_msg->giaddr = %u.%u.%u.%u",
|
2004-11-16 02:41:53 +00:00
|
|
|
((unsigned char *)&dhcp_msg->giaddr)[0], ((unsigned char *)&dhcp_msg->giaddr)[1],
|
2004-12-05 21:28:42 +00:00
|
|
|
((unsigned char *)&dhcp_msg->giaddr)[2], ((unsigned char *)&dhcp_msg->giaddr)[3]);
|
2005-01-21 17:56:19 +00:00
|
|
|
syslog (LOG_INFO, "\tdhcp_msg->sname = \"%s\"", dhcp_msg->sname);
|
|
|
|
|
syslog (LOG_INFO, "\tServer Hardware Address = %02X.%02X.%02X.%02X.%02X.%02X\n",
|
2004-12-05 21:28:42 +00:00
|
|
|
saddr->sll_addr[0], saddr->sll_addr[1], saddr->sll_addr[2], saddr->sll_addr[3],
|
|
|
|
|
saddr->sll_addr[4], saddr->sll_addr[5]);
|
2004-11-16 02:41:53 +00:00
|
|
|
}
|
|
|
|
|
|
2004-12-16 04:24:20 +00:00
|
|
|
#endif
|