예제 #1
0
void lease_update_from_configs(void)
{
  /* changes to the config may change current leases. */
  
  struct dhcp_lease *lease;
  struct dhcp_config *config;
  char *name;
  
  for (lease = leases; lease; lease = lease->next)
    if (lease->flags & (LEASE_TA | LEASE_NA))
      continue;
    else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len, 
				   lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) && 
	     (config->flags & CONFIG_NAME) &&
	     (!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
      lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
    else if ((name = host_from_dns(lease->addr)))
      lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
}
예제 #2
0
파일: dbus.c 프로젝트: Mleaf/dnsmasq
static DBusMessage *dbus_add_lease(DBusMessage* message)
{
  struct dhcp_lease *lease;
  const char *ipaddr, *hwaddr, *hostname, *tmp;
  const unsigned char* clid;
  int clid_len, hostname_len, hw_len, hw_type;
  dbus_uint32_t expires, ia_id;
  dbus_bool_t is_temporary;
  struct all_addr addr;
  time_t now = dnsmasq_time();
  unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];

  DBusMessageIter iter, array_iter;
  if (!dbus_message_iter_init(message, &iter))
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				  "Failed to initialize dbus message iter");

  if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				  "Expected string as first argument");

  dbus_message_iter_get_basic(&iter, &ipaddr);
  dbus_message_iter_next(&iter);

  if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				  "Expected string as second argument");
    
  dbus_message_iter_get_basic(&iter, &hwaddr);
  dbus_message_iter_next(&iter);

  if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
      (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				  "Expected byte array as third argument");
    
  dbus_message_iter_recurse(&iter, &array_iter);
  dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
  tmp = memchr(hostname, '\0', hostname_len);
  if (tmp)
    {
      if (tmp == &hostname[hostname_len - 1])
	hostname_len--;
      else
	return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				      "Hostname contains an embedded NUL character");
    }
  dbus_message_iter_next(&iter);

  if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
      (dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				  "Expected byte array as fourth argument");

  dbus_message_iter_recurse(&iter, &array_iter);
  dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
  dbus_message_iter_next(&iter);

  if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				  "Expected uint32 as fifth argument");
    
  dbus_message_iter_get_basic(&iter, &expires);
  dbus_message_iter_next(&iter);

  if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                    "Expected uint32 as sixth argument");
  
  dbus_message_iter_get_basic(&iter, &ia_id);
  dbus_message_iter_next(&iter);

  if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
    return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				  "Expected uint32 as sixth argument");

  dbus_message_iter_get_basic(&iter, &is_temporary);

  if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
    {
      if (ia_id != 0 || is_temporary)
	return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
				      "ia_id and is_temporary must be zero for IPv4 lease");
      
      if (!(lease = lease_find_by_addr(addr.addr.addr4)))
    	lease = lease4_allocate(addr.addr.addr4);
    }
#ifdef HAVE_DHCP6
  else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
    {
      if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
	lease = lease6_allocate(&addr.addr.addr6,
				is_temporary ? LEASE_TA : LEASE_NA);
      lease_set_iaid(lease, ia_id);
    }
