1415c960b22b4084057577fc371510864378354ddRob Landley/* dhcpd.c - DHCP server for dynamic network configuration. 2415c960b22b4084057577fc371510864378354ddRob Landley * 3415c960b22b4084057577fc371510864378354ddRob Landley * Copyright 2013 Madhur Verma <mad.flexi@gmail.com> 4415c960b22b4084057577fc371510864378354ddRob Landley * Copyright 2013 Kyungwan Han <asura321@gamil.com> 560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh * Copyright 2015 Yeongdeok Suh <skyducks111@gmail.com> 6415c960b22b4084057577fc371510864378354ddRob Landley * 7415c960b22b4084057577fc371510864378354ddRob Landley * No Standard 8c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok SuhUSE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY)) 9415c960b22b4084057577fc371510864378354ddRob Landley 10415c960b22b4084057577fc371510864378354ddRob Landleyconfig DHCPD 11415c960b22b4084057577fc371510864378354ddRob Landley bool "dhcpd" 12415c960b22b4084057577fc371510864378354ddRob Landley default n 13415c960b22b4084057577fc371510864378354ddRob Landley help 1460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE] 15415c960b22b4084057577fc371510864378354ddRob Landley 16415c960b22b4084057577fc371510864378354ddRob Landley -f Run in foreground 1760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh -i Interface to use 18415c960b22b4084057577fc371510864378354ddRob Landley -S Log to syslog too 1960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh -P N Use port N (default ipv4 67, ipv6 547) 2060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh -4, -6 Run as a DHCPv4 or DHCPv6 server 21415c960b22b4084057577fc371510864378354ddRob Landley 22415c960b22b4084057577fc371510864378354ddRob Landleyconfig DEBUG_DHCP 23415c960b22b4084057577fc371510864378354ddRob Landley bool "debugging messeges ON/OFF" 24415c960b22b4084057577fc371510864378354ddRob Landley default n 25415c960b22b4084057577fc371510864378354ddRob Landley depends on DHCPD 26415c960b22b4084057577fc371510864378354ddRob Landley*/ 27415c960b22b4084057577fc371510864378354ddRob Landley 2860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh/* 29c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh * TODO 3060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh * - Working as an relay agent 3160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh * - Rapid commit option support 3260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh * - Additional packet options (commented on the middle of sources) 3360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh * - Create common modules 3460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh */ 3560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 36415c960b22b4084057577fc371510864378354ddRob Landley#define FOR_dhcpd 37415c960b22b4084057577fc371510864378354ddRob Landley 38415c960b22b4084057577fc371510864378354ddRob Landley#include "toys.h" 39415c960b22b4084057577fc371510864378354ddRob Landley#include <linux/sockios.h> 40415c960b22b4084057577fc371510864378354ddRob Landley#include <linux/if_ether.h> 41415c960b22b4084057577fc371510864378354ddRob Landley 42415c960b22b4084057577fc371510864378354ddRob Landley// Todo: headers not in posix 43415c960b22b4084057577fc371510864378354ddRob Landley#include <netinet/ip.h> 4460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#include <netinet/ip6.h> 45415c960b22b4084057577fc371510864378354ddRob Landley#include <netinet/udp.h> 46415c960b22b4084057577fc371510864378354ddRob Landley#include <netpacket/packet.h> 47415c960b22b4084057577fc371510864378354ddRob Landley 48415c960b22b4084057577fc371510864378354ddRob Landley#if CFG_DEBUG_DHCP==1 49415c960b22b4084057577fc371510864378354ddRob Landley# define dbg(fmt, arg...) printf(fmt, ##arg) 50415c960b22b4084057577fc371510864378354ddRob Landley#else 51415c960b22b4084057577fc371510864378354ddRob Landley# define dbg(fmt, arg...) 52415c960b22b4084057577fc371510864378354ddRob Landley#endif 53415c960b22b4084057577fc371510864378354ddRob Landley 54415c960b22b4084057577fc371510864378354ddRob Landley#define LOG_SILENT 0x0 55415c960b22b4084057577fc371510864378354ddRob Landley#define LOG_CONSOLE 0x1 56415c960b22b4084057577fc371510864378354ddRob Landley#define LOG_SYSTEM 0x2 57415c960b22b4084057577fc371510864378354ddRob Landley 58415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_MAGIC 0x63825363 59415c960b22b4084057577fc371510864378354ddRob Landley 60415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPDISCOVER 1 61415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPOFFER 2 62415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPREQUEST 3 63415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPDECLINE 4 64415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPACK 5 65415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPNAK 6 66415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPRELEASE 7 67415c960b22b4084057577fc371510864378354ddRob Landley#define DHCPINFORM 8 68415c960b22b4084057577fc371510864378354ddRob Landley 6960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6SOLICIT 1 7060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6ADVERTISE 2 // server -> client 7160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6REQUEST 3 7260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6CONFIRM 4 7360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6RENEW 5 7460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6REBIND 6 7560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6REPLY 7 // server -> client 7660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6RELEASE 8 7760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6DECLINE 9 7860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6RECONFIGURE 10 // server -> client 7960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6INFOREQUEST 11 8060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6RELAYFLOW 12 // relay -> relay/server 8160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6RELAYREPLY 13 // server/relay -> relay 8260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 83415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_NUM8 (1<<8) 84415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_NUM16 (1<<9) 85415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_NUM32 DHCP_NUM16 | DHCP_NUM8 86415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_STRING (1<<10) 87415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_STRLST (1<<11) 88415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_IP (1<<12) 89415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_IPLIST (1<<13) 90415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_IPPLST (1<<14) 91415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_STCRTS (1<<15) 92415c960b22b4084057577fc371510864378354ddRob Landley 93415c960b22b4084057577fc371510864378354ddRob Landley// DHCP option codes (partial list). See RFC 2132 and 94415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_PADDING 0x00 95415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_HOST_NAME DHCP_STRING | 0x0c // either client informs server or server gives name to client 96415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_REQUESTED_IP DHCP_IP | 0x32 // sent by client if specific IP is wanted 97415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_LEASE_TIME DHCP_NUM32 | 0x33 98415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_OPTION_OVERLOAD 0x34 99415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_MESSAGE_TYPE DHCP_NUM8 | 0x35 100415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_SERVER_ID DHCP_IP | 0x36 // by default server's IP 101415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_PARAM_REQ DHCP_STRING | 0x37 // list of options client wants 102415c960b22b4084057577fc371510864378354ddRob Landley#define DHCP_OPT_END 0xff 103415c960b22b4084057577fc371510864378354ddRob Landley 10460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh// DHCPv6 option codes (partial). See RFC 3315 10560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_CLIENTID 1 10660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_SERVERID 2 10760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_IA_NA 3 10860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_IA_ADDR 5 10960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_ORO 6 11060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_PREFERENCE 7 11160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_ELAPSED_TIME 8 11260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_RELAY_MSG 9 11360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_STATUS_CODE 13 11460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_IA_PD 25 11560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_OPT_IA_PREFIX 26 11660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 11760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_STATUS_SUCCESS 0 11860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_STATUS_NOADDRSAVAIL 2 11960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 12060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_DUID_LLT 1 12160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_DUID_EN 2 12260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_DUID_LL 3 12360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh#define DHCP6_DUID_UUID 4 12460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 125415c960b22b4084057577fc371510864378354ddRob LandleyGLOBALS( 12682d8d7cb7eacabd1a498c001dd5618a1302f854bHyejin Kim char *iface; 127415c960b22b4084057577fc371510864378354ddRob Landley long port; 128415c960b22b4084057577fc371510864378354ddRob Landley); 129415c960b22b4084057577fc371510864378354ddRob Landley 13060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstruct config_keyword { 13160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *keyword; 13260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int (*handler)(const char *str, void *var); 13360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh void *var; 13460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *def; 13560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh}; 13660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 137415c960b22b4084057577fc371510864378354ddRob Landleytypedef struct __attribute__((packed)) dhcp_msg_s { 138415c960b22b4084057577fc371510864378354ddRob Landley uint8_t op; 139415c960b22b4084057577fc371510864378354ddRob Landley uint8_t htype; 140415c960b22b4084057577fc371510864378354ddRob Landley uint8_t hlen; 141415c960b22b4084057577fc371510864378354ddRob Landley uint8_t hops; 142415c960b22b4084057577fc371510864378354ddRob Landley uint32_t xid; 143415c960b22b4084057577fc371510864378354ddRob Landley uint16_t secs; 144415c960b22b4084057577fc371510864378354ddRob Landley uint16_t flags; 145415c960b22b4084057577fc371510864378354ddRob Landley uint32_t ciaddr; 146415c960b22b4084057577fc371510864378354ddRob Landley uint32_t yiaddr; 147415c960b22b4084057577fc371510864378354ddRob Landley uint32_t nsiaddr; 148415c960b22b4084057577fc371510864378354ddRob Landley uint32_t ngiaddr; 149415c960b22b4084057577fc371510864378354ddRob Landley uint8_t chaddr[16]; 150415c960b22b4084057577fc371510864378354ddRob Landley uint8_t sname[64]; 151415c960b22b4084057577fc371510864378354ddRob Landley uint8_t file[128]; 152415c960b22b4084057577fc371510864378354ddRob Landley uint32_t cookie; 153415c960b22b4084057577fc371510864378354ddRob Landley uint8_t options[308]; 154415c960b22b4084057577fc371510864378354ddRob Landley} dhcp_msg_t; 155415c960b22b4084057577fc371510864378354ddRob Landley 15660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhtypedef struct __attribute__((packed)) dhcp6_msg_s { 15760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t msgtype; 15860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t transaction_id[3]; 15960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t options[524]; 16060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} dhcp6_msg_t; 16160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 162415c960b22b4084057577fc371510864378354ddRob Landleytypedef struct __attribute__((packed)) dhcp_raw_s { 163415c960b22b4084057577fc371510864378354ddRob Landley struct iphdr iph; 164415c960b22b4084057577fc371510864378354ddRob Landley struct udphdr udph; 165415c960b22b4084057577fc371510864378354ddRob Landley dhcp_msg_t dhcp; 166415c960b22b4084057577fc371510864378354ddRob Landley} dhcp_raw_t; 167415c960b22b4084057577fc371510864378354ddRob Landley 16860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhtypedef struct __attribute__((packed)) dhcp6_raw_s { 16960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct ip6_hdr iph; 17060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct udphdr udph; 17160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dhcp6_msg_t dhcp6; 17260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} dhcp6_raw_t; 17360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 174415c960b22b4084057577fc371510864378354ddRob Landleytypedef struct static_lease_s { 175415c960b22b4084057577fc371510864378354ddRob Landley struct static_lease_s *next; 176415c960b22b4084057577fc371510864378354ddRob Landley uint32_t nip; 177415c960b22b4084057577fc371510864378354ddRob Landley int mac[6]; 178415c960b22b4084057577fc371510864378354ddRob Landley} static_lease; 179415c960b22b4084057577fc371510864378354ddRob Landley 18060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhtypedef struct static_lease6_s { 18160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct static_lease6_s *next; 18260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t duid_len; 18360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t ia_type; 18460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t iaid; 185c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t nip6[16]; 18660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t duid[20]; 18760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} static_lease6; 18860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 189415c960b22b4084057577fc371510864378354ddRob Landleytypedef struct { 190415c960b22b4084057577fc371510864378354ddRob Landley uint32_t expires; 191415c960b22b4084057577fc371510864378354ddRob Landley uint32_t lease_nip; 192415c960b22b4084057577fc371510864378354ddRob Landley uint8_t lease_mac[6]; 193415c960b22b4084057577fc371510864378354ddRob Landley char hostname[20]; 194415c960b22b4084057577fc371510864378354ddRob Landley uint8_t pad[2]; 195415c960b22b4084057577fc371510864378354ddRob Landley} dyn_lease; 196415c960b22b4084057577fc371510864378354ddRob Landley 19760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhtypedef struct { 19860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t duid_len; 19960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t ia_type; 20060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t expires; 20160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t iaid; 202c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t lease_nip6[16]; 20360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t duid[20]; 20460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} dyn_lease6; 20560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 206415c960b22b4084057577fc371510864378354ddRob Landleytypedef struct option_val_s { 207415c960b22b4084057577fc371510864378354ddRob Landley char *key; 208415c960b22b4084057577fc371510864378354ddRob Landley uint16_t code; 209415c960b22b4084057577fc371510864378354ddRob Landley void *val; 210415c960b22b4084057577fc371510864378354ddRob Landley size_t len; 211415c960b22b4084057577fc371510864378354ddRob Landley} option_val_t; 212415c960b22b4084057577fc371510864378354ddRob Landley 21360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstruct __attribute__((packed)) optval_duid_llt { 21460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t type; 21560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t hwtype; 21660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t time; 217c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t lladdr[]; //flexible 21860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh}; 21960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 22060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstruct __attribute__((packed)) optval_ia_na { 22160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t iaid; 22260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t t1, t2; 223c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t optval[]; //flexible 22460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh}; 22560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstruct __attribute__((packed)) optval_ia_addr { 226c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t ipv6_addr[16]; 22760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t pref_lifetime; 22860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t valid_lifetime; 22960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh}; 23060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstruct __attribute__((packed)) optval_status_code { 23160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t status_code; 232c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t status_msg[]; //flexible 23360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh}; 23460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 235415c960b22b4084057577fc371510864378354ddRob Landleytypedef struct __attribute__((__may_alias__)) server_config_s { 236415c960b22b4084057577fc371510864378354ddRob Landley char *interface; // interface to use 237415c960b22b4084057577fc371510864378354ddRob Landley int ifindex; 238c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t server_nip6[16]; 239415c960b22b4084057577fc371510864378354ddRob Landley uint32_t server_nip; 240415c960b22b4084057577fc371510864378354ddRob Landley uint32_t port; 241415c960b22b4084057577fc371510864378354ddRob Landley uint8_t server_mac[6]; // our MAC address (used only for ARP probing) 242415c960b22b4084057577fc371510864378354ddRob Landley void *options[256]; // list of DHCP options loaded from the config file 243415c960b22b4084057577fc371510864378354ddRob Landley /* start,end are in host order: we need to compare start <= ip <= end*/ 244415c960b22b4084057577fc371510864378354ddRob Landley uint32_t start_ip; // start address of leases, in host order 245415c960b22b4084057577fc371510864378354ddRob Landley uint32_t end_ip; // end of leases, in host order 246c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t start_ip6[16]; // start address of leases, in IPv6 mode 247c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t end_ip6[16]; // end of leases, in IPv6 mode 248415c960b22b4084057577fc371510864378354ddRob Landley uint32_t max_lease_sec; // maximum lease time (host order) 249415c960b22b4084057577fc371510864378354ddRob Landley uint32_t min_lease_sec; // minimum lease time a client can request 250415c960b22b4084057577fc371510864378354ddRob Landley uint32_t max_leases; // maximum number of leases (including reserved addresses) 251415c960b22b4084057577fc371510864378354ddRob Landley uint32_t auto_time; // how long should dhcpd wait before writing a config file. 252415c960b22b4084057577fc371510864378354ddRob Landley // if this is zero, it will only write one on SIGUSR1 253415c960b22b4084057577fc371510864378354ddRob Landley uint32_t decline_time; // how long an address is reserved if a client returns a 254415c960b22b4084057577fc371510864378354ddRob Landley // decline message 255415c960b22b4084057577fc371510864378354ddRob Landley uint32_t conflict_time; // how long an arp conflict offender is leased for 256415c960b22b4084057577fc371510864378354ddRob Landley uint32_t offer_time; // how long an offered address is reserved 257415c960b22b4084057577fc371510864378354ddRob Landley uint32_t siaddr_nip; // "next server" bootp option 258415c960b22b4084057577fc371510864378354ddRob Landley char *lease_file; 25960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *lease6_file; 260415c960b22b4084057577fc371510864378354ddRob Landley char *pidfile; 261415c960b22b4084057577fc371510864378354ddRob Landley char *notify_file; // what to run whenever leases are written 262415c960b22b4084057577fc371510864378354ddRob Landley char *sname; // bootp server name 263415c960b22b4084057577fc371510864378354ddRob Landley char *boot_file; // bootp boot file option 26460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t pref_lifetime; 26560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t valid_lifetime; 26660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t t1,t2; 267415c960b22b4084057577fc371510864378354ddRob Landley struct static_lease *static_leases; // List of ip/mac pairs to assign static leases 268415c960b22b4084057577fc371510864378354ddRob Landley} server_config_t; 269415c960b22b4084057577fc371510864378354ddRob Landley 270415c960b22b4084057577fc371510864378354ddRob Landleytypedef struct __attribute__((__may_alias__)) server_state_s { 271c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t client_nip6[16]; 272c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint32_t client_port; 273415c960b22b4084057577fc371510864378354ddRob Landley uint8_t rqcode; 274415c960b22b4084057577fc371510864378354ddRob Landley int listensock; 27560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh union { 27660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dhcp_msg_t rcvd_pkt; 27760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dhcp6_msg_t rcvd_pkt6; 27860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } rcvd; 279415c960b22b4084057577fc371510864378354ddRob Landley uint8_t* rqopt; 28060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh union { 28160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dhcp_msg_t send_pkt; 28260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dhcp6_msg_t send_pkt6; 28360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } send; 28460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh union { 28560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh static_lease *sleases; 28660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh static_lease6 *sleases6; 28760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } leases; 288415c960b22b4084057577fc371510864378354ddRob Landley struct arg_list *dleases; 289415c960b22b4084057577fc371510864378354ddRob Landley} server_state_t; 290415c960b22b4084057577fc371510864378354ddRob Landley 291415c960b22b4084057577fc371510864378354ddRob Landleystatic option_val_t options_list[] = { 292415c960b22b4084057577fc371510864378354ddRob Landley {"lease" , DHCP_NUM32 | 0x33, NULL, 0}, 293415c960b22b4084057577fc371510864378354ddRob Landley {"subnet" , DHCP_IP | 0x01, NULL, 0}, 294415c960b22b4084057577fc371510864378354ddRob Landley {"broadcast" , DHCP_IP | 0x1c, NULL, 0}, 295415c960b22b4084057577fc371510864378354ddRob Landley {"router" , DHCP_IP | 0x03, NULL, 0}, 296415c960b22b4084057577fc371510864378354ddRob Landley {"ipttl" , DHCP_NUM8 | 0x17, NULL, 0}, 297415c960b22b4084057577fc371510864378354ddRob Landley {"mtu" , DHCP_NUM16 | 0x1a, NULL, 0}, 298415c960b22b4084057577fc371510864378354ddRob Landley {"hostname" , DHCP_STRING | 0x0c, NULL, 0}, 299415c960b22b4084057577fc371510864378354ddRob Landley {"domain" , DHCP_STRING | 0x0f, NULL, 0}, 300415c960b22b4084057577fc371510864378354ddRob Landley {"search" , DHCP_STRLST | 0x77, NULL, 0}, 301415c960b22b4084057577fc371510864378354ddRob Landley {"nisdomain" , DHCP_STRING | 0x28, NULL, 0}, 302415c960b22b4084057577fc371510864378354ddRob Landley {"timezone" , DHCP_NUM32 | 0x02, NULL, 0}, 303415c960b22b4084057577fc371510864378354ddRob Landley {"tftp" , DHCP_STRING | 0x42, NULL, 0}, 304415c960b22b4084057577fc371510864378354ddRob Landley {"bootfile" , DHCP_STRING | 0x43, NULL, 0}, 305415c960b22b4084057577fc371510864378354ddRob Landley {"bootsize" , DHCP_NUM16 | 0x0d, NULL, 0}, 306415c960b22b4084057577fc371510864378354ddRob Landley {"rootpath" , DHCP_STRING | 0x11, NULL, 0}, 307415c960b22b4084057577fc371510864378354ddRob Landley {"wpad" , DHCP_STRING | 0xfc, NULL, 0}, 308415c960b22b4084057577fc371510864378354ddRob Landley {"serverid" , DHCP_IP | 0x36, NULL, 0}, 309415c960b22b4084057577fc371510864378354ddRob Landley {"message" , DHCP_STRING | 0x38, NULL, 0}, 310415c960b22b4084057577fc371510864378354ddRob Landley {"vlanid" , DHCP_NUM32 | 0x84, NULL, 0}, 311415c960b22b4084057577fc371510864378354ddRob Landley {"vlanpriority" , DHCP_NUM32 | 0x85, NULL, 0}, 312415c960b22b4084057577fc371510864378354ddRob Landley {"dns" , DHCP_IPLIST | 0x06, NULL, 0}, 313415c960b22b4084057577fc371510864378354ddRob Landley {"wins" , DHCP_IPLIST | 0x2c, NULL, 0}, 314415c960b22b4084057577fc371510864378354ddRob Landley {"nissrv" , DHCP_IPLIST | 0x29, NULL, 0}, 315415c960b22b4084057577fc371510864378354ddRob Landley {"ntpsrv" , DHCP_IPLIST | 0x2a, NULL, 0}, 316415c960b22b4084057577fc371510864378354ddRob Landley {"lprsrv" , DHCP_IPLIST | 0x09, NULL, 0}, 317415c960b22b4084057577fc371510864378354ddRob Landley {"swapsrv" , DHCP_IP | 0x10, NULL, 0}, 318415c960b22b4084057577fc371510864378354ddRob Landley {"routes" , DHCP_STCRTS | 0x21, NULL, 0}, 319415c960b22b4084057577fc371510864378354ddRob Landley {"staticroutes" , DHCP_STCRTS | 0x79, NULL, 0}, 320415c960b22b4084057577fc371510864378354ddRob Landley {"msstaticroutes" , DHCP_STCRTS | 0xf9, NULL, 0}, 321415c960b22b4084057577fc371510864378354ddRob Landley}; 322415c960b22b4084057577fc371510864378354ddRob Landley 323415c960b22b4084057577fc371510864378354ddRob Landleystruct fd_pair { int rd; int wr; }; 324415c960b22b4084057577fc371510864378354ddRob Landleystatic server_config_t gconfig; 325415c960b22b4084057577fc371510864378354ddRob Landleystatic server_state_t gstate; 326415c960b22b4084057577fc371510864378354ddRob Landleystatic uint8_t infomode; 327415c960b22b4084057577fc371510864378354ddRob Landleystatic struct fd_pair sigfd; 328415c960b22b4084057577fc371510864378354ddRob Landleystatic int constone = 1; 32960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic sa_family_t addr_version = AF_INET; 33060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 331415c960b22b4084057577fc371510864378354ddRob Landley// calculate options size. 332415c960b22b4084057577fc371510864378354ddRob Landleystatic int dhcp_opt_size(uint8_t *optionptr) 333415c960b22b4084057577fc371510864378354ddRob Landley{ 334415c960b22b4084057577fc371510864378354ddRob Landley int i = 0; 33560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh for(;optionptr[i] != 0xff; i++) 33660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(optionptr[i] != 0x00) i += optionptr[i + 1] + 2 -1; 337415c960b22b4084057577fc371510864378354ddRob Landley return i; 338415c960b22b4084057577fc371510864378354ddRob Landley} 339415c960b22b4084057577fc371510864378354ddRob Landley 340415c960b22b4084057577fc371510864378354ddRob Landley// calculates checksum for dhcp messeges. 341415c960b22b4084057577fc371510864378354ddRob Landleystatic uint16_t dhcp_checksum(void *addr, int count) 342415c960b22b4084057577fc371510864378354ddRob Landley{ 343415c960b22b4084057577fc371510864378354ddRob Landley int32_t sum = 0; 344415c960b22b4084057577fc371510864378354ddRob Landley uint16_t tmp = 0, *source = (uint16_t *)addr; 345415c960b22b4084057577fc371510864378354ddRob Landley 346415c960b22b4084057577fc371510864378354ddRob Landley while (count > 1) { 347415c960b22b4084057577fc371510864378354ddRob Landley sum += *source++; 348415c960b22b4084057577fc371510864378354ddRob Landley count -= 2; 349415c960b22b4084057577fc371510864378354ddRob Landley } 350415c960b22b4084057577fc371510864378354ddRob Landley if (count > 0) { 351415c960b22b4084057577fc371510864378354ddRob Landley *(uint8_t*)&tmp = *(uint8_t*)source; 352415c960b22b4084057577fc371510864378354ddRob Landley sum += tmp; 353415c960b22b4084057577fc371510864378354ddRob Landley } 354415c960b22b4084057577fc371510864378354ddRob Landley while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); 355415c960b22b4084057577fc371510864378354ddRob Landley return ~sum; 356415c960b22b4084057577fc371510864378354ddRob Landley} 357415c960b22b4084057577fc371510864378354ddRob Landley 358415c960b22b4084057577fc371510864378354ddRob Landley// gets information of INTERFACE and updates IFINDEX, MAC and IP 359c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suhstatic int get_interface(const char *interface, int *ifindex, void *oip, 36060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t *mac) 361415c960b22b4084057577fc371510864378354ddRob Landley{ 362415c960b22b4084057577fc371510864378354ddRob Landley struct ifreq req; 363415c960b22b4084057577fc371510864378354ddRob Landley struct sockaddr_in *ip; 36460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct sockaddr_in6 ip6; 36560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int fd = xsocket(addr_version, SOCK_RAW, IPPROTO_RAW); 36660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char ipv6_addr[40] = {0,}; 367415c960b22b4084057577fc371510864378354ddRob Landley 36860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh req.ifr_addr.sa_family = addr_version; 36960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh xstrncpy(req.ifr_name, (char *)interface, IFNAMSIZ); 370415c960b22b4084057577fc371510864378354ddRob Landley 371415c960b22b4084057577fc371510864378354ddRob Landley xioctl(fd, SIOCGIFFLAGS, &req); 37260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 373415c960b22b4084057577fc371510864378354ddRob Landley if (!(req.ifr_flags & IFF_UP)) return -1; 37460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 37560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (addr_version == AF_INET6) { 37660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 37760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh FILE *fd6 = fopen("/proc/net/if_inet6", "r"); 378c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t *oip6 = (uint8_t*)oip; 37960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int i; 38060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 38160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while(fgets(toybuf, sizeof(toybuf), fd6)) { 38260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!strstr(toybuf, interface)) 38360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 38460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 385c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (sscanf(toybuf, "%32s \n", ipv6_addr) == 1) 386c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh break; 38760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 38860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh fclose(fd6); 38960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 390c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (oip6) { 39160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *ptr = ipv6_addr+sizeof(ipv6_addr)-1; 39260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 39360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh // convert giant hex string into colon-spearated ipv6 address by 39460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh // inserting ':' every 4 characters. 39560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh for (i = 32; i; i--) 39660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((*(ptr--) = ipv6_addr[i])) if (!(i&3)) *(ptr--) = ':'; 39760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 39860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("ipv6 %s\n", ipv6_addr); 39960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(inet_pton(AF_INET6, ipv6_addr, &ip6.sin6_addr) <= 0) 40060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh error_msg("inet : the ipv6 address is not proper"); 40160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh else 402c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(oip6, ip6.sin6_addr.s6_addr32, sizeof(uint32_t)*4); 40360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 40460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 405c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint32_t *oip4 = (uint32_t*)oip; 406c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (oip4) { 40760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh xioctl(fd, SIOCGIFADDR, &req); 40860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ip = (struct sockaddr_in*) &req.ifr_addr; 40960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("IP %s\n", inet_ntoa(ip->sin_addr)); 410c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh *oip4 = ntohl(ip->sin_addr.s_addr); 41160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 412415c960b22b4084057577fc371510864378354ddRob Landley } 41360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 414415c960b22b4084057577fc371510864378354ddRob Landley if (ifindex) { 415415c960b22b4084057577fc371510864378354ddRob Landley xioctl(fd, SIOCGIFINDEX, &req); 416415c960b22b4084057577fc371510864378354ddRob Landley dbg("Adapter index %d\n", req.ifr_ifindex); 417415c960b22b4084057577fc371510864378354ddRob Landley *ifindex = req.ifr_ifindex; 418415c960b22b4084057577fc371510864378354ddRob Landley } 419415c960b22b4084057577fc371510864378354ddRob Landley if (mac) { 420415c960b22b4084057577fc371510864378354ddRob Landley xioctl(fd, SIOCGIFHWADDR, &req); 421415c960b22b4084057577fc371510864378354ddRob Landley memcpy(mac, req.ifr_hwaddr.sa_data, 6); 422415c960b22b4084057577fc371510864378354ddRob Landley dbg("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 423415c960b22b4084057577fc371510864378354ddRob Landley } 42460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 425415c960b22b4084057577fc371510864378354ddRob Landley close(fd); 426415c960b22b4084057577fc371510864378354ddRob Landley return 0; 427415c960b22b4084057577fc371510864378354ddRob Landley} 428415c960b22b4084057577fc371510864378354ddRob Landley 429415c960b22b4084057577fc371510864378354ddRob Landley/* 430415c960b22b4084057577fc371510864378354ddRob Landley *logs messeges to syslog or console 431415c960b22b4084057577fc371510864378354ddRob Landley *opening the log is still left with applet. 432415c960b22b4084057577fc371510864378354ddRob Landley *FIXME: move to more relevent lib. probably libc.c 433415c960b22b4084057577fc371510864378354ddRob Landley */ 434415c960b22b4084057577fc371510864378354ddRob Landleystatic void infomsg(uint8_t infomode, char *s, ...) 435415c960b22b4084057577fc371510864378354ddRob Landley{ 436415c960b22b4084057577fc371510864378354ddRob Landley int used; 437415c960b22b4084057577fc371510864378354ddRob Landley char *msg; 438415c960b22b4084057577fc371510864378354ddRob Landley va_list p, t; 439415c960b22b4084057577fc371510864378354ddRob Landley 440415c960b22b4084057577fc371510864378354ddRob Landley if (infomode == LOG_SILENT) return; 441415c960b22b4084057577fc371510864378354ddRob Landley va_start(p, s); 442415c960b22b4084057577fc371510864378354ddRob Landley va_copy(t, p); 443415c960b22b4084057577fc371510864378354ddRob Landley used = vsnprintf(NULL, 0, s, t); 444415c960b22b4084057577fc371510864378354ddRob Landley used++; 445415c960b22b4084057577fc371510864378354ddRob Landley va_end(t); 446415c960b22b4084057577fc371510864378354ddRob Landley 447415c960b22b4084057577fc371510864378354ddRob Landley msg = xmalloc(used); 448415c960b22b4084057577fc371510864378354ddRob Landley vsnprintf(msg, used, s, p); 449415c960b22b4084057577fc371510864378354ddRob Landley va_end(p); 450415c960b22b4084057577fc371510864378354ddRob Landley 451415c960b22b4084057577fc371510864378354ddRob Landley if (infomode & LOG_SYSTEM) syslog(LOG_INFO, "%s", msg); 452415c960b22b4084057577fc371510864378354ddRob Landley if (infomode & LOG_CONSOLE) printf("%s\n", msg); 453415c960b22b4084057577fc371510864378354ddRob Landley free(msg); 454415c960b22b4084057577fc371510864378354ddRob Landley} 455415c960b22b4084057577fc371510864378354ddRob Landley 456415c960b22b4084057577fc371510864378354ddRob Landley/* 457415c960b22b4084057577fc371510864378354ddRob Landley * Writes self PID in file PATH 458415c960b22b4084057577fc371510864378354ddRob Landley * FIXME: libc implementation only writes in /var/run 459415c960b22b4084057577fc371510864378354ddRob Landley * this is more generic as some implemenation may provide 460415c960b22b4084057577fc371510864378354ddRob Landley * arguments to write in specific file. as dhcpd does. 461415c960b22b4084057577fc371510864378354ddRob Landley */ 462415c960b22b4084057577fc371510864378354ddRob Landleystatic void write_pid(char *path) 463415c960b22b4084057577fc371510864378354ddRob Landley{ 464415c960b22b4084057577fc371510864378354ddRob Landley int pidfile = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666); 465415c960b22b4084057577fc371510864378354ddRob Landley if (pidfile > 0) { 46679d8bc70539b7a3d459630c97e38d3cdff77e591Rob Landley char pidbuf[12]; 46779d8bc70539b7a3d459630c97e38d3cdff77e591Rob Landley 46879d8bc70539b7a3d459630c97e38d3cdff77e591Rob Landley sprintf(pidbuf, "%u", (unsigned)getpid()); 469415c960b22b4084057577fc371510864378354ddRob Landley write(pidfile, pidbuf, strlen(pidbuf)); 470415c960b22b4084057577fc371510864378354ddRob Landley close(pidfile); 471415c960b22b4084057577fc371510864378354ddRob Landley } 472415c960b22b4084057577fc371510864378354ddRob Landley} 473415c960b22b4084057577fc371510864378354ddRob Landley 474415c960b22b4084057577fc371510864378354ddRob Landley// Generic signal handler real handling is done in main funcrion. 475415c960b22b4084057577fc371510864378354ddRob Landleystatic void signal_handler(int sig) 476415c960b22b4084057577fc371510864378354ddRob Landley{ 477415c960b22b4084057577fc371510864378354ddRob Landley unsigned char ch = sig; 478415c960b22b4084057577fc371510864378354ddRob Landley if (write(sigfd.wr, &ch, 1) != 1) dbg("can't send signal\n"); 479415c960b22b4084057577fc371510864378354ddRob Landley} 480415c960b22b4084057577fc371510864378354ddRob Landley 481415c960b22b4084057577fc371510864378354ddRob Landley// signal setup for SIGUSR1 SIGTERM 482415c960b22b4084057577fc371510864378354ddRob Landleystatic int setup_signal() 483415c960b22b4084057577fc371510864378354ddRob Landley{ 484415c960b22b4084057577fc371510864378354ddRob Landley if (pipe((int *)&sigfd) < 0) { 485415c960b22b4084057577fc371510864378354ddRob Landley dbg("signal pipe failed\n"); 486415c960b22b4084057577fc371510864378354ddRob Landley return -1; 487415c960b22b4084057577fc371510864378354ddRob Landley } 488415c960b22b4084057577fc371510864378354ddRob Landley fcntl(sigfd.wr , F_SETFD, FD_CLOEXEC); 489415c960b22b4084057577fc371510864378354ddRob Landley fcntl(sigfd.rd , F_SETFD, FD_CLOEXEC); 490415c960b22b4084057577fc371510864378354ddRob Landley int flags = fcntl(sigfd.wr, F_GETFL); 491415c960b22b4084057577fc371510864378354ddRob Landley fcntl(sigfd.wr, F_SETFL, flags | O_NONBLOCK); 492415c960b22b4084057577fc371510864378354ddRob Landley signal(SIGUSR1, signal_handler); 493415c960b22b4084057577fc371510864378354ddRob Landley signal(SIGTERM, signal_handler); 494415c960b22b4084057577fc371510864378354ddRob Landley return 0; 495415c960b22b4084057577fc371510864378354ddRob Landley} 496415c960b22b4084057577fc371510864378354ddRob Landley 497415c960b22b4084057577fc371510864378354ddRob Landley// String STR to UINT32 conversion strored in VAR 498415c960b22b4084057577fc371510864378354ddRob Landleystatic int strtou32(const char *str, void *var) 499415c960b22b4084057577fc371510864378354ddRob Landley{ 500415c960b22b4084057577fc371510864378354ddRob Landley char *endptr = NULL; 501415c960b22b4084057577fc371510864378354ddRob Landley int base = 10; 502415c960b22b4084057577fc371510864378354ddRob Landley errno=0; 503415c960b22b4084057577fc371510864378354ddRob Landley *((uint32_t*)(var)) = 0; 504415c960b22b4084057577fc371510864378354ddRob Landley if (str[0]=='0' && (str[1]=='x' || str[1]=='X')) { 505415c960b22b4084057577fc371510864378354ddRob Landley base = 16; 506415c960b22b4084057577fc371510864378354ddRob Landley str+=2; 507415c960b22b4084057577fc371510864378354ddRob Landley } 50860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 509415c960b22b4084057577fc371510864378354ddRob Landley long ret_val = strtol(str, &endptr, base); 510415c960b22b4084057577fc371510864378354ddRob Landley if (errno) infomsg(infomode, "config : Invalid num %s",str); 511415c960b22b4084057577fc371510864378354ddRob Landley else if (endptr && (*endptr!='\0'||endptr == str)) 512415c960b22b4084057577fc371510864378354ddRob Landley infomsg(infomode, "config : Not a valid num %s",str); 513415c960b22b4084057577fc371510864378354ddRob Landley else *((uint32_t*)(var)) = (uint32_t)ret_val; 514415c960b22b4084057577fc371510864378354ddRob Landley return 0; 515415c960b22b4084057577fc371510864378354ddRob Landley} 516415c960b22b4084057577fc371510864378354ddRob Landley 517415c960b22b4084057577fc371510864378354ddRob Landley// copy string STR in variable VAR 518415c960b22b4084057577fc371510864378354ddRob Landleystatic int strinvar(const char *str, void *var) 519415c960b22b4084057577fc371510864378354ddRob Landley{ 520415c960b22b4084057577fc371510864378354ddRob Landley char **dest = var; 521415c960b22b4084057577fc371510864378354ddRob Landley if (*dest) free(*dest); 522415c960b22b4084057577fc371510864378354ddRob Landley *dest = strdup(str); 523415c960b22b4084057577fc371510864378354ddRob Landley return 0; 524415c960b22b4084057577fc371510864378354ddRob Landley} 525415c960b22b4084057577fc371510864378354ddRob Landley 526415c960b22b4084057577fc371510864378354ddRob Landley// IP String STR to binary data. 527415c960b22b4084057577fc371510864378354ddRob Landleystatic int striptovar(const char *str, void *var) 528415c960b22b4084057577fc371510864378354ddRob Landley{ 529415c960b22b4084057577fc371510864378354ddRob Landley *((uint32_t*)(var)) = 0; 530415c960b22b4084057577fc371510864378354ddRob Landley if(!str) { 531415c960b22b4084057577fc371510864378354ddRob Landley error_msg("config : NULL address string \n"); 532415c960b22b4084057577fc371510864378354ddRob Landley return -1; 533415c960b22b4084057577fc371510864378354ddRob Landley } 53460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if((inet_pton(AF_INET6, str, var)<=0) && (inet_pton(AF_INET, str, var)<=0)) { 53560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh error_msg("config : wrong address %s \n", str); 536415c960b22b4084057577fc371510864378354ddRob Landley return -1; 537415c960b22b4084057577fc371510864378354ddRob Landley } 538415c960b22b4084057577fc371510864378354ddRob Landley return 0; 539415c960b22b4084057577fc371510864378354ddRob Landley} 540415c960b22b4084057577fc371510864378354ddRob Landley 541415c960b22b4084057577fc371510864378354ddRob Landley// String to dhcp option conversion 542415c960b22b4084057577fc371510864378354ddRob Landleystatic int strtoopt(const char *str, void *var) 543415c960b22b4084057577fc371510864378354ddRob Landley{ 544415c960b22b4084057577fc371510864378354ddRob Landley char *option, *valstr, *grp, *tp; 545415c960b22b4084057577fc371510864378354ddRob Landley uint32_t optcode = 0, inf = infomode, convtmp, mask, nip, router; 546415c960b22b4084057577fc371510864378354ddRob Landley uint16_t flag = 0; 547415c960b22b4084057577fc371510864378354ddRob Landley int count, size = ARRAY_LEN(options_list); 548415c960b22b4084057577fc371510864378354ddRob Landley 549415c960b22b4084057577fc371510864378354ddRob Landley if (!*str) return 0; 550415c960b22b4084057577fc371510864378354ddRob Landley if (!(option = strtok((char*)str, " \t="))) return -1; 551415c960b22b4084057577fc371510864378354ddRob Landley 552415c960b22b4084057577fc371510864378354ddRob Landley infomode = LOG_SILENT; 553415c960b22b4084057577fc371510864378354ddRob Landley strtou32(option, (uint32_t*)&optcode); 554415c960b22b4084057577fc371510864378354ddRob Landley infomode = inf; 555415c960b22b4084057577fc371510864378354ddRob Landley 556415c960b22b4084057577fc371510864378354ddRob Landley if (optcode > 0 && optcode < 256) { // raw option 557415c960b22b4084057577fc371510864378354ddRob Landley for (count = 0; count < size; count++) { 558415c960b22b4084057577fc371510864378354ddRob Landley if ((options_list[count].code & 0X00FF) == optcode) { 559415c960b22b4084057577fc371510864378354ddRob Landley flag = (options_list[count].code & 0XFF00); 560415c960b22b4084057577fc371510864378354ddRob Landley break; 561415c960b22b4084057577fc371510864378354ddRob Landley } 562415c960b22b4084057577fc371510864378354ddRob Landley } 563415c960b22b4084057577fc371510864378354ddRob Landley } else { //string option 564415c960b22b4084057577fc371510864378354ddRob Landley for (count = 0; count < size; count++) { 565415c960b22b4084057577fc371510864378354ddRob Landley if (!strncmp(options_list[count].key, option, strlen(options_list[count].key))) { 566415c960b22b4084057577fc371510864378354ddRob Landley flag = (options_list[count].code & 0XFF00); 567415c960b22b4084057577fc371510864378354ddRob Landley optcode = (options_list[count].code & 0X00FF); 568415c960b22b4084057577fc371510864378354ddRob Landley break; 569415c960b22b4084057577fc371510864378354ddRob Landley } 570415c960b22b4084057577fc371510864378354ddRob Landley } 571415c960b22b4084057577fc371510864378354ddRob Landley } 572415c960b22b4084057577fc371510864378354ddRob Landley if (count == size) { 573415c960b22b4084057577fc371510864378354ddRob Landley infomsg(inf, "config : Obsolete OR Unknown Option : %s", option); 574415c960b22b4084057577fc371510864378354ddRob Landley return -1; 575415c960b22b4084057577fc371510864378354ddRob Landley } 576415c960b22b4084057577fc371510864378354ddRob Landley 577415c960b22b4084057577fc371510864378354ddRob Landley if (!flag || !optcode) return -1; 578415c960b22b4084057577fc371510864378354ddRob Landley 579415c960b22b4084057577fc371510864378354ddRob Landley if (!(valstr = strtok(NULL, " \t"))) { 580415c960b22b4084057577fc371510864378354ddRob Landley dbg("config : option %s has no value defined.\n", option); 581415c960b22b4084057577fc371510864378354ddRob Landley return -1; 582415c960b22b4084057577fc371510864378354ddRob Landley } 583415c960b22b4084057577fc371510864378354ddRob Landley dbg(" value : %-20s : ", valstr); 584415c960b22b4084057577fc371510864378354ddRob Landley switch (flag) { 585415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_NUM32: 586415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len = sizeof(uint32_t); 587415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].val = xmalloc(sizeof(uint32_t)); 588415c960b22b4084057577fc371510864378354ddRob Landley strtou32(valstr, &convtmp); 589415c960b22b4084057577fc371510864378354ddRob Landley memcpy(options_list[count].val, &convtmp, sizeof(uint32_t)); 590415c960b22b4084057577fc371510864378354ddRob Landley break; 591415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_NUM16: 592415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len = sizeof(uint16_t); 593415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].val = xmalloc(sizeof(uint16_t)); 594415c960b22b4084057577fc371510864378354ddRob Landley strtou32(valstr, &convtmp); 595415c960b22b4084057577fc371510864378354ddRob Landley memcpy(options_list[count].val, &convtmp, sizeof(uint16_t)); 596415c960b22b4084057577fc371510864378354ddRob Landley break; 597415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_NUM8: 598415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len = sizeof(uint8_t); 599415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].val = xmalloc(sizeof(uint8_t)); 600415c960b22b4084057577fc371510864378354ddRob Landley strtou32(valstr, &convtmp); 601415c960b22b4084057577fc371510864378354ddRob Landley memcpy(options_list[count].val, &convtmp, sizeof(uint8_t)); 602415c960b22b4084057577fc371510864378354ddRob Landley break; 603415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_IP: 604415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len = sizeof(uint32_t); 605415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].val = xmalloc(sizeof(uint32_t)); 606415c960b22b4084057577fc371510864378354ddRob Landley striptovar(valstr, options_list[count].val); 607415c960b22b4084057577fc371510864378354ddRob Landley break; 608415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_STRING: 609415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len = strlen(valstr); 610415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].val = strdup(valstr); 611415c960b22b4084057577fc371510864378354ddRob Landley break; 612415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_IPLIST: 613415c960b22b4084057577fc371510864378354ddRob Landley while(valstr){ 614415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + sizeof(uint32_t)); 615415c960b22b4084057577fc371510864378354ddRob Landley striptovar(valstr, ((uint8_t*)options_list[count].val)+options_list[count].len); 616415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len += sizeof(uint32_t); 617415c960b22b4084057577fc371510864378354ddRob Landley valstr = strtok(NULL," \t"); 618415c960b22b4084057577fc371510864378354ddRob Landley } 619415c960b22b4084057577fc371510864378354ddRob Landley break; 620415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_IPPLST: 621415c960b22b4084057577fc371510864378354ddRob Landley break; 622415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_STCRTS: 623415c960b22b4084057577fc371510864378354ddRob Landley /* Option binary format: 624415c960b22b4084057577fc371510864378354ddRob Landley * mask [one byte, 0..32] 625415c960b22b4084057577fc371510864378354ddRob Landley * ip [0..4 bytes depending on mask] 626415c960b22b4084057577fc371510864378354ddRob Landley * router [4 bytes] 627415c960b22b4084057577fc371510864378354ddRob Landley * may be repeated 628415c960b22b4084057577fc371510864378354ddRob Landley * staticroutes 10.0.0.0/8 10.127.0.1, 10.11.12.0/24 10.11.12.1 629415c960b22b4084057577fc371510864378354ddRob Landley */ 630415c960b22b4084057577fc371510864378354ddRob Landley grp = strtok(valstr, ",");; 631415c960b22b4084057577fc371510864378354ddRob Landley while(grp){ 632415c960b22b4084057577fc371510864378354ddRob Landley while(*grp == ' ' || *grp == '\t') grp++; 633415c960b22b4084057577fc371510864378354ddRob Landley tp = strchr(grp, '/'); 634415c960b22b4084057577fc371510864378354ddRob Landley if (!tp) error_exit("wrong formated static route option"); 635415c960b22b4084057577fc371510864378354ddRob Landley *tp = '\0'; 636415c960b22b4084057577fc371510864378354ddRob Landley mask = strtol(++tp, &tp, 10); 637415c960b22b4084057577fc371510864378354ddRob Landley if (striptovar(grp, (uint8_t*)&nip)<0) error_exit("wrong formated static route option"); 638415c960b22b4084057577fc371510864378354ddRob Landley while(*tp == ' ' || *tp == '\t' || *tp == '-') tp++; 639415c960b22b4084057577fc371510864378354ddRob Landley if (striptovar(tp, (uint8_t*)&router)<0) error_exit("wrong formated static route option"); 640415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + 1 + mask/8 + 4); 641415c960b22b4084057577fc371510864378354ddRob Landley memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &mask, 1); 642415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len += 1; 643415c960b22b4084057577fc371510864378354ddRob Landley memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &nip, mask/8); 644415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len += mask/8; 645415c960b22b4084057577fc371510864378354ddRob Landley memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &router, 4); 646415c960b22b4084057577fc371510864378354ddRob Landley options_list[count].len += 4; 647415c960b22b4084057577fc371510864378354ddRob Landley tp = NULL; 648415c960b22b4084057577fc371510864378354ddRob Landley grp = strtok(NULL, ","); 649415c960b22b4084057577fc371510864378354ddRob Landley } 650415c960b22b4084057577fc371510864378354ddRob Landley break; 651415c960b22b4084057577fc371510864378354ddRob Landley } 652415c960b22b4084057577fc371510864378354ddRob Landley return 0; 653415c960b22b4084057577fc371510864378354ddRob Landley} 654415c960b22b4084057577fc371510864378354ddRob Landley 655415c960b22b4084057577fc371510864378354ddRob Landley// Reads Static leases from STR and updates inner structures. 656415c960b22b4084057577fc371510864378354ddRob Landleystatic int get_staticlease(const char *str, void *var) 657415c960b22b4084057577fc371510864378354ddRob Landley{ 658415c960b22b4084057577fc371510864378354ddRob Landley struct static_lease_s *sltmp; 659415c960b22b4084057577fc371510864378354ddRob Landley char *tkmac, *tkip; 660415c960b22b4084057577fc371510864378354ddRob Landley int count; 661415c960b22b4084057577fc371510864378354ddRob Landley 662415c960b22b4084057577fc371510864378354ddRob Landley if (!*str) return 0; 663415c960b22b4084057577fc371510864378354ddRob Landley 664415c960b22b4084057577fc371510864378354ddRob Landley if (!(tkmac = strtok((char*)str, " \t"))) { 665415c960b22b4084057577fc371510864378354ddRob Landley infomsg(infomode, "config : static lease : mac not found"); 666415c960b22b4084057577fc371510864378354ddRob Landley return 0; 667415c960b22b4084057577fc371510864378354ddRob Landley } 668415c960b22b4084057577fc371510864378354ddRob Landley if (!(tkip = strtok(NULL, " \t"))) { 669415c960b22b4084057577fc371510864378354ddRob Landley infomsg(infomode, "config : static lease : no ip bind to mac %s", tkmac); 670415c960b22b4084057577fc371510864378354ddRob Landley return 0; 671415c960b22b4084057577fc371510864378354ddRob Landley } 672415c960b22b4084057577fc371510864378354ddRob Landley sltmp = xzalloc(sizeof(struct static_lease_s)); 673415c960b22b4084057577fc371510864378354ddRob Landley for (count = 0; count < 6; count++, tkmac++) { 674415c960b22b4084057577fc371510864378354ddRob Landley errno = 0; 675415c960b22b4084057577fc371510864378354ddRob Landley sltmp->mac[count] = strtol(tkmac, &tkmac, 16); 676415c960b22b4084057577fc371510864378354ddRob Landley if (sltmp->mac[count]>255 || sltmp->mac[count]<0 || (*tkmac && *tkmac!=':') || errno) { 677415c960b22b4084057577fc371510864378354ddRob Landley infomsg(infomode, "config : static lease : mac address wrong format"); 678415c960b22b4084057577fc371510864378354ddRob Landley free(sltmp); 679415c960b22b4084057577fc371510864378354ddRob Landley return 0; 680415c960b22b4084057577fc371510864378354ddRob Landley } 681415c960b22b4084057577fc371510864378354ddRob Landley } 682415c960b22b4084057577fc371510864378354ddRob Landley striptovar(tkip, &sltmp->nip); 68360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh sltmp->next = gstate.leases.sleases; 68460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.leases.sleases = sltmp; 685415c960b22b4084057577fc371510864378354ddRob Landley 686415c960b22b4084057577fc371510864378354ddRob Landley return 0; 687415c960b22b4084057577fc371510864378354ddRob Landley} 688415c960b22b4084057577fc371510864378354ddRob Landley 689415c960b22b4084057577fc371510864378354ddRob Landleystatic struct config_keyword keywords[] = { 69060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh// keyword handler variable address default 691415c960b22b4084057577fc371510864378354ddRob Landley {"start" , striptovar , (void*)&gconfig.start_ip , "192.168.0.20"}, 692415c960b22b4084057577fc371510864378354ddRob Landley {"end" , striptovar , (void*)&gconfig.end_ip , "192.168.0.254"}, 693415c960b22b4084057577fc371510864378354ddRob Landley {"interface" , strinvar , (void*)&gconfig.interface , "eth0"}, 694415c960b22b4084057577fc371510864378354ddRob Landley {"port" , strtou32 , (void*)&gconfig.port , "67"}, 695415c960b22b4084057577fc371510864378354ddRob Landley {"min_lease" , strtou32 , (void*)&gconfig.min_lease_sec, "60"}, 696415c960b22b4084057577fc371510864378354ddRob Landley {"max_leases" , strtou32 , (void*)&gconfig.max_leases , "235"}, 697415c960b22b4084057577fc371510864378354ddRob Landley {"auto_time" , strtou32 , (void*)&gconfig.auto_time , "7200"}, 698415c960b22b4084057577fc371510864378354ddRob Landley {"decline_time" , strtou32 , (void*)&gconfig.decline_time , "3600"}, 699415c960b22b4084057577fc371510864378354ddRob Landley {"conflict_time", strtou32 , (void*)&gconfig.conflict_time, "3600"}, 700415c960b22b4084057577fc371510864378354ddRob Landley {"offer_time" , strtou32 , (void*)&gconfig.offer_time , "60"}, 701415c960b22b4084057577fc371510864378354ddRob Landley {"lease_file" , strinvar , (void*)&gconfig.lease_file , "/var/lib/misc/dhcpd.leases"}, //LEASES_FILE 70260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh {"lease6_file" , strinvar , (void*)&gconfig.lease6_file , "/var/lib/misc/dhcpd6.leases"}, //LEASES_FILE 703415c960b22b4084057577fc371510864378354ddRob Landley {"pidfile" , strinvar , (void*)&gconfig.pidfile , "/var/run/dhcpd.pid"}, //DPID_FILE 704415c960b22b4084057577fc371510864378354ddRob Landley {"siaddr" , striptovar , (void*)&gconfig.siaddr_nip , "0.0.0.0"}, 705415c960b22b4084057577fc371510864378354ddRob Landley {"option" , strtoopt , (void*)&gconfig.options , ""}, 706415c960b22b4084057577fc371510864378354ddRob Landley {"opt" , strtoopt , (void*)&gconfig.options , ""}, 707415c960b22b4084057577fc371510864378354ddRob Landley {"notify_file" , strinvar , (void*)&gconfig.notify_file , ""}, 708415c960b22b4084057577fc371510864378354ddRob Landley {"sname" , strinvar , (void*)&gconfig.sname , ""}, 709415c960b22b4084057577fc371510864378354ddRob Landley {"boot_file" , strinvar , (void*)&gconfig.boot_file , ""}, 710415c960b22b4084057577fc371510864378354ddRob Landley {"static_lease" , get_staticlease , (void*)&gconfig.static_leases, ""}, 71160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh {"start6" , striptovar , (void*)&gconfig.start_ip6 , "2001:620:40b:555::100"}, 71260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh {"end6" , striptovar , (void*)&gconfig.end_ip6 , "2001:620:40b:555::200"}, 71360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh {"preferred_lifetime" , strtou32 , (void*)&gconfig.pref_lifetime, "3600"}, 71460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh {"valid_lifetime" , strtou32 , (void*)&gconfig.valid_lifetime, "7200"}, 71560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh {"t1" , strtou32 , (void*)&gconfig.t1 , "3600"}, 71660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh {"t2" , strtou32 , (void*)&gconfig.t2 , "5400"}, 717415c960b22b4084057577fc371510864378354ddRob Landley}; 718415c960b22b4084057577fc371510864378354ddRob Landley 719415c960b22b4084057577fc371510864378354ddRob Landley// Parses the server config file and updates the global server config accordingly. 720415c960b22b4084057577fc371510864378354ddRob Landleystatic int parse_server_config(char *config_file, struct config_keyword *confkey) 721415c960b22b4084057577fc371510864378354ddRob Landley{ 722415c960b22b4084057577fc371510864378354ddRob Landley FILE *fs = NULL; 723415c960b22b4084057577fc371510864378354ddRob Landley char *confline_temp = NULL,*confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL}; 724415c960b22b4084057577fc371510864378354ddRob Landley int len, linelen, tcount, count, size = ARRAY_LEN(keywords); 725415c960b22b4084057577fc371510864378354ddRob Landley 726415c960b22b4084057577fc371510864378354ddRob Landley for (count = 0; count < size; count++) 72760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (confkey[count].handler) 72860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh confkey[count].handler(confkey[count].def, confkey[count].var); 729415c960b22b4084057577fc371510864378354ddRob Landley 730415c960b22b4084057577fc371510864378354ddRob Landley if (!(fs = fopen(config_file, "r"))) perror_msg("%s", config_file); 731415c960b22b4084057577fc371510864378354ddRob Landley for (len = 0, linelen = 0; fs;) { 732415c960b22b4084057577fc371510864378354ddRob Landley len = getline(&confline_temp, (size_t*) &linelen, fs); 733415c960b22b4084057577fc371510864378354ddRob Landley confline = confline_temp; 734415c960b22b4084057577fc371510864378354ddRob Landley if (len <= 0) break; 735415c960b22b4084057577fc371510864378354ddRob Landley for (; *confline == ' '; confline++, len--); 736415c960b22b4084057577fc371510864378354ddRob Landley if ((confline[0] == '#') || (confline[0] == '\n')) goto free_conf_continue; 737415c960b22b4084057577fc371510864378354ddRob Landley tk = strchr(confline, '#'); 738415c960b22b4084057577fc371510864378354ddRob Landley if (tk) { 739415c960b22b4084057577fc371510864378354ddRob Landley for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--); 740415c960b22b4084057577fc371510864378354ddRob Landley *tk = '\0'; 741415c960b22b4084057577fc371510864378354ddRob Landley } 742415c960b22b4084057577fc371510864378354ddRob Landley tk = strchr(confline, '\n'); 743415c960b22b4084057577fc371510864378354ddRob Landley if (tk) { 744415c960b22b4084057577fc371510864378354ddRob Landley for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--); 745415c960b22b4084057577fc371510864378354ddRob Landley *tk = '\0'; 746415c960b22b4084057577fc371510864378354ddRob Landley } 747415c960b22b4084057577fc371510864378354ddRob Landley for (tcount=0, tk=strtok(confline, " \t"); tk && (tcount < 2); 748415c960b22b4084057577fc371510864378354ddRob Landley tcount++, tk=strtok(NULL,(tcount==1)?"":" \t")) { 749415c960b22b4084057577fc371510864378354ddRob Landley while ((*tk == '\t') || (*tk == ' ')) tk++; 750415c960b22b4084057577fc371510864378354ddRob Landley tokens[tcount] = xstrdup(tk); 751415c960b22b4084057577fc371510864378354ddRob Landley } 752415c960b22b4084057577fc371510864378354ddRob Landley if (tcount<=1) goto free_tk0_continue; 753415c960b22b4084057577fc371510864378354ddRob Landley for (count = 0; count < size; count++) { 754415c960b22b4084057577fc371510864378354ddRob Landley if (!strcmp(confkey[count].keyword,tokens[0])) { 755415c960b22b4084057577fc371510864378354ddRob Landley dbg("got config : %15s : ", confkey[count].keyword); 756415c960b22b4084057577fc371510864378354ddRob Landley if (confkey[count].handler(tokens[1], confkey[count].var) == 0) 757415c960b22b4084057577fc371510864378354ddRob Landley dbg("%s \n", tokens[1]); 758415c960b22b4084057577fc371510864378354ddRob Landley break; 759415c960b22b4084057577fc371510864378354ddRob Landley } 760415c960b22b4084057577fc371510864378354ddRob Landley } 761415c960b22b4084057577fc371510864378354ddRob Landley if (tokens[1]) { free(tokens[1]); tokens[1] = NULL; } 762415c960b22b4084057577fc371510864378354ddRob Landleyfree_tk0_continue: 763415c960b22b4084057577fc371510864378354ddRob Landley if (tokens[0]) { free(tokens[0]); tokens[0] = NULL; } 764415c960b22b4084057577fc371510864378354ddRob Landleyfree_conf_continue: 765415c960b22b4084057577fc371510864378354ddRob Landley free(confline_temp); 766415c960b22b4084057577fc371510864378354ddRob Landley confline_temp = NULL; 767415c960b22b4084057577fc371510864378354ddRob Landley } 768415c960b22b4084057577fc371510864378354ddRob Landley if (fs) fclose(fs); 769415c960b22b4084057577fc371510864378354ddRob Landley return 0; 770415c960b22b4084057577fc371510864378354ddRob Landley} 771415c960b22b4084057577fc371510864378354ddRob Landley 77260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh// opens UDP socket for listen ipv6 packets 77360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic int open_listensock6(void) 77460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 77560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct sockaddr_in6 addr6; 77660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct ipv6_mreq mreq; 77760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 77860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gstate.listensock > 0) close(gstate.listensock); 77960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 78060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface); 78160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 78260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.listensock = xsocket(PF_INET6, SOCK_DGRAM, 0); 78360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone)); 784c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_CHECKSUM, &constone, sizeof(constone)); 78560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 78660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &constone, 78760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh sizeof(constone)) == -1) { 78860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh error_msg("failed to receive ipv6 packets.\n"); 78960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(gstate.listensock); 79060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -1; 79160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 79260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 79360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, gconfig.interface, strlen(gconfig.interface)+1); 79460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 79560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(&addr6, 0, sizeof(addr6)); 79660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh addr6.sin6_family = AF_INET6; 797c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh addr6.sin6_port = htons(gconfig.port); //SERVER_PORT 79860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh addr6.sin6_scope_id = if_nametoindex(gconfig.interface); 79960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Listening for multicast packet 80060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh inet_pton(AF_INET6, "ff02::1:2", &addr6.sin6_addr); 80160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 80260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (bind(gstate.listensock, (struct sockaddr *) &addr6, sizeof(addr6)) == -1) { 80360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(gstate.listensock); 80460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh perror_exit("bind failed"); 80560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 80660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 80760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(&mreq, 0, sizeof(mreq)); 80860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh mreq.ipv6mr_interface = if_nametoindex(gconfig.interface); 80960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&mreq.ipv6mr_multiaddr, &addr6.sin6_addr, sizeof(addr6.sin6_addr)); 81060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 81160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) { 81260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh error_msg("failed to join a multicast group.\n"); 81360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(gstate.listensock); 81460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -1; 81560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 81660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 81760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("OPEN : success\n"); 81860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return 0; 81960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 82060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 821415c960b22b4084057577fc371510864378354ddRob Landley// opens UDP socket for listen 822415c960b22b4084057577fc371510864378354ddRob Landleystatic int open_listensock(void) 823415c960b22b4084057577fc371510864378354ddRob Landley{ 824415c960b22b4084057577fc371510864378354ddRob Landley struct sockaddr_in addr; 825415c960b22b4084057577fc371510864378354ddRob Landley struct ifreq ifr; 826415c960b22b4084057577fc371510864378354ddRob Landley 827415c960b22b4084057577fc371510864378354ddRob Landley if (gstate.listensock > 0) close(gstate.listensock); 828415c960b22b4084057577fc371510864378354ddRob Landley 829415c960b22b4084057577fc371510864378354ddRob Landley dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface); 830415c960b22b4084057577fc371510864378354ddRob Landley gstate.listensock = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 831415c960b22b4084057577fc371510864378354ddRob Landley setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone)); 832415c960b22b4084057577fc371510864378354ddRob Landley if (setsockopt(gstate.listensock, SOL_SOCKET, SO_BROADCAST, &constone, sizeof(constone)) == -1) { 83360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh error_msg("failed to receive brodcast packets.\n"); 83460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(gstate.listensock); 83560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -1; 836415c960b22b4084057577fc371510864378354ddRob Landley } 837415c960b22b4084057577fc371510864378354ddRob Landley memset(&ifr, 0, sizeof(ifr)); 83882effc97f9f2d1c258ea50cb11b130753b8ba805Rob Landley xstrncpy(ifr.ifr_name, gconfig.interface, IFNAMSIZ); 839415c960b22b4084057577fc371510864378354ddRob Landley setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)); 840415c960b22b4084057577fc371510864378354ddRob Landley 841415c960b22b4084057577fc371510864378354ddRob Landley memset(&addr, 0, sizeof(addr)); 842415c960b22b4084057577fc371510864378354ddRob Landley addr.sin_family = AF_INET; 843c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh addr.sin_port = htons(gconfig.port); //SERVER_PORT 844415c960b22b4084057577fc371510864378354ddRob Landley addr.sin_addr.s_addr = INADDR_ANY ; 845415c960b22b4084057577fc371510864378354ddRob Landley 846415c960b22b4084057577fc371510864378354ddRob Landley if (bind(gstate.listensock, (struct sockaddr *) &addr, sizeof(addr))) { 847415c960b22b4084057577fc371510864378354ddRob Landley close(gstate.listensock); 848415c960b22b4084057577fc371510864378354ddRob Landley perror_exit("bind failed"); 849415c960b22b4084057577fc371510864378354ddRob Landley } 850415c960b22b4084057577fc371510864378354ddRob Landley dbg("OPEN : success\n"); 851415c960b22b4084057577fc371510864378354ddRob Landley return 0; 852415c960b22b4084057577fc371510864378354ddRob Landley} 853415c960b22b4084057577fc371510864378354ddRob Landley 85460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic int send_packet6(uint8_t relay, uint8_t *client_lla, uint16_t optlen) 85560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 85660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct sockaddr_ll dest_sll; 85760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dhcp6_raw_t packet; 85860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh unsigned padding; 85960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int fd, result = -1; 86060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 86160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(&packet, 0, sizeof(dhcp6_raw_t)); 86260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&packet.dhcp6, &gstate.send.send_pkt6, sizeof(dhcp6_msg_t)); 86360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh padding = sizeof(packet.dhcp6.options) - optlen; 86460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 86560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6))) < 0) { 86660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("SEND : ipv6 socket failed\n"); 86760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -1; 86860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 86960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(&dest_sll, 0, sizeof(dest_sll)); 87060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dest_sll.sll_family = AF_PACKET; 87160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dest_sll.sll_protocol = htons(ETH_P_IPV6); 87260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dest_sll.sll_ifindex = gconfig.ifindex; 87360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dest_sll.sll_halen = ETH_ALEN; 874c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(dest_sll.sll_addr, client_lla, sizeof(uint8_t)*6); 87560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 87660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) { 87760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("SEND : bind failed\n"); 87860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(fd); 87960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -1; 88060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 88160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&packet.iph.ip6_src, &gconfig.server_nip6, sizeof(uint32_t)*4); 882c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(&packet.iph.ip6_dst, &gstate.client_nip6, sizeof(uint32_t)*4); 883c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh 884c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh packet.udph.source = htons(gconfig.port); //SERVER_PORT 885c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh packet.udph.dest = gstate.client_port; //CLIENT_PORT 88660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh packet.udph.len = htons(sizeof(dhcp6_raw_t) - sizeof(struct ip6_hdr) - padding); 88760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(ntohs(packet.udph.len) + 0x11); 88860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp6_raw_t) - padding); 88960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh packet.iph.ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000); 89060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = packet.udph.len; 89160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh packet.iph.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP; 89260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh packet.iph.ip6_ctlun.ip6_un1.ip6_un1_hlim = 0x64; 89360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 89460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh result = sendto(fd, &packet, sizeof(dhcp6_raw_t)-padding, 89560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 0, (struct sockaddr *) &dest_sll, sizeof(dest_sll)); 89660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 89760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("sendto %d\n", result); 89860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(fd); 89960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (result < 0) dbg("PACKET send error\n"); 90060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return result; 90160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 90260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 903415c960b22b4084057577fc371510864378354ddRob Landley// Sends data through raw socket. 904415c960b22b4084057577fc371510864378354ddRob Landleystatic int send_packet(uint8_t broadcast) 905415c960b22b4084057577fc371510864378354ddRob Landley{ 906415c960b22b4084057577fc371510864378354ddRob Landley struct sockaddr_ll dest_sll; 907415c960b22b4084057577fc371510864378354ddRob Landley dhcp_raw_t packet; 908415c960b22b4084057577fc371510864378354ddRob Landley unsigned padding; 909415c960b22b4084057577fc371510864378354ddRob Landley int fd, result = -1; 910415c960b22b4084057577fc371510864378354ddRob Landley uint8_t bmacaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 911415c960b22b4084057577fc371510864378354ddRob Landley 912415c960b22b4084057577fc371510864378354ddRob Landley memset(&packet, 0, sizeof(dhcp_raw_t)); 91360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&packet.dhcp, &gstate.send.send_pkt, sizeof(dhcp_msg_t)); 914415c960b22b4084057577fc371510864378354ddRob Landley 915415c960b22b4084057577fc371510864378354ddRob Landley if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) { 916415c960b22b4084057577fc371510864378354ddRob Landley dbg("SEND : socket failed\n"); 917415c960b22b4084057577fc371510864378354ddRob Landley return -1; 918415c960b22b4084057577fc371510864378354ddRob Landley } 919415c960b22b4084057577fc371510864378354ddRob Landley memset(&dest_sll, 0, sizeof(dest_sll)); 920415c960b22b4084057577fc371510864378354ddRob Landley dest_sll.sll_family = AF_PACKET; 921415c960b22b4084057577fc371510864378354ddRob Landley dest_sll.sll_protocol = htons(ETH_P_IP); 922415c960b22b4084057577fc371510864378354ddRob Landley dest_sll.sll_ifindex = gconfig.ifindex; 923415c960b22b4084057577fc371510864378354ddRob Landley dest_sll.sll_halen = 6; 92460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(dest_sll.sll_addr, (broadcast)?bmacaddr:gstate.rcvd.rcvd_pkt.chaddr , 6); 925415c960b22b4084057577fc371510864378354ddRob Landley 926415c960b22b4084057577fc371510864378354ddRob Landley if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) { 927415c960b22b4084057577fc371510864378354ddRob Landley dbg("SEND : bind failed\n"); 928415c960b22b4084057577fc371510864378354ddRob Landley close(fd); 929415c960b22b4084057577fc371510864378354ddRob Landley return -1; 930415c960b22b4084057577fc371510864378354ddRob Landley } 93160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh padding = 308 - 1 - dhcp_opt_size(gstate.send.send_pkt.options); 932415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.protocol = IPPROTO_UDP; 933415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.saddr = gconfig.server_nip; 934c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh packet.iph.daddr = (broadcast || (gstate.rcvd.rcvd_pkt.ciaddr == 0))? 935c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh INADDR_BROADCAST : gstate.rcvd.rcvd_pkt.ciaddr; 936c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh packet.udph.source = htons(gconfig.port);//SERVER_PORT 937c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh packet.udph.dest = gstate.client_port; //CLIENT_PORT 938415c960b22b4084057577fc371510864378354ddRob Landley packet.udph.len = htons(sizeof(dhcp_raw_t) - sizeof(struct iphdr) - padding); 939415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.tot_len = packet.udph.len; 940415c960b22b4084057577fc371510864378354ddRob Landley packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp_raw_t) - padding); 941415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.tot_len = htons(sizeof(dhcp_raw_t) - padding); 942415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.ihl = sizeof(packet.iph) >> 2; 943415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.version = IPVERSION; 944415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.ttl = IPDEFTTL; 945415c960b22b4084057577fc371510864378354ddRob Landley packet.iph.check = dhcp_checksum(&packet.iph, sizeof(packet.iph)); 946415c960b22b4084057577fc371510864378354ddRob Landley 947415c960b22b4084057577fc371510864378354ddRob Landley result = sendto(fd, &packet, sizeof(dhcp_raw_t) - padding, 0, 948415c960b22b4084057577fc371510864378354ddRob Landley (struct sockaddr *) &dest_sll, sizeof(dest_sll)); 949415c960b22b4084057577fc371510864378354ddRob Landley 950415c960b22b4084057577fc371510864378354ddRob Landley dbg("sendto %d\n", result); 951415c960b22b4084057577fc371510864378354ddRob Landley close(fd); 952415c960b22b4084057577fc371510864378354ddRob Landley if (result < 0) dbg("PACKET send error\n"); 953415c960b22b4084057577fc371510864378354ddRob Landley return result; 954415c960b22b4084057577fc371510864378354ddRob Landley} 955415c960b22b4084057577fc371510864378354ddRob Landley 95660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic int read_packet6(void) 95760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 95860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int ret; 959c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh struct sockaddr_in6 c_addr; 960c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh socklen_t c_addr_size = sizeof(c_addr); 96160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 96260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(&gstate.rcvd.rcvd_pkt6, 0, sizeof(dhcp6_msg_t)); 963c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh ret = recvfrom(gstate.listensock, &gstate.rcvd.rcvd_pkt6, sizeof(dhcp6_msg_t), 964c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh 0, (struct sockaddr*) &c_addr, &c_addr_size); 965c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(gstate.client_nip6, &c_addr.sin6_addr, sizeof(uint32_t)*4); 966c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(&gstate.client_port, &c_addr.sin6_port, sizeof(uint32_t)); 96760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (ret < 0) { 96860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Packet read error, ignoring. \n"); 96960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return ret; // returns -1 97060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 97160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gstate.rcvd.rcvd_pkt6.msgtype < 1) { 97260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Bad message type, igroning. \n"); 97360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -2; 97460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 97560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 97660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Received an ipv6 packet. Size : %d \n", ret); 97760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return ret; 97860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 97960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 980415c960b22b4084057577fc371510864378354ddRob Landley// Reads from UDP socket 981415c960b22b4084057577fc371510864378354ddRob Landleystatic int read_packet(void) 982415c960b22b4084057577fc371510864378354ddRob Landley{ 983415c960b22b4084057577fc371510864378354ddRob Landley int ret; 984c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh struct sockaddr_in c_addr; 985c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh socklen_t c_addr_size = sizeof(c_addr); 986415c960b22b4084057577fc371510864378354ddRob Landley 98760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(&gstate.rcvd.rcvd_pkt, 0, sizeof(dhcp_msg_t)); 988c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh ret = recvfrom(gstate.listensock, &gstate.rcvd.rcvd_pkt, sizeof(dhcp_msg_t), 989c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh 0, (struct sockaddr*) &c_addr, &c_addr_size); 990c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(&gstate.client_port, &c_addr.sin_port, sizeof(uint32_t)); 991c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh /*ret = read(gstate.listensock, &gstate.rcvd.rcvd_pkt, sizeof(dhcp_msg_t));*/ 992415c960b22b4084057577fc371510864378354ddRob Landley if (ret < 0) { 993415c960b22b4084057577fc371510864378354ddRob Landley dbg("Packet read error, ignoring. \n"); 994415c960b22b4084057577fc371510864378354ddRob Landley return ret; // returns -1 995415c960b22b4084057577fc371510864378354ddRob Landley } 99660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gstate.rcvd.rcvd_pkt.cookie != htonl(DHCP_MAGIC)) { 997415c960b22b4084057577fc371510864378354ddRob Landley dbg("Packet with bad magic, ignoring. \n"); 998415c960b22b4084057577fc371510864378354ddRob Landley return -2; 999415c960b22b4084057577fc371510864378354ddRob Landley } 100060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gstate.rcvd.rcvd_pkt.op != 1) { //BOOTPREQUEST 1001415c960b22b4084057577fc371510864378354ddRob Landley dbg("Not a BOOT REQUEST ignoring. \n"); 1002415c960b22b4084057577fc371510864378354ddRob Landley return -2; 1003415c960b22b4084057577fc371510864378354ddRob Landley } 100460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gstate.rcvd.rcvd_pkt.hlen != 6) { 1005415c960b22b4084057577fc371510864378354ddRob Landley dbg("hlen != 6 ignoring. \n"); 1006415c960b22b4084057577fc371510864378354ddRob Landley return -2; 1007415c960b22b4084057577fc371510864378354ddRob Landley } 1008415c960b22b4084057577fc371510864378354ddRob Landley dbg("Received a packet. Size : %d \n", ret); 1009415c960b22b4084057577fc371510864378354ddRob Landley return ret; 1010415c960b22b4084057577fc371510864378354ddRob Landley} 1011415c960b22b4084057577fc371510864378354ddRob Landley 1012415c960b22b4084057577fc371510864378354ddRob Landley// Preapres a dhcp packet with defaults and configs 1013415c960b22b4084057577fc371510864378354ddRob Landleystatic uint8_t* prepare_send_pkt(void) 1014415c960b22b4084057577fc371510864378354ddRob Landley{ 101560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset((void*)&gstate.send.send_pkt, 0, sizeof(gstate.send.send_pkt)); 101660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.op = 2; //BOOTPREPLY 101760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.htype = 1; 101860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.hlen = 6; 101960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.xid = gstate.rcvd.rcvd_pkt.xid; 102060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.cookie = htonl(DHCP_MAGIC); 102160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.nsiaddr = gconfig.server_nip; 102260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(gstate.send.send_pkt.chaddr, gstate.rcvd.rcvd_pkt.chaddr, 16); 102360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.options[0] = DHCP_OPT_END; 102460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return gstate.send.send_pkt.options; 102560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 102660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 102760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic uint8_t* prepare_send_pkt6(uint16_t opt) 102860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 102960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset((void*)&gstate.send.send_pkt6, 0, sizeof(gstate.send.send_pkt6)); 103060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt6.msgtype = opt; 103160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(gstate.send.send_pkt6.transaction_id, gstate.rcvd.rcvd_pkt6.transaction_id, 3); 103260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return gstate.send.send_pkt6.options; 1033415c960b22b4084057577fc371510864378354ddRob Landley} 1034415c960b22b4084057577fc371510864378354ddRob Landley 1035415c960b22b4084057577fc371510864378354ddRob Landley// Sets a option value in dhcp packet's option field 1036415c960b22b4084057577fc371510864378354ddRob Landleystatic uint8_t* set_optval(uint8_t *optptr, uint16_t opt, void *var, size_t len) 1037415c960b22b4084057577fc371510864378354ddRob Landley{ 1038415c960b22b4084057577fc371510864378354ddRob Landley while (*optptr != DHCP_OPT_END) optptr++; 1039415c960b22b4084057577fc371510864378354ddRob Landley *optptr++ = (uint8_t)(opt & 0x00FF); 1040415c960b22b4084057577fc371510864378354ddRob Landley *optptr++ = (uint8_t) len; 1041415c960b22b4084057577fc371510864378354ddRob Landley memcpy(optptr, var, len); 1042415c960b22b4084057577fc371510864378354ddRob Landley optptr += len; 1043415c960b22b4084057577fc371510864378354ddRob Landley *optptr = DHCP_OPT_END; 1044415c960b22b4084057577fc371510864378354ddRob Landley return optptr; 1045415c960b22b4084057577fc371510864378354ddRob Landley} 1046415c960b22b4084057577fc371510864378354ddRob Landley 104760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic uint8_t* set_optval6(uint8_t *optptr, uint16_t opt, void *var, size_t len) 104860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 104960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh *((uint16_t*)optptr) = htons(opt); 105060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh *(uint16_t*)(optptr+2) = htons(len); 105160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(optptr+4, var, len); 105260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr += len+4; 105360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return optptr; 105460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 105560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1056415c960b22b4084057577fc371510864378354ddRob Landley// Gets a option value from dhcp packet's option field 1057415c960b22b4084057577fc371510864378354ddRob Landleystatic uint8_t* get_optval(uint8_t *optptr, uint16_t opt, void *var) 1058415c960b22b4084057577fc371510864378354ddRob Landley{ 1059415c960b22b4084057577fc371510864378354ddRob Landley size_t len; 1060415c960b22b4084057577fc371510864378354ddRob Landley uint8_t overloaded = 0; 1061415c960b22b4084057577fc371510864378354ddRob Landley 1062415c960b22b4084057577fc371510864378354ddRob Landley while (1) { 1063415c960b22b4084057577fc371510864378354ddRob Landley while (*optptr == DHCP_OPT_PADDING) optptr++; 1064415c960b22b4084057577fc371510864378354ddRob Landley if ((*optptr & 0x00FF) == DHCP_OPT_END) break; 1065415c960b22b4084057577fc371510864378354ddRob Landley if ((*optptr & 0x00FF) == DHCP_OPT_OPTION_OVERLOAD) { 1066415c960b22b4084057577fc371510864378354ddRob Landley overloaded = optptr[2]; 1067415c960b22b4084057577fc371510864378354ddRob Landley optptr += optptr[1] + 2; 1068415c960b22b4084057577fc371510864378354ddRob Landley } 1069415c960b22b4084057577fc371510864378354ddRob Landley len = optptr[1]; 1070415c960b22b4084057577fc371510864378354ddRob Landley if (*optptr == (opt & 0x00FF)) 1071415c960b22b4084057577fc371510864378354ddRob Landley switch (opt & 0xFF00) { 1072415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_NUM32: // FALLTHROUGH 1073415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_IP: 1074415c960b22b4084057577fc371510864378354ddRob Landley memcpy(var, optptr+2, sizeof(uint32_t)); 1075415c960b22b4084057577fc371510864378354ddRob Landley optptr += len + 2; 1076415c960b22b4084057577fc371510864378354ddRob Landley return optptr; 1077415c960b22b4084057577fc371510864378354ddRob Landley break; 1078415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_NUM16: 1079415c960b22b4084057577fc371510864378354ddRob Landley memcpy(var, optptr+2, sizeof(uint16_t)); 1080415c960b22b4084057577fc371510864378354ddRob Landley optptr += len + 2; 1081415c960b22b4084057577fc371510864378354ddRob Landley return optptr; 1082415c960b22b4084057577fc371510864378354ddRob Landley break; 1083415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_NUM8: 1084415c960b22b4084057577fc371510864378354ddRob Landley memcpy(var, optptr+2, sizeof(uint8_t)); 1085415c960b22b4084057577fc371510864378354ddRob Landley optptr += len + 2; 1086415c960b22b4084057577fc371510864378354ddRob Landley return optptr; 1087415c960b22b4084057577fc371510864378354ddRob Landley break; 1088415c960b22b4084057577fc371510864378354ddRob Landley case DHCP_STRING: 1089415c960b22b4084057577fc371510864378354ddRob Landley var = xstrndup((char*) optptr, len); 1090415c960b22b4084057577fc371510864378354ddRob Landley optptr += len + 2; 1091415c960b22b4084057577fc371510864378354ddRob Landley return optptr; 1092415c960b22b4084057577fc371510864378354ddRob Landley break; 1093415c960b22b4084057577fc371510864378354ddRob Landley } 1094415c960b22b4084057577fc371510864378354ddRob Landley optptr += len + 2; 1095415c960b22b4084057577fc371510864378354ddRob Landley } 109660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((overloaded == 1) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.file, opt, var); 109760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((overloaded == 2) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.sname, opt, var); 109860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return optptr; 109960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 110060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 110160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic uint8_t* get_optval6(uint8_t *optptr, uint16_t opt, uint16_t *datalen, void **var) 110260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 110360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t optcode; 110460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t len; 110560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 110660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&optcode, optptr, sizeof(uint16_t)); 110760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&len, optptr+2, sizeof(uint16_t)); 110860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(!optcode) { 110960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Option %d is not exist.\n", opt); 111060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return optptr; 111160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 111260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optcode = ntohs(optcode); 111360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh len = ntohs(len); 111460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 111560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (opt == optcode) { 111660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh *var = xmalloc(len); 111760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(*var, optptr+4, len); 111860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = optptr + len + 4; 111960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(datalen, &len, sizeof(uint16_t)); 112060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 112160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh else { 112260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = get_optval6(optptr+len+4, opt, datalen, var); 112360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 112460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1125415c960b22b4084057577fc371510864378354ddRob Landley return optptr; 1126415c960b22b4084057577fc371510864378354ddRob Landley} 1127415c960b22b4084057577fc371510864378354ddRob Landley 1128415c960b22b4084057577fc371510864378354ddRob Landley// Retrives Requested Parameter list from dhcp req packet. 1129415c960b22b4084057577fc371510864378354ddRob Landleystatic uint8_t get_reqparam(uint8_t **list) 1130415c960b22b4084057577fc371510864378354ddRob Landley{ 1131415c960b22b4084057577fc371510864378354ddRob Landley uint8_t len, *optptr; 1132415c960b22b4084057577fc371510864378354ddRob Landley if(*list) free(*list); 113360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh for (optptr = gstate.rcvd.rcvd_pkt.options; 1134415c960b22b4084057577fc371510864378354ddRob Landley *optptr && *optptr!=((DHCP_OPT_PARAM_REQ) & 0x00FF); optptr+=optptr[1]+2); 1135415c960b22b4084057577fc371510864378354ddRob Landley len = *++optptr; 1136415c960b22b4084057577fc371510864378354ddRob Landley *list = xzalloc(len+1); 1137415c960b22b4084057577fc371510864378354ddRob Landley memcpy(*list, ++optptr, len); 1138415c960b22b4084057577fc371510864378354ddRob Landley return len; 1139415c960b22b4084057577fc371510864378354ddRob Landley} 1140415c960b22b4084057577fc371510864378354ddRob Landley 1141415c960b22b4084057577fc371510864378354ddRob Landley// Sets values of req param in dhcp offer packet. 1142415c960b22b4084057577fc371510864378354ddRob Landleystatic uint8_t* set_reqparam(uint8_t *optptr, uint8_t *list) 1143415c960b22b4084057577fc371510864378354ddRob Landley{ 1144415c960b22b4084057577fc371510864378354ddRob Landley uint8_t reqcode; 1145415c960b22b4084057577fc371510864378354ddRob Landley int count, size = ARRAY_LEN(options_list); 1146415c960b22b4084057577fc371510864378354ddRob Landley 1147415c960b22b4084057577fc371510864378354ddRob Landley while (*list) { 1148415c960b22b4084057577fc371510864378354ddRob Landley reqcode = *list++; 1149415c960b22b4084057577fc371510864378354ddRob Landley for (count = 0; count < size; count++) { 1150415c960b22b4084057577fc371510864378354ddRob Landley if ((options_list[count].code & 0X00FF)==reqcode) { 1151415c960b22b4084057577fc371510864378354ddRob Landley if (!(options_list[count].len) || !(options_list[count].val)) break; 1152415c960b22b4084057577fc371510864378354ddRob Landley for (; *optptr && *optptr!=DHCP_OPT_END; optptr+=optptr[1]+2); 1153415c960b22b4084057577fc371510864378354ddRob Landley *optptr++ = (uint8_t) (options_list[count].code & 0x00FF); 1154415c960b22b4084057577fc371510864378354ddRob Landley *optptr++ = (uint8_t) options_list[count].len; 1155415c960b22b4084057577fc371510864378354ddRob Landley memcpy(optptr, options_list[count].val, options_list[count].len); 1156415c960b22b4084057577fc371510864378354ddRob Landley optptr += options_list[count].len; 1157415c960b22b4084057577fc371510864378354ddRob Landley *optptr = DHCP_OPT_END; 1158415c960b22b4084057577fc371510864378354ddRob Landley break; 1159415c960b22b4084057577fc371510864378354ddRob Landley } 1160415c960b22b4084057577fc371510864378354ddRob Landley } 1161415c960b22b4084057577fc371510864378354ddRob Landley } 1162415c960b22b4084057577fc371510864378354ddRob Landley return optptr; 1163415c960b22b4084057577fc371510864378354ddRob Landley} 1164415c960b22b4084057577fc371510864378354ddRob Landley 1165415c960b22b4084057577fc371510864378354ddRob Landleystatic void run_notify(char **argv) 1166415c960b22b4084057577fc371510864378354ddRob Landley{ 1167415c960b22b4084057577fc371510864378354ddRob Landley struct stat sts; 1168415c960b22b4084057577fc371510864378354ddRob Landley volatile int error = 0; 1169415c960b22b4084057577fc371510864378354ddRob Landley pid_t pid; 1170415c960b22b4084057577fc371510864378354ddRob Landley 1171415c960b22b4084057577fc371510864378354ddRob Landley if (stat(argv[0], &sts) == -1 && errno == ENOENT) { 1172415c960b22b4084057577fc371510864378354ddRob Landley infomsg(infomode, "notify file: %s : not exist.", argv[0]); 1173415c960b22b4084057577fc371510864378354ddRob Landley return; 1174415c960b22b4084057577fc371510864378354ddRob Landley } 1175415c960b22b4084057577fc371510864378354ddRob Landley fflush(NULL); 1176415c960b22b4084057577fc371510864378354ddRob Landley 1177415c960b22b4084057577fc371510864378354ddRob Landley pid = vfork(); 1178415c960b22b4084057577fc371510864378354ddRob Landley if (pid < 0) { 1179415c960b22b4084057577fc371510864378354ddRob Landley dbg("Fork failed.\n"); 1180415c960b22b4084057577fc371510864378354ddRob Landley return; 1181415c960b22b4084057577fc371510864378354ddRob Landley } 1182415c960b22b4084057577fc371510864378354ddRob Landley if (!pid) { 1183415c960b22b4084057577fc371510864378354ddRob Landley execvp(argv[0], argv); 1184415c960b22b4084057577fc371510864378354ddRob Landley error = errno; 1185415c960b22b4084057577fc371510864378354ddRob Landley _exit(111); 1186415c960b22b4084057577fc371510864378354ddRob Landley } 1187415c960b22b4084057577fc371510864378354ddRob Landley if (error) { 1188415c960b22b4084057577fc371510864378354ddRob Landley waitpid(pid, NULL, 0); 1189415c960b22b4084057577fc371510864378354ddRob Landley errno = error; 1190415c960b22b4084057577fc371510864378354ddRob Landley } 1191415c960b22b4084057577fc371510864378354ddRob Landley dbg("script complete.\n"); 1192415c960b22b4084057577fc371510864378354ddRob Landley} 1193415c960b22b4084057577fc371510864378354ddRob Landley 119460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic void write_leasefile(void) 1195415c960b22b4084057577fc371510864378354ddRob Landley{ 1196415c960b22b4084057577fc371510864378354ddRob Landley int fd; 1197415c960b22b4084057577fc371510864378354ddRob Landley uint32_t curr, tmp_time; 1198415c960b22b4084057577fc371510864378354ddRob Landley int64_t timestamp; 1199415c960b22b4084057577fc371510864378354ddRob Landley struct arg_list *listdls = gstate.dleases; 1200415c960b22b4084057577fc371510864378354ddRob Landley dyn_lease *dls; 1201415c960b22b4084057577fc371510864378354ddRob Landley 1202aebcdfa659679e5a1f92a9ad12e7c36621962988Rob Landley if ((fd = open(gconfig.lease_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { 1203415c960b22b4084057577fc371510864378354ddRob Landley perror_msg("can't open %s ", gconfig.lease_file); 120460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 120560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh curr = timestamp = time(NULL); 120660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh timestamp = SWAP_BE64(timestamp); 120760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh writeall(fd, ×tamp, sizeof(timestamp)); 120860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 120960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while (listdls) { 121060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls = (dyn_lease*)listdls->arg; 121160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh tmp_time = dls->expires; 121260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls->expires -= curr; 121360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((int32_t) dls->expires < 0) goto skip; 121460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls->expires = htonl(dls->expires); 121560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh writeall(fd, dls, sizeof(dyn_lease)); 121660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhskip: 121760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls->expires = tmp_time; 121860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh listdls = listdls->next; 121960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 122060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(fd); 122160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gconfig.notify_file) { 122260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *argv[3]; 122360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh argv[0] = gconfig.notify_file; 122460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh argv[1] = gconfig.lease_file; 122560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh argv[2] = NULL; 122660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh run_notify(argv); 122760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 1228415c960b22b4084057577fc371510864378354ddRob Landley } 122960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 1230415c960b22b4084057577fc371510864378354ddRob Landley 123160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic void write_lease6file(void) 123260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 123360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int fd; 123460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t curr, tmp_time; 123560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int64_t timestamp; 123660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct arg_list *listdls = gstate.dleases; 123760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dyn_lease6 *dls6; 1238415c960b22b4084057577fc371510864378354ddRob Landley 123960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((fd = open(gconfig.lease6_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { 124060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh perror_msg("can't open %s ", gconfig.lease6_file); 124160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 124260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh curr = timestamp = time(NULL); 124360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh timestamp = SWAP_BE64(timestamp); 124460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh writeall(fd, ×tamp, sizeof(timestamp)); 124560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 124660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while (listdls) { 124760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6 = (dyn_lease6*)listdls->arg; 124860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh tmp_time = dls6->expires; 124960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6->expires -= curr; 125060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((int32_t) dls6->expires < 0) goto skip; 125160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6->expires = htonl(dls6->expires); 125260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh writeall(fd, dls6, sizeof(dyn_lease6)); 1253415c960b22b4084057577fc371510864378354ddRob Landleyskip: 125460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6->expires = tmp_time; 125560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh listdls = listdls->next; 125660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 125760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(fd); 125860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gconfig.notify_file) { 125960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *argv[3]; 126060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh argv[0] = gconfig.notify_file; 126160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh argv[1] = gconfig.lease6_file; 126260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh argv[2] = NULL; 126360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh run_notify(argv); 126460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 1265415c960b22b4084057577fc371510864378354ddRob Landley } 1266415c960b22b4084057577fc371510864378354ddRob Landley} 1267415c960b22b4084057577fc371510864378354ddRob Landley 1268415c960b22b4084057577fc371510864378354ddRob Landley// Update max lease time from options. 1269415c960b22b4084057577fc371510864378354ddRob Landleystatic void set_maxlease(void) 1270415c960b22b4084057577fc371510864378354ddRob Landley{ 1271415c960b22b4084057577fc371510864378354ddRob Landley int count, size = ARRAY_LEN(options_list); 1272415c960b22b4084057577fc371510864378354ddRob Landley for (count = 0; count < size; count++) 1273415c960b22b4084057577fc371510864378354ddRob Landley if (options_list[count].val && options_list[count].code == (DHCP_OPT_LEASE_TIME)) { 1274415c960b22b4084057577fc371510864378354ddRob Landley gconfig.max_lease_sec = *((uint32_t*)options_list[count].val); 1275415c960b22b4084057577fc371510864378354ddRob Landley break; 1276415c960b22b4084057577fc371510864378354ddRob Landley } 1277415c960b22b4084057577fc371510864378354ddRob Landley if (!gconfig.max_lease_sec) gconfig.max_lease_sec = (60*60*24*10);// DEFAULT_LEASE_TIME; 1278415c960b22b4084057577fc371510864378354ddRob Landley} 1279415c960b22b4084057577fc371510864378354ddRob Landley 1280415c960b22b4084057577fc371510864378354ddRob Landley// Returns lease time for client. 1281415c960b22b4084057577fc371510864378354ddRob Landleystatic uint32_t get_lease(uint32_t req_exp) 1282415c960b22b4084057577fc371510864378354ddRob Landley{ 1283415c960b22b4084057577fc371510864378354ddRob Landley uint32_t now = time(NULL); 1284415c960b22b4084057577fc371510864378354ddRob Landley req_exp = req_exp - now; 128560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(addr_version == AF_INET6) { 128660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((req_exp <= 0) || req_exp > gconfig.pref_lifetime || 128760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh req_exp > gconfig.valid_lifetime) { 128860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((gconfig.pref_lifetime > gconfig.valid_lifetime)) { 128960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh error_msg("The valid lifetime must be greater than the preferred lifetime, \ 129060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh setting to valid lifetime", gconfig.valid_lifetime); 129160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return gconfig.valid_lifetime; 129260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 129360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return gconfig.pref_lifetime; 129460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 129560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 129660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((req_exp <= 0) || (req_exp > gconfig.max_lease_sec)) 129760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return gconfig.max_lease_sec; 1298415c960b22b4084057577fc371510864378354ddRob Landley 129960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (req_exp < gconfig.min_lease_sec) 130060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return gconfig.min_lease_sec; 130160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 1302415c960b22b4084057577fc371510864378354ddRob Landley 1303415c960b22b4084057577fc371510864378354ddRob Landley return req_exp; 1304415c960b22b4084057577fc371510864378354ddRob Landley} 1305415c960b22b4084057577fc371510864378354ddRob Landley 1306c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suhstatic int verifyip6_in_lease(uint8_t *nip6, uint8_t *duid, uint16_t ia_type, uint32_t iaid) 130760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 130860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh static_lease6 *sls6; 130960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct arg_list *listdls; 131060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 131160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh for (listdls = gstate.dleases; listdls; listdls = listdls->next) { 131260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!memcmp(((dyn_lease6*) listdls->arg)->lease_nip6, nip6, sizeof(uint32_t)*4)) 131360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -1; 131460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 131560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len) 131660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh && ((dyn_lease6*) listdls->arg)->ia_type == ia_type) 131760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -1; 131860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 131960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh for (sls6 = gstate.leases.sleases6; sls6; sls6 = sls6->next) 132060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (memcmp(sls6->nip6, nip6, sizeof(uint32_t)*4)==0) return -2; 132160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1322c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (memcmp(nip6, gconfig.start_ip6, sizeof(uint32_t)*4) < 0 || 1323c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcmp(nip6, gconfig.end_ip6, sizeof(uint32_t)*4) > 0) 132460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return -3; 132560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 132660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return 0; 132760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 132860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1329415c960b22b4084057577fc371510864378354ddRob Landley// Verify ip NIP in current leases ( assigned or not) 1330415c960b22b4084057577fc371510864378354ddRob Landleystatic int verifyip_in_lease(uint32_t nip, uint8_t mac[6]) 1331415c960b22b4084057577fc371510864378354ddRob Landley{ 1332415c960b22b4084057577fc371510864378354ddRob Landley static_lease *sls; 1333415c960b22b4084057577fc371510864378354ddRob Landley struct arg_list *listdls; 1334415c960b22b4084057577fc371510864378354ddRob Landley 1335415c960b22b4084057577fc371510864378354ddRob Landley for (listdls = gstate.dleases; listdls; listdls = listdls->next) { 1336415c960b22b4084057577fc371510864378354ddRob Landley if (((dyn_lease*) listdls->arg)->lease_nip == nip) { 1337415c960b22b4084057577fc371510864378354ddRob Landley if (((int32_t)(((dyn_lease*) listdls->arg)->expires) - time(NULL)) < 0) 1338415c960b22b4084057577fc371510864378354ddRob Landley return 0; 1339415c960b22b4084057577fc371510864378354ddRob Landley return -1; 1340415c960b22b4084057577fc371510864378354ddRob Landley } 1341415c960b22b4084057577fc371510864378354ddRob Landley if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) return -1; 1342415c960b22b4084057577fc371510864378354ddRob Landley } 134360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh for (sls = gstate.leases.sleases; sls; sls = sls->next) 1344415c960b22b4084057577fc371510864378354ddRob Landley if (sls->nip == nip) return -2; 1345415c960b22b4084057577fc371510864378354ddRob Landley 1346415c960b22b4084057577fc371510864378354ddRob Landley if ((ntohl(nip) < gconfig.start_ip) || (ntohl(nip) > gconfig.end_ip)) 1347415c960b22b4084057577fc371510864378354ddRob Landley return -3; 1348415c960b22b4084057577fc371510864378354ddRob Landley 1349415c960b22b4084057577fc371510864378354ddRob Landley return 0; 1350415c960b22b4084057577fc371510864378354ddRob Landley} 1351415c960b22b4084057577fc371510864378354ddRob Landley 1352415c960b22b4084057577fc371510864378354ddRob Landley// add ip assigned_nip to dynamic lease. 1353415c960b22b4084057577fc371510864378354ddRob Landleystatic int addip_to_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname, uint8_t update) 1354415c960b22b4084057577fc371510864378354ddRob Landley{ 1355415c960b22b4084057577fc371510864378354ddRob Landley dyn_lease *dls; 1356415c960b22b4084057577fc371510864378354ddRob Landley struct arg_list *listdls = gstate.dleases; 1357415c960b22b4084057577fc371510864378354ddRob Landley uint32_t now = time(NULL); 1358415c960b22b4084057577fc371510864378354ddRob Landley 1359415c960b22b4084057577fc371510864378354ddRob Landley while (listdls) { 1360415c960b22b4084057577fc371510864378354ddRob Landley if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) { 1361415c960b22b4084057577fc371510864378354ddRob Landley if (update) *req_exp = get_lease(*req_exp + ((dyn_lease*) listdls->arg)->expires); 1362415c960b22b4084057577fc371510864378354ddRob Landley ((dyn_lease*) listdls->arg)->expires = *req_exp + now; 1363415c960b22b4084057577fc371510864378354ddRob Landley return 0; 1364415c960b22b4084057577fc371510864378354ddRob Landley } 1365415c960b22b4084057577fc371510864378354ddRob Landley listdls = listdls->next; 1366415c960b22b4084057577fc371510864378354ddRob Landley } 1367415c960b22b4084057577fc371510864378354ddRob Landley 1368415c960b22b4084057577fc371510864378354ddRob Landley dls = xzalloc(sizeof(dyn_lease)); 1369415c960b22b4084057577fc371510864378354ddRob Landley memcpy(dls->lease_mac, mac, 6); 1370415c960b22b4084057577fc371510864378354ddRob Landley dls->lease_nip = assigned_nip; 1371415c960b22b4084057577fc371510864378354ddRob Landley if (hostname) memcpy(dls->hostname, hostname, 20); 1372415c960b22b4084057577fc371510864378354ddRob Landley 1373415c960b22b4084057577fc371510864378354ddRob Landley if (update) *req_exp = get_lease(*req_exp + now); 1374415c960b22b4084057577fc371510864378354ddRob Landley dls->expires = *req_exp + now; 1375415c960b22b4084057577fc371510864378354ddRob Landley 1376415c960b22b4084057577fc371510864378354ddRob Landley listdls = xzalloc(sizeof(struct arg_list)); 1377415c960b22b4084057577fc371510864378354ddRob Landley listdls->next = gstate.dleases; 1378415c960b22b4084057577fc371510864378354ddRob Landley listdls->arg = (char*)dls; 1379415c960b22b4084057577fc371510864378354ddRob Landley gstate.dleases = listdls; 1380415c960b22b4084057577fc371510864378354ddRob Landley 1381415c960b22b4084057577fc371510864378354ddRob Landley return 0; 1382415c960b22b4084057577fc371510864378354ddRob Landley} 1383415c960b22b4084057577fc371510864378354ddRob Landley 1384c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suhstatic int addip6_to_lease(uint8_t *assigned_nip, uint8_t *duid, uint16_t duid_len, uint16_t ia_type, uint32_t iaid, uint32_t *lifetime, uint8_t update) 138560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 138660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dyn_lease6 *dls6; 138760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct arg_list *listdls = gstate.dleases; 138860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t now = time(NULL); 138960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 139060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while (listdls) { 139160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len)) { 139260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (update) *lifetime = get_lease(*lifetime + ((dyn_lease6*) listdls->arg)->expires); 139360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ((dyn_lease6*) listdls->arg)->expires = *lifetime + now; 139460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return 0; 139560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 139660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh listdls = listdls->next; 139760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 139860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 139960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6 = xzalloc(sizeof(dyn_lease6)); 1400c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh dls6->duid_len = duid_len; 1401c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(dls6->duid, duid, duid_len); 140260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6->ia_type = ia_type; 140360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6->iaid = iaid; 140460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(dls6->lease_nip6, assigned_nip, sizeof(uint32_t)*4); 140560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 140660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (update) *lifetime = get_lease(*lifetime + now); 140760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6->expires = *lifetime + now; 140860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 140960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh listdls = xzalloc(sizeof(struct arg_list)); 141060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh listdls->next = gstate.dleases; 141160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh listdls->arg = (char*)dls6; 141260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.dleases = listdls; 141360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 141460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return 0; 141560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 141660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1417415c960b22b4084057577fc371510864378354ddRob Landley// delete ip assigned_nip from dynamic lease. 1418415c960b22b4084057577fc371510864378354ddRob Landleystatic int delip_from_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t del_time) 1419415c960b22b4084057577fc371510864378354ddRob Landley{ 1420415c960b22b4084057577fc371510864378354ddRob Landley struct arg_list *listdls = gstate.dleases; 1421415c960b22b4084057577fc371510864378354ddRob Landley 1422415c960b22b4084057577fc371510864378354ddRob Landley while (listdls) { 1423415c960b22b4084057577fc371510864378354ddRob Landley if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) { 1424415c960b22b4084057577fc371510864378354ddRob Landley ((dyn_lease*) listdls->arg)->expires = del_time + time(NULL); 1425415c960b22b4084057577fc371510864378354ddRob Landley return 0; 1426415c960b22b4084057577fc371510864378354ddRob Landley } 1427415c960b22b4084057577fc371510864378354ddRob Landley listdls = listdls->next; 1428415c960b22b4084057577fc371510864378354ddRob Landley } 1429415c960b22b4084057577fc371510864378354ddRob Landley return -1; 1430415c960b22b4084057577fc371510864378354ddRob Landley} 1431415c960b22b4084057577fc371510864378354ddRob Landley 1432415c960b22b4084057577fc371510864378354ddRob Landley// returns a IP from static, dynamic leases or free ip pool, 0 otherwise. 1433415c960b22b4084057577fc371510864378354ddRob Landleystatic uint32_t getip_from_pool(uint32_t req_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname) 1434415c960b22b4084057577fc371510864378354ddRob Landley{ 1435415c960b22b4084057577fc371510864378354ddRob Landley uint32_t nip = 0; 143660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh static_lease *sls = gstate.leases.sleases; 1437415c960b22b4084057577fc371510864378354ddRob Landley struct arg_list *listdls = gstate.dleases, *tmp = NULL; 1438415c960b22b4084057577fc371510864378354ddRob Landley 1439415c960b22b4084057577fc371510864378354ddRob Landley if (req_nip && (!verifyip_in_lease(req_nip, mac))) nip = req_nip; 1440415c960b22b4084057577fc371510864378354ddRob Landley 1441415c960b22b4084057577fc371510864378354ddRob Landley if (!nip) { 1442415c960b22b4084057577fc371510864378354ddRob Landley while (listdls) { 1443415c960b22b4084057577fc371510864378354ddRob Landley if (!memcmp(((dyn_lease*)listdls->arg)->lease_mac, mac, 6)) { 1444415c960b22b4084057577fc371510864378354ddRob Landley nip = ((dyn_lease*)listdls->arg)->lease_nip; 1445415c960b22b4084057577fc371510864378354ddRob Landley if (tmp) tmp->next = listdls->next; 1446415c960b22b4084057577fc371510864378354ddRob Landley else gstate.dleases = listdls->next; 1447415c960b22b4084057577fc371510864378354ddRob Landley free(listdls->arg); 1448415c960b22b4084057577fc371510864378354ddRob Landley free(listdls); 1449415c960b22b4084057577fc371510864378354ddRob Landley if (verifyip_in_lease(nip, mac) < 0) nip = 0; 1450415c960b22b4084057577fc371510864378354ddRob Landley break; 1451415c960b22b4084057577fc371510864378354ddRob Landley } 1452415c960b22b4084057577fc371510864378354ddRob Landley tmp = listdls; 1453415c960b22b4084057577fc371510864378354ddRob Landley listdls = listdls->next; 1454415c960b22b4084057577fc371510864378354ddRob Landley } 1455415c960b22b4084057577fc371510864378354ddRob Landley } 1456415c960b22b4084057577fc371510864378354ddRob Landley if (!nip) { 1457415c960b22b4084057577fc371510864378354ddRob Landley while (sls) { 1458415c960b22b4084057577fc371510864378354ddRob Landley if (memcmp(sls->mac, mac, 6) == 0) { 1459415c960b22b4084057577fc371510864378354ddRob Landley nip = sls->nip; 1460415c960b22b4084057577fc371510864378354ddRob Landley break; 1461415c960b22b4084057577fc371510864378354ddRob Landley } 1462415c960b22b4084057577fc371510864378354ddRob Landley sls = sls->next; 1463415c960b22b4084057577fc371510864378354ddRob Landley } 1464415c960b22b4084057577fc371510864378354ddRob Landley } 1465415c960b22b4084057577fc371510864378354ddRob Landley if (!nip) { 1466415c960b22b4084057577fc371510864378354ddRob Landley for (nip = htonl(gconfig.start_ip); ntohl(nip) <= gconfig.end_ip; ) { 1467415c960b22b4084057577fc371510864378354ddRob Landley if (!verifyip_in_lease(nip, mac)) break; 1468415c960b22b4084057577fc371510864378354ddRob Landley nip = ntohl(nip); 1469415c960b22b4084057577fc371510864378354ddRob Landley nip = htonl(++nip); 1470415c960b22b4084057577fc371510864378354ddRob Landley } 1471415c960b22b4084057577fc371510864378354ddRob Landley if (ntohl(nip) > gconfig.end_ip) { 1472415c960b22b4084057577fc371510864378354ddRob Landley nip = 0; 1473415c960b22b4084057577fc371510864378354ddRob Landley infomsg(infomode, "can't find free IP in IP Pool."); 1474415c960b22b4084057577fc371510864378354ddRob Landley } 1475415c960b22b4084057577fc371510864378354ddRob Landley } 1476415c960b22b4084057577fc371510864378354ddRob Landley if (nip) addip_to_lease(nip, mac, req_exp, hostname, 1); 1477415c960b22b4084057577fc371510864378354ddRob Landley return nip; 1478415c960b22b4084057577fc371510864378354ddRob Landley} 1479415c960b22b4084057577fc371510864378354ddRob Landley 1480c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suhstatic uint8_t *getip6_from_pool(uint8_t *duid, uint16_t duid_len, uint16_t ia_type, uint32_t iaid, uint32_t *lifetime) 148160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 1482c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh static uint8_t nip6[16] = {0, }; 148360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh static_lease6 *sls6 = gstate.leases.sleases6; 148460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct arg_list *listdls6 = gstate.dleases, *tmp = NULL; 148560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 148660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while(listdls6) { 148760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!memcmp(((dyn_lease6*)listdls6->arg)->duid, duid, duid_len)) { 148860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(nip6, ((dyn_lease6*)listdls6->arg)->lease_nip6, sizeof(nip6)); 148960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(tmp) tmp->next = listdls6->next; 149060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh else gstate.dleases = listdls6->next; 149160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(listdls6->arg); 149260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(listdls6); 149360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 149460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(verifyip6_in_lease(nip6, duid, ia_type, iaid) < 0) 149560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(nip6, 0, sizeof(nip6)); 149660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 149760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 149860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh tmp = listdls6; 149960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh listdls6 = listdls6->next; 150060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 150160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1502c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if(!memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) { 150360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while(sls6) { 150460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(!memcmp(sls6->duid, duid, 6)) { 150560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(nip6, sls6->nip6, sizeof(nip6)); 150660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 150760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 150860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh sls6 = sls6->next; 150960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 151060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 151160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1512c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if(!memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) { 1513c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(nip6, gconfig.start_ip6, sizeof(nip6)); 1514c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh while(memcmp(nip6, gconfig.end_ip6, sizeof(nip6)) < 0) { 151560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(!verifyip6_in_lease(nip6, duid, ia_type, iaid)) break; 1516c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh int i=sizeof(nip6); 151760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while(i--) { 1518c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh ++nip6[i]; 1519c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (!nip6[i]) { 1520c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if(i==(sizeof(nip6)-1)) ++nip6[i]; 1521c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh ++nip6[i-1]; 1522c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh } else 152360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 152460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 152560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 152660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1527c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (memcmp(nip6, gconfig.end_ip6, sizeof(nip6)) > 0) { 152860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memset(nip6, 0, sizeof(nip6)); 152960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh infomsg(infomode, "can't find free IP in IPv6 Pool."); 153060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 153160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 153260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1533c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if(memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) { 1534c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh addip6_to_lease(nip6, duid, duid_len, ia_type, iaid, lifetime, 1); 1535c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh infomsg(infomode, "Assigned IPv6 %02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", 1536c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh nip6[0], nip6[1], nip6[2], nip6[3], nip6[4], nip6[5], nip6[6], nip6[7], nip6[8], 1537c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh nip6[9], nip6[10], nip6[11], nip6[12], nip6[13], nip6[14], nip6[15]); 1538c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh } 153960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh return nip6; 154060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 154160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 154260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic void read_leasefile(void) 1543415c960b22b4084057577fc371510864378354ddRob Landley{ 1544415c960b22b4084057577fc371510864378354ddRob Landley uint32_t passed, ip; 1545415c960b22b4084057577fc371510864378354ddRob Landley int32_t tmp_time; 1546415c960b22b4084057577fc371510864378354ddRob Landley int64_t timestamp; 1547415c960b22b4084057577fc371510864378354ddRob Landley dyn_lease *dls; 154860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int fd = open(gconfig.lease_file, O_RDONLY); 1549415c960b22b4084057577fc371510864378354ddRob Landley 1550415c960b22b4084057577fc371510864378354ddRob Landley dls = xzalloc(sizeof(dyn_lease)); 1551415c960b22b4084057577fc371510864378354ddRob Landley 155260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (read(fd, ×tamp, sizeof(timestamp)) != sizeof(timestamp)) 155360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh goto lease_error_exit; 1554415c960b22b4084057577fc371510864378354ddRob Landley 1555415c960b22b4084057577fc371510864378354ddRob Landley timestamp = SWAP_BE64(timestamp); 1556415c960b22b4084057577fc371510864378354ddRob Landley passed = time(NULL) - timestamp; 155760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((uint64_t)passed > 12 * 60 * 60) goto lease_error_exit; 1558415c960b22b4084057577fc371510864378354ddRob Landley 1559415c960b22b4084057577fc371510864378354ddRob Landley while (read(fd, dls, sizeof(dyn_lease)) == sizeof(dyn_lease)) { 1560415c960b22b4084057577fc371510864378354ddRob Landley ip = ntohl(dls->lease_nip); 1561415c960b22b4084057577fc371510864378354ddRob Landley if (ip >= gconfig.start_ip && ip <= gconfig.end_ip) { 1562415c960b22b4084057577fc371510864378354ddRob Landley tmp_time = ntohl(dls->expires) - passed; 1563415c960b22b4084057577fc371510864378354ddRob Landley if (tmp_time < 0) continue; 156460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh addip_to_lease(dls->lease_nip, dls->lease_mac, 156560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (uint32_t*)&tmp_time, dls->hostname, 0); 1566415c960b22b4084057577fc371510864378354ddRob Landley } 1567415c960b22b4084057577fc371510864378354ddRob Landley } 156860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhlease_error_exit: 1569415c960b22b4084057577fc371510864378354ddRob Landley free(dls); 1570415c960b22b4084057577fc371510864378354ddRob Landley close(fd); 157160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh} 157260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 157360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhstatic void read_lease6file(void) 157460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh{ 1575c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint32_t passed; 157660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint32_t tmp_time; 157760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int64_t timestamp; 157860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dyn_lease6 *dls6; 157960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int fd = open(gconfig.lease6_file, O_RDONLY); 158060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 158160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dls6 = xzalloc(sizeof(dyn_lease6)); 158260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 158360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (read(fd, ×tamp, sizeof(timestamp)) != sizeof(timestamp)) 158460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh goto lease6_error_exit; 158560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 158660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh timestamp = SWAP_BE64(timestamp); 158760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh passed = time(NULL) - timestamp; 158860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if ((uint64_t)passed > 12 * 60 * 60) goto lease6_error_exit; 158960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 159060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh while (read(fd, dls6, sizeof(dyn_lease6)) == sizeof(dyn_lease6)) { 1591c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (memcmp(dls6->lease_nip6, gconfig.start_ip6, sizeof(uint32_t)*4) > 0 && 1592c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcmp(dls6->lease_nip6, gconfig.end_ip6, sizeof(uint32_t)*4) < 0) { 159360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh tmp_time = ntohl(dls6->expires) - passed; 159460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (tmp_time < 0U) continue; 1595c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh addip6_to_lease(dls6->lease_nip6, dls6->duid, dls6->duid_len, dls6->ia_type, dls6->iaid, 159660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (uint32_t*)&tmp_time, 0); 159760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 159860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 159960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 160060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suhlease6_error_exit: 160160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(dls6); 160260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh close(fd); 1603415c960b22b4084057577fc371510864378354ddRob Landley} 1604415c960b22b4084057577fc371510864378354ddRob Landley 1605415c960b22b4084057577fc371510864378354ddRob Landleyvoid dhcpd_main(void) 1606415c960b22b4084057577fc371510864378354ddRob Landley{ 1607415c960b22b4084057577fc371510864378354ddRob Landley struct timeval tv; 160860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh int retval, i; 1609415c960b22b4084057577fc371510864378354ddRob Landley uint8_t *optptr, msgtype = 0; 161060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t optlen = 0; 1611415c960b22b4084057577fc371510864378354ddRob Landley uint32_t waited = 0, serverid = 0, requested_nip = 0; 161260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t transactionid[3] = {0,}; 1613415c960b22b4084057577fc371510864378354ddRob Landley uint32_t reqested_lease = 0, ip_pool_size = 0; 1614415c960b22b4084057577fc371510864378354ddRob Landley char *hstname = NULL; 1615415c960b22b4084057577fc371510864378354ddRob Landley fd_set rfds; 1616415c960b22b4084057577fc371510864378354ddRob Landley 1617415c960b22b4084057577fc371510864378354ddRob Landley infomode = LOG_CONSOLE; 1618547c9167565cf8a2bba8bd79850889101866814aRob Landley if (!(toys.optflags & FLAG_f)) { 1619c880061f511e85d55afe3966f5eda0df7c3ebb56Rob Landley daemon(0,0); 1620415c960b22b4084057577fc371510864378354ddRob Landley infomode = LOG_SILENT; 1621415c960b22b4084057577fc371510864378354ddRob Landley } 1622547c9167565cf8a2bba8bd79850889101866814aRob Landley if (toys.optflags & FLAG_S) { 1623415c960b22b4084057577fc371510864378354ddRob Landley openlog("UDHCPD :", LOG_PID, LOG_DAEMON); 1624415c960b22b4084057577fc371510864378354ddRob Landley infomode |= LOG_SYSTEM; 1625415c960b22b4084057577fc371510864378354ddRob Landley } 1626415c960b22b4084057577fc371510864378354ddRob Landley setlinebuf(stdout); 162760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //DHCPD_CONF_FILE 162860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh parse_server_config((toys.optc==1)?toys.optargs[0]:"/etc/dhcpd.conf", keywords); 1629415c960b22b4084057577fc371510864378354ddRob Landley infomsg(infomode, "toybox dhcpd started"); 163060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1631547c9167565cf8a2bba8bd79850889101866814aRob Landley if (toys.optflags & FLAG_6){ 163260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh addr_version = AF_INET6; 163360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gconfig.t1 = ntohl(gconfig.t1); 163460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gconfig.t2 = ntohl(gconfig.t2); 163560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gconfig.pref_lifetime = ntohl(gconfig.pref_lifetime); 163660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gconfig.valid_lifetime = ntohl(gconfig.valid_lifetime); 1637c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh gconfig.port = 547; 163860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh for(i=0;i<4;i++) 163960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ip_pool_size += (gconfig.end_ip6[i]-gconfig.start_ip6[i])<<((3-i)*8); 164060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 164160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gconfig.start_ip = ntohl(gconfig.start_ip); 164260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gconfig.end_ip = ntohl(gconfig.end_ip); 164360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ip_pool_size = gconfig.end_ip - gconfig.start_ip + 1; 164460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 164560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1646415c960b22b4084057577fc371510864378354ddRob Landley if (gconfig.max_leases > ip_pool_size) { 164760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh error_msg("max_leases=%u is too big, setting to %u", 164860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (unsigned) gconfig.max_leases, ip_pool_size); 1649415c960b22b4084057577fc371510864378354ddRob Landley gconfig.max_leases = ip_pool_size; 1650415c960b22b4084057577fc371510864378354ddRob Landley } 1651415c960b22b4084057577fc371510864378354ddRob Landley write_pid(gconfig.pidfile); 1652415c960b22b4084057577fc371510864378354ddRob Landley set_maxlease(); 165382d8d7cb7eacabd1a498c001dd5618a1302f854bHyejin Kim if(TT.iface) gconfig.interface = TT.iface; 1654c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if(TT.port) gconfig.port = TT.port; 165560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (addr_version==AF_INET6) ? read_lease6file() : read_leasefile(); 165660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1657c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh 165860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (get_interface(gconfig.interface, &gconfig.ifindex, 1659c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh (addr_version==AF_INET6)? (void*)gconfig.server_nip6 : 1660c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh (void*)&gconfig.server_nip, gconfig.server_mac) < 0) 1661415c960b22b4084057577fc371510864378354ddRob Landley perror_exit("Failed to get interface %s", gconfig.interface); 1662415c960b22b4084057577fc371510864378354ddRob Landley setup_signal(); 166360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (addr_version==AF_INET6) { 166460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh open_listensock6(); 166560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 166660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gconfig.server_nip = htonl(gconfig.server_nip); 166760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh open_listensock(); 166860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 166960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1670415c960b22b4084057577fc371510864378354ddRob Landley fcntl(gstate.listensock, F_SETFD, FD_CLOEXEC); 1671415c960b22b4084057577fc371510864378354ddRob Landley 1672415c960b22b4084057577fc371510864378354ddRob Landley for (;;) { 1673415c960b22b4084057577fc371510864378354ddRob Landley uint32_t timestmp = time(NULL); 1674415c960b22b4084057577fc371510864378354ddRob Landley FD_ZERO(&rfds); 1675415c960b22b4084057577fc371510864378354ddRob Landley FD_SET(gstate.listensock, &rfds); 1676415c960b22b4084057577fc371510864378354ddRob Landley FD_SET(sigfd.rd, &rfds); 1677415c960b22b4084057577fc371510864378354ddRob Landley tv.tv_sec = gconfig.auto_time - waited; 1678415c960b22b4084057577fc371510864378354ddRob Landley tv.tv_usec = 0; 1679415c960b22b4084057577fc371510864378354ddRob Landley retval = 0; 1680415c960b22b4084057577fc371510864378354ddRob Landley serverid = 0; 1681415c960b22b4084057577fc371510864378354ddRob Landley msgtype = 0; 1682415c960b22b4084057577fc371510864378354ddRob Landley 1683415c960b22b4084057577fc371510864378354ddRob Landley int maxfd = (sigfd.rd > gstate.listensock)? sigfd.rd : gstate.listensock; 1684415c960b22b4084057577fc371510864378354ddRob Landley dbg("select waiting ....\n"); 1685415c960b22b4084057577fc371510864378354ddRob Landley retval = select(maxfd + 1, &rfds, NULL, NULL, (gconfig.auto_time?&tv:NULL)); 1686415c960b22b4084057577fc371510864378354ddRob Landley if (retval < 0) { 1687415c960b22b4084057577fc371510864378354ddRob Landley if (errno == EINTR) { 1688415c960b22b4084057577fc371510864378354ddRob Landley waited += (unsigned) time(NULL) - timestmp; 1689415c960b22b4084057577fc371510864378354ddRob Landley continue; 1690415c960b22b4084057577fc371510864378354ddRob Landley } 1691415c960b22b4084057577fc371510864378354ddRob Landley dbg("Error in select wait again...\n"); 1692415c960b22b4084057577fc371510864378354ddRob Landley continue; 1693415c960b22b4084057577fc371510864378354ddRob Landley } 1694415c960b22b4084057577fc371510864378354ddRob Landley if (!retval) { // Timed out 1695415c960b22b4084057577fc371510864378354ddRob Landley dbg("select wait Timed Out...\n"); 1696415c960b22b4084057577fc371510864378354ddRob Landley waited = 0; 1697c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh (addr_version == AF_INET6)? write_lease6file() : write_leasefile(); 169860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (get_interface(gconfig.interface, &gconfig.ifindex, 1699c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh (addr_version==AF_INET6)? (void*)gconfig.server_nip6 : 1700c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh (void*)&gconfig.server_nip, gconfig.server_mac)<0) 170160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh perror_exit("Failed to get interface %s", gconfig.interface); 1702c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if(addr_version != AF_INET6) { 1703c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh gconfig.server_nip = htonl(gconfig.server_nip); 1704c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh } 1705415c960b22b4084057577fc371510864378354ddRob Landley continue; 1706415c960b22b4084057577fc371510864378354ddRob Landley } 1707415c960b22b4084057577fc371510864378354ddRob Landley if (FD_ISSET(sigfd.rd, &rfds)) { // Some Activity on RDFDs : is signal 1708415c960b22b4084057577fc371510864378354ddRob Landley unsigned char sig; 1709415c960b22b4084057577fc371510864378354ddRob Landley if (read(sigfd.rd, &sig, 1) != 1) { 1710415c960b22b4084057577fc371510864378354ddRob Landley dbg("signal read failed.\n"); 1711415c960b22b4084057577fc371510864378354ddRob Landley continue; 1712415c960b22b4084057577fc371510864378354ddRob Landley } 1713415c960b22b4084057577fc371510864378354ddRob Landley switch (sig) { 171460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case SIGUSR1: 171560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh infomsg(infomode, "Received SIGUSR1"); 171660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (addr_version==AF_INET6)? write_lease6file() : write_leasefile(); 171760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 171860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case SIGTERM: 171960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh infomsg(infomode, "received sigterm"); 172060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (addr_version==AF_INET6)? write_lease6file() : write_leasefile(); 172160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh unlink(gconfig.pidfile); 172260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh exit(0); 172360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 172460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh default: break; 1725415c960b22b4084057577fc371510864378354ddRob Landley } 1726415c960b22b4084057577fc371510864378354ddRob Landley } 1727c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if (FD_ISSET(gstate.listensock, &rfds)) { // Some Activity on RDFDs : is socket 1728415c960b22b4084057577fc371510864378354ddRob Landley dbg("select listen sock read\n"); 172960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(addr_version==AF_INET6) { 173060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh void *client_duid, *server_duid, *client_ia_na, *server_ia_na, 1731c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh *client_ia_pd; 173260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint8_t client_lla[6] = {0,}; 173360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t client_duid_len = 0, server_duid_len = 0, server_ia_na_len = 0, 173460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh client_ia_na_len = 0, client_ia_pd_len = 0; 173560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 173660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(read_packet6() < 0) { 173760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh open_listensock6(); 173860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 173960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 174060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh waited += time(NULL) - timestmp; 174160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 174260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&gstate.rqcode, &gstate.rcvd.rcvd_pkt6.msgtype, sizeof(uint8_t)); 174360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&transactionid, &gstate.rcvd.rcvd_pkt6.transaction_id, 174460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh sizeof(transactionid)); 174560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 174660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!gstate.rqcode || gstate.rqcode < DHCP6SOLICIT || 174760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.rqcode > DHCP6RELAYREPLY) { 174860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("no or bad message type option, ignoring packet.\n"); 174960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 175060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 175160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!gstate.rcvd.rcvd_pkt6.transaction_id || 175260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcmp(gstate.rcvd.rcvd_pkt6.transaction_id, transactionid, 3)) { 175360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("no or bad transaction id, ignoring packet.\n"); 175460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 175560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 175660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 175760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh waited += time(NULL) - timestmp; 175860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh switch (gstate.rqcode) { 175960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case DHCP6SOLICIT: 176060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type: DHCP6SOLICIT\n"); 176160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = prepare_send_pkt6(DHCP6ADVERTISE); 176260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen = 0; 176360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 176460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //TODO policy check 176560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //TODO Receive: ORO check (e.g. DNS) 176660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1767c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh //Receive: Client Identifier (DUID) 1768c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options, 1769c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid); 1770c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh 177160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Receive: Identity Association for Non-temporary Address 177260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options, 177360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) { 177460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t ia_addr_len = sizeof(struct optval_ia_addr); 177560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh void *ia_addr, *status_code; 177660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *status_code_msg; 177760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t status_code_len = 0; 1778c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh server_ia_na_len = sizeof(struct optval_ia_na); 177960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 178060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //IA Address 178160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ia_addr = xzalloc(ia_addr_len); 178260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr; 178360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_addr_p).pref_lifetime = gconfig.pref_lifetime; 178460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_addr_p).valid_lifetime = gconfig.valid_lifetime; 178560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh memcpy(&(*ia_addr_p).ipv6_addr, 178660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh getip6_from_pool(client_duid, client_duid_len, 178760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_IA_NA, (*(struct optval_ia_na*) client_ia_na).iaid, 178860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh &(*ia_addr_p).pref_lifetime), sizeof(uint32_t)*4); 178960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na_len += (ia_addr_len+4); 179060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 179160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Status Code 1792c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh if(memcmp((*ia_addr_p).ipv6_addr, (uint8_t[16]){0}, sizeof(uint32_t)*4)) { 179360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_msg = xstrdup("Assigned an address."); 179460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_len = strlen(status_code_msg)+1; 179560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code = xzalloc(status_code_len); 179660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_status_code *status_code_p = 179760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (struct optval_status_code*)status_code; 179860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS); 1799c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy((*status_code_p).status_msg, status_code_msg, 180060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_len); 180160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na_len += (status_code_len+4); 180260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(status_code_msg); 180360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 180460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_msg = xstrdup("There's no available address."); 180560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_len = strlen(status_code_msg)+1; 180660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code = xzalloc(status_code_len); 180760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_status_code *status_code_p = 180860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (struct optval_status_code*)status_code; 180960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*status_code_p).status_code = htons(DHCP6_STATUS_NOADDRSAVAIL); 1810c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy((*status_code_p).status_msg, status_code_msg, 181160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_len); 181260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na_len += (status_code_len+4); 181360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na_len -= (ia_addr_len+4); 181460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ia_addr_len = 0; 181560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(ia_addr); 181660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(status_code_msg); 181760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //TODO send failed status code 181860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 181960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 182060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 182160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //combine options 182260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na = xzalloc(server_ia_na_len); 182360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na; 182460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid; 182560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_na_p).t1 = gconfig.t1; 182660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_na_p).t2 = gconfig.t2; 182760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1828c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t* ia_na_optptr = (*ia_na_p).optval; 182960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(ia_addr_len) { 183060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR, ia_addr, ia_addr_len); 183160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ia_na_optptr += (ia_addr_len + 4); 183260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(ia_addr); 183360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 183460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(status_code_len) { 183560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE, status_code, 183660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_len); 183760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ia_na_optptr += (status_code_len); 183860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(status_code); 183960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 184060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 184160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Response: Identity Association for Non-temporary Address 184260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval6(optptr, DHCP6_OPT_IA_NA, server_ia_na, 184360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na_len); 184460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen += (server_ia_na_len + 4); 184560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(client_ia_na);free(server_ia_na); 184660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 184760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Receive: Identity Association for Prefix Delegation 184860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh else if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options, 184960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_IA_PD, &client_ia_pd_len, &client_ia_pd)) { 185060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 185160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //TODO 185260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Response: Identity Association for Prefix Delegation 185360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 185460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 185560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //DUID type: link-layer address plus time 185660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(ntohs((*(struct optval_duid_llt*)client_duid).type) == 185760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_DUID_LLT) { 185860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_duid_len = 8+sizeof(gconfig.server_mac); 185960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_duid = xzalloc(server_duid_len); 186060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_duid_llt *server_duid_p = 186160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (struct optval_duid_llt*)server_duid; 186260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*server_duid_p).type = htons(1); 186360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*server_duid_p).hwtype = htons(1); 186460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*server_duid_p).time = htonl((uint32_t) 186560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (time(NULL) - 946684800) & 0xffffffff); 1866c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy((*server_duid_p).lladdr, gconfig.server_mac, 186760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh sizeof(gconfig.server_mac)); 1868c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(&client_lla, (*(struct optval_duid_llt*)client_duid).lladdr, 186960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh sizeof(client_lla)); 187060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 187160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Response: Server Identifier (DUID) 187260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval6(optptr, DHCP6_OPT_SERVERID, server_duid, 187360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_duid_len); 187460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen += (server_duid_len + 4); 187560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Response: Client Identifier 187660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid, 187760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh client_duid_len); 187860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen += (client_duid_len + 4); 187960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(client_duid);free(server_duid); 188060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 188160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 188260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh send_packet6(0, client_lla, optlen); 188360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh write_lease6file(); 188460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 188560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case DHCP6REQUEST: 188660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type: DHCP6REQUEST\n"); 188760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = prepare_send_pkt6(DHCP6REPLY); 188860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen = 0; 188960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 189060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Receive: Client Identifier (DUID) 189160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options, 189260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid); 189360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid, 189460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh client_duid_len); 189560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen += (client_duid_len + 4); 1896c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy(client_lla, (*(struct optval_duid_llt*)client_duid).lladdr, 189760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh sizeof(client_lla)); 189860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 189960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Receive: Identity Association for Non-temporary Address 190060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options, 190160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) { 190260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh uint16_t ia_addr_len = 0, status_code_len = 0; 190360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh void *ia_addr, *status_code; 1904c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint16_t server_ia_na_len = sizeof(struct optval_ia_na); 190560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh char *status_code_msg; 190660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 190760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Check IA Address 1908c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh get_optval6((uint8_t*)(*(struct optval_ia_na*)client_ia_na).optval, 190960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_IA_ADDR, &ia_addr_len, &ia_addr); 191060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr; 191160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(verifyip6_in_lease((*ia_addr_p).ipv6_addr, client_duid, 191260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_IA_NA, (*(struct optval_ia_na*)client_ia_na).iaid) 191360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh == -1) { 191460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na_len += (ia_addr_len + 4); 191560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Add Status Code 191660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_msg = xstrdup("Assigned an address."); 191760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_len = strlen(status_code_msg) + 1; 191860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code = xzalloc(status_code_len); 191960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_status_code *status_code_p = 192060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (struct optval_status_code*)status_code; 192160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS); 1922c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh memcpy((*status_code_p).status_msg, status_code_msg, 192360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code_len); 192460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na_len += (status_code_len+4); 192560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 192660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //TODO send failed status code 192760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 192860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 192960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 193060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //combine options 193160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na = xzalloc(server_ia_na_len); 193260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na; 193360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid; 193460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_na_p).t1 = gconfig.t1; 193560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (*ia_na_p).t2 = gconfig.t2; 193660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 1937c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh uint8_t* ia_na_optptr = (*ia_na_p).optval; 193860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR, 193960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ia_addr, ia_addr_len); 194060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(ia_addr); 194160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 194260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(status_code_len) { 194360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE, 194460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh status_code, status_code_len); 194560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(status_code); 194660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 194760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 194860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Response: Identity Association for Non-temporary Address 194960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //(Status Code added) 195060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval6(optptr, DHCP6_OPT_IA_NA, 195160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_ia_na, server_ia_na_len); 195260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen += (server_ia_na_len + 4); 195360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(client_ia_na);free(server_ia_na); 195460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 195560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 195660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh //Receive: Server Identifier (DUID) 195760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options, 195860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP6_OPT_SERVERID, &server_duid_len, &server_duid); 195960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval6(optptr, DHCP6_OPT_SERVERID, 196060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh server_duid, server_duid_len); 196160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optlen += (server_duid_len + 4); 196260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 196360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh free(client_duid); free(server_duid); 196460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 196560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh send_packet6(0, client_lla, optlen); 196660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh write_lease6file(); 196760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 1968c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh case DHCP6DECLINE: //TODO 1969c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh case DHCP6RENEW: //TODO 1970c9e2a656c7305fac00a5a8c09201e1e39fea6a1bYeongdeok Suh case DHCP6REBIND: //TODO 197160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case DHCP6RELEASE: 197260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type: DHCP6RELEASE\n"); 197360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = prepare_send_pkt6(DHCP6REPLY); 197460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 197560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh default: 197660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type : %u\n", gstate.rqcode); 197760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 197860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 197960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 198060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } else { 198160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(read_packet() < 0) { 198260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh open_listensock(); 198360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 198460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 198560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh waited += time(NULL) - timestmp; 198660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 198760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.options, 198860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_MESSAGE_TYPE, &gstate.rqcode); 198960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (gstate.rqcode == 0 || gstate.rqcode < DHCPDISCOVER 199060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh || gstate.rqcode > DHCPINFORM) { 199160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("no or bad message type option, ignoring packet.\n"); 199260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 199360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 199460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 199560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_SERVER_ID, &serverid); 199660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (serverid && (serverid != gconfig.server_nip)) { 199760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("server ID doesn't match, ignoring packet.\n"); 199860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh continue; 199960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 200060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh 200160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh waited += time(NULL) - timestmp; 200260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh switch (gstate.rqcode) { 200360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case DHCPDISCOVER: 200460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh msgtype = DHCPOFFER; 200560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type : DHCPDISCOVER\n"); 200660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 200760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_REQUESTED_IP, &requested_nip); 200860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 200960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_HOST_NAME, &hstname); 201060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh reqested_lease = gconfig.offer_time; 201160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_reqparam(&gstate.rqopt); 201260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = prepare_send_pkt(); 201360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip, 201460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname); 201560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if(!gstate.send.send_pkt.yiaddr){ 201660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh msgtype = DHCPNAK; 201760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1); 201860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh send_packet(1); 201960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 202060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 202160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 202260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_LEASE_TIME, &reqested_lease); 202360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh reqested_lease = htonl(get_lease(reqested_lease + time(NULL))); 2024415c960b22b4084057577fc371510864378354ddRob Landley optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1); 202560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4); 202660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4); 202760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_reqparam(optptr, gstate.rqopt); 2028415c960b22b4084057577fc371510864378354ddRob Landley send_packet(1); 2029415c960b22b4084057577fc371510864378354ddRob Landley break; 203060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case DHCPREQUEST: 203160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh msgtype = DHCPACK; 203260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type : DHCPREQUEST\n"); 203360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = prepare_send_pkt(); 203460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 203560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_REQUESTED_IP, &requested_nip); 203660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 203760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_LEASE_TIME, &reqested_lease); 203860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 203960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_HOST_NAME, &hstname); 204060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip, 204160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname); 204260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!serverid) reqested_lease = gconfig.max_lease_sec; 204360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (!gstate.send.send_pkt.yiaddr) { 204460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh msgtype = DHCPNAK; 204560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1); 204660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh send_packet(1); 204760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 204860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 2049415c960b22b4084057577fc371510864378354ddRob Landley optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1); 205060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4); 205160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh reqested_lease = htonl(reqested_lease); 205260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4); 2053415c960b22b4084057577fc371510864378354ddRob Landley send_packet(1); 205460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh write_leasefile(); 2055415c960b22b4084057577fc371510864378354ddRob Landley break; 205660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case DHCPDECLINE:// FALL THROUGH 205760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh case DHCPRELEASE: 205860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type : DHCPDECLINE or DHCPRELEASE \n"); 205960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 206060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_SERVER_ID, &serverid); 206160cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh if (serverid != gconfig.server_nip) break; 206260cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options, 206360cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh DHCP_OPT_REQUESTED_IP, &requested_nip); 206460cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh delip_from_lease(requested_nip, gstate.rcvd.rcvd_pkt.chaddr, 206560cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh (gstate.rqcode==DHCPRELEASE)?0:gconfig.decline_time); 206660cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 206760cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh default: 206860cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh dbg("Message Type : %u\n", gstate.rqcode); 206960cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh break; 207060cdc06c4825de7688a3879892bf442e0e2f282aYeongdeok Suh } 2071415c960b22b4084057577fc371510864378354ddRob Landley } 2072415c960b22b4084057577fc371510864378354ddRob Landley } 2073415c960b22b4084057577fc371510864378354ddRob Landley } 2074415c960b22b4084057577fc371510864378354ddRob Landley} 2075