dhcp6_parser.yy 54 KB

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