1 1.4 andvar /* $NetBSD: parse.y,v 1.4 2023/03/17 17:12:54 andvar Exp $ */ 2 1.1 degroote 3 1.1 degroote /*- 4 1.1 degroote * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 1.1 degroote * All rights reserved. 6 1.1 degroote * 7 1.1 degroote * Redistribution and use in source and binary forms, with or without 8 1.1 degroote * modification, are permitted provided that the following conditions 9 1.1 degroote * are met: 10 1.1 degroote * 1. Redistributions of source code must retain the above copyright 11 1.1 degroote * notice, this list of conditions and the following disclaimer. 12 1.1 degroote * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 degroote * notice, this list of conditions and the following disclaimer in the 14 1.1 degroote * documentation and/or other materials provided with the distribution. 15 1.1 degroote * 16 1.1 degroote * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 degroote * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 degroote * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 degroote * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 degroote * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 degroote * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 degroote * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 degroote * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 degroote * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 degroote * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 degroote * POSSIBILITY OF SUCH DAMAGE. 27 1.1 degroote */ 28 1.1 degroote 29 1.1 degroote %{ 30 1.1 degroote #include <sys/cdefs.h> 31 1.1 degroote 32 1.1 degroote #ifndef lint 33 1.4 andvar __RCSID("$NetBSD: parse.y,v 1.4 2023/03/17 17:12:54 andvar Exp $"); 34 1.1 degroote #endif 35 1.1 degroote 36 1.1 degroote #include <stdio.h> 37 1.1 degroote #include <stdlib.h> 38 1.1 degroote #include <string.h> 39 1.1 degroote #include <stdint.h> 40 1.1 degroote #include <stdbool.h> 41 1.1 degroote #include <inttypes.h> 42 1.1 degroote #include <errno.h> 43 1.1 degroote 44 1.1 degroote #include <net/if.h> 45 1.1 degroote #include <netinet/in.h> 46 1.1 degroote #include <net/pfvar.h> 47 1.1 degroote #include <arpa/inet.h> 48 1.1 degroote #include <netdb.h> 49 1.1 degroote #include <netinet/tcp_fsm.h> 50 1.1 degroote 51 1.1 degroote #include "parser.h" 52 1.1 degroote 53 1.3 joerg int lineno; 54 1.3 joerg 55 1.3 joerg struct pfioc_states* states; 56 1.3 joerg size_t allocated; 57 1.3 joerg 58 1.1 degroote // XXX it is really correct ? 59 1.1 degroote extern const char * const tcpstates[]; 60 1.1 degroote 61 1.1 degroote 62 1.1 degroote struct pfsync_state global_state; 63 1.1 degroote struct pfsync_state_peer *src_peer, *dst_peer; 64 1.1 degroote struct pfsync_state_peer current_peer; 65 1.1 degroote 66 1.1 degroote static void parse_init(void); 67 1.1 degroote static void add_state(void); 68 1.1 degroote static bool get_pfsync_host(const char*, struct pfsync_state_host*, sa_family_t*); 69 1.1 degroote static uint8_t retrieve_peer_state(const char*, int); 70 1.1 degroote static bool retrieve_seq(const char*, struct pfsync_state_peer*); 71 1.1 degroote static bool strtou32(const char*, uint32_t*); 72 1.1 degroote 73 1.1 degroote %} 74 1.1 degroote 75 1.1 degroote %union { 76 1.1 degroote uintmax_t num; 77 1.1 degroote char* str; 78 1.1 degroote } 79 1.1 degroote 80 1.1 degroote %token STATE 81 1.1 degroote %token IN OUT 82 1.1 degroote %token ON PROTO 83 1.1 degroote %token FROM TO USING 84 1.1 degroote %token ID CID EXPIRE TIMEOUT 85 1.1 degroote %token SRC DST 86 1.1 degroote %token SEQ MAX_WIN WSCALE MSS 87 1.1 degroote %token NOSCRUB SCRUB FLAGS TTL MODE 88 1.1 degroote %token NUMBER STRING 89 1.1 degroote 90 1.1 degroote %type <str> STRING 91 1.1 degroote %type <num> NUMBER 92 1.1 degroote %% 93 1.1 degroote 94 1.1 degroote states 95 1.1 degroote : /* NOTHING */ 96 1.1 degroote | state states { parse_init(); } 97 1.1 degroote ; 98 1.1 degroote 99 1.1 degroote state 100 1.1 degroote : STATE direction iface proto addrs id cid expire timeout src_peer dst_peer { 101 1.1 degroote add_state(); 102 1.1 degroote } 103 1.1 degroote ; 104 1.1 degroote 105 1.1 degroote direction 106 1.1 degroote : IN { 107 1.1 degroote global_state.direction = PF_IN; 108 1.1 degroote src_peer = &global_state.dst; 109 1.1 degroote dst_peer = &global_state.src; 110 1.1 degroote } 111 1.1 degroote | OUT { 112 1.1 degroote global_state.direction = PF_OUT; 113 1.1 degroote src_peer = &global_state.src; 114 1.1 degroote dst_peer = &global_state.dst; 115 1.1 degroote } 116 1.1 degroote ; 117 1.1 degroote 118 1.1 degroote iface 119 1.1 degroote : ON STRING { 120 1.1 degroote strlcpy(global_state.ifname, $2, sizeof(global_state.ifname)); 121 1.1 degroote free($2); 122 1.1 degroote } 123 1.1 degroote ; 124 1.1 degroote 125 1.1 degroote proto 126 1.1 degroote : PROTO STRING { 127 1.1 degroote struct protoent *p; 128 1.1 degroote p = getprotobyname($2); 129 1.1 degroote if (p == NULL) 130 1.1 degroote yyfatal("Invalid protocol name"); 131 1.1 degroote global_state.proto = p->p_proto; 132 1.1 degroote free($2); 133 1.1 degroote } 134 1.1 degroote | PROTO NUMBER { 135 1.1 degroote // check that the number may be valid proto ? 136 1.1 degroote global_state.proto = $2; 137 1.1 degroote } 138 1.1 degroote ; 139 1.1 degroote 140 1.1 degroote addrs 141 1.1 degroote : FROM STRING TO STRING { 142 1.1 degroote get_pfsync_host($2, &global_state.lan, &global_state.af); 143 1.1 degroote get_pfsync_host($4, &global_state.ext, &global_state.af); 144 1.1 degroote memcpy(&global_state.gwy, &global_state.lan, sizeof(struct pfsync_state_host)); 145 1.1 degroote free($2); 146 1.1 degroote free($4); 147 1.1 degroote } 148 1.1 degroote | FROM STRING TO STRING USING STRING { 149 1.1 degroote get_pfsync_host($2, &global_state.lan, &global_state.af); 150 1.1 degroote get_pfsync_host($4, &global_state.ext, &global_state.af); 151 1.1 degroote get_pfsync_host($6, &global_state.gwy, &global_state.af); 152 1.1 degroote free($2); 153 1.1 degroote free($4); 154 1.1 degroote free($6); 155 1.1 degroote } 156 1.1 degroote ; 157 1.1 degroote 158 1.1 degroote id 159 1.1 degroote : ID NUMBER { 160 1.1 degroote if ( $2 > UINT64_MAX) 161 1.1 degroote yyfatal("id is too big"); 162 1.1 degroote uint64_t value = (uint64_t)$2; 163 1.1 degroote memcpy(global_state.id, &value, sizeof(global_state.id)); 164 1.1 degroote } 165 1.1 degroote ; 166 1.1 degroote 167 1.1 degroote cid 168 1.1 degroote : CID NUMBER { 169 1.1 degroote if ( $2 > UINT32_MAX) 170 1.1 degroote yyfatal("creator id is too big"); 171 1.1 degroote global_state.creatorid = (uint32_t)$2; 172 1.1 degroote } 173 1.1 degroote ; 174 1.1 degroote 175 1.1 degroote expire 176 1.1 degroote : EXPIRE NUMBER { 177 1.1 degroote if ( $2 > UINT32_MAX) 178 1.1 degroote yyfatal("expire time is too big"); 179 1.1 degroote global_state.expire = (uint32_t) $2; 180 1.1 degroote } 181 1.1 degroote ; 182 1.1 degroote 183 1.1 degroote timeout 184 1.1 degroote : TIMEOUT NUMBER { 185 1.1 degroote if ($2 > UINT8_MAX) 186 1.1 degroote yyfatal("timeout time is too big"); 187 1.1 degroote global_state.timeout = (uint8_t) $2; 188 1.1 degroote } 189 1.1 degroote ; 190 1.1 degroote 191 1.1 degroote src_peer 192 1.1 degroote : SRC peer { 193 1.1 degroote memcpy(src_peer, ¤t_peer, sizeof(current_peer)); 194 1.1 degroote } 195 1.1 degroote ; 196 1.1 degroote 197 1.1 degroote dst_peer 198 1.1 degroote : DST peer { 199 1.1 degroote memcpy(dst_peer, ¤t_peer, sizeof(current_peer)); 200 1.1 degroote } 201 1.1 degroote ; 202 1.1 degroote 203 1.1 degroote peer 204 1.1 degroote : peer_state scrub 205 1.1 degroote | peer_state tcp_options scrub 206 1.1 degroote ; 207 1.1 degroote 208 1.1 degroote peer_state 209 1.1 degroote : STATE STRING { 210 1.1 degroote current_peer.state = retrieve_peer_state($2, global_state.proto); 211 1.1 degroote free($2); 212 1.1 degroote } 213 1.1 degroote | STATE NUMBER { 214 1.1 degroote if ( $2 > UINT8_MAX) 215 1.1 degroote yyfatal("peer state is too big"); 216 1.1 degroote current_peer.state = $2; 217 1.1 degroote } 218 1.1 degroote ; 219 1.1 degroote 220 1.1 degroote tcp_options 221 1.1 degroote : SEQ seqs MAX_WIN NUMBER WSCALE NUMBER { 222 1.1 degroote if ($4 > UINT16_MAX) 223 1.1 degroote yyfatal("max_win is too big"); 224 1.1 degroote current_peer.max_win = $4; 225 1.1 degroote 226 1.1 degroote if ($6 > UINT8_MAX) 227 1.1 degroote yyfatal("wscale is too big"); 228 1.1 degroote current_peer.wscale = $6; 229 1.1 degroote } 230 1.1 degroote | SEQ seqs MAX_WIN NUMBER WSCALE NUMBER MSS NUMBER { 231 1.1 degroote if ($4 > UINT16_MAX) 232 1.1 degroote yyfatal("max_win is too big"); 233 1.1 degroote current_peer.max_win = $4; 234 1.1 degroote 235 1.1 degroote if ($6 > UINT8_MAX) 236 1.1 degroote yyfatal("wscale is too big"); 237 1.1 degroote current_peer.wscale = $6; 238 1.1 degroote 239 1.1 degroote if ($8 > UINT16_MAX) 240 1.1 degroote yyfatal("mss is too big"); 241 1.1 degroote current_peer.mss = $8; 242 1.1 degroote } 243 1.1 degroote ; 244 1.1 degroote 245 1.1 degroote seqs 246 1.1 degroote : STRING { 247 1.1 degroote if (!retrieve_seq($1, ¤t_peer)) 248 1.1 degroote yyfatal("invalid seq number"); 249 1.1 degroote 250 1.1 degroote free($1); 251 1.1 degroote } 252 1.1 degroote ; 253 1.1 degroote 254 1.1 degroote scrub 255 1.1 degroote : NOSCRUB { current_peer.scrub.scrub_flag= 0;} 256 1.1 degroote | SCRUB FLAGS NUMBER MODE NUMBER TTL NUMBER { 257 1.1 degroote current_peer.scrub.scrub_flag= PFSYNC_SCRUB_FLAG_VALID; 258 1.1 degroote if ($3 > UINT16_MAX) 259 1.1 degroote yyfatal("scrub flags is too big"); 260 1.1 degroote current_peer.scrub.pfss_flags = $3; 261 1.1 degroote 262 1.1 degroote if ($5 > UINT32_MAX) 263 1.1 degroote yyfatal("scrub mode is too big"); 264 1.1 degroote current_peer.scrub.pfss_ts_mod = $5; 265 1.1 degroote 266 1.1 degroote if ($7 > UINT8_MAX) 267 1.1 degroote yyfatal("scrub ttl is too big"); 268 1.1 degroote current_peer.scrub.pfss_ttl = $7; 269 1.1 degroote } 270 1.1 degroote ; 271 1.1 degroote 272 1.1 degroote 273 1.1 degroote %% 274 1.1 degroote 275 1.1 degroote static void 276 1.1 degroote parse_init(void) 277 1.1 degroote { 278 1.1 degroote memset(&global_state, 0, sizeof(global_state)); 279 1.1 degroote memset(¤t_peer, 0, sizeof(current_peer)); 280 1.1 degroote src_peer = NULL; 281 1.1 degroote dst_peer = NULL; 282 1.1 degroote } 283 1.1 degroote 284 1.1 degroote static bool 285 1.1 degroote get_pfsync_host(const char* str, struct pfsync_state_host* host, sa_family_t* af) 286 1.1 degroote { 287 1.1 degroote size_t count_colon, addr_len, port_len; 288 1.1 degroote const char* p, *last_colon, *first_bracket, *last_bracket; 289 1.1 degroote char buf[48]; 290 1.1 degroote char buf_port[6]; 291 1.1 degroote 292 1.1 degroote if (str == NULL || *str == '\0') 293 1.1 degroote return false; 294 1.1 degroote 295 1.1 degroote p = str; 296 1.1 degroote last_colon = NULL; 297 1.1 degroote count_colon = 0; 298 1.1 degroote 299 1.1 degroote while (*p != '\0') { 300 1.1 degroote if (*p == ':') { 301 1.1 degroote count_colon++; 302 1.1 degroote last_colon = p; 303 1.1 degroote } 304 1.1 degroote p++; 305 1.1 degroote } 306 1.1 degroote 307 1.1 degroote /* 308 1.1 degroote * If no colon, it is not an expected addr 309 1.1 degroote * If there are more than one colon, we guess that af = AF_INET6 310 1.1 degroote */ 311 1.1 degroote 312 1.1 degroote if (count_colon == 0) 313 1.1 degroote return false; 314 1.1 degroote 315 1.1 degroote if (count_colon == 1) 316 1.1 degroote *af = AF_INET; 317 1.1 degroote else 318 1.1 degroote *af = AF_INET6; 319 1.1 degroote 320 1.1 degroote /* 321 1.1 degroote * First bracket must be next character after last colon 322 1.1 degroote * Last bracket must be the last character 323 1.1 degroote * distance between both must be <= 7 324 1.1 degroote */ 325 1.1 degroote 326 1.1 degroote if (*(last_colon+1) == '[') 327 1.1 degroote first_bracket = last_colon + 1; 328 1.1 degroote else 329 1.1 degroote return false; 330 1.1 degroote 331 1.1 degroote last_bracket = str + (strlen(str) - 1); 332 1.1 degroote if (*last_bracket != ']') 333 1.1 degroote return false; 334 1.1 degroote 335 1.1 degroote port_len = last_bracket - first_bracket; 336 1.1 degroote if (last_bracket - first_bracket > 7) 337 1.1 degroote return false; 338 1.1 degroote 339 1.1 degroote memcpy(buf_port, first_bracket +1, port_len - 1); 340 1.1 degroote buf_port[port_len-1]= '\0'; 341 1.1 degroote 342 1.1 degroote addr_len = last_colon - str; 343 1.1 degroote if (addr_len >= sizeof(buf)) 344 1.1 degroote return false; 345 1.1 degroote memcpy(buf, str, addr_len); 346 1.1 degroote buf[addr_len] = '\0'; 347 1.1 degroote 348 1.1 degroote if (inet_pton(*af, buf, &host->addr) != 1) 349 1.1 degroote return false; 350 1.1 degroote 351 1.1 degroote host->port = htons(atoi(buf_port)); 352 1.1 degroote 353 1.1 degroote return true; 354 1.1 degroote } 355 1.1 degroote 356 1.1 degroote static uint8_t 357 1.1 degroote retrieve_peer_state(const char* str, int proto) 358 1.1 degroote { 359 1.1 degroote uint8_t i; 360 1.1 degroote 361 1.1 degroote if (proto == IPPROTO_TCP) { 362 1.1 degroote i = 0; 363 1.1 degroote while (i < TCP_NSTATES) { 364 1.1 degroote if (strcmp(str, tcpstates[i]) == 0) 365 1.1 degroote return i; 366 1.1 degroote i++; 367 1.1 degroote } 368 1.1 degroote yyfatal("Invalid peer state"); 369 1.1 degroote 370 1.1 degroote } else { 371 1.1 degroote if (proto == IPPROTO_UDP) { 372 1.1 degroote const char* mystates[] = PFUDPS_NAMES; 373 1.1 degroote i = 0; 374 1.1 degroote 375 1.1 degroote while (i < PFUDPS_NSTATES) { 376 1.1 degroote if (strcmp(str, mystates[i]) == 0) 377 1.1 degroote return i; 378 1.1 degroote i++; 379 1.1 degroote } 380 1.1 degroote 381 1.1 degroote yyfatal("Invalid peer state"); 382 1.1 degroote } else { 383 1.1 degroote const char *mystates[] = PFOTHERS_NAMES; 384 1.1 degroote i = 0; 385 1.1 degroote 386 1.1 degroote while (i < PFOTHERS_NSTATES) { 387 1.1 degroote if (strcmp(str, mystates[i]) == 0) 388 1.1 degroote return i; 389 1.1 degroote i++; 390 1.1 degroote } 391 1.1 degroote 392 1.1 degroote yyfatal("Invalid peer state"); 393 1.1 degroote } 394 1.1 degroote } 395 1.1 degroote /*NOTREACHED*/ 396 1.1 degroote return 0; 397 1.1 degroote } 398 1.1 degroote 399 1.1 degroote static bool 400 1.1 degroote strtou32(const char* str, uint32_t* res) 401 1.1 degroote { 402 1.1 degroote uintmax_t u; 403 1.1 degroote errno = 0; 404 1.1 degroote u = strtoumax(str, NULL, 10); 405 1.1 degroote if (errno == ERANGE && u == UINTMAX_MAX) 406 1.1 degroote return false; 407 1.1 degroote if (u > UINT32_MAX) 408 1.1 degroote return false; 409 1.1 degroote *res = (uint32_t) u; 410 1.1 degroote return true; 411 1.1 degroote } 412 1.1 degroote 413 1.1 degroote static bool 414 1.1 degroote retrieve_seq(const char* str, struct pfsync_state_peer* peer) 415 1.1 degroote { 416 1.1 degroote const char* p, *p_colon, *p_comma; 417 1.1 degroote char buf[100]; 418 1.1 degroote size_t size; 419 1.1 degroote 420 1.1 degroote if (str == NULL || *str == '\0') 421 1.1 degroote return false; 422 1.1 degroote 423 1.1 degroote if (*str != '[' || *(str+(strlen(str) -1)) != ']') 424 1.1 degroote return false; 425 1.1 degroote 426 1.1 degroote p = str; 427 1.1 degroote p_colon = NULL; 428 1.1 degroote p_comma = NULL; 429 1.1 degroote while (*p != '\0') { 430 1.1 degroote if (*p == ':') { 431 1.1 degroote if (p_colon !=NULL) 432 1.1 degroote return false; 433 1.1 degroote else 434 1.1 degroote p_colon = p; 435 1.1 degroote } 436 1.1 degroote 437 1.1 degroote if (*p == ',') { 438 1.1 degroote if (p_comma != NULL) 439 1.1 degroote return false; 440 1.1 degroote else 441 1.1 degroote p_comma = p; 442 1.1 degroote } 443 1.1 degroote p++; 444 1.1 degroote } 445 1.1 degroote 446 1.1 degroote size = p_colon - str; 447 1.1 degroote if (size > sizeof(buf)) 448 1.1 degroote return false; 449 1.1 degroote memcpy(buf, str+1, size-1); 450 1.1 degroote buf[size-1] = '\0'; 451 1.1 degroote 452 1.1 degroote if (!strtou32(buf, &peer->seqlo)) 453 1.1 degroote return false; 454 1.1 degroote 455 1.1 degroote 456 1.1 degroote if (p_comma == NULL) 457 1.1 degroote size = str + strlen(str) - 1 - p_colon; 458 1.1 degroote else 459 1.1 degroote size = p_comma - p_colon; 460 1.1 degroote 461 1.1 degroote if (size > sizeof(buf)) 462 1.1 degroote return false; 463 1.1 degroote memcpy(buf, p_colon+1, size -1); 464 1.1 degroote buf[size-1] = '\0'; 465 1.1 degroote 466 1.1 degroote if (!strtou32(buf, &peer->seqhi)) 467 1.1 degroote return false; 468 1.1 degroote 469 1.1 degroote if (p_comma == NULL) { 470 1.1 degroote peer->seqdiff = 0; 471 1.1 degroote } else { 472 1.1 degroote size = str + strlen(str) - 1 - p_comma; 473 1.1 degroote if (size > sizeof(buf)) 474 1.1 degroote return false; 475 1.1 degroote memcpy(buf, p_comma +1, size -1); 476 1.1 degroote buf[size-1] = '\0'; 477 1.1 degroote 478 1.1 degroote if (!strtou32(buf, &peer->seqdiff)) 479 1.1 degroote return false; 480 1.1 degroote } 481 1.1 degroote 482 1.1 degroote return true; 483 1.1 degroote } 484 1.1 degroote 485 1.1 degroote static void 486 1.1 degroote add_state(void) 487 1.1 degroote { 488 1.1 degroote 489 1.1 degroote if (allocated == 0) { 490 1.1 degroote allocated = 5; 491 1.1 degroote states->ps_buf = malloc(allocated * sizeof(struct pfsync_state)); 492 1.1 degroote if (states->ps_buf == NULL) 493 1.4 andvar yyfatal("Not enough memory"); 494 1.1 degroote } 495 1.1 degroote 496 1.1 degroote if (allocated == (states->ps_len / sizeof(struct pfsync_state))) { 497 1.1 degroote void *buf; 498 1.1 degroote allocated = allocated * 2 + 1; 499 1.1 degroote buf = realloc(states->ps_buf, allocated * sizeof(struct pfsync_state)); 500 1.1 degroote if (buf == NULL) { 501 1.1 degroote free(states->ps_buf); 502 1.4 andvar yyfatal("Not enough memory"); 503 1.1 degroote } 504 1.1 degroote states->ps_buf = buf; 505 1.1 degroote } 506 1.1 degroote 507 1.1 degroote } 508