1 /* $KAME: dhcp6c_script.c,v 1.11 2004/11/28 10:48:38 jinmei Exp $ */
4 * Copyright (C) 2003 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/queue.h>
38 #if TIME_WITH_SYS_TIME
39 # include <sys/time.h>
43 # include <sys/time.h>
49 #include <netinet/in.h>
63 static char sipserver_str
[] = "new_sip_servers";
64 static char sipname_str
[] = "new_sip_name";
65 static char dnsserver_str
[] = "new_domain_name_servers";
66 static char dnsname_str
[] = "new_domain_name";
67 static char ntpserver_str
[] = "new_ntp_servers";
68 static char nisserver_str
[] = "new_nis_servers";
69 static char nisname_str
[] = "new_nis_name";
70 static char nispserver_str
[] = "new_nisp_servers";
71 static char nispname_str
[] = "new_nisp_name";
72 static char bcmcsserver_str
[] = "new_bcmcs_servers";
73 static char bcmcsname_str
[] = "new_bcmcs_name";
76 client6_script(scriptpath
, state
, optinfo
)
79 struct dhcp6_optinfo
*optinfo
;
81 int i
, dnsservers
, ntpservers
, dnsnamelen
, envc
, elen
, ret
= 0;
82 int sipservers
, sipnamelen
;
83 int nisservers
, nisnamelen
;
84 int nispservers
, nispnamelen
;
85 int bcmcsservers
, bcmcsnamelen
;
87 char reason
[] = "REASON=NBI";
88 struct dhcp6_listval
*v
;
91 /* if a script is not specified, do nothing */
92 if (scriptpath
== NULL
|| strlen(scriptpath
) == 0)
95 /* initialize counters */
107 envc
= 2; /* we at least include the reason and the terminator */
109 /* count the number of variables */
110 for (v
= TAILQ_FIRST(&optinfo
->dns_list
); v
; v
= TAILQ_NEXT(v
, link
))
112 envc
+= dnsservers
? 1 : 0;
113 for (v
= TAILQ_FIRST(&optinfo
->dnsname_list
); v
;
114 v
= TAILQ_NEXT(v
, link
)) {
115 dnsnamelen
+= v
->val_vbuf
.dv_len
;
117 envc
+= dnsnamelen
? 1 : 0;
118 for (v
= TAILQ_FIRST(&optinfo
->ntp_list
); v
; v
= TAILQ_NEXT(v
, link
))
120 envc
+= ntpservers
? 1 : 0;
121 for (v
= TAILQ_FIRST(&optinfo
->sip_list
); v
; v
= TAILQ_NEXT(v
, link
))
123 envc
+= sipservers
? 1 : 0;
124 for (v
= TAILQ_FIRST(&optinfo
->sipname_list
); v
;
125 v
= TAILQ_NEXT(v
, link
)) {
126 sipnamelen
+= v
->val_vbuf
.dv_len
;
128 envc
+= sipnamelen
? 1 : 0;
130 for (v
= TAILQ_FIRST(&optinfo
->nis_list
); v
; v
= TAILQ_NEXT(v
, link
))
132 envc
+= nisservers
? 1 : 0;
133 for (v
= TAILQ_FIRST(&optinfo
->nisname_list
); v
;
134 v
= TAILQ_NEXT(v
, link
)) {
135 nisnamelen
+= v
->val_vbuf
.dv_len
;
137 envc
+= nisnamelen
? 1 : 0;
139 for (v
= TAILQ_FIRST(&optinfo
->nisp_list
); v
; v
= TAILQ_NEXT(v
, link
))
141 envc
+= nispservers
? 1 : 0;
142 for (v
= TAILQ_FIRST(&optinfo
->nispname_list
); v
;
143 v
= TAILQ_NEXT(v
, link
)) {
144 nispnamelen
+= v
->val_vbuf
.dv_len
;
146 envc
+= nispnamelen
? 1 : 0;
148 for (v
= TAILQ_FIRST(&optinfo
->bcmcs_list
); v
; v
= TAILQ_NEXT(v
, link
))
150 envc
+= bcmcsservers
? 1 : 0;
151 for (v
= TAILQ_FIRST(&optinfo
->bcmcsname_list
); v
;
152 v
= TAILQ_NEXT(v
, link
)) {
153 bcmcsnamelen
+= v
->val_vbuf
.dv_len
;
155 envc
+= bcmcsnamelen
? 1 : 0;
157 /* allocate an environments array */
158 if ((envp
= malloc(sizeof (char *) * envc
)) == NULL
) {
159 dprintf(LOG_NOTICE
, FNAME
,
160 "failed to allocate environment buffer");
163 memset(envp
, 0, sizeof (char *) * envc
);
166 * Copy the parameters as environment variables
170 if ((envp
[i
++] = strdup(reason
)) == NULL
) {
171 dprintf(LOG_NOTICE
, FNAME
,
172 "failed to allocate reason strings");
176 /* "var=addr1 addr2 ... addrN" + null char for termination */
178 elen
= sizeof (dnsserver_str
) +
179 (INET6_ADDRSTRLEN
+ 1) * dnsservers
+ 1;
180 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
181 dprintf(LOG_NOTICE
, FNAME
,
182 "failed to allocate strings for DNS servers");
187 snprintf(s
, elen
, "%s=", dnsserver_str
);
188 for (v
= TAILQ_FIRST(&optinfo
->dns_list
); v
;
189 v
= TAILQ_NEXT(v
, link
)) {
192 addr
= in6addr2str(&v
->val_addr6
, 0);
193 strlcat(s
, addr
, elen
);
194 strlcat(s
, " ", elen
);
198 elen
= sizeof (ntpserver_str
) +
199 (INET6_ADDRSTRLEN
+ 1) * ntpservers
+ 1;
200 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
201 dprintf(LOG_NOTICE
, FNAME
,
202 "failed to allocate strings for NTP servers");
207 snprintf(s
, elen
, "%s=", ntpserver_str
);
208 for (v
= TAILQ_FIRST(&optinfo
->ntp_list
); v
;
209 v
= TAILQ_NEXT(v
, link
)) {
212 addr
= in6addr2str(&v
->val_addr6
, 0);
213 strlcat(s
, addr
, elen
);
214 strlcat(s
, " ", elen
);
219 elen
= sizeof (dnsname_str
) + dnsnamelen
+ 1;
220 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
221 dprintf(LOG_NOTICE
, FNAME
,
222 "failed to allocate strings for DNS name");
227 snprintf(s
, elen
, "%s=", dnsname_str
);
228 for (v
= TAILQ_FIRST(&optinfo
->dnsname_list
); v
;
229 v
= TAILQ_NEXT(v
, link
)) {
230 strlcat(s
, v
->val_vbuf
.dv_buf
, elen
);
231 strlcat(s
, " ", elen
);
236 elen
= sizeof (sipserver_str
) +
237 (INET6_ADDRSTRLEN
+ 1) * sipservers
+ 1;
238 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
239 dprintf(LOG_NOTICE
, FNAME
,
240 "failed to allocate strings for SIP servers");
245 snprintf(s
, elen
, "%s=", sipserver_str
);
246 for (v
= TAILQ_FIRST(&optinfo
->sip_list
); v
;
247 v
= TAILQ_NEXT(v
, link
)) {
250 addr
= in6addr2str(&v
->val_addr6
, 0);
251 strlcat(s
, addr
, elen
);
252 strlcat(s
, " ", elen
);
256 elen
= sizeof (sipname_str
) + sipnamelen
+ 1;
257 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
258 dprintf(LOG_NOTICE
, FNAME
,
259 "failed to allocate strings for SIP domain name");
264 snprintf(s
, elen
, "%s=", sipname_str
);
265 for (v
= TAILQ_FIRST(&optinfo
->sipname_list
); v
;
266 v
= TAILQ_NEXT(v
, link
)) {
267 strlcat(s
, v
->val_vbuf
.dv_buf
, elen
);
268 strlcat(s
, " ", elen
);
273 elen
= sizeof (nisserver_str
) +
274 (INET6_ADDRSTRLEN
+ 1) * nisservers
+ 1;
275 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
276 dprintf(LOG_NOTICE
, FNAME
,
277 "failed to allocate strings for NIS servers");
282 snprintf(s
, elen
, "%s=", nisserver_str
);
283 for (v
= TAILQ_FIRST(&optinfo
->nis_list
); v
;
284 v
= TAILQ_NEXT(v
, link
)) {
287 addr
= in6addr2str(&v
->val_addr6
, 0);
288 strlcat(s
, addr
, elen
);
289 strlcat(s
, " ", elen
);
293 elen
= sizeof (nisname_str
) + nisnamelen
+ 1;
294 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
295 dprintf(LOG_NOTICE
, FNAME
,
296 "failed to allocate strings for NIS domain name");
301 snprintf(s
, elen
, "%s=", nisname_str
);
302 for (v
= TAILQ_FIRST(&optinfo
->nisname_list
); v
;
303 v
= TAILQ_NEXT(v
, link
)) {
304 strlcat(s
, v
->val_vbuf
.dv_buf
, elen
);
305 strlcat(s
, " ", elen
);
310 elen
= sizeof (nispserver_str
) +
311 (INET6_ADDRSTRLEN
+ 1) * nispservers
+ 1;
312 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
313 dprintf(LOG_NOTICE
, FNAME
,
314 "failed to allocate strings for NIS+ servers");
319 snprintf(s
, elen
, "%s=", nispserver_str
);
320 for (v
= TAILQ_FIRST(&optinfo
->nisp_list
); v
;
321 v
= TAILQ_NEXT(v
, link
)) {
324 addr
= in6addr2str(&v
->val_addr6
, 0);
325 strlcat(s
, addr
, elen
);
326 strlcat(s
, " ", elen
);
330 elen
= sizeof (nispname_str
) + nispnamelen
+ 1;
331 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
332 dprintf(LOG_NOTICE
, FNAME
,
333 "failed to allocate strings for NIS+ domain name");
338 snprintf(s
, elen
, "%s=", nispname_str
);
339 for (v
= TAILQ_FIRST(&optinfo
->nispname_list
); v
;
340 v
= TAILQ_NEXT(v
, link
)) {
341 strlcat(s
, v
->val_vbuf
.dv_buf
, elen
);
342 strlcat(s
, " ", elen
);
347 elen
= sizeof (bcmcsserver_str
) +
348 (INET6_ADDRSTRLEN
+ 1) * bcmcsservers
+ 1;
349 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
350 dprintf(LOG_NOTICE
, FNAME
,
351 "failed to allocate strings for BCMC servers");
356 snprintf(s
, elen
, "%s=", bcmcsserver_str
);
357 for (v
= TAILQ_FIRST(&optinfo
->bcmcs_list
); v
;
358 v
= TAILQ_NEXT(v
, link
)) {
361 addr
= in6addr2str(&v
->val_addr6
, 0);
362 strlcat(s
, addr
, elen
);
363 strlcat(s
, " ", elen
);
367 elen
= sizeof (bcmcsname_str
) + bcmcsnamelen
+ 1;
368 if ((s
= envp
[i
++] = malloc(elen
)) == NULL
) {
369 dprintf(LOG_NOTICE
, FNAME
,
370 "failed to allocate strings for BCMC domain name");
375 snprintf(s
, elen
, "%s=", bcmcsname_str
);
376 for (v
= TAILQ_FIRST(&optinfo
->bcmcsname_list
); v
;
377 v
= TAILQ_NEXT(v
, link
)) {
378 strlcat(s
, v
->val_vbuf
.dv_buf
, elen
);
379 strlcat(s
, " ", elen
);
383 /* launch the script */
386 dprintf(LOG_ERR
, FNAME
, "failed to fork: %s", strerror(errno
));
393 wpid
= wait(&wstatus
);
394 } while (wpid
!= pid
&& wpid
> 0);
397 dprintf(LOG_ERR
, FNAME
, "wait: %s", strerror(errno
));
399 dprintf(LOG_DEBUG
, FNAME
,
400 "script \"%s\" terminated", scriptpath
);
406 argv
[0] = scriptpath
;
409 if (safefile(scriptpath
)) {
410 dprintf(LOG_ERR
, FNAME
,
411 "script \"%s\" cannot be executed safely",
416 if (foreground
== 0 && (fd
= open("/dev/null", O_RDWR
)) != -1) {
417 dup2(fd
, STDIN_FILENO
);
418 dup2(fd
, STDOUT_FILENO
);
419 dup2(fd
, STDERR_FILENO
);
420 if (fd
> STDERR_FILENO
)
424 execve(scriptpath
, argv
, envp
);
426 dprintf(LOG_ERR
, FNAME
, "child: exec failed: %s",
432 for (i
= 0; i
< envc
; i
++)