summaryrefslogtreecommitdiff
path: root/proto/rpki/config.Y
blob: d6d326b814a8f3de77a1529361503977a549f68d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 *	BIRD -- The Resource Public Key Infrastructure (RPKI) to Router Protocol
 *
 *	(c) 2015 CZ.NIC
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

CF_HDR

#include "proto/rpki/rpki.h"

CF_DEFINES

#define RPKI_CFG ((struct rpki_config *) this_proto)
#define RPKI_TR_SSH_CFG ((struct rpki_tr_ssh_config *) RPKI_CFG->tr_config.spec)

static void
rpki_check_unused_hostname(void)
{
  if (RPKI_CFG->hostname != NULL)
    cf_error("Only one cache server per protocol allowed");
}

static void
rpki_check_unused_transport(void)
{
  if (RPKI_CFG->tr_config.spec != NULL)
    cf_error("At the most one transport per protocol allowed");
}

CF_DECLS

CF_KEYWORDS(RPKI, REMOTE, BIRD, PRIVATE, PUBLIC, KEY, TCP, SSH, TRANSPORT, USER,
	    RETRY, REFRESH, EXPIRE, KEEP, IGNORE, MAX, LENGTH)

%type <i> rpki_keep_interval

CF_GRAMMAR

proto: rpki_proto ;

rpki_proto_start: proto_start RPKI {
  this_proto = proto_config_new(&proto_rpki, $1);
  RPKI_CFG->retry_interval = RPKI_RETRY_INTERVAL;
  RPKI_CFG->refresh_interval = RPKI_REFRESH_INTERVAL;
  RPKI_CFG->expire_interval = RPKI_EXPIRE_INTERVAL;
};

rpki_proto: rpki_proto_start proto_name '{' rpki_proto_opts '}' { rpki_check_config(RPKI_CFG); };

rpki_proto_opts:
   /* empty */
 | rpki_proto_opts rpki_proto_item ';'
 ;

rpki_proto_item:
   proto_item
 | proto_channel
 | REMOTE rpki_cache_addr
 | REMOTE rpki_cache_addr rpki_proto_item_port
 | rpki_proto_item_port
 | TRANSPORT rpki_transport
 | REFRESH rpki_keep_interval expr {
     if (rpki_check_refresh_interval($3))
       cf_error(rpki_check_refresh_interval($3));
     RPKI_CFG->refresh_interval = $3;
     RPKI_CFG->keep_refresh_interval = $2;
   }
 | RETRY rpki_keep_interval expr {
     if (rpki_check_retry_interval($3))
       cf_error(rpki_check_retry_interval($3));
     RPKI_CFG->retry_interval = $3;
     RPKI_CFG->keep_retry_interval = $2;
   }
 | EXPIRE rpki_keep_interval expr {
     if (rpki_check_expire_interval($3))
       cf_error(rpki_check_expire_interval($3));
     RPKI_CFG->expire_interval = $3;
     RPKI_CFG->keep_expire_interval = $2;
   }
 | IGNORE MAX LENGTH bool { RPKI_CFG->ignore_max_length = $4; }
 ;

rpki_keep_interval:
 /* empty */ { $$ = 0; }
 | KEEP { $$ = 1; }
 ;

rpki_proto_item_port: PORT expr { check_u16($2); RPKI_CFG->port = $2; };

rpki_cache_addr:
   text {
     rpki_check_unused_hostname();
     RPKI_CFG->hostname = $1;
   }
 | ipa {
     rpki_check_unused_hostname();
     RPKI_CFG->ip = $1;
     /* Ensure hostname is filled */
     char *hostname = cfg_allocz(INET6_ADDRSTRLEN + 1);
     bsnprintf(hostname, INET6_ADDRSTRLEN+1, "%I", RPKI_CFG->ip);
     RPKI_CFG->hostname = hostname;
   }
 ;

rpki_transport:
   TCP rpki_transport_tcp_init
 | SSH rpki_transport_ssh_init '{' rpki_transport_ssh_opts '}' rpki_transport_ssh_check
 ;

rpki_transport_tcp_init:
{
  rpki_check_unused_transport();
  RPKI_CFG->tr_config.spec = cfg_allocz(sizeof(struct rpki_tr_tcp_config));
  RPKI_CFG->tr_config.type = RPKI_TR_TCP;
};

rpki_transport_ssh_init:
{
#if HAVE_LIBSSH
  rpki_check_unused_transport();
  RPKI_CFG->tr_config.spec = cfg_allocz(sizeof(struct rpki_tr_ssh_config));
  RPKI_CFG->tr_config.type = RPKI_TR_SSH;
#else
  cf_error("This build doesn't support SSH");
#endif
};

rpki_transport_ssh_opts:
   /* empty */
 | rpki_transport_ssh_opts rpki_transport_ssh_item ';'
 ;

rpki_transport_ssh_item:
   BIRD PRIVATE KEY text  { RPKI_TR_SSH_CFG->bird_private_key = $4; }
 | REMOTE PUBLIC KEY text { RPKI_TR_SSH_CFG->cache_public_key = $4; }
 | USER text              { RPKI_TR_SSH_CFG->user = $2; }
 ;

rpki_transport_ssh_check:
{
  if (RPKI_TR_SSH_CFG->user == NULL)
    cf_error("User must be set");
};

CF_CODE

CF_END