1 /* $NetBSD: parse.c,v 1.18 2013/07/17 15:42:03 christos Exp $ */
4 * Copyright (c) 2008 David Young. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: parse.c,v 1.18 2013/07/17 15:42:03 christos Exp $");
42 #include <arpa/inet.h>
43 #include <sys/param.h>
45 #include <net/if_dl.h>
46 #include <netatalk/at.h>
53 #define dbg_warnx(__fmt, ...) warnx(__fmt, __VA_ARGS__)
55 #define dbg_warnx(__fmt, ...) /* empty */
58 static int parser_default_init(struct parser
*);
59 static int pbranch_init(struct parser
*);
60 static int pkw_init(struct parser
*);
62 static int pterm_match(const struct parser
*, const struct match
*,
63 struct match
*, int, const char *);
65 static int paddr_match(const struct parser
*, const struct match
*,
66 struct match
*, int, const char *);
68 static int pbranch_match(const struct parser
*, const struct match
*,
69 struct match
*, int, const char *);
71 static int piface_match(const struct parser
*, const struct match
*,
72 struct match
*, int, const char *);
74 static int pstr_match(const struct parser
*, const struct match
*,
75 struct match
*, int, const char *);
77 static int pinteger_match(const struct parser
*, const struct match
*,
78 struct match
*, int, const char *);
80 static int pkw_match(const struct parser
*, const struct match
*,
81 struct match
*, int, const char *);
83 const struct parser_methods pterm_methods
= {
84 .pm_match
= pterm_match
88 const struct parser_methods pstr_methods
= {
89 .pm_match
= pstr_match
90 , .pm_init
= parser_default_init
93 const struct parser_methods pinteger_methods
= {
94 .pm_match
= pinteger_match
95 , .pm_init
= parser_default_init
98 const struct parser_methods paddr_methods
= {
99 .pm_match
= paddr_match
100 , .pm_init
= parser_default_init
103 const struct parser_methods piface_methods
= {
104 .pm_match
= piface_match
105 , .pm_init
= parser_default_init
108 const struct parser_methods pbranch_methods
= {
109 .pm_match
= pbranch_match
110 , .pm_init
= pbranch_init
113 const struct parser_methods pkw_methods
= {
114 .pm_match
= pkw_match
115 , .pm_init
= pkw_init
119 match_setenv(const struct match
*im
, struct match
*om
, const char *key
,
123 om
->m_env
= prop_dictionary_create();
125 om
->m_env
= prop_dictionary_copy(im
->m_env
);
127 if (om
->m_env
== NULL
)
130 if (key
!= NULL
&& !prop_dictionary_set(om
->m_env
, key
, o
))
134 prop_object_release((prop_object_t
)o
);
138 prop_object_release((prop_object_t
)om
->m_env
);
141 prop_object_release((prop_object_t
)o
);
147 pstr_match(const struct parser
*p
, const struct match
*im
, struct match
*om
,
148 int argidx
, const char *arg
)
151 const struct pstr
*ps
= (const struct pstr
*)p
;
160 len
= (int)sizeof(buf
);
161 if (get_string(arg
, NULL
, buf
, &len
, ps
->ps_hexok
) == NULL
) {
166 o
= (prop_object_t
)prop_data_create_data(buf
, len
);
173 if (match_setenv(im
, om
, ps
->ps_key
, o
) == -1)
176 om
->m_argidx
= argidx
;
178 om
->m_nextparser
= p
->p_nextparser
;
184 pinteger_match(const struct parser
*p
, const struct match
*im
, struct match
*om
,
185 int argidx
, const char *arg
)
188 const struct pinteger
*pi
= (const struct pinteger
*)p
;
197 val
= strtoimax(arg
, &end
, pi
->pi_base
);
198 if ((val
== INTMAX_MIN
|| val
== INTMAX_MAX
) && errno
== ERANGE
)
206 if (val
< pi
->pi_min
|| val
> pi
->pi_max
) {
211 o
= (prop_object_t
)prop_number_create_integer(val
);
218 if (match_setenv(im
, om
, pi
->pi_key
, o
) == -1)
221 om
->m_argidx
= argidx
;
223 om
->m_nextparser
= p
->p_nextparser
;
229 parse_linkaddr(const char *addr
, struct sockaddr_storage
*ss
)
231 static const size_t maxlen
=
232 sizeof(*ss
) - offsetof(struct sockaddr_dl
, sdl_data
[0]);
234 LLADDR_S_INITIAL
= 0,
235 LLADDR_S_ONE_OCTET
= 1,
236 LLADDR_S_TWO_OCTETS
= 2,
238 } state
= LLADDR_S_INITIAL
;
239 uint8_t octet
= 0, val
;
240 struct sockaddr_dl
*sdl
;
244 memset(ss
, 0, sizeof(*ss
));
245 ss
->ss_family
= AF_LINK
;
246 sdl
= (struct sockaddr_dl
*)ss
;
248 for (i
= 0, p
= addr
; i
< maxlen
; p
++) {
249 dbg_warnx("%s.%d: *p == %c, state %d", __func__
, __LINE__
, *p
,
252 dbg_warnx("%s.%d", __func__
, __LINE__
);
253 if (state
!= LLADDR_S_ONE_OCTET
&&
254 state
!= LLADDR_S_TWO_OCTETS
)
256 dbg_warnx("%s.%d", __func__
, __LINE__
);
257 sdl
->sdl_data
[i
++] = octet
;
258 sdl
->sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
)
259 + i
* sizeof(sdl
->sdl_data
[0]);
264 dbg_warnx("%s.%d", __func__
, __LINE__
);
265 if (state
!= LLADDR_S_ONE_OCTET
&&
266 state
!= LLADDR_S_TWO_OCTETS
)
268 dbg_warnx("%s.%d", __func__
, __LINE__
);
269 sdl
->sdl_data
[i
++] = octet
;
270 state
= LLADDR_S_COLON
;
273 if ('a' <= *p
&& *p
<= 'f')
275 else if ('A' <= *p
&& *p
<= 'F')
277 else if ('0' <= *p
&& *p
<= '9')
282 dbg_warnx("%s.%d", __func__
, __LINE__
);
283 if (state
== LLADDR_S_ONE_OCTET
) {
284 state
= LLADDR_S_TWO_OCTETS
;
287 } else if (state
!= LLADDR_S_INITIAL
&& state
!= LLADDR_S_COLON
)
290 state
= LLADDR_S_ONE_OCTET
;
293 dbg_warnx("%s.%d", __func__
, __LINE__
);
299 paddr_match(const struct parser
*p
, const struct match
*im
, struct match
*om
,
300 int argidx
, const char *arg0
)
302 unsigned int net
, node
;
306 struct sockaddr_at sat
;
307 struct sockaddr_in sin
;
308 struct sockaddr_storage ss
;
310 const struct paddr
*pa
= (const struct paddr
*)p
;
315 struct paddr_prefix
*pfx
, *mask
;
316 const struct sockaddr
*sa
= NULL
;
317 struct addrinfo hints
, *result
= NULL
;
318 char *arg
, *end
, *plen
= NULL
, *servname0
;
319 const char *servname
;
328 if (pa
->pa_activator
!= NULL
&&
329 prop_dictionary_get(im
->m_env
, pa
->pa_activator
) == NULL
)
332 if (pa
->pa_deactivator
!= NULL
&&
333 prop_dictionary_get(im
->m_env
, pa
->pa_deactivator
) != NULL
)
336 if (!prop_dictionary_get_int64(im
->m_env
, "af", &af0
))
341 memset(&u
, 0, sizeof(u
));
347 if ((arg
= strdup(arg0
)) == NULL
)
351 (void)strsep(&servname0
, ",");
352 servname
= (servname0
== NULL
) ? "0" : servname0
;
354 if (pa
->pa_maskkey
== NULL
)
356 else if ((plen
= strrchr(arg
, '/')) != NULL
)
359 memset(&hints
, 0, sizeof(hints
));
361 hints
.ai_flags
= AI_NUMERICHOST
| AI_PASSIVE
;
362 hints
.ai_family
= af
;
363 hints
.ai_socktype
= SOCK_DGRAM
;
366 rc
= getaddrinfo(arg
, servname
, &hints
, &result
);
368 if (result
->ai_next
== NULL
)
369 sa
= result
->ai_addr
;
373 } else if ((hints
.ai_flags
& AI_NUMERICHOST
) != 0 &&
374 (af
== AF_INET
|| af
== AF_UNSPEC
) &&
375 inet_aton(arg
, &u
.sin
.sin_addr
) == 1) {
376 u
.sin
.sin_family
= AF_INET
;
377 u
.sin
.sin_len
= sizeof(u
.sin
);
380 } else if ((hints
.ai_flags
& AI_NUMERICHOST
) == 0 ||
385 hints
.ai_flags
&= ~AI_NUMERICHOST
;
392 prefixlen
= strtol(plen
, &end
, 10);
393 if (end
!= NULL
&& *end
!= '\0')
395 if (prefixlen
< 0 || prefixlen
>= UINT8_MAX
) {
402 if (sa
!= NULL
|| af
!= AF_UNSPEC
)
406 if (sscanf(arg0
, "%u.%u%n", &net
, &node
, &nread
) == 2 &&
407 net
!= 0 && net
<= 0xffff && node
!= 0 && node
<= 0xfe &&
408 arg0
[nread
] == '\0') {
409 u
.sat
.sat_family
= AF_APPLETALK
;
410 u
.sat
.sat_len
= sizeof(u
.sat
);
411 u
.sat
.sat_addr
.s_net
= htons(net
);
412 u
.sat
.sat_addr
.s_node
= node
;
417 if (parse_linkaddr(arg0
, &u
.ss
) == -1)
427 len
= offsetof(struct paddr_prefix
, pfx_addr
) + sa
->sa_len
;
429 if ((pfx
= malloc(len
)) == NULL
)
436 for (i
= 0; i
< sa
->sa_len
; i
++)
437 printf(" %02x", ((const uint8_t *)sa
)[i
]);
442 pfx
->pfx_len
= (int16_t)prefixlen
;
443 memcpy(&pfx
->pfx_addr
, sa
, sa
->sa_len
);
447 freeaddrinfo(result
);
449 o
= (prop_object_t
)prop_data_create_data(pfx
, len
);
456 if (match_setenv(im
, om
, pa
->pa_addrkey
, o
) == -1)
459 if (pa
->pa_maskkey
!= NULL
&& plen
!= NULL
) {
462 if ((mask
= prefixlen_to_mask(af
, prefixlen
)) == NULL
) {
463 err(EXIT_FAILURE
, "%s: prefixlen_to_mask(%d, %ld)",
464 __func__
, af
, prefixlen
);
468 masklen
= paddr_prefix_size(mask
);
470 d
= prop_data_create_data(mask
, masklen
);
474 err(EXIT_FAILURE
, "%s: prop_data_create_data",
479 rc
= prop_dictionary_set(om
->m_env
, pa
->pa_maskkey
,
480 (prop_object_t
)d
) ? 0 : -1;
482 prop_object_release((prop_object_t
)d
);
485 err(EXIT_FAILURE
, "%s: prop_dictionary_set", __func__
);
490 om
->m_argidx
= argidx
;
492 om
->m_nextparser
= p
->p_nextparser
;
497 pterm_match(const struct parser
*p
, const struct match
*im
,
498 struct match
*om
, int argidx
, const char *arg
)
500 const struct pterm
*pt
= (const struct pterm
*)p
;
507 b
= prop_bool_create(true);
509 if (match_setenv(im
, om
, pt
->pt_key
, (prop_object_t
)b
) == -1)
512 om
->m_argidx
= argidx
;
514 om
->m_nextparser
= NULL
;
519 piface_match(const struct parser
*p
, const struct match
*im
,
520 struct match
*om
, int argidx
, const char *arg
)
522 const struct piface
*pif
= (const struct piface
*)p
;
525 if (arg
== NULL
|| strlen(arg
) > IFNAMSIZ
) {
530 if ((o
= (prop_object_t
)prop_string_create_cstring(arg
)) == NULL
) {
535 if (match_setenv(im
, om
, pif
->pif_key
, o
) == -1)
538 om
->m_argidx
= argidx
;
540 om
->m_nextparser
= p
->p_nextparser
;
545 match_cleanup(struct match
*dst
)
547 if (dst
->m_env
!= NULL
)
548 prop_object_release((prop_object_t
)dst
->m_env
);
549 memset(dst
, 0, sizeof(*dst
));
553 match_copy(struct match
*dst
, const struct match
*src
)
557 prop_object_retain((prop_object_t
)src
->m_env
);
562 pbranch_match(const struct parser
*p
, const struct match
*im
,
563 struct match
*om
, int argidx
, const char *arg
)
565 const struct parser
*nextp
;
567 const struct pbranch
*pb
= (const struct pbranch
*)p
;
569 int nforbid
= 0, nmatch
= 0, rc
;
570 parser_match_t matchfunc
;
572 memset(&tmpm
, 0, sizeof(tmpm
));
574 SIMPLEQ_FOREACH(b
, &pb
->pb_branches
, b_next
) {
575 nextp
= b
->b_nextparser
;
576 dbg_warnx("%s: b->b_nextparser %p [%s]", __func__
,
577 nextp
, nextp
? nextp
->p_name
: "(null)");
581 match_setenv(im
, om
, NULL
, NULL
);
582 om
->m_nextparser
= NULL
;
584 om
->m_argidx
= argidx
;
588 matchfunc
= nextp
->p_methods
->pm_match
;
589 rc
= (*matchfunc
)(nextp
, im
, &tmpm
, argidx
, arg
);
591 match_copy(om
, &tmpm
);
592 match_cleanup(&tmpm
);
594 dbg_warnx("%s: branch %s ok", __func__
, nextp
->p_name
);
595 if (pb
->pb_match_first
)
597 } else if (rc
== 1) {
599 if (pb
->pb_match_first
)
602 dbg_warnx("%s: fail branch %s", __func__
,
609 return (nforbid
== 0) ? -1 : 1;
611 dbg_warnx("%s: branch ok", __func__
);
621 pkw_match(const struct parser
*p
, const struct match
*im
,
622 struct match
*om
, int argidx
, const char *arg
)
624 prop_object_t o
= NULL
;
626 union kwval
*u
= NULL
;
627 const struct pkw
*pk
= (const struct pkw
*)p
;
634 SIMPLEQ_FOREACH(k
, &pk
->pk_keywords
, k_next
) {
635 if (k
->k_act
!= NULL
&&
636 prop_dictionary_get(im
->m_env
, k
->k_act
) == NULL
)
639 if (k
->k_neg
&& arg
[0] == '-' &&
640 strcmp(k
->k_word
, arg
+ 1) == 0)
642 else if (strcmp(k
->k_word
, arg
) == 0)
647 if (k
->k_altdeact
!= NULL
&&
648 prop_dictionary_get(im
->m_env
, k
->k_altdeact
) != NULL
)
651 if (k
->k_deact
!= NULL
&&
652 prop_dictionary_get(im
->m_env
, k
->k_deact
) != NULL
)
664 o
= (prop_object_t
)prop_bool_create(u
->u_bool
);
669 o
= (prop_object_t
)prop_number_create_integer(u
->u_sint
);
674 o
= (prop_object_t
)prop_number_create_unsigned_integer(
683 o
= (prop_object_t
)prop_string_create_cstring_nocopy(u
->u_str
);
688 errx(EXIT_FAILURE
, "unknown keyword type %d", k
->k_type
);
691 if (match_setenv(im
, om
, (o
== NULL
) ? NULL
: k
->k_key
, o
) == -1)
694 om
->m_argidx
= argidx
;
696 om
->m_nextparser
= k
->k_nextparser
;
697 om
->m_exec
= k
->k_exec
;
705 paddr_create(const char *name
, parser_exec_t pexec
, const char *addrkey
,
706 const char *maskkey
, struct parser
*next
)
710 if ((pa
= calloc(sizeof(*pa
), 1)) == NULL
)
713 pa
->pa_parser
.p_methods
= &paddr_methods
;
714 pa
->pa_parser
.p_exec
= pexec
;
715 pa
->pa_parser
.p_name
= name
;
716 pa
->pa_parser
.p_nextparser
= next
;
718 pa
->pa_addrkey
= addrkey
;
719 pa
->pa_maskkey
= maskkey
;
725 piface_create(const char *name
, parser_exec_t pexec
, const char *defkey
,
726 struct parser
*defnext
)
730 if ((pif
= calloc(sizeof(*pif
), 1)) == NULL
)
733 pif
->pif_parser
.p_methods
= &piface_methods
;
734 pif
->pif_parser
.p_exec
= pexec
;
735 pif
->pif_parser
.p_name
= name
;
736 pif
->pif_parser
.p_nextparser
= defnext
;
738 pif
->pif_key
= defkey
;
744 pbranch_addbranch(struct pbranch
*pb
, struct parser
*p
)
748 if ((b
= malloc(sizeof(*b
))) == NULL
)
751 SIMPLEQ_INSERT_HEAD(&pb
->pb_branches
, b
, b_next
);
752 pb
->pb_parser
.p_initialized
= false;
753 return parser_init(&pb
->pb_parser
);
757 pbranch_setbranches(struct pbranch
*pb
, const struct branch
*brs
, size_t nbr
)
762 dbg_warnx("%s: nbr %zu", __func__
, nbr
);
764 while ((b
= SIMPLEQ_FIRST(&pb
->pb_branches
)) != NULL
) {
765 SIMPLEQ_REMOVE_HEAD(&pb
->pb_branches
, b_next
);
769 for (i
= 0; i
< nbr
; i
++) {
770 if ((b
= malloc(sizeof(*b
))) == NULL
)
773 dbg_warnx("%s: b->b_nextparser %p [%s]", __func__
,
774 b
->b_nextparser
, b
->b_nextparser
? b
->b_nextparser
->p_name
776 SIMPLEQ_INSERT_TAIL(&pb
->pb_branches
, b
, b_next
);
781 while ((b
= SIMPLEQ_FIRST(&pb
->pb_branches
)) != NULL
) {
782 SIMPLEQ_REMOVE_HEAD(&pb
->pb_branches
, b_next
);
789 pbranch_init(struct parser
*p
)
792 struct pbranch
*pb
= (struct pbranch
*)p
;
795 if (pb
->pb_nbrinit
== 0)
797 else if (pbranch_setbranches(pb
, pb
->pb_brinit
, pb
->pb_nbrinit
) == -1)
802 SIMPLEQ_FOREACH(b
, &pb
->pb_branches
, b_next
) {
803 np
= b
->b_nextparser
;
804 if (np
!= NULL
&& parser_init(np
) == -1)
811 pbranch_create(const char *name
, const struct branch
*brs
, size_t nbr
,
816 dbg_warnx("%s: nbr %zu", __func__
, nbr
);
818 if ((pb
= calloc(1, sizeof(*pb
))) == NULL
)
821 pb
->pb_parser
.p_methods
= &pbranch_methods
;
822 pb
->pb_parser
.p_name
= name
;
824 SIMPLEQ_INIT(&pb
->pb_branches
);
826 if (pbranch_setbranches(pb
, brs
, nbr
) == -1)
829 pb
->pb_match_first
= match_first
;
837 parser_default_init(struct parser
*p
)
841 np
= p
->p_nextparser
;
842 if (np
!= NULL
&& parser_init(np
) == -1)
849 pkw_setwords(struct pkw
*pk
, parser_exec_t defexec
, const char *defkey
,
850 const struct kwinst
*kws
, size_t nkw
, struct parser
*defnext
)
855 for (i
= 0; i
< nkw
; i
++) {
856 if (kws
[i
].k_word
== NULL
)
858 if ((k
= malloc(sizeof(*k
))) == NULL
)
861 if (k
->k_nextparser
== NULL
)
862 k
->k_nextparser
= defnext
;
863 if (k
->k_key
== NULL
)
865 if (k
->k_exec
== NULL
)
867 SIMPLEQ_INSERT_TAIL(&pk
->pk_keywords
, k
, k_next
);
872 while ((k
= SIMPLEQ_FIRST(&pk
->pk_keywords
)) != NULL
) {
873 SIMPLEQ_REMOVE_HEAD(&pk
->pk_keywords
, k_next
);
880 pkw_init(struct parser
*p
)
883 struct pkw
*pk
= (struct pkw
*)p
;
886 if (pk
->pk_nkwinit
== 0)
888 else if (pkw_setwords(pk
, pk
->pk_execinit
, pk
->pk_keyinit
,
889 pk
->pk_kwinit
, pk
->pk_nkwinit
, pk
->pk_nextinit
) == -1)
894 SIMPLEQ_FOREACH(k
, &pk
->pk_keywords
, k_next
) {
895 np
= k
->k_nextparser
;
896 if (np
!= NULL
&& parser_init(np
) == -1)
903 pkw_create(const char *name
, parser_exec_t defexec
, const char *defkey
,
904 const struct kwinst
*kws
, size_t nkw
, struct parser
*defnext
)
908 if ((pk
= calloc(1, sizeof(*pk
))) == NULL
)
911 pk
->pk_parser
.p_methods
= &pkw_methods
;
912 pk
->pk_parser
.p_exec
= defexec
;
913 pk
->pk_parser
.p_name
= name
;
915 SIMPLEQ_INIT(&pk
->pk_keywords
);
917 if (pkw_setwords(pk
, defexec
, defkey
, kws
, nkw
, defnext
) == -1)
927 parse(int argc
, char **argv
, const struct parser
*p0
, struct match
*matches
,
928 size_t *nmatch
, int *narg
)
931 struct match
*lastm
= NULL
, *m
= matches
;
932 const struct parser
*p
= p0
;
934 for (i
= 0; i
< argc
&& p
!= NULL
; i
++) {
935 if ((size_t)(m
- matches
) >= *nmatch
) {
940 rc
= (*p
->p_methods
->pm_match
)(p
, lastm
, m
, i
, argv
[i
]);
946 for (; (size_t)(m
- matches
) < *nmatch
&& p
!= NULL
; ) {
947 rc
= (*p
->p_methods
->pm_match
)(p
, lastm
, m
, i
, NULL
);
954 *nmatch
= m
- matches
;
960 matches_exec(const struct match
*matches
, prop_dictionary_t oenv
, size_t nmatch
)
964 const struct match
*m
;
968 for (i
= 0; i
< nmatch
; i
++) {
970 dbg_warnx("%s.%d: i %zu", __func__
, __LINE__
, i
);
971 pexec
= (m
->m_parser
->p_exec
!= NULL
)
972 ? m
->m_parser
->p_exec
: m
->m_exec
;
975 dbg_warnx("%s.%d: m->m_parser->p_name %s", __func__
, __LINE__
,
976 m
->m_parser
->p_name
);
977 d
= prop_dictionary_augment(m
->m_env
, oenv
);
978 rc
= (*pexec
)(d
, oenv
);
979 prop_object_release((prop_object_t
)d
);
987 parser_init(struct parser
*p
)
989 if (p
->p_initialized
)
991 p
->p_initialized
= true;
992 if (p
->p_methods
->pm_init
== NULL
)
994 return (*p
->p_methods
->pm_init
)(p
);