#endif
  else
    return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
					 "Invalid IP address '%s'", ipaddr);
   
  hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
		     &hw_type);
  if (hw_type == 0 && hw_len != 0)
    hw_type = ARPHRD_ETHER;

    lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
                   clid_len, now, 0);
  lease_set_expires(lease, expires, now);
  if (hostname_len != 0)
    lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
    
  lease_update_file(now);
  lease_update_dns(0);

  return NULL;
}
예제 #3
0
void lease_init(time_t now)
{
  unsigned long ei;
  struct all_addr addr;
  struct dhcp_lease *lease;
  int clid_len, hw_len, hw_type;
  FILE *leasestream;
  
  leases_left = daemon->dhcp_max;
  
  if (option_bool(OPT_LEASE_RO))
    {
      /* run "<lease_change_script> init" once to get the
	 initial state of the database. If leasefile-ro is
	 set without a script, we just do without any 
	 lease database. */
#ifdef HAVE_SCRIPT
      if (daemon->lease_change_command)
	{
	  strcpy(daemon->dhcp_buff, daemon->lease_change_command);
	  strcat(daemon->dhcp_buff, " init");
	  leasestream = popen(daemon->dhcp_buff, "r");
	}
      else
#endif
	{
          file_dirty = dns_dirty = 0;
          return;
        }

    }
  else
    {
      /* NOTE: need a+ mode to create file if it doesn't exist */
      leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
      
      if (!leasestream)
	die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
      
      /* a+ mode leaves pointer at end. */
      rewind(leasestream);
    }
  
  /* client-id max length is 255 which is 255*2 digits + 254 colons 
     borrow DNS packet buffer which is always larger than 1000 bytes */
  if (leasestream)
    while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
      {
#ifdef HAVE_DHCP6
	if (strcmp(daemon->dhcp_buff3, "duid") == 0)
	  {
	    daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
	    daemon->duid = safe_malloc(daemon->duid_len);
	    memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
	    continue;
	  }
#endif

	ei = atol(daemon->dhcp_buff3);
	
	if (fscanf(leasestream, " %64s %255s %764s",
		   daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
	  break;
	
	clid_len = 0;
	if (strcmp(daemon->packet, "*") != 0)
	  clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
	
	if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
	    (lease = lease4_allocate(addr.addr.addr4)))
	  {
	    hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
	    /* For backwards compatibility, no explict MAC address type means ether. */
	    if (hw_type == 0 && hw_len != 0)
	      hw_type = ARPHRD_ETHER; 

	    lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet, 
			     hw_len, hw_type, clid_len, now, 0);
	    
	    if (strcmp(daemon->dhcp_buff, "*") !=  0)
	      lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
	  }
#ifdef HAVE_DHCP6
	else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
	  {
	    char *s = daemon->dhcp_buff2;
	    int lease_type = LEASE_NA;
	    int iaid;

	    if (s[0] == 'T')
	      {
		lease_type = LEASE_TA;
		s++;
	      }
	    
	    iaid = strtoul(s, NULL, 10);
	    
	    if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
	      {
		lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0);
		lease_set_iaid(lease, iaid);
		if (strcmp(daemon->dhcp_buff, "*") !=  0)
		  lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
	      }
	  }
#endif
	else
	  break;

	if (!lease)
	  die (_("too many stored leases"), NULL, EC_MISC);
       	
//Some ASUS & TOMATO tweaks
#if defined(HAVE_BROKEN_RTC) || defined(HAVE_LEASEFILE_EXPIRE)
	if (ei != 0)
	  lease->expires = (time_t)ei + now;
	else
	  lease->expires = (time_t)0;
#ifdef HAVE_BROKEN_RT
	lease->length = ei;
#endif
#else
	/* strictly time_t is opaque, but this hack should work on all sane systems,
	   even when sizeof(time_t) == 8 */
	lease->expires = (time_t)ei;
#endif
	
	/* set these correctly: the "old" events are generated later from
	   the startup synthesised SIGHUP. */
	lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
      }
  
#ifdef HAVE_SCRIPT
  if (!daemon->lease_stream)
    {
      int rc = 0;

      /* shell returns 127 for "command not found", 126 for bad permissions. */
      if (!leasestream || (rc = pclose(leasestream)) == -1 || WEXITSTATUS(rc) == 127 || WEXITSTATUS(rc) == 126)
	{
	  if (WEXITSTATUS(rc) == 127)
	    errno = ENOENT;
	  else if (WEXITSTATUS(rc) == 126)
	    errno = EACCES;
	  die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
	}
      
      if (WEXITSTATUS(rc) != 0)
	{
	  sprintf(daemon->dhcp_buff, "%d", WEXITSTATUS(rc));
	  die(_("lease-init script returned exit code %s"), daemon->dhcp_buff, WEXITSTATUS(rc) + EC_INIT_OFFSET);
	}
    }
#endif

  /* Some leases may have expired */
  file_dirty = 0;
  lease_prune(NULL, now);
  dns_dirty = 1;
}