1 // Copyright (C) 2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <run_script.h>
10 
11 using namespace isc::asiolink;
12 using namespace isc::data;
13 using namespace isc::hooks;
14 using namespace isc::util;
15 using namespace isc::dhcp;
16 using namespace std;
17 
18 namespace isc {
19 namespace run_script {
20 
21 IOServicePtr RunScriptImpl::io_service_;
22 
RunScriptImpl()23 RunScriptImpl::RunScriptImpl() : name_(), sync_(false) {
24 }
25 
26 void
configure(LibraryHandle & handle)27 RunScriptImpl::configure(LibraryHandle& handle) {
28     ConstElementPtr name = handle.getParameter("name");
29     if (!name) {
30         isc_throw(NotFound, "The 'name' parameter is mandatory");
31     }
32     if (name->getType() != Element::string) {
33         isc_throw(InvalidParameter, "The 'name' parameter must be a string");
34     }
35     try {
36         ProcessSpawn process(IOServicePtr(), name->stringValue());
37     } catch (const isc::Exception& ex) {
38         isc_throw(InvalidParameter, "Invalid 'name' parameter: " << ex.what());
39     }
40     setName(name->stringValue());
41     ConstElementPtr sync = handle.getParameter("sync");
42     if (sync) {
43         if (sync->getType() != Element::boolean) {
44             isc_throw(InvalidParameter, "The 'sync' parameter must be a boolean");
45         }
46         setSync(sync->boolValue());
47     }
48 }
49 
50 void
runScript(const ProcessArgs & args,const ProcessEnvVars & vars)51 RunScriptImpl::runScript(const ProcessArgs& args, const ProcessEnvVars& vars) {
52     ProcessSpawn process(getIOService(), name_, args, vars);
53     process.spawn(true);
54 }
55 
56 void
extractBoolean(ProcessEnvVars & vars,const bool value,const string & prefix,const string & suffix)57 RunScriptImpl::extractBoolean(ProcessEnvVars& vars,
58                               const bool value,
59                               const string& prefix,
60                               const string& suffix) {
61     string data;
62     if (value) {
63         data = "true";
64     } else {
65         data = "false";
66     }
67     string exported_data = prefix + suffix + "=" + data;
68     vars.push_back(exported_data);
69 }
70 
71 void
extractInteger(ProcessEnvVars & vars,const uint64_t value,const string & prefix,const string & suffix)72 RunScriptImpl::extractInteger(ProcessEnvVars& vars,
73                               const uint64_t value,
74                               const string& prefix,
75                               const string& suffix) {
76     string exported_data = prefix + suffix + "=" + boost::lexical_cast<string>(value);
77     vars.push_back(exported_data);
78 }
79 
80 void
extractString(ProcessEnvVars & vars,const string & value,const string & prefix,const string & suffix)81 RunScriptImpl::extractString(ProcessEnvVars& vars,
82                              const string& value,
83                              const string& prefix,
84                              const string& suffix) {
85     string exported_data = prefix + suffix + "=" + value;
86     vars.push_back(exported_data);
87 }
88 
89 void
extractHWAddr(ProcessEnvVars & vars,const HWAddrPtr & hwaddr,const string & prefix,const string & suffix)90 RunScriptImpl::extractHWAddr(ProcessEnvVars& vars,
91                              const HWAddrPtr& hwaddr,
92                              const string& prefix,
93                              const string& suffix) {
94     if (hwaddr) {
95         RunScriptImpl::extractString(vars, hwaddr->toText(false), prefix, suffix);
96         RunScriptImpl::extractInteger(vars, hwaddr->htype_, prefix + "_TYPE", suffix);
97     } else {
98         RunScriptImpl::extractString(vars, "", prefix, suffix);
99         RunScriptImpl::extractString(vars, "", prefix + "_TYPE", suffix);
100     }
101 }
102 
103 void
extractDUID(ProcessEnvVars & vars,const DuidPtr duid,const string & prefix,const string & suffix)104 RunScriptImpl::extractDUID(ProcessEnvVars& vars,
105                            const DuidPtr duid,
106                            const string& prefix,
107                            const string& suffix) {
108     if (duid) {
109         RunScriptImpl::extractString(vars, duid->toText(),
110                                      prefix, suffix);
111     } else {
112         RunScriptImpl::extractString(vars, "", prefix, suffix);
113     }
114 }
115 
116 void
extractOption(ProcessEnvVars & vars,const OptionPtr option,const string & prefix,const string & suffix)117 RunScriptImpl::extractOption(ProcessEnvVars& vars,
118                              const OptionPtr option,
119                              const string& prefix,
120                              const string& suffix) {
121     if (option) {
122         RunScriptImpl::extractString(vars, option->toHexString(),
123                                      prefix + "_OPTION_" +
124                                      boost::lexical_cast<string>(option->getType()),
125                                      suffix);
126     }
127 }
128 
129 void
extractSubOption(ProcessEnvVars & vars,const OptionPtr option,uint16_t code,const string & prefix,const string & suffix)130 RunScriptImpl::extractSubOption(ProcessEnvVars& vars,
131                                 const OptionPtr option,
132                                 uint16_t code,
133                                 const string& prefix,
134                                 const string& suffix) {
135     if (option) {
136         RunScriptImpl::extractOption(vars, option->getOption(code),
137                                      prefix + "_OPTION_" +
138                                      boost::lexical_cast<string>(option->getType()) +
139                                      "_SUB", suffix);
140     }
141 }
142 
143 void
extractOptionIA(ProcessEnvVars & vars,const Option6IAPtr option6IA,const string & prefix,const string & suffix)144 RunScriptImpl::extractOptionIA(ProcessEnvVars& vars,
145                                const Option6IAPtr option6IA,
146                                const string& prefix,
147                                const string& suffix) {
148     if (option6IA) {
149         RunScriptImpl::extractInteger(vars, option6IA->getIAID(),
150                                       prefix + "_IAID", suffix);
151         RunScriptImpl::extractInteger(vars, option6IA->getType(),
152                                       prefix + "_IA_TYPE", suffix);
153         RunScriptImpl::extractInteger(vars, option6IA->getT1(),
154                                       prefix + "_IA_T1", suffix);
155         RunScriptImpl::extractInteger(vars, option6IA->getT2(),
156                                       prefix + "_IA_T2", suffix);
157     } else {
158         RunScriptImpl::extractString(vars, "", prefix + "_IAID", suffix);
159         RunScriptImpl::extractString(vars, "", prefix + "_IA_TYPE", suffix);
160         RunScriptImpl::extractString(vars, "", prefix + "_IA_T1", suffix);
161         RunScriptImpl::extractString(vars, "", prefix + "_IA_T2", suffix);
162     }
163 }
164 
165 void
extractSubnet4(ProcessEnvVars & vars,const Subnet4Ptr subnet4,const string & prefix,const string & suffix)166 RunScriptImpl::extractSubnet4(ProcessEnvVars& vars,
167                               const Subnet4Ptr subnet4,
168                               const string& prefix,
169                               const string& suffix) {
170     if (subnet4) {
171         RunScriptImpl::extractInteger(vars, subnet4->getID(),
172                                       prefix + "_ID", suffix);
173         RunScriptImpl::extractString(vars, subnet4->toText(),
174                                      prefix + "_NAME", suffix);
175         auto prefix_data = subnet4->get();
176         RunScriptImpl::extractString(vars, prefix_data.first.toText(),
177                                      prefix + "_PREFIX", suffix);
178         RunScriptImpl::extractInteger(vars, prefix_data.second,
179                                       prefix + "_PREFIX_LEN", suffix);
180     } else {
181         RunScriptImpl::extractString(vars, "", prefix + "_ID", suffix);
182         RunScriptImpl::extractString(vars, "", prefix + "_NAME", suffix);
183         RunScriptImpl::extractString(vars, "", prefix + "_PREFIX", suffix);
184         RunScriptImpl::extractString(vars, "", prefix + "_PREFIX_LEN", suffix);
185     }
186 }
187 
188 void
extractSubnet6(ProcessEnvVars & vars,const Subnet6Ptr subnet6,const string & prefix,const string & suffix)189 RunScriptImpl::extractSubnet6(ProcessEnvVars& vars,
190                               const Subnet6Ptr subnet6,
191                               const string& prefix,
192                               const string& suffix) {
193     if (subnet6) {
194         RunScriptImpl::extractInteger(vars, subnet6->getID(),
195                                       prefix + "_ID", suffix);
196         RunScriptImpl::extractString(vars, subnet6->toText(),
197                                      prefix + "_NAME", suffix);
198         auto prefix_data = subnet6->get();
199         RunScriptImpl::extractString(vars, prefix_data.first.toText(),
200                                      prefix + "_PREFIX", suffix);
201         RunScriptImpl::extractInteger(vars, prefix_data.second,
202                                       prefix + "_PREFIX_LEN", suffix);
203     } else {
204         RunScriptImpl::extractString(vars, "", prefix + "_ID", suffix);
205         RunScriptImpl::extractString(vars, "", prefix + "_NAME", suffix);
206         RunScriptImpl::extractString(vars, "", prefix + "_PREFIX", suffix);
207         RunScriptImpl::extractString(vars, "", prefix + "_PREFIX_LEN", suffix);
208     }
209 }
210 
211 void
extractLease4(ProcessEnvVars & vars,const Lease4Ptr & lease4,const string & prefix,const string & suffix)212 RunScriptImpl::extractLease4(ProcessEnvVars& vars,
213                              const Lease4Ptr& lease4,
214                              const string& prefix,
215                              const string& suffix) {
216     if (lease4) {
217         RunScriptImpl::extractString(vars, lease4->addr_.toText(),
218                                      prefix + "_ADDRESS", suffix);
219         RunScriptImpl::extractInteger(vars, static_cast<uint64_t>(lease4->cltt_),
220                                       prefix + "_CLTT", suffix);
221         RunScriptImpl::extractString(vars, lease4->hostname_,
222                                      prefix + "_HOSTNAME", suffix);
223         RunScriptImpl::extractHWAddr(vars, lease4->hwaddr_,
224                                      prefix + "_HWADDR", suffix);
225         RunScriptImpl::extractString(vars, Lease4::statesToText(lease4->state_),
226                                      prefix + "_STATE", suffix);
227         RunScriptImpl::extractInteger(vars, lease4->subnet_id_,
228                                       prefix + "_SUBNET_ID", suffix);
229         RunScriptImpl::extractInteger(vars, lease4->valid_lft_,
230                                       prefix + "_VALID_LIFETIME", suffix);
231         RunScriptImpl::extractDUID(vars, lease4->client_id_,
232                                    prefix + "_CLIENT_ID", suffix);
233     } else {
234         RunScriptImpl::extractString(vars, "", prefix + "_ADDRESS", suffix);
235         RunScriptImpl::extractString(vars, "", prefix + "_CLTT", suffix);
236         RunScriptImpl::extractString(vars, "", prefix + "_HOSTNAME", suffix);
237         RunScriptImpl::extractHWAddr(vars, HWAddrPtr(), prefix + "_HWADDR", suffix);
238         RunScriptImpl::extractString(vars, "", prefix + "_STATE", suffix);
239         RunScriptImpl::extractString(vars, "", prefix + "_SUBNET_ID", suffix);
240         RunScriptImpl::extractString(vars, "", prefix + "_VALID_LIFETIME", suffix);
241         RunScriptImpl::extractDUID(vars, DuidPtr(), prefix + "_CLIENT_ID", suffix);
242     }
243 }
244 
245 void
extractLease6(ProcessEnvVars & vars,const Lease6Ptr & lease6,const string & prefix,const string & suffix)246 RunScriptImpl::extractLease6(ProcessEnvVars& vars,
247                              const Lease6Ptr& lease6,
248                              const string& prefix,
249                              const string& suffix) {
250     if (lease6) {
251         RunScriptImpl::extractString(vars, lease6->addr_.toText(),
252                                      prefix + "_ADDRESS", suffix);
253         RunScriptImpl::extractInteger(vars, static_cast<uint64_t>(lease6->cltt_),
254                                       prefix + "_CLTT", suffix);
255         RunScriptImpl::extractString(vars, lease6->hostname_,
256                                      prefix + "_HOSTNAME", suffix);
257         RunScriptImpl::extractHWAddr(vars, lease6->hwaddr_,
258                                      prefix + "_HWADDR", suffix);
259         RunScriptImpl::extractString(vars, Lease6::statesToText(lease6->state_),
260                                      prefix + "_STATE", suffix);
261         RunScriptImpl::extractInteger(vars, lease6->subnet_id_,
262                                       prefix + "_SUBNET_ID", suffix);
263         RunScriptImpl::extractInteger(vars, lease6->valid_lft_,
264                                       prefix + "_VALID_LIFETIME", suffix);
265         RunScriptImpl::extractDUID(vars, lease6->duid_,
266                                    prefix + "_DUID", suffix);
267         RunScriptImpl::extractInteger(vars, lease6->iaid_,
268                                       prefix + "_IAID", suffix);
269         RunScriptImpl::extractInteger(vars, lease6->preferred_lft_,
270                                       prefix + "_PREFERRED_LIFETIME", suffix);
271         RunScriptImpl::extractInteger(vars, lease6->prefixlen_,
272                                       prefix + "_PREFIX_LEN", suffix);
273         RunScriptImpl::extractString(vars, Lease::typeToText(lease6->type_),
274                                      prefix + "_TYPE", suffix);
275     } else {
276         RunScriptImpl::extractString(vars, "", prefix + "_ADDRESS", suffix);
277         RunScriptImpl::extractString(vars, "", prefix + "_CLTT", suffix);
278         RunScriptImpl::extractString(vars, "", prefix + "_HOSTNAME", suffix);
279         RunScriptImpl::extractHWAddr(vars, HWAddrPtr(), prefix + "_HWADDR", suffix);
280         RunScriptImpl::extractString(vars, "", prefix + "_STATE", suffix);
281         RunScriptImpl::extractString(vars, "", prefix + "_SUBNET_ID", suffix);
282         RunScriptImpl::extractString(vars, "", prefix + "_VALID_LIFETIME", suffix);
283         RunScriptImpl::extractDUID(vars, DuidPtr(), prefix + "_DUID", suffix);
284         RunScriptImpl::extractString(vars, "", prefix + "_IAID", suffix);
285         RunScriptImpl::extractString(vars, "", prefix + "_PREFERRED_LIFETIME", suffix);
286         RunScriptImpl::extractString(vars, "", prefix + "_PREFIX_LEN", suffix);
287         RunScriptImpl::extractString(vars, "", prefix + "_TYPE", suffix);
288     }
289 }
290 
291 void
extractLeases4(ProcessEnvVars & vars,const Lease4CollectionPtr & leases4,const string & prefix,const string & suffix)292 RunScriptImpl::extractLeases4(ProcessEnvVars& vars,
293                               const Lease4CollectionPtr& leases4,
294                               const string& prefix,
295                               const string& suffix) {
296     if (leases4) {
297         RunScriptImpl::extractInteger(vars, leases4->size(),
298                                       prefix + "_SIZE", suffix);
299         for (size_t i = 0; i < leases4->size(); ++i) {
300             RunScriptImpl::extractLease4(vars, leases4->at(i),
301                                          prefix + "_AT" +
302                                          boost::lexical_cast<string>(i),
303                                          suffix);
304         }
305     } else {
306         RunScriptImpl::extractString(vars, "0", prefix + "_SIZE", suffix);
307     }
308 }
309 
310 void
extractLeases6(ProcessEnvVars & vars,const Lease6CollectionPtr & leases6,const string & prefix,const string & suffix)311 RunScriptImpl::extractLeases6(ProcessEnvVars& vars,
312                               const Lease6CollectionPtr& leases6,
313                               const string& prefix,
314                               const string& suffix) {
315     if (leases6) {
316         RunScriptImpl::extractInteger(vars, leases6->size(),
317                                       prefix + "_SIZE", suffix);
318         for (size_t i = 0; i < leases6->size(); ++i) {
319             RunScriptImpl::extractLease6(vars, leases6->at(i),
320                                          prefix + "_AT" +
321                                          boost::lexical_cast<string>(i),
322                                          suffix);
323         }
324     } else {
325         RunScriptImpl::extractString(vars, "0", prefix + "_SIZE", suffix);
326     }
327 }
328 
329 void
extractPkt4(ProcessEnvVars & vars,const Pkt4Ptr & pkt4,const string & prefix,const string & suffix)330 RunScriptImpl::extractPkt4(ProcessEnvVars& vars,
331                            const Pkt4Ptr& pkt4,
332                            const string& prefix,
333                            const string& suffix) {
334     if (pkt4) {
335         RunScriptImpl::extractString(vars, pkt4->getName(pkt4->getType()),
336                                      prefix + "_TYPE", suffix);
337         RunScriptImpl::extractInteger(vars, pkt4->getTransid(),
338                                       prefix + "_TXID", suffix);
339         RunScriptImpl::extractString(vars, pkt4->getLocalAddr().toText(),
340                                      prefix + "_LOCAL_ADDR", suffix);
341         RunScriptImpl::extractInteger(vars, pkt4->getLocalPort(),
342                                       prefix + "_LOCAL_PORT", suffix);
343         RunScriptImpl::extractString(vars, pkt4->getRemoteAddr().toText(),
344                                      prefix + "_REMOTE_ADDR", suffix);
345         RunScriptImpl::extractInteger(vars, pkt4->getRemotePort(),
346                                       prefix + "_REMOTE_PORT", suffix);
347         RunScriptImpl::extractInteger(vars, pkt4->getIndex(),
348                                       prefix + "_IFACE_INDEX", suffix);
349         RunScriptImpl::extractString(vars, pkt4->getIface(),
350                                      prefix + "_IFACE_NAME", suffix);
351         RunScriptImpl::extractInteger(vars, pkt4->getHops(),
352                                       prefix + "_HOPS", suffix);
353         RunScriptImpl::extractInteger(vars, pkt4->getSecs(),
354                                       prefix + "_SECS", suffix);
355         RunScriptImpl::extractInteger(vars, pkt4->getFlags(),
356                                       prefix + "_FLAGS", suffix);
357         RunScriptImpl::extractString(vars, pkt4->getCiaddr().toText(),
358                                      prefix + "_CIADDR", suffix);
359         RunScriptImpl::extractString(vars, pkt4->getSiaddr().toText(),
360                                      prefix + "_SIADDR", suffix);
361         RunScriptImpl::extractString(vars, pkt4->getYiaddr().toText(),
362                                      prefix + "_YIADDR", suffix);
363         RunScriptImpl::extractString(vars, pkt4->getGiaddr().toText(),
364                                      prefix + "_GIADDR", suffix);
365         RunScriptImpl::extractBoolean(vars, pkt4->isRelayed(),
366                                       prefix + "_RELAYED", suffix);
367         RunScriptImpl::extractHWAddr(vars, pkt4->getHWAddr(),
368                                      prefix + "_HWADDR", suffix);
369         RunScriptImpl::extractHWAddr(vars, pkt4->getLocalHWAddr(),
370                                      prefix + "_LOCAL_HWADDR", suffix);
371         RunScriptImpl::extractHWAddr(vars, pkt4->getRemoteHWAddr(),
372                                      prefix + "_REMOTE_HWADDR", suffix);
373         RunScriptImpl::extractOption(vars,
374                                      pkt4->getOption(DHO_DHCP_AGENT_OPTIONS),
375                                      prefix, suffix);
376         RunScriptImpl::extractSubOption(vars,
377                                         pkt4->getOption(DHO_DHCP_AGENT_OPTIONS),
378                                         RAI_OPTION_AGENT_CIRCUIT_ID,
379                                         prefix, suffix);
380         RunScriptImpl::extractSubOption(vars,
381                                         pkt4->getOption(DHO_DHCP_AGENT_OPTIONS),
382                                         RAI_OPTION_REMOTE_ID,
383                                         prefix, suffix);
384     } else {
385         RunScriptImpl::extractString(vars, "", prefix + "_TYPE", suffix);
386         RunScriptImpl::extractString(vars, "", prefix + "_TXID", suffix);
387         RunScriptImpl::extractString(vars, "", prefix + "_LOCAL_ADDR", suffix);
388         RunScriptImpl::extractString(vars, "", prefix + "_LOCAL_PORT", suffix);
389         RunScriptImpl::extractString(vars, "", prefix + "_REMOTE_ADDR", suffix);
390         RunScriptImpl::extractString(vars, "", prefix + "_REMOTE_PORT", suffix);
391         RunScriptImpl::extractString(vars, "", prefix + "_IFACE_INDEX", suffix);
392         RunScriptImpl::extractString(vars, "", prefix + "_IFACE_NAME", suffix);
393         RunScriptImpl::extractString(vars, "", prefix + "_HOPS", suffix);
394         RunScriptImpl::extractString(vars, "", prefix + "_SECS", suffix);
395         RunScriptImpl::extractString(vars, "", prefix + "_FLAGS", suffix);
396         RunScriptImpl::extractString(vars, "", prefix + "_CIADDR", suffix);
397         RunScriptImpl::extractString(vars, "", prefix + "_SIADDR", suffix);
398         RunScriptImpl::extractString(vars, "", prefix + "_YIADDR", suffix);
399         RunScriptImpl::extractString(vars, "", prefix + "_GIADDR", suffix);
400         RunScriptImpl::extractString(vars, "", prefix + "_RELAYED", suffix);
401         RunScriptImpl::extractHWAddr(vars, HWAddrPtr(),
402                                      prefix + "_HWADDR", suffix);
403         RunScriptImpl::extractHWAddr(vars, HWAddrPtr(),
404                                      prefix + "_LOCAL_HWADDR", suffix);
405         RunScriptImpl::extractHWAddr(vars, HWAddrPtr(),
406                                      prefix + "_REMOTE_HWADDR", suffix);
407     }
408 }
409 
410 void
extractPkt6(ProcessEnvVars & vars,const Pkt6Ptr & pkt6,const string & prefix,const string & suffix)411 RunScriptImpl::extractPkt6(ProcessEnvVars& vars,
412                            const Pkt6Ptr& pkt6,
413                            const string& prefix,
414                            const string& suffix) {
415     if (pkt6) {
416         RunScriptImpl::extractString(vars, pkt6->getName(pkt6->getType()),
417                                      prefix + "_TYPE", suffix);
418         RunScriptImpl::extractInteger(vars, pkt6->getTransid(),
419                                       prefix + "_TXID", suffix);
420         RunScriptImpl::extractString(vars, pkt6->getLocalAddr().toText(),
421                                      prefix + "_LOCAL_ADDR", suffix);
422         RunScriptImpl::extractInteger(vars, pkt6->getLocalPort(),
423                                       prefix + "_LOCAL_PORT", suffix);
424         RunScriptImpl::extractString(vars, pkt6->getRemoteAddr().toText(),
425                                      prefix + "_REMOTE_ADDR", suffix);
426         RunScriptImpl::extractInteger(vars, pkt6->getRemotePort(),
427                                       prefix + "_REMOTE_PORT", suffix);
428         RunScriptImpl::extractInteger(vars, pkt6->getIndex(),
429                                       prefix + "_IFACE_INDEX", suffix);
430         RunScriptImpl::extractString(vars, pkt6->getIface(),
431                                      prefix + "_IFACE_NAME", suffix);
432         RunScriptImpl::extractHWAddr(vars, pkt6->getRemoteHWAddr(),
433                                      prefix + "_REMOTE_HWADDR", suffix);
434         string proto_data = (pkt6->getProto() == Pkt6::UDP ? "UDP" : "TCP");
435         RunScriptImpl::extractString(vars, proto_data,
436                                      prefix + "_PROTO", suffix);
437         RunScriptImpl::extractDUID(vars, pkt6->getClientId(),
438                                    prefix + "_CLIENT_ID", suffix);
439     } else {
440         RunScriptImpl::extractString(vars, "", prefix + "_TYPE", suffix);
441         RunScriptImpl::extractString(vars, "", prefix + "_TXID", suffix);
442         RunScriptImpl::extractString(vars, "", prefix + "_LOCAL_ADDR", suffix);
443         RunScriptImpl::extractString(vars, "", prefix + "_LOCAL_PORT", suffix);
444         RunScriptImpl::extractString(vars, "", prefix + "_REMOTE_ADDR", suffix);
445         RunScriptImpl::extractString(vars, "", prefix + "_REMOTE_PORT", suffix);
446         RunScriptImpl::extractString(vars, "", prefix + "_IFACE_INDEX", suffix);
447         RunScriptImpl::extractString(vars, "", prefix + "_IFACE_NAME", suffix);
448         RunScriptImpl::extractHWAddr(vars, HWAddrPtr(),
449                                      prefix + "_REMOTE_HWADDR", suffix);
450         RunScriptImpl::extractString(vars, "", prefix + "_PROTO", suffix);
451         RunScriptImpl::extractDUID(vars, DuidPtr(),
452                                    prefix + "_CLIENT_ID", suffix);
453     }
454 }
455 
456 } // namespace run_script
457 } // namespace isc
458