dhcp6_parser.yy 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910
  1. /* Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
  2. This Source Code Form is subject to the terms of the Mozilla Public
  3. License, v. 2.0. If a copy of the MPL was not distributed with this
  4. file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. %skeleton "lalr1.cc" /* -*- C++ -*- */
  6. %require "3.0.0"
  7. %defines
  8. %define parser_class_name {Dhcp6Parser}
  9. %define api.prefix {parser6_}
  10. %define api.token.constructor
  11. %define api.value.type variant
  12. %define api.namespace {isc::dhcp}
  13. %define parse.assert
  14. %code requires
  15. {
  16. #include <string>
  17. #include <cc/data.h>
  18. #include <dhcp/option.h>
  19. #include <boost/lexical_cast.hpp>
  20. #include <dhcp6/parser_context_decl.h>
  21. using namespace isc::dhcp;
  22. using namespace isc::data;
  23. using namespace std;
  24. }
  25. // The parsing context.
  26. %param { isc::dhcp::Parser6Context& ctx }
  27. %locations
  28. %define parse.trace
  29. %define parse.error verbose
  30. %code
  31. {
  32. #include <dhcp6/parser_context.h>
  33. }
  34. %define api.token.prefix {TOKEN_}
  35. // Tokens in an order which makes sense and related to the intented use.
  36. // Actual regexps for tokens are defined in dhcp6_lexer.ll.
  37. %token
  38. END 0 "end of file"
  39. COMMA ","
  40. COLON ":"
  41. LSQUARE_BRACKET "["
  42. RSQUARE_BRACKET "]"
  43. LCURLY_BRACKET "{"
  44. RCURLY_BRACKET "}"
  45. NULL_TYPE "null"
  46. DHCP6 "Dhcp6"
  47. INTERFACES_CONFIG "interfaces-config"
  48. INTERFACES "interfaces"
  49. RE_DETECT "re-detect"
  50. LEASE_DATABASE "lease-database"
  51. HOSTS_DATABASE "hosts-database"
  52. TYPE "type"
  53. MEMFILE "memfile"
  54. MYSQL "mysql"
  55. POSTGRESQL "postgresql"
  56. CQL "cql"
  57. USER "user"
  58. PASSWORD "password"
  59. HOST "host"
  60. PORT "port"
  61. PERSIST "persist"
  62. LFC_INTERVAL "lfc-interval"
  63. READONLY "readonly"
  64. CONNECT_TIMEOUT "connect-timeout"
  65. CONTACT_POINTS "contact-points"
  66. KEYSPACE "keyspace"
  67. PREFERRED_LIFETIME "preferred-lifetime"
  68. VALID_LIFETIME "valid-lifetime"
  69. RENEW_TIMER "renew-timer"
  70. REBIND_TIMER "rebind-timer"
  71. DECLINE_PROBATION_PERIOD "decline-probation-period"
  72. SUBNET6 "subnet6"
  73. OPTION_DEF "option-def"
  74. OPTION_DATA "option-data"
  75. NAME "name"
  76. DATA "data"
  77. CODE "code"
  78. SPACE "space"
  79. CSV_FORMAT "csv-format"
  80. ALWAYS_SEND "always-send"
  81. RECORD_TYPES "record-types"
  82. ENCAPSULATE "encapsulate"
  83. ARRAY "array"
  84. POOLS "pools"
  85. POOL "pool"
  86. PD_POOLS "pd-pools"
  87. PREFIX "prefix"
  88. PREFIX_LEN "prefix-len"
  89. EXCLUDED_PREFIX "excluded-prefix"
  90. EXCLUDED_PREFIX_LEN "excluded-prefix-len"
  91. DELEGATED_LEN "delegated-len"
  92. USER_CONTEXT "user-context"
  93. SUBNET "subnet"
  94. INTERFACE "interface"
  95. INTERFACE_ID "interface-id"
  96. ID "id"
  97. RAPID_COMMIT "rapid-commit"
  98. RESERVATION_MODE "reservation-mode"
  99. DISABLED "disabled"
  100. OUT_OF_POOL "out-of-pool"
  101. ALL "all"
  102. MAC_SOURCES "mac-sources"
  103. RELAY_SUPPLIED_OPTIONS "relay-supplied-options"
  104. HOST_RESERVATION_IDENTIFIERS "host-reservation-identifiers"
  105. CLIENT_CLASSES "client-classes"
  106. TEST "test"
  107. CLIENT_CLASS "client-class"
  108. RESERVATIONS "reservations"
  109. IP_ADDRESSES "ip-addresses"
  110. PREFIXES "prefixes"
  111. DUID "duid"
  112. HW_ADDRESS "hw-address"
  113. HOSTNAME "hostname"
  114. FLEX_ID "flex-id"
  115. RELAY "relay"
  116. IP_ADDRESS "ip-address"
  117. HOOKS_LIBRARIES "hooks-libraries"
  118. LIBRARY "library"
  119. PARAMETERS "parameters"
  120. EXPIRED_LEASES_PROCESSING "expired-leases-processing"
  121. RECLAIM_TIMER_WAIT_TIME "reclaim-timer-wait-time"
  122. FLUSH_RECLAIMED_TIMER_WAIT_TIME "flush-reclaimed-timer-wait-time"
  123. HOLD_RECLAIMED_TIME "hold-reclaimed-time"
  124. MAX_RECLAIM_LEASES "max-reclaim-leases"
  125. MAX_RECLAIM_TIME "max-reclaim-time"
  126. UNWARNED_RECLAIM_CYCLES "unwarned-reclaim-cycles"
  127. SERVER_ID "server-id"
  128. LLT "LLT"
  129. EN "EN"
  130. LL "LL"
  131. IDENTIFIER "identifier"
  132. HTYPE "htype"
  133. TIME "time"
  134. ENTERPRISE_ID "enterprise-id"
  135. DHCP4O6_PORT "dhcp4o6-port"
  136. CONTROL_SOCKET "control-socket"
  137. SOCKET_TYPE "socket-type"
  138. SOCKET_NAME "socket-name"
  139. DHCP_DDNS "dhcp-ddns"
  140. ENABLE_UPDATES "enable-updates"
  141. QUALIFYING_SUFFIX "qualifying-suffix"
  142. SERVER_IP "server-ip"
  143. SERVER_PORT "server-port"
  144. SENDER_IP "sender-ip"
  145. SENDER_PORT "sender-port"
  146. MAX_QUEUE_SIZE "max-queue-size"
  147. NCR_PROTOCOL "ncr-protocol"
  148. NCR_FORMAT "ncr-format"
  149. ALWAYS_INCLUDE_FQDN "always-include-fqdn"
  150. OVERRIDE_NO_UPDATE "override-no-update"
  151. OVERRIDE_CLIENT_UPDATE "override-client-update"
  152. REPLACE_CLIENT_NAME "replace-client-name"
  153. GENERATED_PREFIX "generated-prefix"
  154. UDP "UDP"
  155. TCP "TCP"
  156. JSON "JSON"
  157. WHEN_PRESENT "when-present"
  158. NEVER "never"
  159. ALWAYS "always"
  160. WHEN_NOT_PRESENT "when-not-present"
  161. LOGGING "Logging"
  162. LOGGERS "loggers"
  163. OUTPUT_OPTIONS "output_options"
  164. OUTPUT "output"
  165. DEBUGLEVEL "debuglevel"
  166. SEVERITY "severity"
  167. FLUSH "flush"
  168. MAXSIZE "maxsize"
  169. MAXVER "maxver"
  170. DHCP4 "Dhcp4"
  171. DHCPDDNS "DhcpDdns"
  172. CONTROL_AGENT "Control-agent"
  173. // Not real tokens, just a way to signal what the parser is expected to
  174. // parse.
  175. TOPLEVEL_JSON
  176. TOPLEVEL_DHCP6
  177. SUB_DHCP6
  178. SUB_INTERFACES6
  179. SUB_SUBNET6
  180. SUB_POOL6
  181. SUB_PD_POOL
  182. SUB_RESERVATION
  183. SUB_OPTION_DEF
  184. SUB_OPTION_DATA
  185. SUB_HOOKS_LIBRARY
  186. SUB_DHCP_DDNS
  187. ;
  188. %token <std::string> STRING "constant string"
  189. %token <int64_t> INTEGER "integer"
  190. %token <double> FLOAT "floating point"
  191. %token <bool> BOOLEAN "boolean"
  192. %type <ElementPtr> value
  193. %type <ElementPtr> map_value
  194. %type <ElementPtr> db_type
  195. %type <ElementPtr> hr_mode
  196. %type <ElementPtr> duid_type
  197. %type <ElementPtr> ncr_protocol_value
  198. %type <ElementPtr> replace_client_name_value
  199. %printer { yyoutput << $$; } <*>;
  200. %%
  201. // The whole grammar starts with a map, because the config file
  202. // consists of Dhcp, Logger and DhcpDdns entries in one big { }.
  203. // We made the same for subparsers at the exception of the JSON value.
  204. %start start;
  205. start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
  206. | TOPLEVEL_DHCP6 { ctx.ctx_ = ctx.CONFIG; } syntax_map
  207. | SUB_DHCP6 { ctx.ctx_ = ctx.DHCP6; } sub_dhcp6
  208. | SUB_INTERFACES6 { ctx.ctx_ = ctx.INTERFACES_CONFIG; } sub_interfaces6
  209. | SUB_SUBNET6 { ctx.ctx_ = ctx.SUBNET6; } sub_subnet6
  210. | SUB_POOL6 { ctx.ctx_ = ctx.POOLS; } sub_pool6
  211. | SUB_PD_POOL { ctx.ctx_ = ctx.PD_POOLS; } sub_pd_pool
  212. | SUB_RESERVATION { ctx.ctx_ = ctx.RESERVATIONS; } sub_reservation
  213. | SUB_OPTION_DEF { ctx.ctx_ = ctx.OPTION_DEF; } sub_option_def
  214. | SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
  215. | SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
  216. | SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
  217. ;
  218. // ---- generic JSON parser ---------------------------------
  219. // Note that ctx_ is NO_KEYWORD here
  220. // Values rule
  221. value: INTEGER { $$ = ElementPtr(new IntElement($1, ctx.loc2pos(@1))); }
  222. | FLOAT { $$ = ElementPtr(new DoubleElement($1, ctx.loc2pos(@1))); }
  223. | BOOLEAN { $$ = ElementPtr(new BoolElement($1, ctx.loc2pos(@1))); }
  224. | STRING { $$ = ElementPtr(new StringElement($1, ctx.loc2pos(@1))); }
  225. | NULL_TYPE { $$ = ElementPtr(new NullElement(ctx.loc2pos(@1))); }
  226. | map2 { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); }
  227. | list_generic { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); }
  228. ;
  229. sub_json: value {
  230. // Push back the JSON value on the stack
  231. ctx.stack_.push_back($1);
  232. };
  233. map2: LCURLY_BRACKET {
  234. // This code is executed when we're about to start parsing
  235. // the content of the map
  236. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  237. ctx.stack_.push_back(m);
  238. } map_content RCURLY_BRACKET {
  239. // map parsing completed. If we ever want to do any wrap up
  240. // (maybe some sanity checking), this would be the best place
  241. // for it.
  242. };
  243. map_value: map2 { $$ = ctx.stack_.back(); ctx.stack_.pop_back(); };
  244. // Assignments rule
  245. map_content: %empty // empty map
  246. | not_empty_map
  247. ;
  248. not_empty_map: STRING COLON value {
  249. // map containing a single entry
  250. ctx.stack_.back()->set($1, $3);
  251. }
  252. | not_empty_map COMMA STRING COLON value {
  253. // map consisting of a shorter map followed by
  254. // comma and string:value
  255. ctx.stack_.back()->set($3, $5);
  256. }
  257. ;
  258. list_generic: LSQUARE_BRACKET {
  259. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  260. ctx.stack_.push_back(l);
  261. } list_content RSQUARE_BRACKET {
  262. // list parsing complete. Put any sanity checking here
  263. };
  264. list_content: %empty // Empty list
  265. | not_empty_list
  266. ;
  267. not_empty_list: value {
  268. // List consisting of a single element.
  269. ctx.stack_.back()->add($1);
  270. }
  271. | not_empty_list COMMA value {
  272. // List ending with , and a value.
  273. ctx.stack_.back()->add($3);
  274. }
  275. ;
  276. // This one is used in syntax parser and is restricted to strings.
  277. list_strings: LSQUARE_BRACKET {
  278. // List parsing about to start
  279. } list_strings_content RSQUARE_BRACKET {
  280. // list parsing complete. Put any sanity checking here
  281. //ctx.stack_.pop_back();
  282. };
  283. list_strings_content: %empty // Empty list
  284. | not_empty_list_strings
  285. ;
  286. not_empty_list_strings: STRING {
  287. ElementPtr s(new StringElement($1, ctx.loc2pos(@1)));
  288. ctx.stack_.back()->add(s);
  289. }
  290. | not_empty_list_strings COMMA STRING {
  291. ElementPtr s(new StringElement($3, ctx.loc2pos(@3)));
  292. ctx.stack_.back()->add(s);
  293. }
  294. ;
  295. // ---- generic JSON parser ends here ----------------------------------
  296. // ---- syntax checking parser starts here -----------------------------
  297. // Unknown keyword in a map
  298. unknown_map_entry: STRING COLON {
  299. const std::string& where = ctx.contextName();
  300. const std::string& keyword = $1;
  301. error(@1,
  302. "got unexpected keyword \"" + keyword + "\" in " + where + " map.");
  303. };
  304. // This defines the top-level { } that holds Control-agent, Dhcp6, Dhcp4,
  305. // DhcpDdns or Logging objects.
  306. syntax_map: LCURLY_BRACKET {
  307. // This code is executed when we're about to start parsing
  308. // the content of the map
  309. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  310. ctx.stack_.push_back(m);
  311. } global_objects RCURLY_BRACKET {
  312. // map parsing completed. If we ever want to do any wrap up
  313. // (maybe some sanity checking), this would be the best place
  314. // for it.
  315. };
  316. // This represents top-level entries: Dhcp6, Dhcp4, DhcpDdns, Logging
  317. global_objects: global_object
  318. | global_objects COMMA global_object
  319. ;
  320. // This represents a single top level entry, e.g. Dhcp6 or DhcpDdns.
  321. global_object: dhcp6_object
  322. | logging_object
  323. | dhcp4_json_object
  324. | dhcpddns_json_object
  325. | control_agent_json_object
  326. | unknown_map_entry
  327. ;
  328. dhcp6_object: DHCP6 {
  329. // This code is executed when we're about to start parsing
  330. // the content of the map
  331. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  332. ctx.stack_.back()->set("Dhcp6", m);
  333. ctx.stack_.push_back(m);
  334. ctx.enter(ctx.DHCP6);
  335. } COLON LCURLY_BRACKET global_params RCURLY_BRACKET {
  336. // map parsing completed. If we ever want to do any wrap up
  337. // (maybe some sanity checking), this would be the best place
  338. // for it.
  339. ctx.stack_.pop_back();
  340. ctx.leave();
  341. };
  342. // subparser: similar to the corresponding rule but without parent
  343. // so the stack is empty at the rule entry.
  344. sub_dhcp6: LCURLY_BRACKET {
  345. // Parse the Dhcp6 map
  346. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  347. ctx.stack_.push_back(m);
  348. } global_params RCURLY_BRACKET {
  349. // parsing completed
  350. };
  351. global_params: global_param
  352. | global_params COMMA global_param
  353. ;
  354. // These are the parameters that are allowed in the top-level for
  355. // Dhcp6.
  356. global_param: preferred_lifetime
  357. | valid_lifetime
  358. | renew_timer
  359. | rebind_timer
  360. | decline_probation_period
  361. | subnet6_list
  362. | interfaces_config
  363. | lease_database
  364. | hosts_database
  365. | mac_sources
  366. | relay_supplied_options
  367. | host_reservation_identifiers
  368. | client_classes
  369. | option_def_list
  370. | option_data_list
  371. | hooks_libraries
  372. | expired_leases_processing
  373. | server_id
  374. | dhcp4o6_port
  375. | control_socket
  376. | dhcp_ddns
  377. | unknown_map_entry
  378. ;
  379. preferred_lifetime: PREFERRED_LIFETIME COLON INTEGER {
  380. ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
  381. ctx.stack_.back()->set("preferred-lifetime", prf);
  382. };
  383. valid_lifetime: VALID_LIFETIME COLON INTEGER {
  384. ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
  385. ctx.stack_.back()->set("valid-lifetime", prf);
  386. };
  387. renew_timer: RENEW_TIMER COLON INTEGER {
  388. ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
  389. ctx.stack_.back()->set("renew-timer", prf);
  390. };
  391. rebind_timer: REBIND_TIMER COLON INTEGER {
  392. ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
  393. ctx.stack_.back()->set("rebind-timer", prf);
  394. };
  395. decline_probation_period: DECLINE_PROBATION_PERIOD COLON INTEGER {
  396. ElementPtr dpp(new IntElement($3, ctx.loc2pos(@3)));
  397. ctx.stack_.back()->set("decline-probation-period", dpp);
  398. };
  399. interfaces_config: INTERFACES_CONFIG {
  400. ElementPtr i(new MapElement(ctx.loc2pos(@1)));
  401. ctx.stack_.back()->set("interfaces-config", i);
  402. ctx.stack_.push_back(i);
  403. ctx.enter(ctx.INTERFACES_CONFIG);
  404. } COLON LCURLY_BRACKET interfaces_config_params RCURLY_BRACKET {
  405. ctx.stack_.pop_back();
  406. ctx.leave();
  407. };
  408. sub_interfaces6: LCURLY_BRACKET {
  409. // Parse the interfaces-config map
  410. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  411. ctx.stack_.push_back(m);
  412. } interfaces_config_params RCURLY_BRACKET {
  413. // parsing completed
  414. };
  415. interfaces_config_params: interfaces_config_param
  416. | interfaces_config_params COMMA interfaces_config_param
  417. ;
  418. interfaces_config_param: interfaces_list
  419. | re_detect
  420. ;
  421. interfaces_list: INTERFACES {
  422. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  423. ctx.stack_.back()->set("interfaces", l);
  424. ctx.stack_.push_back(l);
  425. ctx.enter(ctx.NO_KEYWORD);
  426. } COLON list_strings {
  427. ctx.stack_.pop_back();
  428. ctx.leave();
  429. };
  430. re_detect: RE_DETECT COLON BOOLEAN {
  431. ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
  432. ctx.stack_.back()->set("re-detect", b);
  433. };
  434. lease_database: LEASE_DATABASE {
  435. ElementPtr i(new MapElement(ctx.loc2pos(@1)));
  436. ctx.stack_.back()->set("lease-database", i);
  437. ctx.stack_.push_back(i);
  438. ctx.enter(ctx.LEASE_DATABASE);
  439. } COLON LCURLY_BRACKET database_map_params RCURLY_BRACKET {
  440. ctx.stack_.pop_back();
  441. ctx.leave();
  442. };
  443. hosts_database: HOSTS_DATABASE {
  444. ElementPtr i(new MapElement(ctx.loc2pos(@1)));
  445. ctx.stack_.back()->set("hosts-database", i);
  446. ctx.stack_.push_back(i);
  447. ctx.enter(ctx.HOSTS_DATABASE);
  448. } COLON LCURLY_BRACKET database_map_params RCURLY_BRACKET {
  449. ctx.stack_.pop_back();
  450. ctx.leave();
  451. };
  452. database_map_params: database_map_param
  453. | database_map_params COMMA database_map_param
  454. ;
  455. database_map_param: database_type
  456. | user
  457. | password
  458. | host
  459. | port
  460. | name
  461. | persist
  462. | lfc_interval
  463. | readonly
  464. | connect_timeout
  465. | contact_points
  466. | keyspace
  467. | unknown_map_entry
  468. ;
  469. database_type: TYPE {
  470. ctx.enter(ctx.DATABASE_TYPE);
  471. } COLON db_type {
  472. ctx.stack_.back()->set("type", $4);
  473. ctx.leave();
  474. };
  475. db_type: MEMFILE { $$ = ElementPtr(new StringElement("memfile", ctx.loc2pos(@1))); }
  476. | MYSQL { $$ = ElementPtr(new StringElement("mysql", ctx.loc2pos(@1))); }
  477. | POSTGRESQL { $$ = ElementPtr(new StringElement("postgresql", ctx.loc2pos(@1))); }
  478. | CQL { $$ = ElementPtr(new StringElement("cql", ctx.loc2pos(@1))); }
  479. ;
  480. user: USER {
  481. ctx.enter(ctx.NO_KEYWORD);
  482. } COLON STRING {
  483. ElementPtr user(new StringElement($4, ctx.loc2pos(@4)));
  484. ctx.stack_.back()->set("user", user);
  485. ctx.leave();
  486. };
  487. password: PASSWORD {
  488. ctx.enter(ctx.NO_KEYWORD);
  489. } COLON STRING {
  490. ElementPtr pwd(new StringElement($4, ctx.loc2pos(@4)));
  491. ctx.stack_.back()->set("password", pwd);
  492. ctx.leave();
  493. };
  494. host: HOST {
  495. ctx.enter(ctx.NO_KEYWORD);
  496. } COLON STRING {
  497. ElementPtr h(new StringElement($4, ctx.loc2pos(@4)));
  498. ctx.stack_.back()->set("host", h);
  499. ctx.leave();
  500. };
  501. port: PORT COLON INTEGER {
  502. ElementPtr p(new IntElement($3, ctx.loc2pos(@3)));
  503. ctx.stack_.back()->set("port", p);
  504. };
  505. name: NAME {
  506. ctx.enter(ctx.NO_KEYWORD);
  507. } COLON STRING {
  508. ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
  509. ctx.stack_.back()->set("name", name);
  510. ctx.leave();
  511. };
  512. persist: PERSIST COLON BOOLEAN {
  513. ElementPtr n(new BoolElement($3, ctx.loc2pos(@3)));
  514. ctx.stack_.back()->set("persist", n);
  515. };
  516. lfc_interval: LFC_INTERVAL COLON INTEGER {
  517. ElementPtr n(new IntElement($3, ctx.loc2pos(@3)));
  518. ctx.stack_.back()->set("lfc-interval", n);
  519. };
  520. readonly: READONLY COLON BOOLEAN {
  521. ElementPtr n(new BoolElement($3, ctx.loc2pos(@3)));
  522. ctx.stack_.back()->set("readonly", n);
  523. };
  524. connect_timeout: CONNECT_TIMEOUT COLON INTEGER {
  525. ElementPtr n(new IntElement($3, ctx.loc2pos(@3)));
  526. ctx.stack_.back()->set("connect-timeout", n);
  527. };
  528. contact_points: CONTACT_POINTS {
  529. ctx.enter(ctx.NO_KEYWORD);
  530. } COLON STRING {
  531. ElementPtr cp(new StringElement($4, ctx.loc2pos(@4)));
  532. ctx.stack_.back()->set("contact-points", cp);
  533. ctx.leave();
  534. };
  535. keyspace: KEYSPACE {
  536. ctx.enter(ctx.NO_KEYWORD);
  537. } COLON STRING {
  538. ElementPtr ks(new StringElement($4, ctx.loc2pos(@4)));
  539. ctx.stack_.back()->set("keyspace", ks);
  540. ctx.leave();
  541. };
  542. mac_sources: MAC_SOURCES {
  543. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  544. ctx.stack_.back()->set("mac-sources", l);
  545. ctx.stack_.push_back(l);
  546. ctx.enter(ctx.MAC_SOURCES);
  547. } COLON LSQUARE_BRACKET mac_sources_list RSQUARE_BRACKET {
  548. ctx.stack_.pop_back();
  549. ctx.leave();
  550. };
  551. mac_sources_list: mac_sources_value
  552. | mac_sources_list COMMA mac_sources_value
  553. ;
  554. mac_sources_value: duid_id
  555. | string_id
  556. ;
  557. duid_id : DUID {
  558. ElementPtr duid(new StringElement("duid", ctx.loc2pos(@1)));
  559. ctx.stack_.back()->add(duid);
  560. };
  561. string_id : STRING {
  562. ElementPtr duid(new StringElement($1, ctx.loc2pos(@1)));
  563. ctx.stack_.back()->add(duid);
  564. };
  565. host_reservation_identifiers: HOST_RESERVATION_IDENTIFIERS {
  566. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  567. ctx.stack_.back()->set("host-reservation-identifiers", l);
  568. ctx.stack_.push_back(l);
  569. ctx.enter(ctx.HOST_RESERVATION_IDENTIFIERS);
  570. } COLON LSQUARE_BRACKET host_reservation_identifiers_list RSQUARE_BRACKET {
  571. ctx.stack_.pop_back();
  572. ctx.leave();
  573. };
  574. host_reservation_identifiers_list: host_reservation_identifier
  575. | host_reservation_identifiers_list COMMA host_reservation_identifier
  576. ;
  577. host_reservation_identifier: duid_id
  578. | hw_address_id
  579. | flex_id
  580. ;
  581. hw_address_id : HW_ADDRESS {
  582. ElementPtr hwaddr(new StringElement("hw-address", ctx.loc2pos(@1)));
  583. ctx.stack_.back()->add(hwaddr);
  584. };
  585. flex_id : FLEX_ID {
  586. ElementPtr flex_id(new StringElement("flex-id", ctx.loc2pos(@1)));
  587. ctx.stack_.back()->add(flex_id);
  588. };
  589. // list_content below accepts any value when options are by name (string)
  590. // or by code (number)
  591. relay_supplied_options: RELAY_SUPPLIED_OPTIONS {
  592. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  593. ctx.stack_.back()->set("relay-supplied-options", l);
  594. ctx.stack_.push_back(l);
  595. ctx.enter(ctx.NO_KEYWORD);
  596. } COLON LSQUARE_BRACKET list_content RSQUARE_BRACKET {
  597. ctx.stack_.pop_back();
  598. ctx.leave();
  599. };
  600. hooks_libraries: HOOKS_LIBRARIES {
  601. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  602. ctx.stack_.back()->set("hooks-libraries", l);
  603. ctx.stack_.push_back(l);
  604. ctx.enter(ctx.HOOKS_LIBRARIES);
  605. } COLON LSQUARE_BRACKET hooks_libraries_list RSQUARE_BRACKET {
  606. ctx.stack_.pop_back();
  607. ctx.leave();
  608. };
  609. hooks_libraries_list: %empty
  610. | not_empty_hooks_libraries_list
  611. ;
  612. not_empty_hooks_libraries_list: hooks_library
  613. | not_empty_hooks_libraries_list COMMA hooks_library
  614. ;
  615. hooks_library: LCURLY_BRACKET {
  616. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  617. ctx.stack_.back()->add(m);
  618. ctx.stack_.push_back(m);
  619. } hooks_params RCURLY_BRACKET {
  620. ctx.stack_.pop_back();
  621. };
  622. sub_hooks_library: LCURLY_BRACKET {
  623. // Parse the hooks-libraries list entry map
  624. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  625. ctx.stack_.push_back(m);
  626. } hooks_params RCURLY_BRACKET {
  627. // parsing completed
  628. };
  629. hooks_params: hooks_param
  630. | hooks_params COMMA hooks_param
  631. | unknown_map_entry
  632. ;
  633. hooks_param: library
  634. | parameters
  635. ;
  636. library: LIBRARY {
  637. ctx.enter(ctx.NO_KEYWORD);
  638. } COLON STRING {
  639. ElementPtr lib(new StringElement($4, ctx.loc2pos(@4)));
  640. ctx.stack_.back()->set("library", lib);
  641. ctx.leave();
  642. };
  643. parameters: PARAMETERS {
  644. ctx.enter(ctx.NO_KEYWORD);
  645. } COLON value {
  646. ctx.stack_.back()->set("parameters", $4);
  647. ctx.leave();
  648. };
  649. // --- expired-leases-processing ------------------------
  650. expired_leases_processing: EXPIRED_LEASES_PROCESSING {
  651. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  652. ctx.stack_.back()->set("expired-leases-processing", m);
  653. ctx.stack_.push_back(m);
  654. ctx.enter(ctx.EXPIRED_LEASES_PROCESSING);
  655. } COLON LCURLY_BRACKET expired_leases_params RCURLY_BRACKET {
  656. ctx.stack_.pop_back();
  657. ctx.leave();
  658. };
  659. expired_leases_params: expired_leases_param
  660. | expired_leases_params COMMA expired_leases_param
  661. ;
  662. expired_leases_param: reclaim_timer_wait_time
  663. | flush_reclaimed_timer_wait_time
  664. | hold_reclaimed_time
  665. | max_reclaim_leases
  666. | max_reclaim_time
  667. | unwarned_reclaim_cycles
  668. ;
  669. reclaim_timer_wait_time: RECLAIM_TIMER_WAIT_TIME COLON INTEGER {
  670. ElementPtr value(new IntElement($3, ctx.loc2pos(@3)));
  671. ctx.stack_.back()->set("reclaim-timer-wait-time", value);
  672. };
  673. flush_reclaimed_timer_wait_time: FLUSH_RECLAIMED_TIMER_WAIT_TIME COLON INTEGER {
  674. ElementPtr value(new IntElement($3, ctx.loc2pos(@3)));
  675. ctx.stack_.back()->set("flush-reclaimed-timer-wait-time", value);
  676. };
  677. hold_reclaimed_time: HOLD_RECLAIMED_TIME COLON INTEGER {
  678. ElementPtr value(new IntElement($3, ctx.loc2pos(@3)));
  679. ctx.stack_.back()->set("hold-reclaimed-time", value);
  680. };
  681. max_reclaim_leases: MAX_RECLAIM_LEASES COLON INTEGER {
  682. ElementPtr value(new IntElement($3, ctx.loc2pos(@3)));
  683. ctx.stack_.back()->set("max-reclaim-leases", value);
  684. };
  685. max_reclaim_time: MAX_RECLAIM_TIME COLON INTEGER {
  686. ElementPtr value(new IntElement($3, ctx.loc2pos(@3)));
  687. ctx.stack_.back()->set("max-reclaim-time", value);
  688. };
  689. unwarned_reclaim_cycles: UNWARNED_RECLAIM_CYCLES COLON INTEGER {
  690. ElementPtr value(new IntElement($3, ctx.loc2pos(@3)));
  691. ctx.stack_.back()->set("unwarned-reclaim-cycles", value);
  692. };
  693. // --- subnet6 ------------------------------------------
  694. // This defines subnet6 as a list of maps.
  695. // "subnet6": [ ... ]
  696. subnet6_list: SUBNET6 {
  697. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  698. ctx.stack_.back()->set("subnet6", l);
  699. ctx.stack_.push_back(l);
  700. ctx.enter(ctx.SUBNET6);
  701. } COLON LSQUARE_BRACKET subnet6_list_content RSQUARE_BRACKET {
  702. ctx.stack_.pop_back();
  703. ctx.leave();
  704. };
  705. // This defines the ... in "subnet6": [ ... ]
  706. // It can either be empty (no subnets defined), have one subnet
  707. // or have multiple subnets separate by comma.
  708. subnet6_list_content: %empty
  709. | not_empty_subnet6_list
  710. ;
  711. not_empty_subnet6_list: subnet6
  712. | not_empty_subnet6_list COMMA subnet6
  713. ;
  714. // --- Subnet definitions -------------------------------
  715. // This defines a single subnet, i.e. a single map with
  716. // subnet6 array.
  717. subnet6: LCURLY_BRACKET {
  718. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  719. ctx.stack_.back()->add(m);
  720. ctx.stack_.push_back(m);
  721. } subnet6_params RCURLY_BRACKET {
  722. // Once we reached this place, the subnet parsing is now complete.
  723. // If we want to, we can implement default values here.
  724. // In particular we can do things like this:
  725. // if (!ctx.stack_.back()->get("interface")) {
  726. // ctx.stack_.back()->set("interface", StringElement("loopback"));
  727. // }
  728. //
  729. // We can also stack up one level (Dhcp6) and copy over whatever
  730. // global parameters we want to:
  731. // if (!ctx.stack_.back()->get("renew-timer")) {
  732. // ElementPtr renew = ctx_stack_[...].get("renew-timer");
  733. // if (renew) {
  734. // ctx.stack_.back()->set("renew-timer", renew);
  735. // }
  736. // }
  737. ctx.stack_.pop_back();
  738. };
  739. sub_subnet6: LCURLY_BRACKET {
  740. // Parse the subnet6 list entry map
  741. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  742. ctx.stack_.push_back(m);
  743. } subnet6_params RCURLY_BRACKET {
  744. // parsing completed
  745. };
  746. // This defines that subnet can have one or more parameters.
  747. subnet6_params: subnet6_param
  748. | subnet6_params COMMA subnet6_param
  749. ;
  750. // This defines a list of allowed parameters for each subnet.
  751. subnet6_param: preferred_lifetime
  752. | valid_lifetime
  753. | renew_timer
  754. | rebind_timer
  755. | option_data_list
  756. | pools_list
  757. | pd_pools_list
  758. | subnet
  759. | interface
  760. | interface_id
  761. | id
  762. | rapid_commit
  763. | client_class
  764. | reservations
  765. | reservation_mode
  766. | relay
  767. | unknown_map_entry
  768. ;
  769. subnet: SUBNET {
  770. ctx.enter(ctx.NO_KEYWORD);
  771. } COLON STRING {
  772. ElementPtr subnet(new StringElement($4, ctx.loc2pos(@4)));
  773. ctx.stack_.back()->set("subnet", subnet);
  774. ctx.leave();
  775. };
  776. interface: INTERFACE {
  777. ctx.enter(ctx.NO_KEYWORD);
  778. } COLON STRING {
  779. ElementPtr iface(new StringElement($4, ctx.loc2pos(@4)));
  780. ctx.stack_.back()->set("interface", iface);
  781. ctx.leave();
  782. };
  783. interface_id: INTERFACE_ID {
  784. ctx.enter(ctx.NO_KEYWORD);
  785. } COLON STRING {
  786. ElementPtr iface(new StringElement($4, ctx.loc2pos(@4)));
  787. ctx.stack_.back()->set("interface-id", iface);
  788. ctx.leave();
  789. };
  790. client_class: CLIENT_CLASS {
  791. ctx.enter(ctx.CLIENT_CLASS);
  792. } COLON STRING {
  793. ElementPtr cls(new StringElement($4, ctx.loc2pos(@4)));
  794. ctx.stack_.back()->set("client-class", cls);
  795. ctx.leave();
  796. };
  797. reservation_mode: RESERVATION_MODE {
  798. ctx.enter(ctx.RESERVATION_MODE);
  799. } COLON hr_mode {
  800. ctx.stack_.back()->set("reservation-mode", $4);
  801. ctx.leave();
  802. };
  803. hr_mode: DISABLED { $$ = ElementPtr(new StringElement("disabled", ctx.loc2pos(@1))); }
  804. | OUT_OF_POOL { $$ = ElementPtr(new StringElement("out-of-pool", ctx.loc2pos(@1))); }
  805. | ALL { $$ = ElementPtr(new StringElement("all", ctx.loc2pos(@1))); }
  806. ;
  807. id: ID COLON INTEGER {
  808. ElementPtr id(new IntElement($3, ctx.loc2pos(@3)));
  809. ctx.stack_.back()->set("id", id);
  810. };
  811. rapid_commit: RAPID_COMMIT COLON BOOLEAN {
  812. ElementPtr rc(new BoolElement($3, ctx.loc2pos(@3)));
  813. ctx.stack_.back()->set("rapid-commit", rc);
  814. };
  815. // ---- option-def --------------------------
  816. // This defines the "option-def": [ ... ] entry that may appear
  817. // at a global option.
  818. option_def_list: OPTION_DEF {
  819. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  820. ctx.stack_.back()->set("option-def", l);
  821. ctx.stack_.push_back(l);
  822. ctx.enter(ctx.OPTION_DEF);
  823. } COLON LSQUARE_BRACKET option_def_list_content RSQUARE_BRACKET {
  824. ctx.stack_.pop_back();
  825. ctx.leave();
  826. };
  827. // This defines the content of option-def. It may be empty,
  828. // have one entry or multiple entries separated by comma.
  829. option_def_list_content: %empty
  830. | not_empty_option_def_list
  831. ;
  832. not_empty_option_def_list: option_def_entry
  833. | not_empty_option_def_list COMMA option_def_entry
  834. ;
  835. // This defines the content of a single entry { ... } within
  836. // option-def list.
  837. option_def_entry: LCURLY_BRACKET {
  838. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  839. ctx.stack_.back()->add(m);
  840. ctx.stack_.push_back(m);
  841. } option_def_params RCURLY_BRACKET {
  842. ctx.stack_.pop_back();
  843. };
  844. // This defines the top level scope when the parser is told to parse a single
  845. // option definition. It's almost exactly the same as option_def_entry, except
  846. // that it does leave its value on stack.
  847. sub_option_def: LCURLY_BRACKET {
  848. // Parse the option-def list entry map
  849. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  850. ctx.stack_.push_back(m);
  851. } option_def_params RCURLY_BRACKET {
  852. // parsing completed
  853. };
  854. // This defines parameters specified inside the map that itself
  855. // is an entry in option-def list.
  856. option_def_params: %empty
  857. | not_empty_option_def_params
  858. ;
  859. not_empty_option_def_params: option_def_param
  860. | not_empty_option_def_params COMMA option_def_param
  861. ;
  862. option_def_param: option_def_name
  863. | option_def_code
  864. | option_def_type
  865. | option_def_record_types
  866. | option_def_space
  867. | option_def_encapsulate
  868. | option_def_array
  869. | unknown_map_entry
  870. ;
  871. option_def_name: name;
  872. code: CODE COLON INTEGER {
  873. ElementPtr code(new IntElement($3, ctx.loc2pos(@3)));
  874. ctx.stack_.back()->set("code", code);
  875. };
  876. option_def_code: code;
  877. option_def_type: TYPE {
  878. ctx.enter(ctx.NO_KEYWORD);
  879. } COLON STRING {
  880. ElementPtr prf(new StringElement($4, ctx.loc2pos(@4)));
  881. ctx.stack_.back()->set("type", prf);
  882. ctx.leave();
  883. };
  884. option_def_record_types: RECORD_TYPES {
  885. ctx.enter(ctx.NO_KEYWORD);
  886. } COLON STRING {
  887. ElementPtr rtypes(new StringElement($4, ctx.loc2pos(@4)));
  888. ctx.stack_.back()->set("record-types", rtypes);
  889. ctx.leave();
  890. };
  891. space: SPACE {
  892. ctx.enter(ctx.NO_KEYWORD);
  893. } COLON STRING {
  894. ElementPtr space(new StringElement($4, ctx.loc2pos(@4)));
  895. ctx.stack_.back()->set("space", space);
  896. ctx.leave();
  897. };
  898. option_def_space: space;
  899. option_def_encapsulate: ENCAPSULATE {
  900. ctx.enter(ctx.NO_KEYWORD);
  901. } COLON STRING {
  902. ElementPtr encap(new StringElement($4, ctx.loc2pos(@4)));
  903. ctx.stack_.back()->set("encapsulate", encap);
  904. ctx.leave();
  905. };
  906. option_def_array: ARRAY COLON BOOLEAN {
  907. ElementPtr array(new BoolElement($3, ctx.loc2pos(@3)));
  908. ctx.stack_.back()->set("array", array);
  909. };
  910. // ---- option-data --------------------------
  911. // This defines the "option-data": [ ... ] entry that may appear
  912. // in several places, but most notably in subnet6 entries.
  913. option_data_list: OPTION_DATA {
  914. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  915. ctx.stack_.back()->set("option-data", l);
  916. ctx.stack_.push_back(l);
  917. ctx.enter(ctx.OPTION_DATA);
  918. } COLON LSQUARE_BRACKET option_data_list_content RSQUARE_BRACKET {
  919. ctx.stack_.pop_back();
  920. ctx.leave();
  921. };
  922. // This defines the content of option-data. It may be empty,
  923. // have one entry or multiple entries separated by comma.
  924. option_data_list_content: %empty
  925. | not_empty_option_data_list
  926. ;
  927. // This defines the content of option-data list. It can either
  928. // be a single value or multiple entries separated by comma.
  929. not_empty_option_data_list: option_data_entry
  930. | not_empty_option_data_list COMMA option_data_entry
  931. ;
  932. // This defines th content of a single entry { ... } within
  933. // option-data list.
  934. option_data_entry: LCURLY_BRACKET {
  935. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  936. ctx.stack_.back()->add(m);
  937. ctx.stack_.push_back(m);
  938. } option_data_params RCURLY_BRACKET {
  939. ctx.stack_.pop_back();
  940. };
  941. // This defines the top level scope when the parser is told to parse a single
  942. // option data. It's almost exactly the same as option_data_entry, except
  943. // that it does leave its value on stack.
  944. sub_option_data: LCURLY_BRACKET {
  945. // Parse the option-data list entry map
  946. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  947. ctx.stack_.push_back(m);
  948. } option_data_params RCURLY_BRACKET {
  949. // parsing completed
  950. };
  951. // This defines parameters specified inside the map that itself
  952. // is an entry in option-data list. It can either be empty
  953. // or have a non-empty list of parameters.
  954. option_data_params: %empty
  955. | not_empty_option_data_params
  956. ;
  957. // Those parameters can either be a single parameter or
  958. // a list of parameters separated by comma.
  959. not_empty_option_data_params: option_data_param
  960. | not_empty_option_data_params COMMA option_data_param
  961. ;
  962. // Each single option-data parameter can be one of the following
  963. // expressions.
  964. option_data_param: option_data_name
  965. | option_data_data
  966. | option_data_code
  967. | option_data_space
  968. | option_data_csv_format
  969. | option_data_always_send
  970. | unknown_map_entry
  971. ;
  972. option_data_name: name;
  973. option_data_data: DATA {
  974. ctx.enter(ctx.NO_KEYWORD);
  975. } COLON STRING {
  976. ElementPtr data(new StringElement($4, ctx.loc2pos(@4)));
  977. ctx.stack_.back()->set("data", data);
  978. ctx.leave();
  979. };
  980. option_data_code: code;
  981. option_data_space: space;
  982. option_data_csv_format: CSV_FORMAT COLON BOOLEAN {
  983. ElementPtr space(new BoolElement($3, ctx.loc2pos(@3)));
  984. ctx.stack_.back()->set("csv-format", space);
  985. };
  986. option_data_always_send: ALWAYS_SEND COLON BOOLEAN {
  987. ElementPtr persist(new BoolElement($3, ctx.loc2pos(@3)));
  988. ctx.stack_.back()->set("always-send", persist);
  989. };
  990. // ---- pools ------------------------------------
  991. // This defines the "pools": [ ... ] entry that may appear in subnet6.
  992. pools_list: POOLS {
  993. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  994. ctx.stack_.back()->set("pools", l);
  995. ctx.stack_.push_back(l);
  996. ctx.enter(ctx.POOLS);
  997. } COLON LSQUARE_BRACKET pools_list_content RSQUARE_BRACKET {
  998. ctx.stack_.pop_back();
  999. ctx.leave();
  1000. };
  1001. // Pools may be empty, contain a single pool entry or multiple entries
  1002. // separate by commas.
  1003. pools_list_content: %empty
  1004. | not_empty_pools_list
  1005. ;
  1006. not_empty_pools_list: pool_list_entry
  1007. | not_empty_pools_list COMMA pool_list_entry
  1008. ;
  1009. pool_list_entry: LCURLY_BRACKET {
  1010. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1011. ctx.stack_.back()->add(m);
  1012. ctx.stack_.push_back(m);
  1013. } pool_params RCURLY_BRACKET {
  1014. ctx.stack_.pop_back();
  1015. };
  1016. sub_pool6: LCURLY_BRACKET {
  1017. // Parse the pool list entry map
  1018. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1019. ctx.stack_.push_back(m);
  1020. } pool_params RCURLY_BRACKET {
  1021. // parsing completed
  1022. };
  1023. pool_params: pool_param
  1024. | pool_params COMMA pool_param
  1025. ;
  1026. pool_param: pool_entry
  1027. | option_data_list
  1028. | user_context
  1029. | unknown_map_entry
  1030. ;
  1031. pool_entry: POOL {
  1032. ctx.enter(ctx.NO_KEYWORD);
  1033. } COLON STRING {
  1034. ElementPtr pool(new StringElement($4, ctx.loc2pos(@4)));
  1035. ctx.stack_.back()->set("pool", pool);
  1036. ctx.leave();
  1037. };
  1038. user_context: USER_CONTEXT {
  1039. ctx.enter(ctx.NO_KEYWORD);
  1040. } COLON map_value {
  1041. ctx.stack_.back()->set("user-context", $4);
  1042. ctx.leave();
  1043. };
  1044. // --- end of pools definition -------------------------------
  1045. // --- pd-pools ----------------------------------------------
  1046. pd_pools_list: PD_POOLS {
  1047. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  1048. ctx.stack_.back()->set("pd-pools", l);
  1049. ctx.stack_.push_back(l);
  1050. ctx.enter(ctx.PD_POOLS);
  1051. } COLON LSQUARE_BRACKET pd_pools_list_content RSQUARE_BRACKET {
  1052. ctx.stack_.pop_back();
  1053. ctx.leave();
  1054. };
  1055. // Pools may be empty, contain a single pool entry or multiple entries
  1056. // separate by commas.
  1057. pd_pools_list_content: %empty
  1058. | not_empty_pd_pools_list
  1059. ;
  1060. not_empty_pd_pools_list: pd_pool_entry
  1061. | not_empty_pd_pools_list COMMA pd_pool_entry
  1062. ;
  1063. pd_pool_entry: LCURLY_BRACKET {
  1064. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1065. ctx.stack_.back()->add(m);
  1066. ctx.stack_.push_back(m);
  1067. } pd_pool_params RCURLY_BRACKET {
  1068. ctx.stack_.pop_back();
  1069. };
  1070. sub_pd_pool: LCURLY_BRACKET {
  1071. // Parse the pd-pool list entry map
  1072. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1073. ctx.stack_.push_back(m);
  1074. } pd_pool_params RCURLY_BRACKET {
  1075. // parsing completed
  1076. };
  1077. pd_pool_params: pd_pool_param
  1078. | pd_pool_params COMMA pd_pool_param
  1079. ;
  1080. pd_pool_param: pd_prefix
  1081. | pd_prefix_len
  1082. | pd_delegated_len
  1083. | option_data_list
  1084. | excluded_prefix
  1085. | excluded_prefix_len
  1086. | user_context
  1087. | unknown_map_entry
  1088. ;
  1089. pd_prefix: PREFIX {
  1090. ctx.enter(ctx.NO_KEYWORD);
  1091. } COLON STRING {
  1092. ElementPtr prf(new StringElement($4, ctx.loc2pos(@4)));
  1093. ctx.stack_.back()->set("prefix", prf);
  1094. ctx.leave();
  1095. };
  1096. pd_prefix_len: PREFIX_LEN COLON INTEGER {
  1097. ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
  1098. ctx.stack_.back()->set("prefix-len", prf);
  1099. };
  1100. excluded_prefix: EXCLUDED_PREFIX {
  1101. ctx.enter(ctx.NO_KEYWORD);
  1102. } COLON STRING {
  1103. ElementPtr prf(new StringElement($4, ctx.loc2pos(@4)));
  1104. ctx.stack_.back()->set("excluded-prefix", prf);
  1105. ctx.leave();
  1106. };
  1107. excluded_prefix_len: EXCLUDED_PREFIX_LEN COLON INTEGER {
  1108. ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
  1109. ctx.stack_.back()->set("excluded-prefix-len", prf);
  1110. };
  1111. pd_delegated_len: DELEGATED_LEN COLON INTEGER {
  1112. ElementPtr deleg(new IntElement($3, ctx.loc2pos(@3)));
  1113. ctx.stack_.back()->set("delegated-len", deleg);
  1114. };
  1115. // --- end of pd-pools ---------------------------------------
  1116. // --- reservations ------------------------------------------
  1117. reservations: RESERVATIONS {
  1118. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  1119. ctx.stack_.back()->set("reservations", l);
  1120. ctx.stack_.push_back(l);
  1121. ctx.enter(ctx.RESERVATIONS);
  1122. } COLON LSQUARE_BRACKET reservations_list RSQUARE_BRACKET {
  1123. ctx.stack_.pop_back();
  1124. ctx.leave();
  1125. };
  1126. reservations_list: %empty
  1127. | not_empty_reservations_list
  1128. ;
  1129. not_empty_reservations_list: reservation
  1130. | not_empty_reservations_list COMMA reservation
  1131. ;
  1132. reservation: LCURLY_BRACKET {
  1133. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1134. ctx.stack_.back()->add(m);
  1135. ctx.stack_.push_back(m);
  1136. } reservation_params RCURLY_BRACKET {
  1137. ctx.stack_.pop_back();
  1138. };
  1139. sub_reservation: LCURLY_BRACKET {
  1140. // Parse the reservations list entry map
  1141. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1142. ctx.stack_.push_back(m);
  1143. } reservation_params RCURLY_BRACKET {
  1144. // parsing completed
  1145. };
  1146. reservation_params: %empty
  1147. | not_empty_reservation_params
  1148. ;
  1149. not_empty_reservation_params: reservation_param
  1150. | not_empty_reservation_params COMMA reservation_param
  1151. ;
  1152. // @todo probably need to add mac-address as well here
  1153. reservation_param: duid
  1154. | reservation_client_classes
  1155. | ip_addresses
  1156. | prefixes
  1157. | hw_address
  1158. | hostname
  1159. | flex_id_value
  1160. | option_data_list
  1161. | unknown_map_entry
  1162. ;
  1163. ip_addresses: IP_ADDRESSES {
  1164. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  1165. ctx.stack_.back()->set("ip-addresses", l);
  1166. ctx.stack_.push_back(l);
  1167. ctx.enter(ctx.NO_KEYWORD);
  1168. } COLON list_strings {
  1169. ctx.stack_.pop_back();
  1170. ctx.leave();
  1171. };
  1172. prefixes: PREFIXES {
  1173. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  1174. ctx.stack_.back()->set("prefixes", l);
  1175. ctx.stack_.push_back(l);
  1176. ctx.enter(ctx.NO_KEYWORD);
  1177. } COLON list_strings {
  1178. ctx.stack_.pop_back();
  1179. ctx.leave();
  1180. };
  1181. duid: DUID {
  1182. ctx.enter(ctx.NO_KEYWORD);
  1183. } COLON STRING {
  1184. ElementPtr d(new StringElement($4, ctx.loc2pos(@4)));
  1185. ctx.stack_.back()->set("duid", d);
  1186. ctx.leave();
  1187. };
  1188. hw_address: HW_ADDRESS {
  1189. ctx.enter(ctx.NO_KEYWORD);
  1190. } COLON STRING {
  1191. ElementPtr hw(new StringElement($4, ctx.loc2pos(@4)));
  1192. ctx.stack_.back()->set("hw-address", hw);
  1193. ctx.leave();
  1194. };
  1195. hostname: HOSTNAME {
  1196. ctx.enter(ctx.NO_KEYWORD);
  1197. } COLON STRING {
  1198. ElementPtr host(new StringElement($4, ctx.loc2pos(@4)));
  1199. ctx.stack_.back()->set("hostname", host);
  1200. ctx.leave();
  1201. };
  1202. flex_id_value: FLEX_ID {
  1203. ctx.enter(ctx.NO_KEYWORD);
  1204. } COLON STRING {
  1205. ElementPtr hw(new StringElement($4, ctx.loc2pos(@4)));
  1206. ctx.stack_.back()->set("flex-id", hw);
  1207. ctx.leave();
  1208. };
  1209. reservation_client_classes: CLIENT_CLASSES {
  1210. ElementPtr c(new ListElement(ctx.loc2pos(@1)));
  1211. ctx.stack_.back()->set("client-classes", c);
  1212. ctx.stack_.push_back(c);
  1213. ctx.enter(ctx.NO_KEYWORD);
  1214. } COLON list_strings {
  1215. ctx.stack_.pop_back();
  1216. ctx.leave();
  1217. };
  1218. // --- end of reservations definitions -----------------------
  1219. // --- relay -------------------------------------------------
  1220. relay: RELAY {
  1221. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1222. ctx.stack_.back()->set("relay", m);
  1223. ctx.stack_.push_back(m);
  1224. ctx.enter(ctx.RELAY);
  1225. } COLON LCURLY_BRACKET relay_map RCURLY_BRACKET {
  1226. ctx.stack_.pop_back();
  1227. ctx.leave();
  1228. };
  1229. relay_map: IP_ADDRESS {
  1230. ctx.enter(ctx.NO_KEYWORD);
  1231. } COLON STRING {
  1232. ElementPtr ip(new StringElement($4, ctx.loc2pos(@4)));
  1233. ctx.stack_.back()->set("ip-address", ip);
  1234. ctx.leave();
  1235. };
  1236. // --- end of relay definitions ------------------------------
  1237. // --- client classes ----------------------------------------
  1238. client_classes: CLIENT_CLASSES {
  1239. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  1240. ctx.stack_.back()->set("client-classes", l);
  1241. ctx.stack_.push_back(l);
  1242. ctx.enter(ctx.CLIENT_CLASSES);
  1243. } COLON LSQUARE_BRACKET client_classes_list RSQUARE_BRACKET {
  1244. ctx.stack_.pop_back();
  1245. ctx.leave();
  1246. };
  1247. client_classes_list: client_class
  1248. | client_classes_list COMMA client_class
  1249. ;
  1250. client_class: LCURLY_BRACKET {
  1251. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1252. ctx.stack_.back()->add(m);
  1253. ctx.stack_.push_back(m);
  1254. } client_class_params RCURLY_BRACKET {
  1255. ctx.stack_.pop_back();
  1256. };
  1257. client_class_params: %empty
  1258. | not_empty_client_class_params
  1259. ;
  1260. not_empty_client_class_params: client_class_param
  1261. | not_empty_client_class_params COMMA client_class_param
  1262. ;
  1263. client_class_param: client_class_name
  1264. | client_class_test
  1265. | option_data_list
  1266. | unknown_map_entry
  1267. ;
  1268. client_class_name: name;
  1269. client_class_test: TEST {
  1270. ctx.enter(ctx.NO_KEYWORD);
  1271. } COLON STRING {
  1272. ElementPtr test(new StringElement($4, ctx.loc2pos(@4)));
  1273. ctx.stack_.back()->set("test", test);
  1274. ctx.leave();
  1275. };
  1276. // --- end of client classes ---------------------------------
  1277. // --- server-id ---------------------------------------------
  1278. server_id: SERVER_ID {
  1279. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1280. ctx.stack_.back()->set("server-id", m);
  1281. ctx.stack_.push_back(m);
  1282. ctx.enter(ctx.SERVER_ID);
  1283. } COLON LCURLY_BRACKET server_id_params RCURLY_BRACKET {
  1284. ctx.stack_.pop_back();
  1285. ctx.leave();
  1286. };
  1287. server_id_params: server_id_param
  1288. | server_id_params COMMA server_id_param
  1289. ;
  1290. server_id_param: server_id_type
  1291. | identifier
  1292. | time
  1293. | htype
  1294. | enterprise_id
  1295. | persist
  1296. | unknown_map_entry
  1297. ;
  1298. server_id_type: TYPE {
  1299. ctx.enter(ctx.DUID_TYPE);
  1300. } COLON duid_type {
  1301. ctx.stack_.back()->set("type", $4);
  1302. ctx.leave();
  1303. };
  1304. duid_type: LLT { $$ = ElementPtr(new StringElement("LLT", ctx.loc2pos(@1))); }
  1305. | EN { $$ = ElementPtr(new StringElement("EN", ctx.loc2pos(@1))); }
  1306. | LL { $$ = ElementPtr(new StringElement("LL", ctx.loc2pos(@1))); }
  1307. ;
  1308. htype: HTYPE COLON INTEGER {
  1309. ElementPtr htype(new IntElement($3, ctx.loc2pos(@3)));
  1310. ctx.stack_.back()->set("htype", htype);
  1311. };
  1312. identifier: IDENTIFIER {
  1313. ctx.enter(ctx.NO_KEYWORD);
  1314. } COLON STRING {
  1315. ElementPtr id(new StringElement($4, ctx.loc2pos(@4)));
  1316. ctx.stack_.back()->set("identifier", id);
  1317. ctx.leave();
  1318. };
  1319. time: TIME COLON INTEGER {
  1320. ElementPtr time(new IntElement($3, ctx.loc2pos(@3)));
  1321. ctx.stack_.back()->set("time", time);
  1322. };
  1323. enterprise_id: ENTERPRISE_ID COLON INTEGER {
  1324. ElementPtr time(new IntElement($3, ctx.loc2pos(@3)));
  1325. ctx.stack_.back()->set("enterprise-id", time);
  1326. };
  1327. // --- end of server-id --------------------------------------
  1328. dhcp4o6_port: DHCP4O6_PORT COLON INTEGER {
  1329. ElementPtr time(new IntElement($3, ctx.loc2pos(@3)));
  1330. ctx.stack_.back()->set("dhcp4o6-port", time);
  1331. };
  1332. // --- control socket ----------------------------------------
  1333. control_socket: CONTROL_SOCKET {
  1334. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1335. ctx.stack_.back()->set("control-socket", m);
  1336. ctx.stack_.push_back(m);
  1337. ctx.enter(ctx.CONTROL_SOCKET);
  1338. } COLON LCURLY_BRACKET control_socket_params RCURLY_BRACKET {
  1339. ctx.stack_.pop_back();
  1340. ctx.leave();
  1341. };
  1342. control_socket_params: control_socket_param
  1343. | control_socket_params COMMA control_socket_param
  1344. ;
  1345. control_socket_param: socket_type
  1346. | socket_name
  1347. ;
  1348. socket_type: SOCKET_TYPE {
  1349. ctx.enter(ctx.NO_KEYWORD);
  1350. } COLON STRING {
  1351. ElementPtr stype(new StringElement($4, ctx.loc2pos(@4)));
  1352. ctx.stack_.back()->set("socket-type", stype);
  1353. ctx.leave();
  1354. };
  1355. socket_name: SOCKET_NAME {
  1356. ctx.enter(ctx.NO_KEYWORD);
  1357. } COLON STRING {
  1358. ElementPtr name(new StringElement($4, ctx.loc2pos(@4)));
  1359. ctx.stack_.back()->set("socket-name", name);
  1360. ctx.leave();
  1361. };
  1362. // --- dhcp ddns ---------------------------------------------
  1363. dhcp_ddns: DHCP_DDNS {
  1364. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1365. ctx.stack_.back()->set("dhcp-ddns", m);
  1366. ctx.stack_.push_back(m);
  1367. ctx.enter(ctx.DHCP_DDNS);
  1368. } COLON LCURLY_BRACKET dhcp_ddns_params RCURLY_BRACKET {
  1369. ctx.stack_.pop_back();
  1370. ctx.leave();
  1371. };
  1372. sub_dhcp_ddns: LCURLY_BRACKET {
  1373. // Parse the dhcp-ddns map
  1374. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1375. ctx.stack_.push_back(m);
  1376. } dhcp_ddns_params RCURLY_BRACKET {
  1377. // parsing completed
  1378. };
  1379. dhcp_ddns_params: dhcp_ddns_param
  1380. | dhcp_ddns_params COMMA dhcp_ddns_param
  1381. ;
  1382. dhcp_ddns_param: enable_updates
  1383. | qualifying_suffix
  1384. | server_ip
  1385. | server_port
  1386. | sender_ip
  1387. | sender_port
  1388. | max_queue_size
  1389. | ncr_protocol
  1390. | ncr_format
  1391. | always_include_fqdn
  1392. | override_no_update
  1393. | override_client_update
  1394. | replace_client_name
  1395. | generated_prefix
  1396. | unknown_map_entry
  1397. ;
  1398. enable_updates: ENABLE_UPDATES COLON BOOLEAN {
  1399. ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
  1400. ctx.stack_.back()->set("enable-updates", b);
  1401. };
  1402. qualifying_suffix: QUALIFYING_SUFFIX {
  1403. ctx.enter(ctx.NO_KEYWORD);
  1404. } COLON STRING {
  1405. ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
  1406. ctx.stack_.back()->set("qualifying-suffix", s);
  1407. ctx.leave();
  1408. };
  1409. server_ip: SERVER_IP {
  1410. ctx.enter(ctx.NO_KEYWORD);
  1411. } COLON STRING {
  1412. ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
  1413. ctx.stack_.back()->set("server-ip", s);
  1414. ctx.leave();
  1415. };
  1416. server_port: SERVER_PORT COLON INTEGER {
  1417. ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
  1418. ctx.stack_.back()->set("server-port", i);
  1419. };
  1420. sender_ip: SENDER_IP {
  1421. ctx.enter(ctx.NO_KEYWORD);
  1422. } COLON STRING {
  1423. ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
  1424. ctx.stack_.back()->set("sender-ip", s);
  1425. ctx.leave();
  1426. };
  1427. sender_port: SENDER_PORT COLON INTEGER {
  1428. ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
  1429. ctx.stack_.back()->set("sender-port", i);
  1430. };
  1431. max_queue_size: MAX_QUEUE_SIZE COLON INTEGER {
  1432. ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
  1433. ctx.stack_.back()->set("max-queue-size", i);
  1434. };
  1435. ncr_protocol: NCR_PROTOCOL {
  1436. ctx.enter(ctx.NCR_PROTOCOL);
  1437. } COLON ncr_protocol_value {
  1438. ctx.stack_.back()->set("ncr-protocol", $4);
  1439. ctx.leave();
  1440. };
  1441. ncr_protocol_value:
  1442. UDP { $$ = ElementPtr(new StringElement("UDP", ctx.loc2pos(@1))); }
  1443. | TCP { $$ = ElementPtr(new StringElement("TCP", ctx.loc2pos(@1))); }
  1444. ;
  1445. ncr_format: NCR_FORMAT {
  1446. ctx.enter(ctx.NCR_FORMAT);
  1447. } COLON JSON {
  1448. ElementPtr json(new StringElement("JSON", ctx.loc2pos(@4)));
  1449. ctx.stack_.back()->set("ncr-format", json);
  1450. ctx.leave();
  1451. };
  1452. always_include_fqdn: ALWAYS_INCLUDE_FQDN COLON BOOLEAN {
  1453. ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
  1454. ctx.stack_.back()->set("always-include-fqdn", b);
  1455. };
  1456. override_no_update: OVERRIDE_NO_UPDATE COLON BOOLEAN {
  1457. ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
  1458. ctx.stack_.back()->set("override-no-update", b);
  1459. };
  1460. override_client_update: OVERRIDE_CLIENT_UPDATE COLON BOOLEAN {
  1461. ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
  1462. ctx.stack_.back()->set("override-client-update", b);
  1463. };
  1464. replace_client_name: REPLACE_CLIENT_NAME {
  1465. ctx.enter(ctx.REPLACE_CLIENT_NAME);
  1466. } COLON replace_client_name_value {
  1467. ctx.stack_.back()->set("replace-client-name", $4);
  1468. ctx.leave();
  1469. };
  1470. replace_client_name_value:
  1471. WHEN_PRESENT {
  1472. $$ = ElementPtr(new StringElement("when-present", ctx.loc2pos(@1)));
  1473. }
  1474. | NEVER {
  1475. $$ = ElementPtr(new StringElement("never", ctx.loc2pos(@1)));
  1476. }
  1477. | ALWAYS {
  1478. $$ = ElementPtr(new StringElement("always", ctx.loc2pos(@1)));
  1479. }
  1480. | WHEN_NOT_PRESENT {
  1481. $$ = ElementPtr(new StringElement("when-not-present", ctx.loc2pos(@1)));
  1482. }
  1483. | BOOLEAN {
  1484. error(@1, "boolean values for the replace-client-name are "
  1485. "no longer supported");
  1486. }
  1487. ;
  1488. generated_prefix: GENERATED_PREFIX {
  1489. ctx.enter(ctx.NO_KEYWORD);
  1490. } COLON STRING {
  1491. ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
  1492. ctx.stack_.back()->set("generated-prefix", s);
  1493. ctx.leave();
  1494. };
  1495. // JSON entries for Dhcp4 and DhcpDdns
  1496. dhcp4_json_object: DHCP4 {
  1497. ctx.enter(ctx.NO_KEYWORD);
  1498. } COLON value {
  1499. ctx.stack_.back()->set("Dhcp4", $4);
  1500. ctx.leave();
  1501. };
  1502. dhcpddns_json_object: DHCPDDNS {
  1503. ctx.enter(ctx.NO_KEYWORD);
  1504. } COLON value {
  1505. ctx.stack_.back()->set("DhcpDdns", $4);
  1506. ctx.leave();
  1507. };
  1508. control_agent_json_object: CONTROL_AGENT {
  1509. ctx.enter(ctx.NO_KEYWORD);
  1510. } COLON value {
  1511. ctx.stack_.back()->set("Control-agent", $4);
  1512. ctx.leave();
  1513. };
  1514. // --- logging entry -----------------------------------------
  1515. // This defines the top level "Logging" object. It parses
  1516. // the following "Logging": { ... }. The ... is defined
  1517. // by logging_params
  1518. logging_object: LOGGING {
  1519. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1520. ctx.stack_.back()->set("Logging", m);
  1521. ctx.stack_.push_back(m);
  1522. ctx.enter(ctx.LOGGING);
  1523. } COLON LCURLY_BRACKET logging_params RCURLY_BRACKET {
  1524. ctx.stack_.pop_back();
  1525. ctx.leave();
  1526. };
  1527. // This defines the list of allowed parameters that may appear
  1528. // in the top-level Logging object. It can either be a single
  1529. // parameter or several parameters separated by commas.
  1530. logging_params: logging_param
  1531. | logging_params COMMA logging_param
  1532. ;
  1533. // There's currently only one parameter defined, which is "loggers".
  1534. logging_param: loggers;
  1535. // "loggers", the only parameter currently defined in "Logging" object,
  1536. // is "Loggers": [ ... ].
  1537. loggers: LOGGERS {
  1538. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  1539. ctx.stack_.back()->set("loggers", l);
  1540. ctx.stack_.push_back(l);
  1541. ctx.enter(ctx.LOGGERS);
  1542. } COLON LSQUARE_BRACKET loggers_entries RSQUARE_BRACKET {
  1543. ctx.stack_.pop_back();
  1544. ctx.leave();
  1545. };
  1546. // These are the parameters allowed in loggers: either one logger
  1547. // entry or multiple entries separate by commas.
  1548. loggers_entries: logger_entry
  1549. | loggers_entries COMMA logger_entry
  1550. ;
  1551. // This defines a single entry defined in loggers in Logging.
  1552. logger_entry: LCURLY_BRACKET {
  1553. ElementPtr l(new MapElement(ctx.loc2pos(@1)));
  1554. ctx.stack_.back()->add(l);
  1555. ctx.stack_.push_back(l);
  1556. } logger_params RCURLY_BRACKET {
  1557. ctx.stack_.pop_back();
  1558. };
  1559. logger_params: logger_param
  1560. | logger_params COMMA logger_param
  1561. ;
  1562. logger_param: name
  1563. | output_options_list
  1564. | debuglevel
  1565. | severity
  1566. | unknown_map_entry
  1567. ;
  1568. debuglevel: DEBUGLEVEL COLON INTEGER {
  1569. ElementPtr dl(new IntElement($3, ctx.loc2pos(@3)));
  1570. ctx.stack_.back()->set("debuglevel", dl);
  1571. };
  1572. severity: SEVERITY {
  1573. ctx.enter(ctx.NO_KEYWORD);
  1574. } COLON STRING {
  1575. ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
  1576. ctx.stack_.back()->set("severity", sev);
  1577. ctx.leave();
  1578. };
  1579. output_options_list: OUTPUT_OPTIONS {
  1580. ElementPtr l(new ListElement(ctx.loc2pos(@1)));
  1581. ctx.stack_.back()->set("output_options", l);
  1582. ctx.stack_.push_back(l);
  1583. ctx.enter(ctx.OUTPUT_OPTIONS);
  1584. } COLON LSQUARE_BRACKET output_options_list_content RSQUARE_BRACKET {
  1585. ctx.stack_.pop_back();
  1586. ctx.leave();
  1587. };
  1588. output_options_list_content: output_entry
  1589. | output_options_list_content COMMA output_entry
  1590. ;
  1591. output_entry: LCURLY_BRACKET {
  1592. ElementPtr m(new MapElement(ctx.loc2pos(@1)));
  1593. ctx.stack_.back()->add(m);
  1594. ctx.stack_.push_back(m);
  1595. } output_params_list RCURLY_BRACKET {
  1596. ctx.stack_.pop_back();
  1597. };
  1598. output_params_list: output_params
  1599. | output_params_list COMMA output_params
  1600. ;
  1601. output_params: output
  1602. | flush
  1603. | maxsize
  1604. | maxver
  1605. ;
  1606. output: OUTPUT {
  1607. ctx.enter(ctx.NO_KEYWORD);
  1608. } COLON STRING {
  1609. ElementPtr sev(new StringElement($4, ctx.loc2pos(@4)));
  1610. ctx.stack_.back()->set("output", sev);
  1611. ctx.leave();
  1612. };
  1613. flush: FLUSH COLON BOOLEAN {
  1614. ElementPtr flush(new BoolElement($3, ctx.loc2pos(@3)));
  1615. ctx.stack_.back()->set("flush", flush);
  1616. }
  1617. maxsize: MAXSIZE COLON INTEGER {
  1618. ElementPtr maxsize(new IntElement($3, ctx.loc2pos(@3)));
  1619. ctx.stack_.back()->set("maxsize", maxsize);
  1620. }
  1621. maxver: MAXVER COLON INTEGER {
  1622. ElementPtr maxver(new IntElement($3, ctx.loc2pos(@3)));
  1623. ctx.stack_.back()->set("maxver", maxver);
  1624. }
  1625. %%
  1626. void
  1627. isc::dhcp::Dhcp6Parser::error(const location_type& loc,
  1628. const std::string& what)
  1629. {
  1630. ctx.error(loc, what);
  1631. }