dhcpd.c 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073
  1. /* dhcpd.c - DHCP server for dynamic network configuration.
  2. *
  3. * Copyright 2013 Madhur Verma <mad.flexi@gmail.com>
  4. * Copyright 2013 Kyungwan Han <asura321@gamil.com>
  5. * Copyright 2015 Yeongdeok Suh <skyducks111@gmail.com>
  6. *
  7. * No Standard
  8. USE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
  9. config DHCPD
  10. bool "dhcpd"
  11. default n
  12. help
  13. usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE]
  14. -f Run in foreground
  15. -i Interface to use
  16. -S Log to syslog too
  17. -P N Use port N (default ipv4 67, ipv6 547)
  18. -4, -6 Run as a DHCPv4 or DHCPv6 server
  19. config DEBUG_DHCP
  20. bool "debugging messeges ON/OFF"
  21. default n
  22. depends on DHCPD
  23. */
  24. /*
  25. * TODO
  26. * - Working as an relay agent
  27. * - Rapid commit option support
  28. * - Additional packet options (commented on the middle of sources)
  29. * - Create common modules
  30. */
  31. #define FOR_dhcpd
  32. #include "toys.h"
  33. #include <linux/sockios.h>
  34. #include <linux/if_ether.h>
  35. // Todo: headers not in posix
  36. #include <netinet/ip.h>
  37. #include <netinet/ip6.h>
  38. #include <netinet/udp.h>
  39. #include <netpacket/packet.h>
  40. #if CFG_DEBUG_DHCP==1
  41. # define dbg(fmt, arg...) printf(fmt, ##arg)
  42. #else
  43. # define dbg(fmt, arg...)
  44. #endif
  45. #define LOG_SILENT 0x0
  46. #define LOG_CONSOLE 0x1
  47. #define LOG_SYSTEM 0x2
  48. #define DHCP_MAGIC 0x63825363
  49. #define DHCPDISCOVER 1
  50. #define DHCPOFFER 2
  51. #define DHCPREQUEST 3
  52. #define DHCPDECLINE 4
  53. #define DHCPACK 5
  54. #define DHCPNAK 6
  55. #define DHCPRELEASE 7
  56. #define DHCPINFORM 8
  57. #define DHCP6SOLICIT 1
  58. #define DHCP6ADVERTISE 2 // server -> client
  59. #define DHCP6REQUEST 3
  60. #define DHCP6CONFIRM 4
  61. #define DHCP6RENEW 5
  62. #define DHCP6REBIND 6
  63. #define DHCP6REPLY 7 // server -> client
  64. #define DHCP6RELEASE 8
  65. #define DHCP6DECLINE 9
  66. #define DHCP6RECONFIGURE 10 // server -> client
  67. #define DHCP6INFOREQUEST 11
  68. #define DHCP6RELAYFLOW 12 // relay -> relay/server
  69. #define DHCP6RELAYREPLY 13 // server/relay -> relay
  70. #define DHCP_NUM8 (1<<8)
  71. #define DHCP_NUM16 (1<<9)
  72. #define DHCP_NUM32 DHCP_NUM16 | DHCP_NUM8
  73. #define DHCP_STRING (1<<10)
  74. #define DHCP_STRLST (1<<11)
  75. #define DHCP_IP (1<<12)
  76. #define DHCP_IPLIST (1<<13)
  77. #define DHCP_IPPLST (1<<14)
  78. #define DHCP_STCRTS (1<<15)
  79. // DHCP option codes (partial list). See RFC 2132 and
  80. #define DHCP_OPT_PADDING 0x00
  81. #define DHCP_OPT_HOST_NAME DHCP_STRING | 0x0c // either client informs server or server gives name to client
  82. #define DHCP_OPT_REQUESTED_IP DHCP_IP | 0x32 // sent by client if specific IP is wanted
  83. #define DHCP_OPT_LEASE_TIME DHCP_NUM32 | 0x33
  84. #define DHCP_OPT_OPTION_OVERLOAD 0x34
  85. #define DHCP_OPT_MESSAGE_TYPE DHCP_NUM8 | 0x35
  86. #define DHCP_OPT_SERVER_ID DHCP_IP | 0x36 // by default server's IP
  87. #define DHCP_OPT_PARAM_REQ DHCP_STRING | 0x37 // list of options client wants
  88. #define DHCP_OPT_END 0xff
  89. // DHCPv6 option codes (partial). See RFC 3315
  90. #define DHCP6_OPT_CLIENTID 1
  91. #define DHCP6_OPT_SERVERID 2
  92. #define DHCP6_OPT_IA_NA 3
  93. #define DHCP6_OPT_IA_ADDR 5
  94. #define DHCP6_OPT_ORO 6
  95. #define DHCP6_OPT_PREFERENCE 7
  96. #define DHCP6_OPT_ELAPSED_TIME 8
  97. #define DHCP6_OPT_RELAY_MSG 9
  98. #define DHCP6_OPT_STATUS_CODE 13
  99. #define DHCP6_OPT_IA_PD 25
  100. #define DHCP6_OPT_IA_PREFIX 26
  101. #define DHCP6_STATUS_SUCCESS 0
  102. #define DHCP6_STATUS_NOADDRSAVAIL 2
  103. #define DHCP6_DUID_LLT 1
  104. #define DHCP6_DUID_EN 2
  105. #define DHCP6_DUID_LL 3
  106. #define DHCP6_DUID_UUID 4
  107. GLOBALS(
  108. char *iface;
  109. long port;
  110. )
  111. struct config_keyword {
  112. char *keyword;
  113. int (*handler)(const char *str, void *var);
  114. void *var;
  115. char *def;
  116. };
  117. typedef struct __attribute__((packed)) dhcp_msg_s {
  118. uint8_t op;
  119. uint8_t htype;
  120. uint8_t hlen;
  121. uint8_t hops;
  122. uint32_t xid;
  123. uint16_t secs;
  124. uint16_t flags;
  125. uint32_t ciaddr;
  126. uint32_t yiaddr;
  127. uint32_t nsiaddr;
  128. uint32_t ngiaddr;
  129. uint8_t chaddr[16];
  130. uint8_t sname[64];
  131. uint8_t file[128];
  132. uint32_t cookie;
  133. uint8_t options[308];
  134. } dhcp_msg_t;
  135. typedef struct __attribute__((packed)) dhcp6_msg_s {
  136. uint8_t msgtype;
  137. uint8_t transaction_id[3];
  138. uint8_t options[524];
  139. } dhcp6_msg_t;
  140. typedef struct __attribute__((packed)) dhcp_raw_s {
  141. struct iphdr iph;
  142. struct udphdr udph;
  143. dhcp_msg_t dhcp;
  144. } dhcp_raw_t;
  145. typedef struct __attribute__((packed)) dhcp6_raw_s {
  146. struct ip6_hdr iph;
  147. struct udphdr udph;
  148. dhcp6_msg_t dhcp6;
  149. } dhcp6_raw_t;
  150. typedef struct static_lease_s {
  151. struct static_lease_s *next;
  152. uint32_t nip;
  153. int mac[6];
  154. } static_lease;
  155. typedef struct static_lease6_s {
  156. struct static_lease6_s *next;
  157. uint16_t duid_len;
  158. uint16_t ia_type;
  159. uint32_t iaid;
  160. uint8_t nip6[16];
  161. uint8_t duid[20];
  162. } static_lease6;
  163. typedef struct {
  164. uint32_t expires;
  165. uint32_t lease_nip;
  166. uint8_t lease_mac[6];
  167. char hostname[20];
  168. uint8_t pad[2];
  169. } dyn_lease;
  170. typedef struct {
  171. uint16_t duid_len;
  172. uint16_t ia_type;
  173. uint32_t expires;
  174. uint32_t iaid;
  175. uint8_t lease_nip6[16];
  176. uint8_t duid[20];
  177. } dyn_lease6;
  178. typedef struct option_val_s {
  179. char *key;
  180. uint16_t code;
  181. void *val;
  182. size_t len;
  183. } option_val_t;
  184. struct __attribute__((packed)) optval_duid_llt {
  185. uint16_t type;
  186. uint16_t hwtype;
  187. uint32_t time;
  188. uint8_t lladdr[]; //flexible
  189. };
  190. struct __attribute__((packed)) optval_ia_na {
  191. uint32_t iaid;
  192. uint32_t t1, t2;
  193. uint8_t optval[]; //flexible
  194. };
  195. struct __attribute__((packed)) optval_ia_addr {
  196. uint8_t ipv6_addr[16];
  197. uint32_t pref_lifetime;
  198. uint32_t valid_lifetime;
  199. };
  200. struct __attribute__((packed)) optval_status_code {
  201. uint16_t status_code;
  202. uint8_t status_msg[]; //flexible
  203. };
  204. typedef struct __attribute__((__may_alias__)) server_config_s {
  205. char *interface; // interface to use
  206. int ifindex;
  207. uint8_t server_nip6[16];
  208. uint32_t server_nip;
  209. uint32_t port;
  210. uint8_t server_mac[6]; // our MAC address (used only for ARP probing)
  211. void *options[256]; // list of DHCP options loaded from the config file
  212. /* start,end are in host order: we need to compare start <= ip <= end*/
  213. uint32_t start_ip; // start address of leases, in host order
  214. uint32_t end_ip; // end of leases, in host order
  215. uint8_t start_ip6[16]; // start address of leases, in IPv6 mode
  216. uint8_t end_ip6[16]; // end of leases, in IPv6 mode
  217. uint32_t max_lease_sec; // maximum lease time (host order)
  218. uint32_t min_lease_sec; // minimum lease time a client can request
  219. uint32_t max_leases; // maximum number of leases (including reserved addresses)
  220. uint32_t auto_time; // how long should dhcpd wait before writing a config file.
  221. // if this is zero, it will only write one on SIGUSR1
  222. uint32_t decline_time; // how long an address is reserved if a client returns a
  223. // decline message
  224. uint32_t conflict_time; // how long an arp conflict offender is leased for
  225. uint32_t offer_time; // how long an offered address is reserved
  226. uint32_t siaddr_nip; // "next server" bootp option
  227. char *lease_file;
  228. char *lease6_file;
  229. char *pidfile;
  230. char *notify_file; // what to run whenever leases are written
  231. char *sname; // bootp server name
  232. char *boot_file; // bootp boot file option
  233. uint32_t pref_lifetime;
  234. uint32_t valid_lifetime;
  235. uint32_t t1,t2;
  236. struct static_lease *static_leases; // List of ip/mac pairs to assign static leases
  237. } server_config_t;
  238. typedef struct __attribute__((__may_alias__)) server_state_s {
  239. uint8_t client_nip6[16];
  240. uint32_t client_port;
  241. uint8_t rqcode;
  242. int listensock;
  243. union {
  244. dhcp_msg_t rcvd_pkt;
  245. dhcp6_msg_t rcvd_pkt6;
  246. } rcvd;
  247. uint8_t* rqopt;
  248. union {
  249. dhcp_msg_t send_pkt;
  250. dhcp6_msg_t send_pkt6;
  251. } send;
  252. union {
  253. static_lease *sleases;
  254. static_lease6 *sleases6;
  255. } leases;
  256. struct arg_list *dleases;
  257. } server_state_t;
  258. static option_val_t options_list[] = {
  259. {"lease" , DHCP_NUM32 | 0x33, NULL, 0},
  260. {"subnet" , DHCP_IP | 0x01, NULL, 0},
  261. {"broadcast" , DHCP_IP | 0x1c, NULL, 0},
  262. {"router" , DHCP_IP | 0x03, NULL, 0},
  263. {"ipttl" , DHCP_NUM8 | 0x17, NULL, 0},
  264. {"mtu" , DHCP_NUM16 | 0x1a, NULL, 0},
  265. {"hostname" , DHCP_STRING | 0x0c, NULL, 0},
  266. {"domain" , DHCP_STRING | 0x0f, NULL, 0},
  267. {"search" , DHCP_STRLST | 0x77, NULL, 0},
  268. {"nisdomain" , DHCP_STRING | 0x28, NULL, 0},
  269. {"timezone" , DHCP_NUM32 | 0x02, NULL, 0},
  270. {"tftp" , DHCP_STRING | 0x42, NULL, 0},
  271. {"bootfile" , DHCP_STRING | 0x43, NULL, 0},
  272. {"bootsize" , DHCP_NUM16 | 0x0d, NULL, 0},
  273. {"rootpath" , DHCP_STRING | 0x11, NULL, 0},
  274. {"wpad" , DHCP_STRING | 0xfc, NULL, 0},
  275. {"serverid" , DHCP_IP | 0x36, NULL, 0},
  276. {"message" , DHCP_STRING | 0x38, NULL, 0},
  277. {"vlanid" , DHCP_NUM32 | 0x84, NULL, 0},
  278. {"vlanpriority" , DHCP_NUM32 | 0x85, NULL, 0},
  279. {"dns" , DHCP_IPLIST | 0x06, NULL, 0},
  280. {"wins" , DHCP_IPLIST | 0x2c, NULL, 0},
  281. {"nissrv" , DHCP_IPLIST | 0x29, NULL, 0},
  282. {"ntpsrv" , DHCP_IPLIST | 0x2a, NULL, 0},
  283. {"lprsrv" , DHCP_IPLIST | 0x09, NULL, 0},
  284. {"swapsrv" , DHCP_IP | 0x10, NULL, 0},
  285. {"routes" , DHCP_STCRTS | 0x21, NULL, 0},
  286. {"staticroutes" , DHCP_STCRTS | 0x79, NULL, 0},
  287. {"msstaticroutes" , DHCP_STCRTS | 0xf9, NULL, 0},
  288. };
  289. struct fd_pair { int rd; int wr; };
  290. static server_config_t gconfig;
  291. static server_state_t gstate;
  292. static uint8_t infomode;
  293. static struct fd_pair sigfd;
  294. static int constone = 1;
  295. static sa_family_t addr_version = AF_INET;
  296. // calculate options size.
  297. static int dhcp_opt_size(uint8_t *optionptr)
  298. {
  299. int i = 0;
  300. for(;optionptr[i] != 0xff; i++)
  301. if(optionptr[i] != 0x00) i += optionptr[i + 1] + 2 -1;
  302. return i;
  303. }
  304. // calculates checksum for dhcp messeges.
  305. static uint16_t dhcp_checksum(void *addr, int count)
  306. {
  307. int32_t sum = 0;
  308. uint16_t tmp = 0, *source = (uint16_t *)addr;
  309. while (count > 1) {
  310. sum += *source++;
  311. count -= 2;
  312. }
  313. if (count > 0) {
  314. *(uint8_t*)&tmp = *(uint8_t*)source;
  315. sum += tmp;
  316. }
  317. while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
  318. return ~sum;
  319. }
  320. // gets information of INTERFACE and updates IFINDEX, MAC and IP
  321. static int get_interface(const char *interface, int *ifindex, void *oip,
  322. uint8_t *mac)
  323. {
  324. struct ifreq req;
  325. struct sockaddr_in *ip;
  326. struct sockaddr_in6 ip6;
  327. int fd = xsocket(addr_version, SOCK_RAW, IPPROTO_RAW);
  328. char ipv6_addr[40] = {0,};
  329. req.ifr_addr.sa_family = addr_version;
  330. xstrncpy(req.ifr_name, (char *)interface, IFNAMSIZ);
  331. xioctl(fd, SIOCGIFFLAGS, &req);
  332. if (!(req.ifr_flags & IFF_UP)) return -1;
  333. if (addr_version == AF_INET6) {
  334. FILE *fd6 = fopen("/proc/net/if_inet6", "r");
  335. uint8_t *oip6 = (uint8_t*)oip;
  336. int i;
  337. while(fgets(toybuf, sizeof(toybuf), fd6)) {
  338. if (!strstr(toybuf, interface))
  339. continue;
  340. if (sscanf(toybuf, "%32s \n", ipv6_addr) == 1)
  341. break;
  342. }
  343. fclose(fd6);
  344. if (oip6) {
  345. char *ptr = ipv6_addr+sizeof(ipv6_addr)-1;
  346. // convert giant hex string into colon-spearated ipv6 address by
  347. // inserting ':' every 4 characters.
  348. for (i = 32; i; i--)
  349. if ((*(ptr--) = ipv6_addr[i])) if (!(i&3)) *(ptr--) = ':';
  350. dbg("ipv6 %s\n", ipv6_addr);
  351. if(inet_pton(AF_INET6, ipv6_addr, &ip6.sin6_addr) <= 0)
  352. error_msg("inet : the ipv6 address is not proper");
  353. else
  354. memcpy(oip6, ip6.sin6_addr.s6_addr32, sizeof(uint32_t)*4);
  355. }
  356. } else {
  357. uint32_t *oip4 = (uint32_t*)oip;
  358. if (oip4) {
  359. xioctl(fd, SIOCGIFADDR, &req);
  360. ip = (struct sockaddr_in*) &req.ifr_addr;
  361. dbg("IP %s\n", inet_ntoa(ip->sin_addr));
  362. *oip4 = ntohl(ip->sin_addr.s_addr);
  363. }
  364. }
  365. if (ifindex) {
  366. xioctl(fd, SIOCGIFINDEX, &req);
  367. dbg("Adapter index %d\n", req.ifr_ifindex);
  368. *ifindex = req.ifr_ifindex;
  369. }
  370. if (mac) {
  371. xioctl(fd, SIOCGIFHWADDR, &req);
  372. memcpy(mac, req.ifr_hwaddr.sa_data, 6);
  373. dbg("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  374. }
  375. close(fd);
  376. return 0;
  377. }
  378. /*
  379. *logs messeges to syslog or console
  380. *opening the log is still left with applet.
  381. *FIXME: move to more relevent lib. probably libc.c
  382. */
  383. static void infomsg(uint8_t infomode, char *s, ...)
  384. {
  385. int used;
  386. char *msg;
  387. va_list p, t;
  388. if (infomode == LOG_SILENT) return;
  389. va_start(p, s);
  390. va_copy(t, p);
  391. used = vsnprintf(NULL, 0, s, t);
  392. used++;
  393. va_end(t);
  394. msg = xmalloc(used);
  395. vsnprintf(msg, used, s, p);
  396. va_end(p);
  397. if (infomode & LOG_SYSTEM) syslog(LOG_INFO, "%s", msg);
  398. if (infomode & LOG_CONSOLE) printf("%s\n", msg);
  399. free(msg);
  400. }
  401. /*
  402. * Writes self PID in file PATH
  403. * FIXME: libc implementation only writes in /var/run
  404. * this is more generic as some implemenation may provide
  405. * arguments to write in specific file. as dhcpd does.
  406. */
  407. static void write_pid(char *path)
  408. {
  409. int pidfile = open(path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
  410. if (pidfile > 0) {
  411. char pidbuf[12];
  412. sprintf(pidbuf, "%u", (unsigned)getpid());
  413. write(pidfile, pidbuf, strlen(pidbuf));
  414. close(pidfile);
  415. }
  416. }
  417. // Generic signal handler real handling is done in main funcrion.
  418. static void signal_handler(int sig)
  419. {
  420. unsigned char ch = sig;
  421. if (write(sigfd.wr, &ch, 1) != 1) dbg("can't send signal\n");
  422. }
  423. // signal setup for SIGUSR1 SIGTERM
  424. static int setup_signal()
  425. {
  426. if (pipe((int *)&sigfd) < 0) {
  427. dbg("signal pipe failed\n");
  428. return -1;
  429. }
  430. fcntl(sigfd.wr , F_SETFD, FD_CLOEXEC);
  431. fcntl(sigfd.rd , F_SETFD, FD_CLOEXEC);
  432. int flags = fcntl(sigfd.wr, F_GETFL);
  433. fcntl(sigfd.wr, F_SETFL, flags | O_NONBLOCK);
  434. signal(SIGUSR1, signal_handler);
  435. signal(SIGTERM, signal_handler);
  436. return 0;
  437. }
  438. // String STR to UINT32 conversion strored in VAR
  439. static int strtou32(const char *str, void *var)
  440. {
  441. char *endptr = NULL;
  442. int base = 10;
  443. errno=0;
  444. *((uint32_t*)(var)) = 0;
  445. if (str[0]=='0' && (str[1]=='x' || str[1]=='X')) {
  446. base = 16;
  447. str+=2;
  448. }
  449. long ret_val = strtol(str, &endptr, base);
  450. if (errno) infomsg(infomode, "config : Invalid num %s",str);
  451. else if (endptr && (*endptr!='\0'||endptr == str))
  452. infomsg(infomode, "config : Not a valid num %s",str);
  453. else *((uint32_t*)(var)) = (uint32_t)ret_val;
  454. return 0;
  455. }
  456. // copy string STR in variable VAR
  457. static int strinvar(const char *str, void *var)
  458. {
  459. char **dest = var;
  460. if (*dest) free(*dest);
  461. *dest = strdup(str);
  462. return 0;
  463. }
  464. // IP String STR to binary data.
  465. static int striptovar(const char *str, void *var)
  466. {
  467. *((uint32_t*)(var)) = 0;
  468. if(!str) {
  469. error_msg("config : NULL address string \n");
  470. return -1;
  471. }
  472. if((inet_pton(AF_INET6, str, var)<=0) && (inet_pton(AF_INET, str, var)<=0)) {
  473. error_msg("config : wrong address %s \n", str);
  474. return -1;
  475. }
  476. return 0;
  477. }
  478. // String to dhcp option conversion
  479. static int strtoopt(const char *str, void *var)
  480. {
  481. char *option, *valstr, *grp, *tp;
  482. uint32_t optcode = 0, inf = infomode, convtmp, mask, nip, router;
  483. uint16_t flag = 0;
  484. int count, size = ARRAY_LEN(options_list);
  485. if (!*str) return 0;
  486. if (!(option = strtok((char*)str, " \t="))) return -1;
  487. infomode = LOG_SILENT;
  488. strtou32(option, (uint32_t*)&optcode);
  489. infomode = inf;
  490. if (optcode > 0 && optcode < 256) { // raw option
  491. for (count = 0; count < size; count++) {
  492. if ((options_list[count].code & 0X00FF) == optcode) {
  493. flag = (options_list[count].code & 0XFF00);
  494. break;
  495. }
  496. }
  497. } else { //string option
  498. for (count = 0; count < size; count++) {
  499. if (!strncmp(options_list[count].key, option, strlen(options_list[count].key))) {
  500. flag = (options_list[count].code & 0XFF00);
  501. optcode = (options_list[count].code & 0X00FF);
  502. break;
  503. }
  504. }
  505. }
  506. if (count == size) {
  507. infomsg(inf, "config : Obsolete OR Unknown Option : %s", option);
  508. return -1;
  509. }
  510. if (!flag || !optcode) return -1;
  511. if (!(valstr = strtok(NULL, " \t"))) {
  512. dbg("config : option %s has no value defined.\n", option);
  513. return -1;
  514. }
  515. dbg(" value : %-20s : ", valstr);
  516. switch (flag) {
  517. case DHCP_NUM32:
  518. options_list[count].len = sizeof(uint32_t);
  519. options_list[count].val = xmalloc(sizeof(uint32_t));
  520. strtou32(valstr, &convtmp);
  521. memcpy(options_list[count].val, &convtmp, sizeof(uint32_t));
  522. break;
  523. case DHCP_NUM16:
  524. options_list[count].len = sizeof(uint16_t);
  525. options_list[count].val = xmalloc(sizeof(uint16_t));
  526. strtou32(valstr, &convtmp);
  527. memcpy(options_list[count].val, &convtmp, sizeof(uint16_t));
  528. break;
  529. case DHCP_NUM8:
  530. options_list[count].len = sizeof(uint8_t);
  531. options_list[count].val = xmalloc(sizeof(uint8_t));
  532. strtou32(valstr, &convtmp);
  533. memcpy(options_list[count].val, &convtmp, sizeof(uint8_t));
  534. break;
  535. case DHCP_IP:
  536. options_list[count].len = sizeof(uint32_t);
  537. options_list[count].val = xmalloc(sizeof(uint32_t));
  538. striptovar(valstr, options_list[count].val);
  539. break;
  540. case DHCP_STRING:
  541. options_list[count].len = strlen(valstr);
  542. options_list[count].val = strdup(valstr);
  543. break;
  544. case DHCP_IPLIST:
  545. while(valstr){
  546. options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + sizeof(uint32_t));
  547. striptovar(valstr, ((uint8_t*)options_list[count].val)+options_list[count].len);
  548. options_list[count].len += sizeof(uint32_t);
  549. valstr = strtok(NULL," \t");
  550. }
  551. break;
  552. case DHCP_IPPLST:
  553. break;
  554. case DHCP_STCRTS:
  555. /* Option binary format:
  556. * mask [one byte, 0..32]
  557. * ip [0..4 bytes depending on mask]
  558. * router [4 bytes]
  559. * may be repeated
  560. * staticroutes 10.0.0.0/8 10.127.0.1, 10.11.12.0/24 10.11.12.1
  561. */
  562. grp = strtok(valstr, ",");;
  563. while(grp){
  564. while(*grp == ' ' || *grp == '\t') grp++;
  565. tp = strchr(grp, '/');
  566. if (!tp) error_exit("wrong formatted static route option");
  567. *tp = '\0';
  568. mask = strtol(++tp, &tp, 10);
  569. if (striptovar(grp, (uint8_t*)&nip)<0) error_exit("wrong formatted static route option");
  570. while(*tp == ' ' || *tp == '\t' || *tp == '-') tp++;
  571. if (striptovar(tp, (uint8_t*)&router)<0) error_exit("wrong formatted static route option");
  572. options_list[count].val = xrealloc(options_list[count].val, options_list[count].len + 1 + mask/8 + 4);
  573. memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &mask, 1);
  574. options_list[count].len += 1;
  575. memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &nip, mask/8);
  576. options_list[count].len += mask/8;
  577. memcpy(((uint8_t*)options_list[count].val)+options_list[count].len, &router, 4);
  578. options_list[count].len += 4;
  579. tp = NULL;
  580. grp = strtok(NULL, ",");
  581. }
  582. break;
  583. }
  584. return 0;
  585. }
  586. // Reads Static leases from STR and updates inner structures.
  587. static int get_staticlease(const char *str, void *var)
  588. {
  589. struct static_lease_s *sltmp;
  590. char *tkmac, *tkip;
  591. int count;
  592. if (!*str) return 0;
  593. if (!(tkmac = strtok((char*)str, " \t"))) {
  594. infomsg(infomode, "config : static lease : mac not found");
  595. return 0;
  596. }
  597. if (!(tkip = strtok(NULL, " \t"))) {
  598. infomsg(infomode, "config : static lease : no ip bind to mac %s", tkmac);
  599. return 0;
  600. }
  601. sltmp = xzalloc(sizeof(struct static_lease_s));
  602. for (count = 0; count < 6; count++, tkmac++) {
  603. errno = 0;
  604. sltmp->mac[count] = strtol(tkmac, &tkmac, 16);
  605. if (sltmp->mac[count]>255 || sltmp->mac[count]<0 || (*tkmac && *tkmac!=':') || errno) {
  606. infomsg(infomode, "config : static lease : mac address wrong format");
  607. free(sltmp);
  608. return 0;
  609. }
  610. }
  611. striptovar(tkip, &sltmp->nip);
  612. sltmp->next = gstate.leases.sleases;
  613. gstate.leases.sleases = sltmp;
  614. return 0;
  615. }
  616. static struct config_keyword keywords[] = {
  617. // keyword handler variable address default
  618. {"start" , striptovar , (void*)&gconfig.start_ip , "192.168.0.20"},
  619. {"end" , striptovar , (void*)&gconfig.end_ip , "192.168.0.254"},
  620. {"interface" , strinvar , (void*)&gconfig.interface , "eth0"},
  621. {"port" , strtou32 , (void*)&gconfig.port , "67"},
  622. {"min_lease" , strtou32 , (void*)&gconfig.min_lease_sec, "60"},
  623. {"max_leases" , strtou32 , (void*)&gconfig.max_leases , "235"},
  624. {"auto_time" , strtou32 , (void*)&gconfig.auto_time , "7200"},
  625. {"decline_time" , strtou32 , (void*)&gconfig.decline_time , "3600"},
  626. {"conflict_time", strtou32 , (void*)&gconfig.conflict_time, "3600"},
  627. {"offer_time" , strtou32 , (void*)&gconfig.offer_time , "60"},
  628. {"lease_file" , strinvar , (void*)&gconfig.lease_file , "/var/lib/misc/dhcpd.leases"}, //LEASES_FILE
  629. {"lease6_file" , strinvar , (void*)&gconfig.lease6_file , "/var/lib/misc/dhcpd6.leases"}, //LEASES_FILE
  630. {"pidfile" , strinvar , (void*)&gconfig.pidfile , "/var/run/dhcpd.pid"}, //DPID_FILE
  631. {"siaddr" , striptovar , (void*)&gconfig.siaddr_nip , "0.0.0.0"},
  632. {"option" , strtoopt , (void*)&gconfig.options , ""},
  633. {"opt" , strtoopt , (void*)&gconfig.options , ""},
  634. {"notify_file" , strinvar , (void*)&gconfig.notify_file , ""},
  635. {"sname" , strinvar , (void*)&gconfig.sname , ""},
  636. {"boot_file" , strinvar , (void*)&gconfig.boot_file , ""},
  637. {"static_lease" , get_staticlease , (void*)&gconfig.static_leases, ""},
  638. {"start6" , striptovar , (void*)&gconfig.start_ip6 , "2001:620:40b:555::100"},
  639. {"end6" , striptovar , (void*)&gconfig.end_ip6 , "2001:620:40b:555::200"},
  640. {"preferred_lifetime" , strtou32 , (void*)&gconfig.pref_lifetime, "3600"},
  641. {"valid_lifetime" , strtou32 , (void*)&gconfig.valid_lifetime, "7200"},
  642. {"t1" , strtou32 , (void*)&gconfig.t1 , "3600"},
  643. {"t2" , strtou32 , (void*)&gconfig.t2 , "5400"},
  644. };
  645. // Parses the server config file and updates the global server config accordingly.
  646. static int parse_server_config(char *config_file, struct config_keyword *confkey)
  647. {
  648. FILE *fs = NULL;
  649. char *confline_temp = NULL,*confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL};
  650. int len, linelen, tcount, count, size = ARRAY_LEN(keywords);
  651. for (count = 0; count < size; count++)
  652. if (confkey[count].handler)
  653. confkey[count].handler(confkey[count].def, confkey[count].var);
  654. if (!(fs = fopen(config_file, "r"))) perror_msg("%s", config_file);
  655. for (len = 0, linelen = 0; fs;) {
  656. len = getline(&confline_temp, (size_t*) &linelen, fs);
  657. confline = confline_temp;
  658. if (len <= 0) break;
  659. for (; *confline == ' '; confline++, len--);
  660. if ((confline[0] == '#') || (confline[0] == '\n')) goto free_conf_continue;
  661. tk = strchr(confline, '#');
  662. if (tk) {
  663. for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--);
  664. *tk = '\0';
  665. }
  666. tk = strchr(confline, '\n');
  667. if (tk) {
  668. for (; *(tk-1)==' ' || *(tk-1)=='\t'; tk--);
  669. *tk = '\0';
  670. }
  671. for (tcount=0, tk=strtok(confline, " \t"); tk && (tcount < 2);
  672. tcount++, tk=strtok(NULL,(tcount==1)?"":" \t")) {
  673. while ((*tk == '\t') || (*tk == ' ')) tk++;
  674. tokens[tcount] = xstrdup(tk);
  675. }
  676. if (tcount<=1) goto free_tk0_continue;
  677. for (count = 0; count < size; count++) {
  678. if (!strcmp(confkey[count].keyword,tokens[0])) {
  679. dbg("got config : %15s : ", confkey[count].keyword);
  680. if (confkey[count].handler(tokens[1], confkey[count].var) == 0)
  681. dbg("%s \n", tokens[1]);
  682. break;
  683. }
  684. }
  685. if (tokens[1]) { free(tokens[1]); tokens[1] = NULL; }
  686. free_tk0_continue:
  687. if (tokens[0]) { free(tokens[0]); tokens[0] = NULL; }
  688. free_conf_continue:
  689. free(confline_temp);
  690. confline_temp = NULL;
  691. }
  692. if (fs) fclose(fs);
  693. return 0;
  694. }
  695. // opens UDP socket for listen ipv6 packets
  696. static int open_listensock6(void)
  697. {
  698. struct sockaddr_in6 addr6;
  699. struct ipv6_mreq mreq;
  700. if (gstate.listensock > 0) close(gstate.listensock);
  701. dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface);
  702. gstate.listensock = xsocket(PF_INET6, SOCK_DGRAM, 0);
  703. setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
  704. setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_CHECKSUM, &constone, sizeof(constone));
  705. if (setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &constone,
  706. sizeof(constone)) == -1) {
  707. error_msg("failed to receive ipv6 packets.\n");
  708. close(gstate.listensock);
  709. return -1;
  710. }
  711. setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, gconfig.interface, strlen(gconfig.interface)+1);
  712. memset(&addr6, 0, sizeof(addr6));
  713. addr6.sin6_family = AF_INET6;
  714. addr6.sin6_port = htons(gconfig.port); //SERVER_PORT
  715. addr6.sin6_scope_id = if_nametoindex(gconfig.interface);
  716. //Listening for multicast packet
  717. inet_pton(AF_INET6, "ff02::1:2", &addr6.sin6_addr);
  718. if (bind(gstate.listensock, (struct sockaddr *) &addr6, sizeof(addr6)) == -1) {
  719. close(gstate.listensock);
  720. perror_exit("bind failed");
  721. }
  722. memset(&mreq, 0, sizeof(mreq));
  723. mreq.ipv6mr_interface = if_nametoindex(gconfig.interface);
  724. memcpy(&mreq.ipv6mr_multiaddr, &addr6.sin6_addr, sizeof(addr6.sin6_addr));
  725. if(setsockopt(gstate.listensock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) {
  726. error_msg("failed to join a multicast group.\n");
  727. close(gstate.listensock);
  728. return -1;
  729. }
  730. dbg("OPEN : success\n");
  731. return 0;
  732. }
  733. // opens UDP socket for listen
  734. static int open_listensock(void)
  735. {
  736. struct sockaddr_in addr;
  737. struct ifreq ifr;
  738. if (gstate.listensock > 0) close(gstate.listensock);
  739. dbg("Opening listen socket on *:%d %s\n", gconfig.port, gconfig.interface);
  740. gstate.listensock = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  741. setsockopt(gstate.listensock, SOL_SOCKET, SO_REUSEADDR, &constone, sizeof(constone));
  742. if (setsockopt(gstate.listensock, SOL_SOCKET, SO_BROADCAST, &constone, sizeof(constone)) == -1) {
  743. error_msg("failed to receive brodcast packets.\n");
  744. close(gstate.listensock);
  745. return -1;
  746. }
  747. memset(&ifr, 0, sizeof(ifr));
  748. xstrncpy(ifr.ifr_name, gconfig.interface, IFNAMSIZ);
  749. setsockopt(gstate.listensock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
  750. memset(&addr, 0, sizeof(addr));
  751. addr.sin_family = AF_INET;
  752. addr.sin_port = htons(gconfig.port); //SERVER_PORT
  753. addr.sin_addr.s_addr = INADDR_ANY ;
  754. if (bind(gstate.listensock, (struct sockaddr *) &addr, sizeof(addr))) {
  755. close(gstate.listensock);
  756. perror_exit("bind failed");
  757. }
  758. dbg("OPEN : success\n");
  759. return 0;
  760. }
  761. static int send_packet6(uint8_t relay, uint8_t *client_lla, uint16_t optlen)
  762. {
  763. struct sockaddr_ll dest_sll;
  764. dhcp6_raw_t packet;
  765. unsigned padding;
  766. int fd, result = -1;
  767. memset(&packet, 0, sizeof(dhcp6_raw_t));
  768. memcpy(&packet.dhcp6, &gstate.send.send_pkt6, sizeof(dhcp6_msg_t));
  769. padding = sizeof(packet.dhcp6.options) - optlen;
  770. if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6))) < 0) {
  771. dbg("SEND : ipv6 socket failed\n");
  772. return -1;
  773. }
  774. memset(&dest_sll, 0, sizeof(dest_sll));
  775. dest_sll.sll_family = AF_PACKET;
  776. dest_sll.sll_protocol = htons(ETH_P_IPV6);
  777. dest_sll.sll_ifindex = gconfig.ifindex;
  778. dest_sll.sll_halen = ETH_ALEN;
  779. memcpy(dest_sll.sll_addr, client_lla, sizeof(uint8_t)*6);
  780. if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) {
  781. dbg("SEND : bind failed\n");
  782. close(fd);
  783. return -1;
  784. }
  785. memcpy(&packet.iph.ip6_src, &gconfig.server_nip6, sizeof(uint32_t)*4);
  786. memcpy(&packet.iph.ip6_dst, &gstate.client_nip6, sizeof(uint32_t)*4);
  787. packet.udph.source = htons(gconfig.port); //SERVER_PORT
  788. packet.udph.dest = gstate.client_port; //CLIENT_PORT
  789. packet.udph.len = htons(sizeof(dhcp6_raw_t) - sizeof(struct ip6_hdr) - padding);
  790. packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(ntohs(packet.udph.len) + 0x11);
  791. packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp6_raw_t) - padding);
  792. packet.iph.ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
  793. packet.iph.ip6_ctlun.ip6_un1.ip6_un1_plen = packet.udph.len;
  794. packet.iph.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_UDP;
  795. packet.iph.ip6_ctlun.ip6_un1.ip6_un1_hlim = 0x64;
  796. result = sendto(fd, &packet, sizeof(dhcp6_raw_t)-padding,
  797. 0, (struct sockaddr *) &dest_sll, sizeof(dest_sll));
  798. dbg("sendto %d\n", result);
  799. close(fd);
  800. if (result < 0) dbg("PACKET send error\n");
  801. return result;
  802. }
  803. // Sends data through raw socket.
  804. static int send_packet(uint8_t broadcast)
  805. {
  806. struct sockaddr_ll dest_sll;
  807. dhcp_raw_t packet;
  808. unsigned padding;
  809. int fd, result = -1;
  810. uint8_t bmacaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  811. memset(&packet, 0, sizeof(dhcp_raw_t));
  812. memcpy(&packet.dhcp, &gstate.send.send_pkt, sizeof(dhcp_msg_t));
  813. if ((fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0) {
  814. dbg("SEND : socket failed\n");
  815. return -1;
  816. }
  817. memset(&dest_sll, 0, sizeof(dest_sll));
  818. dest_sll.sll_family = AF_PACKET;
  819. dest_sll.sll_protocol = htons(ETH_P_IP);
  820. dest_sll.sll_ifindex = gconfig.ifindex;
  821. dest_sll.sll_halen = 6;
  822. memcpy(dest_sll.sll_addr, (broadcast)?bmacaddr:gstate.rcvd.rcvd_pkt.chaddr , 6);
  823. if (bind(fd, (struct sockaddr *) &dest_sll, sizeof(dest_sll)) < 0) {
  824. dbg("SEND : bind failed\n");
  825. close(fd);
  826. return -1;
  827. }
  828. padding = 308 - 1 - dhcp_opt_size(gstate.send.send_pkt.options);
  829. packet.iph.protocol = IPPROTO_UDP;
  830. packet.iph.saddr = gconfig.server_nip;
  831. packet.iph.daddr = (broadcast || (gstate.rcvd.rcvd_pkt.ciaddr == 0))?
  832. INADDR_BROADCAST : gstate.rcvd.rcvd_pkt.ciaddr;
  833. packet.udph.source = htons(gconfig.port);//SERVER_PORT
  834. packet.udph.dest = gstate.client_port; //CLIENT_PORT
  835. packet.udph.len = htons(sizeof(dhcp_raw_t) - sizeof(struct iphdr) - padding);
  836. packet.iph.tot_len = packet.udph.len;
  837. packet.udph.check = dhcp_checksum(&packet, sizeof(dhcp_raw_t) - padding);
  838. packet.iph.tot_len = htons(sizeof(dhcp_raw_t) - padding);
  839. packet.iph.ihl = sizeof(packet.iph) >> 2;
  840. packet.iph.version = IPVERSION;
  841. packet.iph.ttl = IPDEFTTL;
  842. packet.iph.check = dhcp_checksum(&packet.iph, sizeof(packet.iph));
  843. result = sendto(fd, &packet, sizeof(dhcp_raw_t) - padding, 0,
  844. (struct sockaddr *) &dest_sll, sizeof(dest_sll));
  845. dbg("sendto %d\n", result);
  846. close(fd);
  847. if (result < 0) dbg("PACKET send error\n");
  848. return result;
  849. }
  850. static int read_packet6(void)
  851. {
  852. int ret;
  853. struct sockaddr_in6 c_addr;
  854. socklen_t c_addr_size = sizeof(c_addr);
  855. memset(&gstate.rcvd.rcvd_pkt6, 0, sizeof(dhcp6_msg_t));
  856. ret = recvfrom(gstate.listensock, &gstate.rcvd.rcvd_pkt6, sizeof(dhcp6_msg_t),
  857. 0, (struct sockaddr*) &c_addr, &c_addr_size);
  858. memcpy(gstate.client_nip6, &c_addr.sin6_addr, sizeof(uint32_t)*4);
  859. memcpy(&gstate.client_port, &c_addr.sin6_port, sizeof(uint32_t));
  860. if (ret < 0) {
  861. dbg("Packet read error, ignoring. \n");
  862. return ret; // returns -1
  863. }
  864. if (gstate.rcvd.rcvd_pkt6.msgtype < 1) {
  865. dbg("Bad message type, igroning. \n");
  866. return -2;
  867. }
  868. dbg("Received an ipv6 packet. Size : %d \n", ret);
  869. return ret;
  870. }
  871. // Reads from UDP socket
  872. static int read_packet(void)
  873. {
  874. int ret;
  875. struct sockaddr_in c_addr;
  876. socklen_t c_addr_size = sizeof(c_addr);
  877. memset(&gstate.rcvd.rcvd_pkt, 0, sizeof(dhcp_msg_t));
  878. ret = recvfrom(gstate.listensock, &gstate.rcvd.rcvd_pkt, sizeof(dhcp_msg_t),
  879. 0, (struct sockaddr*) &c_addr, &c_addr_size);
  880. memcpy(&gstate.client_port, &c_addr.sin_port, sizeof(uint32_t));
  881. /*ret = read(gstate.listensock, &gstate.rcvd.rcvd_pkt, sizeof(dhcp_msg_t));*/
  882. if (ret < 0) {
  883. dbg("Packet read error, ignoring. \n");
  884. return ret; // returns -1
  885. }
  886. if (gstate.rcvd.rcvd_pkt.cookie != htonl(DHCP_MAGIC)) {
  887. dbg("Packet with bad magic, ignoring. \n");
  888. return -2;
  889. }
  890. if (gstate.rcvd.rcvd_pkt.op != 1) { //BOOTPREQUEST
  891. dbg("Not a BOOT REQUEST ignoring. \n");
  892. return -2;
  893. }
  894. if (gstate.rcvd.rcvd_pkt.hlen != 6) {
  895. dbg("hlen != 6 ignoring. \n");
  896. return -2;
  897. }
  898. dbg("Received a packet. Size : %d \n", ret);
  899. return ret;
  900. }
  901. // Preapres a dhcp packet with defaults and configs
  902. static uint8_t* prepare_send_pkt(void)
  903. {
  904. memset((void*)&gstate.send.send_pkt, 0, sizeof(gstate.send.send_pkt));
  905. gstate.send.send_pkt.op = 2; //BOOTPREPLY
  906. gstate.send.send_pkt.htype = 1;
  907. gstate.send.send_pkt.hlen = 6;
  908. gstate.send.send_pkt.xid = gstate.rcvd.rcvd_pkt.xid;
  909. gstate.send.send_pkt.cookie = htonl(DHCP_MAGIC);
  910. gstate.send.send_pkt.nsiaddr = gconfig.server_nip;
  911. memcpy(gstate.send.send_pkt.chaddr, gstate.rcvd.rcvd_pkt.chaddr, 16);
  912. gstate.send.send_pkt.options[0] = DHCP_OPT_END;
  913. return gstate.send.send_pkt.options;
  914. }
  915. static uint8_t* prepare_send_pkt6(uint16_t opt)
  916. {
  917. memset((void*)&gstate.send.send_pkt6, 0, sizeof(gstate.send.send_pkt6));
  918. gstate.send.send_pkt6.msgtype = opt;
  919. memcpy(gstate.send.send_pkt6.transaction_id, gstate.rcvd.rcvd_pkt6.transaction_id, 3);
  920. return gstate.send.send_pkt6.options;
  921. }
  922. // Sets a option value in dhcp packet's option field
  923. static uint8_t* set_optval(uint8_t *optptr, uint16_t opt, void *var, size_t len)
  924. {
  925. while (*optptr != DHCP_OPT_END) optptr++;
  926. *optptr++ = (uint8_t)(opt & 0x00FF);
  927. *optptr++ = (uint8_t) len;
  928. memcpy(optptr, var, len);
  929. optptr += len;
  930. *optptr = DHCP_OPT_END;
  931. return optptr;
  932. }
  933. static uint8_t* set_optval6(uint8_t *optptr, uint16_t opt, void *var, size_t len)
  934. {
  935. *((uint16_t*)optptr) = htons(opt);
  936. *(uint16_t*)(optptr+2) = htons(len);
  937. memcpy(optptr+4, var, len);
  938. optptr += len+4;
  939. return optptr;
  940. }
  941. // Gets a option value from dhcp packet's option field
  942. static uint8_t* get_optval(uint8_t *optptr, uint16_t opt, void *var)
  943. {
  944. size_t len;
  945. uint8_t overloaded = 0;
  946. while (1) {
  947. while (*optptr == DHCP_OPT_PADDING) optptr++;
  948. if ((*optptr & 0x00FF) == DHCP_OPT_END) break;
  949. if ((*optptr & 0x00FF) == DHCP_OPT_OPTION_OVERLOAD) {
  950. overloaded = optptr[2];
  951. optptr += optptr[1] + 2;
  952. }
  953. len = optptr[1];
  954. if (*optptr == (opt & 0x00FF))
  955. switch (opt & 0xFF00) {
  956. case DHCP_NUM32: // FALLTHROUGH
  957. case DHCP_IP:
  958. memcpy(var, optptr+2, sizeof(uint32_t));
  959. optptr += len + 2;
  960. return optptr;
  961. break;
  962. case DHCP_NUM16:
  963. memcpy(var, optptr+2, sizeof(uint16_t));
  964. optptr += len + 2;
  965. return optptr;
  966. break;
  967. case DHCP_NUM8:
  968. memcpy(var, optptr+2, sizeof(uint8_t));
  969. optptr += len + 2;
  970. return optptr;
  971. break;
  972. case DHCP_STRING:
  973. var = xstrndup((char*) optptr, len);
  974. optptr += len + 2;
  975. return optptr;
  976. break;
  977. }
  978. optptr += len + 2;
  979. }
  980. if ((overloaded == 1) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.file, opt, var);
  981. if ((overloaded == 2) | (overloaded == 3)) get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.sname, opt, var);
  982. return optptr;
  983. }
  984. static uint8_t* get_optval6(uint8_t *optptr, uint16_t opt, uint16_t *datalen, void **var)
  985. {
  986. uint16_t optcode;
  987. uint16_t len;
  988. memcpy(&optcode, optptr, sizeof(uint16_t));
  989. memcpy(&len, optptr+2, sizeof(uint16_t));
  990. if(!optcode) {
  991. dbg("Option %d is not exist.\n", opt);
  992. return optptr;
  993. }
  994. optcode = ntohs(optcode);
  995. len = ntohs(len);
  996. if (opt == optcode) {
  997. *var = xmalloc(len);
  998. memcpy(*var, optptr+4, len);
  999. optptr = optptr + len + 4;
  1000. memcpy(datalen, &len, sizeof(uint16_t));
  1001. }
  1002. else {
  1003. optptr = get_optval6(optptr+len+4, opt, datalen, var);
  1004. }
  1005. return optptr;
  1006. }
  1007. // Retrives Requested Parameter list from dhcp req packet.
  1008. static uint8_t get_reqparam(uint8_t **list)
  1009. {
  1010. uint8_t len, *optptr;
  1011. if(*list) free(*list);
  1012. for (optptr = gstate.rcvd.rcvd_pkt.options;
  1013. *optptr && *optptr!=((DHCP_OPT_PARAM_REQ) & 0x00FF); optptr+=optptr[1]+2);
  1014. len = *++optptr;
  1015. *list = xzalloc(len+1);
  1016. memcpy(*list, ++optptr, len);
  1017. return len;
  1018. }
  1019. // Sets values of req param in dhcp offer packet.
  1020. static uint8_t* set_reqparam(uint8_t *optptr, uint8_t *list)
  1021. {
  1022. uint8_t reqcode;
  1023. int count, size = ARRAY_LEN(options_list);
  1024. while (*list) {
  1025. reqcode = *list++;
  1026. for (count = 0; count < size; count++) {
  1027. if ((options_list[count].code & 0X00FF)==reqcode) {
  1028. if (!(options_list[count].len) || !(options_list[count].val)) break;
  1029. for (; *optptr && *optptr!=DHCP_OPT_END; optptr+=optptr[1]+2);
  1030. *optptr++ = (uint8_t) (options_list[count].code & 0x00FF);
  1031. *optptr++ = (uint8_t) options_list[count].len;
  1032. memcpy(optptr, options_list[count].val, options_list[count].len);
  1033. optptr += options_list[count].len;
  1034. *optptr = DHCP_OPT_END;
  1035. break;
  1036. }
  1037. }
  1038. }
  1039. return optptr;
  1040. }
  1041. static void run_notify(char **argv)
  1042. {
  1043. struct stat sts;
  1044. volatile int error = 0;
  1045. pid_t pid;
  1046. if (stat(argv[0], &sts) == -1 && errno == ENOENT) {
  1047. infomsg(infomode, "notify file: %s : not exist.", argv[0]);
  1048. return;
  1049. }
  1050. fflush(NULL);
  1051. pid = vfork();
  1052. if (pid < 0) {
  1053. dbg("Fork failed.\n");
  1054. return;
  1055. }
  1056. if (!pid) {
  1057. execvp(argv[0], argv);
  1058. error = errno;
  1059. _exit(111);
  1060. }
  1061. if (error) {
  1062. waitpid(pid, NULL, 0);
  1063. errno = error;
  1064. }
  1065. dbg("script complete.\n");
  1066. }
  1067. static void write_leasefile(void)
  1068. {
  1069. int fd;
  1070. uint32_t curr, tmp_time;
  1071. int64_t timestamp;
  1072. struct arg_list *listdls = gstate.dleases;
  1073. dyn_lease *dls;
  1074. if ((fd = open(gconfig.lease_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
  1075. perror_msg("can't open %s ", gconfig.lease_file);
  1076. } else {
  1077. curr = timestamp = time(NULL);
  1078. timestamp = SWAP_BE64(timestamp);
  1079. writeall(fd, &timestamp, sizeof(timestamp));
  1080. while (listdls) {
  1081. dls = (dyn_lease*)listdls->arg;
  1082. tmp_time = dls->expires;
  1083. dls->expires -= curr;
  1084. if ((int32_t) dls->expires < 0) goto skip;
  1085. dls->expires = htonl(dls->expires);
  1086. writeall(fd, dls, sizeof(dyn_lease));
  1087. skip:
  1088. dls->expires = tmp_time;
  1089. listdls = listdls->next;
  1090. }
  1091. close(fd);
  1092. if (gconfig.notify_file) {
  1093. char *argv[3];
  1094. argv[0] = gconfig.notify_file;
  1095. argv[1] = gconfig.lease_file;
  1096. argv[2] = NULL;
  1097. run_notify(argv);
  1098. }
  1099. }
  1100. }
  1101. static void write_lease6file(void)
  1102. {
  1103. int fd;
  1104. uint32_t curr, tmp_time;
  1105. int64_t timestamp;
  1106. struct arg_list *listdls = gstate.dleases;
  1107. dyn_lease6 *dls6;
  1108. if ((fd = open(gconfig.lease6_file, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
  1109. perror_msg("can't open %s ", gconfig.lease6_file);
  1110. } else {
  1111. curr = timestamp = time(NULL);
  1112. timestamp = SWAP_BE64(timestamp);
  1113. writeall(fd, &timestamp, sizeof(timestamp));
  1114. while (listdls) {
  1115. dls6 = (dyn_lease6*)listdls->arg;
  1116. tmp_time = dls6->expires;
  1117. dls6->expires -= curr;
  1118. if ((int32_t) dls6->expires < 0) goto skip;
  1119. dls6->expires = htonl(dls6->expires);
  1120. writeall(fd, dls6, sizeof(dyn_lease6));
  1121. skip:
  1122. dls6->expires = tmp_time;
  1123. listdls = listdls->next;
  1124. }
  1125. close(fd);
  1126. if (gconfig.notify_file) {
  1127. char *argv[3];
  1128. argv[0] = gconfig.notify_file;
  1129. argv[1] = gconfig.lease6_file;
  1130. argv[2] = NULL;
  1131. run_notify(argv);
  1132. }
  1133. }
  1134. }
  1135. // Update max lease time from options.
  1136. static void set_maxlease(void)
  1137. {
  1138. int count, size = ARRAY_LEN(options_list);
  1139. for (count = 0; count < size; count++)
  1140. if (options_list[count].val && options_list[count].code == (DHCP_OPT_LEASE_TIME)) {
  1141. gconfig.max_lease_sec = *((uint32_t*)options_list[count].val);
  1142. break;
  1143. }
  1144. if (!gconfig.max_lease_sec) gconfig.max_lease_sec = (60*60*24*10);// DEFAULT_LEASE_TIME;
  1145. }
  1146. // Returns lease time for client.
  1147. static uint32_t get_lease(uint32_t req_exp)
  1148. {
  1149. uint32_t now = time(NULL);
  1150. req_exp = req_exp - now;
  1151. if(addr_version == AF_INET6) {
  1152. if ((req_exp <= 0) || req_exp > gconfig.pref_lifetime ||
  1153. req_exp > gconfig.valid_lifetime) {
  1154. if ((gconfig.pref_lifetime > gconfig.valid_lifetime)) {
  1155. error_msg("The valid lifetime must be greater than the preferred lifetime, \
  1156. setting to valid lifetime %u", gconfig.valid_lifetime);
  1157. return gconfig.valid_lifetime;
  1158. }
  1159. return gconfig.pref_lifetime;
  1160. }
  1161. } else {
  1162. if ((req_exp <= 0) || (req_exp > gconfig.max_lease_sec))
  1163. return gconfig.max_lease_sec;
  1164. if (req_exp < gconfig.min_lease_sec)
  1165. return gconfig.min_lease_sec;
  1166. }
  1167. return req_exp;
  1168. }
  1169. static int verifyip6_in_lease(uint8_t *nip6, uint8_t *duid, uint16_t ia_type, uint32_t iaid)
  1170. {
  1171. static_lease6 *sls6;
  1172. struct arg_list *listdls;
  1173. for (listdls = gstate.dleases; listdls; listdls = listdls->next) {
  1174. if (!memcmp(((dyn_lease6*) listdls->arg)->lease_nip6, nip6, sizeof(uint32_t)*4))
  1175. return -1;
  1176. if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len)
  1177. && ((dyn_lease6*) listdls->arg)->ia_type == ia_type)
  1178. return -1;
  1179. }
  1180. for (sls6 = gstate.leases.sleases6; sls6; sls6 = sls6->next)
  1181. if (memcmp(sls6->nip6, nip6, sizeof(uint32_t)*4)==0) return -2;
  1182. if (memcmp(nip6, gconfig.start_ip6, sizeof(uint32_t)*4) < 0 ||
  1183. memcmp(nip6, gconfig.end_ip6, sizeof(uint32_t)*4) > 0)
  1184. return -3;
  1185. return 0;
  1186. }
  1187. // Verify ip NIP in current leases ( assigned or not)
  1188. static int verifyip_in_lease(uint32_t nip, uint8_t mac[6])
  1189. {
  1190. static_lease *sls;
  1191. struct arg_list *listdls;
  1192. for (listdls = gstate.dleases; listdls; listdls = listdls->next) {
  1193. if (((dyn_lease*) listdls->arg)->lease_nip == nip) {
  1194. if (((int32_t)(((dyn_lease*) listdls->arg)->expires) - time(NULL)) < 0)
  1195. return 0;
  1196. return -1;
  1197. }
  1198. if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) return -1;
  1199. }
  1200. for (sls = gstate.leases.sleases; sls; sls = sls->next)
  1201. if (sls->nip == nip) return -2;
  1202. if ((ntohl(nip) < gconfig.start_ip) || (ntohl(nip) > gconfig.end_ip))
  1203. return -3;
  1204. return 0;
  1205. }
  1206. // add ip assigned_nip to dynamic lease.
  1207. static int addip_to_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname, uint8_t update)
  1208. {
  1209. dyn_lease *dls;
  1210. struct arg_list *listdls = gstate.dleases;
  1211. uint32_t now = time(NULL);
  1212. while (listdls) {
  1213. if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) {
  1214. if (update) *req_exp = get_lease(*req_exp + ((dyn_lease*) listdls->arg)->expires);
  1215. ((dyn_lease*) listdls->arg)->expires = *req_exp + now;
  1216. return 0;
  1217. }
  1218. listdls = listdls->next;
  1219. }
  1220. dls = xzalloc(sizeof(dyn_lease));
  1221. memcpy(dls->lease_mac, mac, 6);
  1222. dls->lease_nip = assigned_nip;
  1223. if (hostname) memcpy(dls->hostname, hostname, 20);
  1224. if (update) *req_exp = get_lease(*req_exp + now);
  1225. dls->expires = *req_exp + now;
  1226. listdls = xzalloc(sizeof(struct arg_list));
  1227. listdls->next = gstate.dleases;
  1228. listdls->arg = (char*)dls;
  1229. gstate.dleases = listdls;
  1230. return 0;
  1231. }
  1232. static 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)
  1233. {
  1234. dyn_lease6 *dls6;
  1235. struct arg_list *listdls = gstate.dleases;
  1236. uint32_t now = time(NULL);
  1237. while (listdls) {
  1238. if (!memcmp(((dyn_lease6*) listdls->arg)->duid, duid, ((dyn_lease6*) listdls->arg)->duid_len)) {
  1239. if (update) *lifetime = get_lease(*lifetime + ((dyn_lease6*) listdls->arg)->expires);
  1240. ((dyn_lease6*) listdls->arg)->expires = *lifetime + now;
  1241. return 0;
  1242. }
  1243. listdls = listdls->next;
  1244. }
  1245. dls6 = xzalloc(sizeof(dyn_lease6));
  1246. dls6->duid_len = duid_len;
  1247. memcpy(dls6->duid, duid, duid_len);
  1248. dls6->ia_type = ia_type;
  1249. dls6->iaid = iaid;
  1250. memcpy(dls6->lease_nip6, assigned_nip, sizeof(uint32_t)*4);
  1251. if (update) *lifetime = get_lease(*lifetime + now);
  1252. dls6->expires = *lifetime + now;
  1253. listdls = xzalloc(sizeof(struct arg_list));
  1254. listdls->next = gstate.dleases;
  1255. listdls->arg = (char*)dls6;
  1256. gstate.dleases = listdls;
  1257. return 0;
  1258. }
  1259. // delete ip assigned_nip from dynamic lease.
  1260. static int delip_from_lease(uint32_t assigned_nip, uint8_t mac[6], uint32_t del_time)
  1261. {
  1262. struct arg_list *listdls = gstate.dleases;
  1263. while (listdls) {
  1264. if (!memcmp(((dyn_lease*) listdls->arg)->lease_mac, mac, 6)) {
  1265. ((dyn_lease*) listdls->arg)->expires = del_time + time(NULL);
  1266. return 0;
  1267. }
  1268. listdls = listdls->next;
  1269. }
  1270. return -1;
  1271. }
  1272. // returns a IP from static, dynamic leases or free ip pool, 0 otherwise.
  1273. static uint32_t getip_from_pool(uint32_t req_nip, uint8_t mac[6], uint32_t *req_exp, char *hostname)
  1274. {
  1275. uint32_t nip = 0;
  1276. static_lease *sls = gstate.leases.sleases;
  1277. struct arg_list *listdls = gstate.dleases, *tmp = NULL;
  1278. if (req_nip && (!verifyip_in_lease(req_nip, mac))) nip = req_nip;
  1279. if (!nip) {
  1280. while (listdls) {
  1281. if (!memcmp(((dyn_lease*)listdls->arg)->lease_mac, mac, 6)) {
  1282. nip = ((dyn_lease*)listdls->arg)->lease_nip;
  1283. if (tmp) tmp->next = listdls->next;
  1284. else gstate.dleases = listdls->next;
  1285. free(listdls->arg);
  1286. free(listdls);
  1287. if (verifyip_in_lease(nip, mac) < 0) nip = 0;
  1288. break;
  1289. }
  1290. tmp = listdls;
  1291. listdls = listdls->next;
  1292. }
  1293. }
  1294. if (!nip) {
  1295. while (sls) {
  1296. if (memcmp(sls->mac, mac, 6) == 0) {
  1297. nip = sls->nip;
  1298. break;
  1299. }
  1300. sls = sls->next;
  1301. }
  1302. }
  1303. if (!nip) {
  1304. for (nip = htonl(gconfig.start_ip); ntohl(nip) <= gconfig.end_ip; ) {
  1305. if (!verifyip_in_lease(nip, mac)) break;
  1306. nip = ntohl(nip);
  1307. nip = htonl(++nip);
  1308. }
  1309. if (ntohl(nip) > gconfig.end_ip) {
  1310. nip = 0;
  1311. infomsg(infomode, "can't find free IP in IP Pool.");
  1312. }
  1313. }
  1314. if (nip) addip_to_lease(nip, mac, req_exp, hostname, 1);
  1315. return nip;
  1316. }
  1317. static uint8_t *getip6_from_pool(uint8_t *duid, uint16_t duid_len, uint16_t ia_type, uint32_t iaid, uint32_t *lifetime)
  1318. {
  1319. static uint8_t nip6[16] = {0, };
  1320. static_lease6 *sls6 = gstate.leases.sleases6;
  1321. struct arg_list *listdls6 = gstate.dleases, *tmp = NULL;
  1322. while(listdls6) {
  1323. if (!memcmp(((dyn_lease6*)listdls6->arg)->duid, duid, duid_len)) {
  1324. memcpy(nip6, ((dyn_lease6*)listdls6->arg)->lease_nip6, sizeof(nip6));
  1325. if(tmp) tmp->next = listdls6->next;
  1326. else gstate.dleases = listdls6->next;
  1327. free(listdls6->arg);
  1328. free(listdls6);
  1329. if(verifyip6_in_lease(nip6, duid, ia_type, iaid) < 0)
  1330. memset(nip6, 0, sizeof(nip6));
  1331. break;
  1332. }
  1333. tmp = listdls6;
  1334. listdls6 = listdls6->next;
  1335. }
  1336. if(!memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
  1337. while(sls6) {
  1338. if(!memcmp(sls6->duid, duid, 6)) {
  1339. memcpy(nip6, sls6->nip6, sizeof(nip6));
  1340. break;
  1341. }
  1342. sls6 = sls6->next;
  1343. }
  1344. }
  1345. if(!memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
  1346. memcpy(nip6, gconfig.start_ip6, sizeof(nip6));
  1347. while(memcmp(nip6, gconfig.end_ip6, sizeof(nip6)) < 0) {
  1348. if(!verifyip6_in_lease(nip6, duid, ia_type, iaid)) break;
  1349. int i=sizeof(nip6);
  1350. while(i--) {
  1351. ++nip6[i];
  1352. if (!nip6[i]) {
  1353. if(i==(sizeof(nip6)-1)) ++nip6[i];
  1354. ++nip6[i-1];
  1355. } else
  1356. break;
  1357. }
  1358. }
  1359. if (memcmp(nip6, gconfig.end_ip6, sizeof(nip6)) > 0) {
  1360. memset(nip6, 0, sizeof(nip6));
  1361. infomsg(infomode, "can't find free IP in IPv6 Pool.");
  1362. }
  1363. }
  1364. if(memcmp(nip6, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
  1365. addip6_to_lease(nip6, duid, duid_len, ia_type, iaid, lifetime, 1);
  1366. infomsg(infomode, "Assigned IPv6 %02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X",
  1367. nip6[0], nip6[1], nip6[2], nip6[3], nip6[4], nip6[5], nip6[6], nip6[7], nip6[8],
  1368. nip6[9], nip6[10], nip6[11], nip6[12], nip6[13], nip6[14], nip6[15]);
  1369. }
  1370. return nip6;
  1371. }
  1372. static void read_leasefile(void)
  1373. {
  1374. uint32_t passed, ip;
  1375. int32_t tmp_time;
  1376. int64_t timestamp;
  1377. dyn_lease *dls;
  1378. int fd = open(gconfig.lease_file, O_RDONLY);
  1379. dls = xzalloc(sizeof(dyn_lease));
  1380. if (read(fd, &timestamp, sizeof(timestamp)) != sizeof(timestamp))
  1381. goto lease_error_exit;
  1382. timestamp = SWAP_BE64(timestamp);
  1383. passed = time(NULL) - timestamp;
  1384. if ((uint64_t)passed > 12 * 60 * 60) goto lease_error_exit;
  1385. while (read(fd, dls, sizeof(dyn_lease)) == sizeof(dyn_lease)) {
  1386. ip = ntohl(dls->lease_nip);
  1387. if (ip >= gconfig.start_ip && ip <= gconfig.end_ip) {
  1388. tmp_time = ntohl(dls->expires) - passed;
  1389. if (tmp_time < 0) continue;
  1390. addip_to_lease(dls->lease_nip, dls->lease_mac,
  1391. (uint32_t*)&tmp_time, dls->hostname, 0);
  1392. }
  1393. }
  1394. lease_error_exit:
  1395. free(dls);
  1396. close(fd);
  1397. }
  1398. static void read_lease6file(void)
  1399. {
  1400. uint32_t passed;
  1401. uint32_t tmp_time;
  1402. int64_t timestamp;
  1403. dyn_lease6 *dls6;
  1404. int fd = open(gconfig.lease6_file, O_RDONLY);
  1405. dls6 = xzalloc(sizeof(dyn_lease6));
  1406. if (read(fd, &timestamp, sizeof(timestamp)) != sizeof(timestamp))
  1407. goto lease6_error_exit;
  1408. timestamp = SWAP_BE64(timestamp);
  1409. passed = time(NULL) - timestamp;
  1410. if ((uint64_t)passed > 12 * 60 * 60) goto lease6_error_exit;
  1411. while (read(fd, dls6, sizeof(dyn_lease6)) == sizeof(dyn_lease6)) {
  1412. if (memcmp(dls6->lease_nip6, gconfig.start_ip6, sizeof(uint32_t)*4) > 0 &&
  1413. memcmp(dls6->lease_nip6, gconfig.end_ip6, sizeof(uint32_t)*4) < 0) {
  1414. tmp_time = ntohl(dls6->expires) - passed;
  1415. if (tmp_time < 0U) continue;
  1416. addip6_to_lease(dls6->lease_nip6, dls6->duid, dls6->duid_len, dls6->ia_type, dls6->iaid,
  1417. (uint32_t*)&tmp_time, 0);
  1418. }
  1419. }
  1420. lease6_error_exit:
  1421. free(dls6);
  1422. close(fd);
  1423. }
  1424. void dhcpd_main(void)
  1425. {
  1426. struct timeval tv;
  1427. int retval, i;
  1428. uint8_t *optptr, msgtype = 0;
  1429. uint16_t optlen = 0;
  1430. uint32_t waited = 0, serverid = 0, requested_nip = 0;
  1431. uint8_t transactionid[3] = {0,};
  1432. uint32_t reqested_lease = 0, ip_pool_size = 0;
  1433. char *hstname = NULL;
  1434. fd_set rfds;
  1435. infomode = LOG_CONSOLE;
  1436. if (!(toys.optflags & FLAG_f)) {
  1437. daemon(0,0);
  1438. infomode = LOG_SILENT;
  1439. }
  1440. if (toys.optflags & FLAG_S) {
  1441. openlog("UDHCPD :", LOG_PID, LOG_DAEMON);
  1442. infomode |= LOG_SYSTEM;
  1443. }
  1444. setlinebuf(stdout);
  1445. //DHCPD_CONF_FILE
  1446. parse_server_config((toys.optc==1)?toys.optargs[0]:"/etc/dhcpd.conf", keywords);
  1447. infomsg(infomode, "toybox dhcpd started");
  1448. if (toys.optflags & FLAG_6){
  1449. addr_version = AF_INET6;
  1450. gconfig.t1 = ntohl(gconfig.t1);
  1451. gconfig.t2 = ntohl(gconfig.t2);
  1452. gconfig.pref_lifetime = ntohl(gconfig.pref_lifetime);
  1453. gconfig.valid_lifetime = ntohl(gconfig.valid_lifetime);
  1454. gconfig.port = 547;
  1455. for(i=0;i<4;i++)
  1456. ip_pool_size += (gconfig.end_ip6[i]-gconfig.start_ip6[i])<<((3-i)*8);
  1457. } else {
  1458. gconfig.start_ip = ntohl(gconfig.start_ip);
  1459. gconfig.end_ip = ntohl(gconfig.end_ip);
  1460. ip_pool_size = gconfig.end_ip - gconfig.start_ip + 1;
  1461. }
  1462. if (gconfig.max_leases > ip_pool_size) {
  1463. error_msg("max_leases=%u is too big, setting to %u",
  1464. (unsigned) gconfig.max_leases, ip_pool_size);
  1465. gconfig.max_leases = ip_pool_size;
  1466. }
  1467. write_pid(gconfig.pidfile);
  1468. set_maxlease();
  1469. if(TT.iface) gconfig.interface = TT.iface;
  1470. if(TT.port) gconfig.port = TT.port;
  1471. (addr_version==AF_INET6) ? read_lease6file() : read_leasefile();
  1472. if (get_interface(gconfig.interface, &gconfig.ifindex,
  1473. (addr_version==AF_INET6)? (void*)gconfig.server_nip6 :
  1474. (void*)&gconfig.server_nip, gconfig.server_mac) < 0)
  1475. perror_exit("Failed to get interface %s", gconfig.interface);
  1476. setup_signal();
  1477. if (addr_version==AF_INET6) {
  1478. open_listensock6();
  1479. } else {
  1480. gconfig.server_nip = htonl(gconfig.server_nip);
  1481. open_listensock();
  1482. }
  1483. fcntl(gstate.listensock, F_SETFD, FD_CLOEXEC);
  1484. for (;;) {
  1485. uint32_t timestmp = time(NULL);
  1486. FD_ZERO(&rfds);
  1487. FD_SET(gstate.listensock, &rfds);
  1488. FD_SET(sigfd.rd, &rfds);
  1489. tv.tv_sec = gconfig.auto_time - waited;
  1490. tv.tv_usec = 0;
  1491. retval = 0;
  1492. serverid = 0;
  1493. msgtype = 0;
  1494. int maxfd = (sigfd.rd > gstate.listensock)? sigfd.rd : gstate.listensock;
  1495. dbg("select waiting ....\n");
  1496. retval = select(maxfd + 1, &rfds, NULL, NULL, (gconfig.auto_time?&tv:NULL));
  1497. if (retval < 0) {
  1498. if (errno == EINTR) {
  1499. waited += (unsigned) time(NULL) - timestmp;
  1500. continue;
  1501. }
  1502. dbg("Error in select wait again...\n");
  1503. continue;
  1504. }
  1505. if (!retval) { // Timed out
  1506. dbg("select wait Timed Out...\n");
  1507. waited = 0;
  1508. (addr_version == AF_INET6)? write_lease6file() : write_leasefile();
  1509. if (get_interface(gconfig.interface, &gconfig.ifindex,
  1510. (addr_version==AF_INET6)? (void*)gconfig.server_nip6 :
  1511. (void*)&gconfig.server_nip, gconfig.server_mac)<0)
  1512. perror_exit("Failed to get interface %s", gconfig.interface);
  1513. if(addr_version != AF_INET6) {
  1514. gconfig.server_nip = htonl(gconfig.server_nip);
  1515. }
  1516. continue;
  1517. }
  1518. if (FD_ISSET(sigfd.rd, &rfds)) { // Some Activity on RDFDs : is signal
  1519. unsigned char sig;
  1520. if (read(sigfd.rd, &sig, 1) != 1) {
  1521. dbg("signal read failed.\n");
  1522. continue;
  1523. }
  1524. switch (sig) {
  1525. case SIGUSR1:
  1526. infomsg(infomode, "Received SIGUSR1");
  1527. (addr_version==AF_INET6)? write_lease6file() : write_leasefile();
  1528. continue;
  1529. case SIGTERM:
  1530. infomsg(infomode, "received sigterm");
  1531. (addr_version==AF_INET6)? write_lease6file() : write_leasefile();
  1532. unlink(gconfig.pidfile);
  1533. exit(0);
  1534. break;
  1535. default: break;
  1536. }
  1537. }
  1538. if (FD_ISSET(gstate.listensock, &rfds)) { // Some Activity on RDFDs : is socket
  1539. dbg("select listen sock read\n");
  1540. if(addr_version==AF_INET6) {
  1541. void *client_duid, *server_duid, *client_ia_na, *server_ia_na,
  1542. *client_ia_pd;
  1543. uint8_t client_lla[6] = {0,};
  1544. uint16_t client_duid_len = 0, server_duid_len = 0, server_ia_na_len = 0,
  1545. client_ia_na_len = 0, client_ia_pd_len = 0;
  1546. if(read_packet6() < 0) {
  1547. open_listensock6();
  1548. continue;
  1549. }
  1550. waited += time(NULL) - timestmp;
  1551. memcpy(&gstate.rqcode, &gstate.rcvd.rcvd_pkt6.msgtype, sizeof(uint8_t));
  1552. memcpy(&transactionid, &gstate.rcvd.rcvd_pkt6.transaction_id,
  1553. sizeof(transactionid));
  1554. if (!gstate.rqcode || gstate.rqcode < DHCP6SOLICIT ||
  1555. gstate.rqcode > DHCP6RELAYREPLY) {
  1556. dbg("no or bad message type option, ignoring packet.\n");
  1557. continue;
  1558. }
  1559. if (memcmp(gstate.rcvd.rcvd_pkt6.transaction_id, transactionid, 3)) {
  1560. dbg("no or bad transaction id, ignoring packet.\n");
  1561. continue;
  1562. }
  1563. waited += time(NULL) - timestmp;
  1564. switch (gstate.rqcode) {
  1565. case DHCP6SOLICIT:
  1566. dbg("Message Type: DHCP6SOLICIT\n");
  1567. optptr = prepare_send_pkt6(DHCP6ADVERTISE);
  1568. optlen = 0;
  1569. //TODO policy check
  1570. //TODO Receive: ORO check (e.g. DNS)
  1571. //Receive: Client Identifier (DUID)
  1572. get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
  1573. DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid);
  1574. //Receive: Identity Association for Non-temporary Address
  1575. if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
  1576. DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) {
  1577. uint16_t ia_addr_len = sizeof(struct optval_ia_addr);
  1578. void *ia_addr, *status_code;
  1579. char *status_code_msg;
  1580. uint16_t status_code_len = 0;
  1581. server_ia_na_len = sizeof(struct optval_ia_na);
  1582. //IA Address
  1583. ia_addr = xzalloc(ia_addr_len);
  1584. struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr;
  1585. (*ia_addr_p).pref_lifetime = gconfig.pref_lifetime;
  1586. (*ia_addr_p).valid_lifetime = gconfig.valid_lifetime;
  1587. memcpy(&(*ia_addr_p).ipv6_addr,
  1588. getip6_from_pool(client_duid, client_duid_len,
  1589. DHCP6_OPT_IA_NA, (*(struct optval_ia_na*) client_ia_na).iaid,
  1590. &(*ia_addr_p).pref_lifetime), sizeof(uint32_t)*4);
  1591. server_ia_na_len += (ia_addr_len+4);
  1592. //Status Code
  1593. if(memcmp((*ia_addr_p).ipv6_addr, (uint8_t[16]){0}, sizeof(uint32_t)*4)) {
  1594. status_code_msg = xstrdup("Assigned an address.");
  1595. status_code_len = strlen(status_code_msg)+1;
  1596. status_code = xzalloc(status_code_len);
  1597. struct optval_status_code *status_code_p =
  1598. (struct optval_status_code*)status_code;
  1599. (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS);
  1600. memcpy((*status_code_p).status_msg, status_code_msg,
  1601. status_code_len);
  1602. server_ia_na_len += (status_code_len+4);
  1603. free(status_code_msg);
  1604. } else {
  1605. status_code_msg = xstrdup("There's no available address.");
  1606. status_code_len = strlen(status_code_msg)+1;
  1607. status_code = xzalloc(status_code_len);
  1608. struct optval_status_code *status_code_p =
  1609. (struct optval_status_code*)status_code;
  1610. (*status_code_p).status_code = htons(DHCP6_STATUS_NOADDRSAVAIL);
  1611. memcpy((*status_code_p).status_msg, status_code_msg,
  1612. status_code_len);
  1613. server_ia_na_len += (status_code_len+4);
  1614. server_ia_na_len -= (ia_addr_len+4);
  1615. ia_addr_len = 0;
  1616. free(ia_addr);
  1617. free(status_code_msg);
  1618. //TODO send failed status code
  1619. break;
  1620. }
  1621. //combine options
  1622. server_ia_na = xzalloc(server_ia_na_len);
  1623. struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na;
  1624. (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid;
  1625. (*ia_na_p).t1 = gconfig.t1;
  1626. (*ia_na_p).t2 = gconfig.t2;
  1627. uint8_t* ia_na_optptr = (*ia_na_p).optval;
  1628. if(ia_addr_len) {
  1629. set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR, ia_addr, ia_addr_len);
  1630. ia_na_optptr += (ia_addr_len + 4);
  1631. free(ia_addr);
  1632. }
  1633. if(status_code_len) {
  1634. set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE, status_code,
  1635. status_code_len);
  1636. ia_na_optptr += (status_code_len);
  1637. free(status_code);
  1638. }
  1639. //Response: Identity Association for Non-temporary Address
  1640. optptr = set_optval6(optptr, DHCP6_OPT_IA_NA, server_ia_na,
  1641. server_ia_na_len);
  1642. optlen += (server_ia_na_len + 4);
  1643. free(client_ia_na);free(server_ia_na);
  1644. }
  1645. //Receive: Identity Association for Prefix Delegation
  1646. else if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
  1647. DHCP6_OPT_IA_PD, &client_ia_pd_len, &client_ia_pd)) {
  1648. //TODO
  1649. //Response: Identity Association for Prefix Delegation
  1650. }
  1651. //DUID type: link-layer address plus time
  1652. if(ntohs((*(struct optval_duid_llt*)client_duid).type) ==
  1653. DHCP6_DUID_LLT) {
  1654. server_duid_len = 8+sizeof(gconfig.server_mac);
  1655. server_duid = xzalloc(server_duid_len);
  1656. struct optval_duid_llt *server_duid_p =
  1657. (struct optval_duid_llt*)server_duid;
  1658. (*server_duid_p).type = htons(1);
  1659. (*server_duid_p).hwtype = htons(1);
  1660. (*server_duid_p).time = htonl((uint32_t)
  1661. (time(NULL) - 946684800) & 0xffffffff);
  1662. memcpy((*server_duid_p).lladdr, gconfig.server_mac,
  1663. sizeof(gconfig.server_mac));
  1664. memcpy(&client_lla, (*(struct optval_duid_llt*)client_duid).lladdr,
  1665. sizeof(client_lla));
  1666. //Response: Server Identifier (DUID)
  1667. optptr = set_optval6(optptr, DHCP6_OPT_SERVERID, server_duid,
  1668. server_duid_len);
  1669. optlen += (server_duid_len + 4);
  1670. //Response: Client Identifier
  1671. optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid,
  1672. client_duid_len);
  1673. optlen += (client_duid_len + 4);
  1674. free(client_duid);free(server_duid);
  1675. }
  1676. send_packet6(0, client_lla, optlen);
  1677. write_lease6file();
  1678. break;
  1679. case DHCP6REQUEST:
  1680. dbg("Message Type: DHCP6REQUEST\n");
  1681. optptr = prepare_send_pkt6(DHCP6REPLY);
  1682. optlen = 0;
  1683. //Receive: Client Identifier (DUID)
  1684. get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
  1685. DHCP6_OPT_CLIENTID, &client_duid_len, &client_duid);
  1686. optptr = set_optval6(optptr, DHCP6_OPT_CLIENTID, client_duid,
  1687. client_duid_len);
  1688. optlen += (client_duid_len + 4);
  1689. memcpy(client_lla, (*(struct optval_duid_llt*)client_duid).lladdr,
  1690. sizeof(client_lla));
  1691. //Receive: Identity Association for Non-temporary Address
  1692. if(get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
  1693. DHCP6_OPT_IA_NA, &client_ia_na_len, &client_ia_na)) {
  1694. uint16_t ia_addr_len = 0, status_code_len = 0;
  1695. void *ia_addr, *status_code;
  1696. uint16_t server_ia_na_len = sizeof(struct optval_ia_na);
  1697. char *status_code_msg;
  1698. //Check IA Address
  1699. get_optval6((uint8_t*)(*(struct optval_ia_na*)client_ia_na).optval,
  1700. DHCP6_OPT_IA_ADDR, &ia_addr_len, &ia_addr);
  1701. struct optval_ia_addr *ia_addr_p = (struct optval_ia_addr*)ia_addr;
  1702. if(verifyip6_in_lease((*ia_addr_p).ipv6_addr, client_duid,
  1703. DHCP6_OPT_IA_NA, (*(struct optval_ia_na*)client_ia_na).iaid)
  1704. == -1) {
  1705. server_ia_na_len += (ia_addr_len + 4);
  1706. //Add Status Code
  1707. status_code_msg = xstrdup("Assigned an address.");
  1708. status_code_len = strlen(status_code_msg) + 1;
  1709. status_code = xzalloc(status_code_len);
  1710. struct optval_status_code *status_code_p =
  1711. (struct optval_status_code*)status_code;
  1712. (*status_code_p).status_code = htons(DHCP6_STATUS_SUCCESS);
  1713. memcpy((*status_code_p).status_msg, status_code_msg,
  1714. status_code_len);
  1715. server_ia_na_len += (status_code_len+4);
  1716. } else {
  1717. //TODO send failed status code
  1718. break;
  1719. }
  1720. //combine options
  1721. server_ia_na = xzalloc(server_ia_na_len);
  1722. struct optval_ia_na *ia_na_p = (struct optval_ia_na*)server_ia_na;
  1723. (*ia_na_p).iaid = (*(struct optval_ia_na*)client_ia_na).iaid;
  1724. (*ia_na_p).t1 = gconfig.t1;
  1725. (*ia_na_p).t2 = gconfig.t2;
  1726. uint8_t* ia_na_optptr = (*ia_na_p).optval;
  1727. ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_IA_ADDR,
  1728. ia_addr, ia_addr_len);
  1729. free(ia_addr);
  1730. if(status_code_len) {
  1731. ia_na_optptr = set_optval6(ia_na_optptr, DHCP6_OPT_STATUS_CODE,
  1732. status_code, status_code_len);
  1733. free(status_code);
  1734. }
  1735. //Response: Identity Association for Non-temporary Address
  1736. //(Status Code added)
  1737. optptr = set_optval6(optptr, DHCP6_OPT_IA_NA,
  1738. server_ia_na, server_ia_na_len);
  1739. optlen += (server_ia_na_len + 4);
  1740. free(client_ia_na);free(server_ia_na);
  1741. }
  1742. //Receive: Server Identifier (DUID)
  1743. get_optval6((uint8_t*)&gstate.rcvd.rcvd_pkt6.options,
  1744. DHCP6_OPT_SERVERID, &server_duid_len, &server_duid);
  1745. optptr = set_optval6(optptr, DHCP6_OPT_SERVERID,
  1746. server_duid, server_duid_len);
  1747. optlen += (server_duid_len + 4);
  1748. free(client_duid); free(server_duid);
  1749. send_packet6(0, client_lla, optlen);
  1750. write_lease6file();
  1751. break;
  1752. case DHCP6DECLINE: //TODO
  1753. case DHCP6RENEW: //TODO
  1754. case DHCP6REBIND: //TODO
  1755. case DHCP6RELEASE:
  1756. dbg("Message Type: DHCP6RELEASE\n");
  1757. optptr = prepare_send_pkt6(DHCP6REPLY);
  1758. break;
  1759. default:
  1760. dbg("Message Type : %u\n", gstate.rqcode);
  1761. break;
  1762. }
  1763. } else {
  1764. if(read_packet() < 0) {
  1765. open_listensock();
  1766. continue;
  1767. }
  1768. waited += time(NULL) - timestmp;
  1769. get_optval((uint8_t*)&gstate.rcvd.rcvd_pkt.options,
  1770. DHCP_OPT_MESSAGE_TYPE, &gstate.rqcode);
  1771. if (gstate.rqcode == 0 || gstate.rqcode < DHCPDISCOVER
  1772. || gstate.rqcode > DHCPINFORM) {
  1773. dbg("no or bad message type option, ignoring packet.\n");
  1774. continue;
  1775. }
  1776. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1777. DHCP_OPT_SERVER_ID, &serverid);
  1778. if (serverid && (serverid != gconfig.server_nip)) {
  1779. dbg("server ID doesn't match, ignoring packet.\n");
  1780. continue;
  1781. }
  1782. waited += time(NULL) - timestmp;
  1783. switch (gstate.rqcode) {
  1784. case DHCPDISCOVER:
  1785. msgtype = DHCPOFFER;
  1786. dbg("Message Type : DHCPDISCOVER\n");
  1787. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1788. DHCP_OPT_REQUESTED_IP, &requested_nip);
  1789. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1790. DHCP_OPT_HOST_NAME, &hstname);
  1791. reqested_lease = gconfig.offer_time;
  1792. get_reqparam(&gstate.rqopt);
  1793. optptr = prepare_send_pkt();
  1794. gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip,
  1795. gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname);
  1796. if(!gstate.send.send_pkt.yiaddr){
  1797. msgtype = DHCPNAK;
  1798. optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
  1799. send_packet(1);
  1800. break;
  1801. }
  1802. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1803. DHCP_OPT_LEASE_TIME, &reqested_lease);
  1804. reqested_lease = htonl(get_lease(reqested_lease + time(NULL)));
  1805. optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
  1806. optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4);
  1807. optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4);
  1808. optptr = set_reqparam(optptr, gstate.rqopt);
  1809. send_packet(1);
  1810. break;
  1811. case DHCPREQUEST:
  1812. msgtype = DHCPACK;
  1813. dbg("Message Type : DHCPREQUEST\n");
  1814. optptr = prepare_send_pkt();
  1815. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1816. DHCP_OPT_REQUESTED_IP, &requested_nip);
  1817. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1818. DHCP_OPT_LEASE_TIME, &reqested_lease);
  1819. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1820. DHCP_OPT_HOST_NAME, &hstname);
  1821. gstate.send.send_pkt.yiaddr = getip_from_pool(requested_nip,
  1822. gstate.rcvd.rcvd_pkt.chaddr, &reqested_lease, hstname);
  1823. if (!serverid) reqested_lease = gconfig.max_lease_sec;
  1824. if (!gstate.send.send_pkt.yiaddr) {
  1825. msgtype = DHCPNAK;
  1826. optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
  1827. send_packet(1);
  1828. break;
  1829. }
  1830. optptr = set_optval(optptr, DHCP_OPT_MESSAGE_TYPE, &msgtype, 1);
  1831. optptr = set_optval(optptr, DHCP_OPT_SERVER_ID, &gconfig.server_nip, 4);
  1832. reqested_lease = htonl(reqested_lease);
  1833. optptr = set_optval(optptr, DHCP_OPT_LEASE_TIME, &reqested_lease, 4);
  1834. send_packet(1);
  1835. write_leasefile();
  1836. break;
  1837. case DHCPDECLINE:// FALL THROUGH
  1838. case DHCPRELEASE:
  1839. dbg("Message Type : DHCPDECLINE or DHCPRELEASE \n");
  1840. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1841. DHCP_OPT_SERVER_ID, &serverid);
  1842. if (serverid != gconfig.server_nip) break;
  1843. get_optval((uint8_t*) &gstate.rcvd.rcvd_pkt.options,
  1844. DHCP_OPT_REQUESTED_IP, &requested_nip);
  1845. delip_from_lease(requested_nip, gstate.rcvd.rcvd_pkt.chaddr,
  1846. (gstate.rqcode==DHCPRELEASE)?0:gconfig.decline_time);
  1847. break;
  1848. default:
  1849. dbg("Message Type : %u\n", gstate.rqcode);
  1850. break;
  1851. }
  1852. }
  1853. }
  1854. }
  1855. }