1 #include <iostream> 2 #include <string> 3 4 extern "C" { 5 #include "asn1.h" 6 #include "snmp.h" 7 #include "snmpclient.h" 8 }; 9 10 #include "catch.hpp" 11 12 using namespace std::string_literals; 13 14 static inline int 15 try_parse(struct snmp_client *sc, const char *str) 16 { 17 const int r = snmp_parse_server(sc, str); 18 if (false && r != 0) 19 std::cout << "snmp_parse_server: " << sc->error << "\n"; 20 return r; 21 22 } 23 24 TEST_CASE("snmp_parse_server: empty string", "[snmp_parse_server]") { 25 struct snmp_client sc; 26 snmp_client_init(&sc); 27 28 REQUIRE(try_parse(&sc, "") == 0); 29 REQUIRE(sc.trans == SNMP_TRANS_UDP); 30 REQUIRE(sc.chost == ""s); 31 REQUIRE(sc.cport == "snmp"s); 32 REQUIRE(sc.read_community == "public"s); 33 REQUIRE(sc.write_community == "private"s); 34 } 35 36 TEST_CASE("snmp_parse_server: hostname only", "[snmp_parse_server]") { 37 struct snmp_client sc; 38 snmp_client_init(&sc); 39 40 SECTION("simple name without special characters") { 41 const auto str = "somehost"s; 42 REQUIRE(try_parse(&sc, str.c_str()) == 0); 43 REQUIRE(sc.trans == SNMP_TRANS_UDP); 44 REQUIRE(sc.chost == str); 45 REQUIRE(sc.cport == "snmp"s); 46 REQUIRE(sc.read_community == "public"s); 47 REQUIRE(sc.write_community == "private"s); 48 } 49 SECTION("complex host name without special characters") { 50 const auto str = "some.host.domain"s; 51 REQUIRE(try_parse(&sc, str.c_str()) == 0); 52 REQUIRE(sc.trans == SNMP_TRANS_UDP); 53 REQUIRE(sc.chost == str); 54 REQUIRE(sc.cport == "snmp"s); 55 REQUIRE(sc.read_community == "public"s); 56 REQUIRE(sc.write_community == "private"s); 57 } 58 SECTION("complex host name with special characters") { 59 const auto str = "some-mul.host-32.domain."s; 60 REQUIRE(try_parse(&sc, str.c_str()) == 0); 61 REQUIRE(sc.trans == SNMP_TRANS_UDP); 62 REQUIRE(sc.chost == str); 63 REQUIRE(sc.cport == "snmp"s); 64 REQUIRE(sc.read_community == "public"s); 65 REQUIRE(sc.write_community == "private"s); 66 } 67 SECTION("relative path name") { 68 const auto str = "foo/bar"s; 69 REQUIRE(try_parse(&sc, str.c_str()) == 0); 70 REQUIRE(sc.trans == SNMP_TRANS_LOC_DGRAM); 71 REQUIRE(sc.chost == str); 72 REQUIRE(sc.cport == ""s); 73 REQUIRE(sc.read_community == "public"s); 74 REQUIRE(sc.write_community == "private"s); 75 } 76 SECTION("absolute path name") { 77 const auto str = "/foo/bar"s; 78 REQUIRE(try_parse(&sc, str.c_str()) == 0); 79 REQUIRE(sc.trans == SNMP_TRANS_LOC_DGRAM); 80 REQUIRE(sc.chost == str); 81 REQUIRE(sc.cport == ""s); 82 REQUIRE(sc.read_community == "public"s); 83 REQUIRE(sc.write_community == "private"s); 84 } 85 } 86 87 TEST_CASE("snmp_parse_server: ipv6 address only", "[snmp_parse_server]") { 88 struct snmp_client sc; 89 snmp_client_init(&sc); 90 91 SECTION("in6_addr_any") { 92 const auto host = "::"s; 93 const auto str = "[" + host + "]"; 94 REQUIRE(try_parse(&sc, str.c_str()) == 0); 95 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 96 REQUIRE(sc.chost == host); 97 REQUIRE(sc.cport == "snmp"s); 98 REQUIRE(sc.read_community == "public"s); 99 REQUIRE(sc.write_community == "private"s); 100 } 101 SECTION("localhost") { 102 const auto host = "::1"s; 103 const auto str = "[" + host + "]"; 104 REQUIRE(try_parse(&sc, str.c_str()) == 0); 105 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 106 REQUIRE(sc.chost == host); 107 REQUIRE(sc.cport == "snmp"s); 108 REQUIRE(sc.read_community == "public"s); 109 REQUIRE(sc.write_community == "private"s); 110 } 111 SECTION("link local address") { 112 const auto host = "fc00:0:12::1"s; 113 const auto str = "[" + host + "]"; 114 REQUIRE(try_parse(&sc, str.c_str()) == 0); 115 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 116 REQUIRE(sc.chost == host); 117 REQUIRE(sc.cport == "snmp"s); 118 REQUIRE(sc.read_community == "public"s); 119 REQUIRE(sc.write_community == "private"s); 120 } 121 SECTION("illegal address (bad character)") { 122 const auto host = "fc00:0:1x::1"s; 123 const auto str = "[" + host + "]"; 124 REQUIRE(try_parse(&sc, str.c_str()) == -1); 125 REQUIRE(sc.error == host + ": Name does not resolve"); 126 } 127 SECTION("illegal address (two double colons)") { 128 const auto host = "fc00::0:12::1"s; 129 const auto str = "[" + host + "]"; 130 REQUIRE(try_parse(&sc, str.c_str()) == -1); 131 REQUIRE(sc.error == host + ": Name does not resolve"); 132 } 133 SECTION("illegal address (two many colons)") { 134 const auto host = "1:2:3:4:5:6:7:8:9"s; 135 const auto str = "[" + host + "]"; 136 REQUIRE(try_parse(&sc, str.c_str()) == -1); 137 REQUIRE(sc.error == host + ": Name does not resolve"); 138 } 139 SECTION("ipv6 address and junk") { 140 const auto host = "::"s; 141 const auto str = "[" + host + "]" + "xxx"; 142 REQUIRE(try_parse(&sc, str.c_str()) == -1); 143 REQUIRE(sc.error == "junk at end of server specification 'xxx'"s); 144 } 145 } 146 147 TEST_CASE("snmp_parse_server: hostname and port", "[snmp_parse_server]") { 148 struct snmp_client sc; 149 snmp_client_init(&sc); 150 151 SECTION("simple name and numeric port") { 152 const auto host = "somehost"s; 153 const auto port = "10007"s; 154 const auto str = host + ":" + port; 155 REQUIRE(try_parse(&sc, str.c_str()) == 0); 156 REQUIRE(sc.trans == SNMP_TRANS_UDP); 157 REQUIRE(sc.chost == host); 158 REQUIRE(sc.cport == port); 159 REQUIRE(sc.read_community == "public"s); 160 REQUIRE(sc.write_community == "private"s); 161 } 162 SECTION("simple name and string port") { 163 const auto host = "somehost"s; 164 const auto port = "telnet"s; 165 const auto str = host + ":" + port; 166 REQUIRE(try_parse(&sc, str.c_str()) == 0); 167 REQUIRE(sc.trans == SNMP_TRANS_UDP); 168 REQUIRE(sc.chost == host); 169 REQUIRE(sc.cport == port); 170 REQUIRE(sc.read_community == "public"s); 171 REQUIRE(sc.write_community == "private"s); 172 } 173 SECTION("name with embedded colon and numeric port") { 174 const auto host = "somehost:foo"s; 175 const auto port = "10007"s; 176 const auto str = host + ":" + port; 177 REQUIRE(try_parse(&sc, str.c_str()) == 0); 178 REQUIRE(sc.trans == SNMP_TRANS_UDP); 179 REQUIRE(sc.chost == host); 180 REQUIRE(sc.cport == port); 181 REQUIRE(sc.read_community == "public"s); 182 REQUIRE(sc.write_community == "private"s); 183 } 184 SECTION("FQDN with embedded colon and numeric port") { 185 const auto host = "bla.blub:foo.baz."s; 186 const auto port = "10007"s; 187 const auto str = host + ":" + port; 188 REQUIRE(try_parse(&sc, str.c_str()) == 0); 189 REQUIRE(sc.trans == SNMP_TRANS_UDP); 190 REQUIRE(sc.chost == host); 191 REQUIRE(sc.cport == port); 192 REQUIRE(sc.read_community == "public"s); 193 REQUIRE(sc.write_community == "private"s); 194 } 195 SECTION("simple name and empty port") { 196 const auto host = "somehost"s; 197 const auto port = ""s; 198 const auto str = host + ":" + port; 199 REQUIRE(try_parse(&sc, str.c_str()) == -1); 200 REQUIRE(sc.error == "empty port name"s); 201 } 202 } 203 204 TEST_CASE("snmp_parse_server: ipv6 and port", "[snmp_parse_server]") { 205 struct snmp_client sc; 206 snmp_client_init(&sc); 207 208 SECTION("ANY address and numeric port") { 209 const auto host = "::"s; 210 const auto port = "10007"s; 211 const auto str = "[" + host + "]:" + port; 212 REQUIRE(try_parse(&sc, str.c_str()) == 0); 213 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 214 REQUIRE(sc.chost == host); 215 REQUIRE(sc.cport == port); 216 REQUIRE(sc.read_community == "public"s); 217 REQUIRE(sc.write_community == "private"s); 218 } 219 SECTION("localhost address and string port") { 220 const auto host = "::1"s; 221 const auto port = "snmp"s; 222 const auto str = "[" + host + "]:" + port; 223 REQUIRE(try_parse(&sc, str.c_str()) == 0); 224 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 225 REQUIRE(sc.chost == host); 226 REQUIRE(sc.cport == port); 227 REQUIRE(sc.read_community == "public"s); 228 REQUIRE(sc.write_community == "private"s); 229 } 230 SECTION("some address name and empty port") { 231 const auto host = "fc00:00:01::2:3"s; 232 const auto port = ""s; 233 const auto str = "[" + host + "]:" + port; 234 REQUIRE(try_parse(&sc, str.c_str()) == -1); 235 REQUIRE(sc.error == "empty port name"s); 236 } 237 } 238 239 TEST_CASE("snmp_parse_server: IPv4 address only", "[snmp_parse_server]") { 240 struct snmp_client sc; 241 snmp_client_init(&sc); 242 243 SECTION("single octet address") { 244 const auto host = "127"s; 245 const auto str = host; 246 REQUIRE(try_parse(&sc, str.c_str()) == 0); 247 REQUIRE(sc.trans == SNMP_TRANS_UDP); 248 REQUIRE(sc.chost == host); 249 REQUIRE(sc.cport == "snmp"s); 250 REQUIRE(sc.read_community == "public"s); 251 REQUIRE(sc.write_community == "private"s); 252 } 253 SECTION("two octet address") { 254 const auto host = "127.1"s; 255 const auto str = host; 256 REQUIRE(try_parse(&sc, str.c_str()) == 0); 257 REQUIRE(sc.trans == SNMP_TRANS_UDP); 258 REQUIRE(sc.chost == host); 259 REQUIRE(sc.cport == "snmp"s); 260 REQUIRE(sc.read_community == "public"s); 261 REQUIRE(sc.write_community == "private"s); 262 } 263 SECTION("three octet address") { 264 const auto host = "127.23.1"s; 265 const auto str = host; 266 REQUIRE(try_parse(&sc, str.c_str()) == 0); 267 REQUIRE(sc.trans == SNMP_TRANS_UDP); 268 REQUIRE(sc.chost == host); 269 REQUIRE(sc.cport == "snmp"s); 270 REQUIRE(sc.read_community == "public"s); 271 REQUIRE(sc.write_community == "private"s); 272 } 273 SECTION("four octet address") { 274 const auto host = "127.18.23.1"s; 275 const auto str = host; 276 REQUIRE(try_parse(&sc, str.c_str()) == 0); 277 REQUIRE(sc.trans == SNMP_TRANS_UDP); 278 REQUIRE(sc.chost == host); 279 REQUIRE(sc.cport == "snmp"s); 280 REQUIRE(sc.read_community == "public"s); 281 REQUIRE(sc.write_community == "private"s); 282 } 283 SECTION("four octet octal address") { 284 const auto host = "0300.077.0377.01"s; 285 const auto str = host; 286 REQUIRE(try_parse(&sc, str.c_str()) == 0); 287 REQUIRE(sc.trans == SNMP_TRANS_UDP); 288 REQUIRE(sc.chost == host); 289 REQUIRE(sc.cport == "snmp"s); 290 REQUIRE(sc.read_community == "public"s); 291 REQUIRE(sc.write_community == "private"s); 292 } 293 SECTION("four octet hex address") { 294 const auto host = "x80.x12.xff.x1"s; 295 const auto str = host; 296 REQUIRE(try_parse(&sc, str.c_str()) == 0); 297 REQUIRE(sc.trans == SNMP_TRANS_UDP); 298 REQUIRE(sc.chost == host); 299 REQUIRE(sc.cport == "snmp"s); 300 REQUIRE(sc.read_community == "public"s); 301 REQUIRE(sc.write_community == "private"s); 302 } 303 } 304 305 TEST_CASE("snmp_parse_server: transport and hostname", "[snmp_parse_server]") { 306 struct snmp_client sc; 307 snmp_client_init(&sc); 308 309 SECTION("udp and host") { 310 const auto trans = "udp"s; 311 const auto host = "somehost"s; 312 const auto str = trans + "::" + host; 313 REQUIRE(try_parse(&sc, str.c_str()) == 0); 314 REQUIRE(sc.trans == SNMP_TRANS_UDP); 315 REQUIRE(sc.chost == host); 316 REQUIRE(sc.cport == "snmp"s); 317 REQUIRE(sc.read_community == "public"s); 318 REQUIRE(sc.write_community == "private"s); 319 } 320 SECTION("udp and ipv4 address") { 321 const auto trans = "udp"s; 322 const auto host = "240.0.1.2"s; 323 const auto str = trans + "::" + host; 324 REQUIRE(try_parse(&sc, str.c_str()) == 0); 325 REQUIRE(sc.trans == SNMP_TRANS_UDP); 326 REQUIRE(sc.chost == host); 327 REQUIRE(sc.cport == "snmp"s); 328 REQUIRE(sc.read_community == "public"s); 329 REQUIRE(sc.write_community == "private"s); 330 } 331 SECTION("udp6 and host") { 332 const auto trans = "udp6"s; 333 const auto host = "somehost"s; 334 const auto str = trans + "::" + host; 335 REQUIRE(try_parse(&sc, str.c_str()) == 0); 336 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 337 REQUIRE(sc.chost == host); 338 REQUIRE(sc.cport == "snmp"s); 339 REQUIRE(sc.read_community == "public"s); 340 REQUIRE(sc.write_community == "private"s); 341 } 342 SECTION("udp6 and ipv6 address") { 343 const auto trans = "udp6"s; 344 const auto host = "fec0:0:2::17"s; 345 const auto str = trans + "::[" + host + "]"; 346 REQUIRE(try_parse(&sc, str.c_str()) == 0); 347 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 348 REQUIRE(sc.chost == host); 349 REQUIRE(sc.cport == "snmp"s); 350 REQUIRE(sc.read_community == "public"s); 351 REQUIRE(sc.write_community == "private"s); 352 } 353 SECTION("dgram and host") { 354 const auto trans = "dgram"s; 355 const auto host = "somehost"s; 356 const auto str = trans + "::" + host; 357 REQUIRE(try_parse(&sc, str.c_str()) == 0); 358 REQUIRE(sc.trans == SNMP_TRANS_LOC_DGRAM); 359 REQUIRE(sc.chost == host); 360 REQUIRE(sc.cport == ""s); 361 REQUIRE(sc.read_community == "public"s); 362 REQUIRE(sc.write_community == "private"s); 363 } 364 SECTION("stream and host") { 365 const auto trans = "stream"s; 366 const auto host = "somehost"s; 367 const auto str = trans + "::" + host; 368 REQUIRE(try_parse(&sc, str.c_str()) == 0); 369 REQUIRE(sc.trans == SNMP_TRANS_LOC_STREAM); 370 REQUIRE(sc.chost == host); 371 REQUIRE(sc.cport == ""s); 372 REQUIRE(sc.read_community == "public"s); 373 REQUIRE(sc.write_community == "private"s); 374 } 375 SECTION("unknown transport and host") { 376 const auto trans = "foo"s; 377 const auto host = "somehost"s; 378 const auto str = trans + "::" + host; 379 REQUIRE(try_parse(&sc, str.c_str()) == -1); 380 REQUIRE(sc.error == "unknown transport specifier '" + trans + "'"); 381 } 382 SECTION("empty transport and host") { 383 const auto trans = ""s; 384 const auto host = "somehost"s; 385 const auto str = trans + "::" + host; 386 REQUIRE(try_parse(&sc, str.c_str()) == -1); 387 REQUIRE(sc.error == "empty transport specifier"s); 388 } 389 } 390 391 TEST_CASE("snmp_parse_server: transport, host and port", "[snmp_parse_server]") { 392 struct snmp_client sc; 393 snmp_client_init(&sc); 394 395 SECTION("udp, host and port") { 396 const auto trans = "udp"s; 397 const auto host = "somehost"s; 398 const auto port = "ssh"s; 399 const auto str = trans + "::" + host + ":" + port; 400 REQUIRE(try_parse(&sc, str.c_str()) == 0); 401 REQUIRE(sc.trans == SNMP_TRANS_UDP); 402 REQUIRE(sc.chost == host); 403 REQUIRE(sc.cport == port); 404 REQUIRE(sc.read_community == "public"s); 405 REQUIRE(sc.write_community == "private"s); 406 } 407 SECTION("udp, host with colon and port") { 408 const auto trans = "udp"s; 409 const auto host = "somehost:foo"s; 410 const auto port = "ssh"s; 411 const auto str = trans + "::" + host + ":" + port; 412 REQUIRE(try_parse(&sc, str.c_str()) == 0); 413 REQUIRE(sc.trans == SNMP_TRANS_UDP); 414 REQUIRE(sc.chost == host); 415 REQUIRE(sc.cport == port); 416 REQUIRE(sc.read_community == "public"s); 417 REQUIRE(sc.write_community == "private"s); 418 } 419 SECTION("udp and port") { 420 const auto trans = "udp"s; 421 const auto host = ""s; 422 const auto port = "ssh"s; 423 const auto str = trans + "::" + host + ":" + port; 424 REQUIRE(try_parse(&sc, str.c_str()) == 0); 425 REQUIRE(sc.trans == SNMP_TRANS_UDP); 426 REQUIRE(sc.chost == host); 427 REQUIRE(sc.cport == port); 428 REQUIRE(sc.read_community == "public"s); 429 REQUIRE(sc.write_community == "private"s); 430 } 431 SECTION("udp6, ipv6 and port") { 432 const auto trans = "udp6"s; 433 const auto host = "::1:2"s; 434 const auto port = "ssh"s; 435 const auto str = trans + "::[" + host + "]:" + port; 436 REQUIRE(try_parse(&sc, str.c_str()) == 0); 437 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 438 REQUIRE(sc.chost == host); 439 REQUIRE(sc.cport == port); 440 REQUIRE(sc.read_community == "public"s); 441 REQUIRE(sc.write_community == "private"s); 442 } 443 } 444 445 TEST_CASE("snmp_parse_server: community and host", "[snmp_parse_server]") 446 { 447 struct snmp_client sc; 448 snmp_client_init(&sc); 449 450 SECTION("community and host") { 451 const auto comm = "public"s; 452 const auto host = "server.com"s; 453 const auto str = comm + "@" + host; 454 REQUIRE(try_parse(&sc, str.c_str()) == 0); 455 REQUIRE(sc.trans == SNMP_TRANS_UDP); 456 REQUIRE(sc.chost == host); 457 REQUIRE(sc.cport == "snmp"s); 458 REQUIRE(sc.read_community == comm); 459 REQUIRE(sc.write_community == comm); 460 } 461 SECTION("community with @ and host") { 462 const auto comm = "public@bla"s; 463 const auto host = "server.com"s; 464 const auto str = comm + "@" + host; 465 REQUIRE(try_parse(&sc, str.c_str()) == 0); 466 REQUIRE(sc.trans == SNMP_TRANS_UDP); 467 REQUIRE(sc.chost == host); 468 REQUIRE(sc.cport == "snmp"s); 469 REQUIRE(sc.read_community == comm); 470 REQUIRE(sc.write_community == comm); 471 } 472 SECTION("empty community and host") { 473 const auto comm = ""s; 474 const auto host = "server.com"s; 475 const auto str = comm + "@" + host; 476 REQUIRE(try_parse(&sc, str.c_str()) == 0); 477 REQUIRE(sc.trans == SNMP_TRANS_UDP); 478 REQUIRE(sc.chost == host); 479 REQUIRE(sc.cport == "snmp"s); 480 REQUIRE(sc.read_community == comm); 481 REQUIRE(sc.write_community == comm); 482 } 483 } 484 485 TEST_CASE("snmp_parse_server: transport, community, host and port", "[snmp_parse_server]") 486 { 487 struct snmp_client sc; 488 snmp_client_init(&sc); 489 490 SECTION("transport, community, host and numeric port") { 491 const auto trans = "udp6"s; 492 const auto comm = "public"s; 493 const auto host = "server.com"s; 494 const auto port = "65000"s; 495 const auto str = trans + "::" + comm + "@" + host + ":" + port; 496 REQUIRE(try_parse(&sc, str.c_str()) == 0); 497 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 498 REQUIRE(sc.chost == host); 499 REQUIRE(sc.cport == port); 500 REQUIRE(sc.read_community == comm); 501 REQUIRE(sc.write_community == comm); 502 } 503 SECTION("transport, community, ipv4 and symbolic port") { 504 const auto trans = "udp6"s; 505 const auto comm = "public"s; 506 const auto host = "127.1"s; 507 const auto port = "ftp"s; 508 const auto str = trans + "::" + comm + "@" + host + ":" + port; 509 REQUIRE(try_parse(&sc, str.c_str()) == 0); 510 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 511 REQUIRE(sc.chost == host); 512 REQUIRE(sc.cport == port); 513 REQUIRE(sc.read_community == comm); 514 REQUIRE(sc.write_community == comm); 515 } 516 SECTION("transport, community, ipv6 and symbolic port") { 517 const auto trans = "udp"s; 518 const auto comm = "public"s; 519 const auto host = "fe80::1:2"s; 520 const auto port = "ftp"s; 521 const auto str = trans + "::" + comm + "@[" + host + "]:" + port; 522 REQUIRE(try_parse(&sc, str.c_str()) == 0); 523 REQUIRE(sc.trans == SNMP_TRANS_UDP6); 524 REQUIRE(sc.chost == host); 525 REQUIRE(sc.cport == port); 526 REQUIRE(sc.read_community == comm); 527 REQUIRE(sc.write_community == comm); 528 } 529 } 530