ng_nat.c (e842c54054b846061bf92d0f8a23ee3126ede6a9) | ng_nat.c (fffba935e4085724c899c44c9fb5a10dede5016e) |
---|---|
1/*- 2 * Copyright 2005, Gleb Smirnoff <glebius@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 49 unchanged lines hidden (view full) --- 58 59static unsigned int ng_nat_translate_flags(unsigned int x); 60 61/* Parse type for struct ng_nat_mode. */ 62static const struct ng_parse_struct_field ng_nat_mode_fields[] 63 = NG_NAT_MODE_INFO; 64static const struct ng_parse_type ng_nat_mode_type = { 65 &ng_parse_struct_type, | 1/*- 2 * Copyright 2005, Gleb Smirnoff <glebius@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 49 unchanged lines hidden (view full) --- 58 59static unsigned int ng_nat_translate_flags(unsigned int x); 60 61/* Parse type for struct ng_nat_mode. */ 62static const struct ng_parse_struct_field ng_nat_mode_fields[] 63 = NG_NAT_MODE_INFO; 64static const struct ng_parse_type ng_nat_mode_type = { 65 &ng_parse_struct_type, |
66 ng_nat_mode_fields | 66 &ng_nat_mode_fields |
67}; 68 | 67}; 68 |
69/* Parse type for 'description' field in structs. */ 70static const struct ng_parse_fixedstring_info ng_nat_description_info 71 = { NG_NAT_DESC_LENGTH }; 72static const struct ng_parse_type ng_nat_description_type = { 73 &ng_parse_fixedstring_type, 74 &ng_nat_description_info 75}; 76 77/* Parse type for struct ng_nat_redirect_port. */ 78static const struct ng_parse_struct_field ng_nat_redirect_port_fields[] 79 = NG_NAT_REDIRECT_PORT_TYPE_INFO(&ng_nat_description_type); 80static const struct ng_parse_type ng_nat_redirect_port_type = { 81 &ng_parse_struct_type, 82 &ng_nat_redirect_port_fields 83}; 84 85/* Parse type for struct ng_nat_redirect_addr. */ 86static const struct ng_parse_struct_field ng_nat_redirect_addr_fields[] 87 = NG_NAT_REDIRECT_ADDR_TYPE_INFO(&ng_nat_description_type); 88static const struct ng_parse_type ng_nat_redirect_addr_type = { 89 &ng_parse_struct_type, 90 &ng_nat_redirect_addr_fields 91}; 92 93/* Parse type for struct ng_nat_redirect_proto. */ 94static const struct ng_parse_struct_field ng_nat_redirect_proto_fields[] 95 = NG_NAT_REDIRECT_PROTO_TYPE_INFO(&ng_nat_description_type); 96static const struct ng_parse_type ng_nat_redirect_proto_type = { 97 &ng_parse_struct_type, 98 &ng_nat_redirect_proto_fields 99}; 100 101/* Parse type for struct ng_nat_add_server. */ 102static const struct ng_parse_struct_field ng_nat_add_server_fields[] 103 = NG_NAT_ADD_SERVER_TYPE_INFO; 104static const struct ng_parse_type ng_nat_add_server_type = { 105 &ng_parse_struct_type, 106 &ng_nat_add_server_fields 107}; 108 109/* Parse type for one struct ng_nat_listrdrs_entry. */ 110static const struct ng_parse_struct_field ng_nat_listrdrs_entry_fields[] 111 = NG_NAT_LISTRDRS_ENTRY_TYPE_INFO(&ng_nat_description_type); 112static const struct ng_parse_type ng_nat_listrdrs_entry_type = { 113 &ng_parse_struct_type, 114 &ng_nat_listrdrs_entry_fields 115}; 116 117/* Parse type for 'redirects' array in struct ng_nat_list_redirects. */ 118static int 119ng_nat_listrdrs_ary_getLength(const struct ng_parse_type *type, 120 const u_char *start, const u_char *buf) 121{ 122 const struct ng_nat_list_redirects *lr; 123 124 lr = (const struct ng_nat_list_redirects *) 125 (buf - offsetof(struct ng_nat_list_redirects, redirects)); 126 return lr->total_count; 127} 128 129static const struct ng_parse_array_info ng_nat_listrdrs_ary_info = { 130 &ng_nat_listrdrs_entry_type, 131 &ng_nat_listrdrs_ary_getLength, 132 NULL 133}; 134static const struct ng_parse_type ng_nat_listrdrs_ary_type = { 135 &ng_parse_array_type, 136 &ng_nat_listrdrs_ary_info 137}; 138 139/* Parse type for struct ng_nat_list_redirects. */ 140static const struct ng_parse_struct_field ng_nat_list_redirects_fields[] 141 = NG_NAT_LIST_REDIRECTS_TYPE_INFO(&ng_nat_listrdrs_ary_type); 142static const struct ng_parse_type ng_nat_list_redirects_type = { 143 &ng_parse_struct_type, 144 &ng_nat_list_redirects_fields 145}; 146 |
|
69/* List of commands and how to convert arguments to/from ASCII. */ 70static const struct ng_cmdlist ng_nat_cmdlist[] = { 71 { 72 NGM_NAT_COOKIE, 73 NGM_NAT_SET_IPADDR, 74 "setaliasaddr", 75 &ng_parse_ipaddr_type, 76 NULL --- 7 unchanged lines hidden (view full) --- 84 }, 85 { 86 NGM_NAT_COOKIE, 87 NGM_NAT_SET_TARGET, 88 "settarget", 89 &ng_parse_ipaddr_type, 90 NULL 91 }, | 147/* List of commands and how to convert arguments to/from ASCII. */ 148static const struct ng_cmdlist ng_nat_cmdlist[] = { 149 { 150 NGM_NAT_COOKIE, 151 NGM_NAT_SET_IPADDR, 152 "setaliasaddr", 153 &ng_parse_ipaddr_type, 154 NULL --- 7 unchanged lines hidden (view full) --- 162 }, 163 { 164 NGM_NAT_COOKIE, 165 NGM_NAT_SET_TARGET, 166 "settarget", 167 &ng_parse_ipaddr_type, 168 NULL 169 }, |
170 { 171 NGM_NAT_COOKIE, 172 NGM_NAT_REDIRECT_PORT, 173 "redirectport", 174 &ng_nat_redirect_port_type, 175 &ng_parse_uint32_type 176 }, 177 { 178 NGM_NAT_COOKIE, 179 NGM_NAT_REDIRECT_ADDR, 180 "redirectaddr", 181 &ng_nat_redirect_addr_type, 182 &ng_parse_uint32_type 183 }, 184 { 185 NGM_NAT_COOKIE, 186 NGM_NAT_REDIRECT_PROTO, 187 "redirectproto", 188 &ng_nat_redirect_proto_type, 189 &ng_parse_uint32_type 190 }, 191 { 192 NGM_NAT_COOKIE, 193 NGM_NAT_REDIRECT_DYNAMIC, 194 "redirectdynamic", 195 &ng_parse_uint32_type, 196 NULL 197 }, 198 { 199 NGM_NAT_COOKIE, 200 NGM_NAT_REDIRECT_DELETE, 201 "redirectdelete", 202 &ng_parse_uint32_type, 203 NULL 204 }, 205 { 206 NGM_NAT_COOKIE, 207 NGM_NAT_ADD_SERVER, 208 "addserver", 209 &ng_nat_add_server_type, 210 NULL 211 }, 212 { 213 NGM_NAT_COOKIE, 214 NGM_NAT_LIST_REDIRECTS, 215 "listredirects", 216 NULL, 217 &ng_nat_list_redirects_type 218 }, 219 { 220 NGM_NAT_COOKIE, 221 NGM_NAT_PROXY_RULE, 222 "proxyrule", 223 &ng_parse_string_type, 224 NULL 225 }, |
|
92 { 0 } 93}; 94 95/* Netgraph node type descriptor. */ 96static struct ng_type typestruct = { 97 .version = NG_ABI_VERSION, 98 .name = NG_NAT_NODE_TYPE, 99 .constructor = ng_nat_constructor, 100 .rcvmsg = ng_nat_rcvmsg, 101 .shutdown = ng_nat_shutdown, 102 .newhook = ng_nat_newhook, 103 .rcvdata = ng_nat_rcvdata, 104 .disconnect = ng_nat_disconnect, 105 .cmdlist = ng_nat_cmdlist, 106}; 107NETGRAPH_INIT(nat, &typestruct); 108MODULE_DEPEND(ng_nat, libalias, 1, 1, 1); 109 | 226 { 0 } 227}; 228 229/* Netgraph node type descriptor. */ 230static struct ng_type typestruct = { 231 .version = NG_ABI_VERSION, 232 .name = NG_NAT_NODE_TYPE, 233 .constructor = ng_nat_constructor, 234 .rcvmsg = ng_nat_rcvmsg, 235 .shutdown = ng_nat_shutdown, 236 .newhook = ng_nat_newhook, 237 .rcvdata = ng_nat_rcvdata, 238 .disconnect = ng_nat_disconnect, 239 .cmdlist = ng_nat_cmdlist, 240}; 241NETGRAPH_INIT(nat, &typestruct); 242MODULE_DEPEND(ng_nat, libalias, 1, 1, 1); 243 |
244/* Element for list of redirects. */ 245struct ng_nat_rdr_lst { 246 STAILQ_ENTRY(ng_nat_rdr_lst) entries; 247 struct alias_link *lnk; 248 struct ng_nat_listrdrs_entry rdr; 249}; 250STAILQ_HEAD(rdrhead, ng_nat_rdr_lst); 251 |
|
110/* Information we store for each node. */ 111struct ng_nat_priv { 112 node_p node; /* back pointer to node */ 113 hook_p in; /* hook for demasquerading */ 114 hook_p out; /* hook for masquerading */ 115 struct libalias *lib; /* libalias handler */ 116 uint32_t flags; /* status flags */ | 252/* Information we store for each node. */ 253struct ng_nat_priv { 254 node_p node; /* back pointer to node */ 255 hook_p in; /* hook for demasquerading */ 256 hook_p out; /* hook for masquerading */ 257 struct libalias *lib; /* libalias handler */ 258 uint32_t flags; /* status flags */ |
259 uint32_t rdrcount; /* number or redirects in list */ 260 uint32_t nextid; /* for next in turn in list */ 261 struct rdrhead redirhead; /* redirect list header */ |
|
117}; 118typedef struct ng_nat_priv *priv_p; 119 120/* Values of flags */ 121#define NGNAT_CONNECTED 0x1 /* We have both hooks connected */ 122#define NGNAT_ADDR_DEFINED 0x2 /* NGM_NAT_SET_IPADDR happened */ 123 124static int --- 13 unchanged lines hidden (view full) --- 138 FREE(priv, M_NETGRAPH); 139 return (ENOMEM); 140 } 141 142 /* Set same ports on. */ 143 (void )LibAliasSetMode(priv->lib, PKT_ALIAS_SAME_PORTS, 144 PKT_ALIAS_SAME_PORTS); 145 | 262}; 263typedef struct ng_nat_priv *priv_p; 264 265/* Values of flags */ 266#define NGNAT_CONNECTED 0x1 /* We have both hooks connected */ 267#define NGNAT_ADDR_DEFINED 0x2 /* NGM_NAT_SET_IPADDR happened */ 268 269static int --- 13 unchanged lines hidden (view full) --- 283 FREE(priv, M_NETGRAPH); 284 return (ENOMEM); 285 } 286 287 /* Set same ports on. */ 288 (void )LibAliasSetMode(priv->lib, PKT_ALIAS_SAME_PORTS, 289 PKT_ALIAS_SAME_PORTS); 290 |
291 /* Init redirects housekeeping. */ 292 priv->rdrcount = 0; 293 priv->nextid = 1; 294 STAILQ_INIT(&priv->redirhead); 295 |
|
146 /* Link structs together. */ 147 NG_NODE_SET_PRIVATE(node, priv); 148 priv->node = node; 149 150 /* 151 * libalias is not thread safe, so our node 152 * must be single threaded. 153 */ --- 73 unchanged lines hidden (view full) --- 227 if (msg->header.arglen < sizeof(*ia)) { 228 error = EINVAL; 229 break; 230 } 231 232 LibAliasSetTarget(priv->lib, *ia); 233 } 234 break; | 296 /* Link structs together. */ 297 NG_NODE_SET_PRIVATE(node, priv); 298 priv->node = node; 299 300 /* 301 * libalias is not thread safe, so our node 302 * must be single threaded. 303 */ --- 73 unchanged lines hidden (view full) --- 377 if (msg->header.arglen < sizeof(*ia)) { 378 error = EINVAL; 379 break; 380 } 381 382 LibAliasSetTarget(priv->lib, *ia); 383 } 384 break; |
385 case NGM_NAT_REDIRECT_PORT: 386 { 387 struct ng_nat_rdr_lst *entry; 388 struct ng_nat_redirect_port *const rp = 389 (struct ng_nat_redirect_port *)msg->data; 390 391 if (msg->header.arglen < sizeof(*rp)) { 392 error = EINVAL; 393 break; 394 } 395 396 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst), 397 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) { 398 error = ENOMEM; 399 break; 400 } 401 402 /* Try actual redirect. */ 403 entry->lnk = LibAliasRedirectPort(priv->lib, 404 rp->local_addr, htons(rp->local_port), 405 rp->remote_addr, htons(rp->remote_port), 406 rp->alias_addr, htons(rp->alias_port), 407 rp->proto); 408 409 if (entry->lnk == NULL) { 410 error = ENOMEM; 411 FREE(entry, M_NETGRAPH); 412 break; 413 } 414 415 /* Successful, save info in our internal list. */ 416 entry->rdr.local_addr = rp->local_addr; 417 entry->rdr.alias_addr = rp->alias_addr; 418 entry->rdr.remote_addr = rp->remote_addr; 419 entry->rdr.local_port = rp->local_port; 420 entry->rdr.alias_port = rp->alias_port; 421 entry->rdr.remote_port = rp->remote_port; 422 entry->rdr.proto = rp->proto; 423 bcopy(rp->description, entry->rdr.description, 424 NG_NAT_DESC_LENGTH); 425 426 /* Safety precaution. */ 427 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0'; 428 429 entry->rdr.id = priv->nextid++; 430 priv->rdrcount++; 431 432 /* Link to list of redirects. */ 433 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries); 434 435 /* Response with id of newly added entry. */ 436 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT); 437 if (resp == NULL) { 438 error = ENOMEM; 439 break; 440 } 441 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id)); 442 } 443 break; 444 case NGM_NAT_REDIRECT_ADDR: 445 { 446 struct ng_nat_rdr_lst *entry; 447 struct ng_nat_redirect_addr *const ra = 448 (struct ng_nat_redirect_addr *)msg->data; 449 450 if (msg->header.arglen < sizeof(*ra)) { 451 error = EINVAL; 452 break; 453 } 454 455 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst), 456 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) { 457 error = ENOMEM; 458 break; 459 } 460 461 /* Try actual redirect. */ 462 entry->lnk = LibAliasRedirectAddr(priv->lib, 463 ra->local_addr, ra->alias_addr); 464 465 if (entry->lnk == NULL) { 466 error = ENOMEM; 467 FREE(entry, M_NETGRAPH); 468 break; 469 } 470 471 /* Successful, save info in our internal list. */ 472 entry->rdr.local_addr = ra->local_addr; 473 entry->rdr.alias_addr = ra->alias_addr; 474 entry->rdr.proto = NG_NAT_REDIRPROTO_ADDR; 475 bcopy(ra->description, entry->rdr.description, 476 NG_NAT_DESC_LENGTH); 477 478 /* Safety precaution. */ 479 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0'; 480 481 entry->rdr.id = priv->nextid++; 482 priv->rdrcount++; 483 484 /* Link to list of redirects. */ 485 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries); 486 487 /* Response with id of newly added entry. */ 488 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT); 489 if (resp == NULL) { 490 error = ENOMEM; 491 break; 492 } 493 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id)); 494 } 495 break; 496 case NGM_NAT_REDIRECT_PROTO: 497 { 498 struct ng_nat_rdr_lst *entry; 499 struct ng_nat_redirect_proto *const rp = 500 (struct ng_nat_redirect_proto *)msg->data; 501 502 if (msg->header.arglen < sizeof(*rp)) { 503 error = EINVAL; 504 break; 505 } 506 507 if ((entry = malloc(sizeof(struct ng_nat_rdr_lst), 508 M_NETGRAPH, M_NOWAIT | M_ZERO)) == NULL) { 509 error = ENOMEM; 510 break; 511 } 512 513 /* Try actual redirect. */ 514 entry->lnk = LibAliasRedirectProto(priv->lib, 515 rp->local_addr, rp->remote_addr, 516 rp->alias_addr, rp->proto); 517 518 if (entry->lnk == NULL) { 519 error = ENOMEM; 520 FREE(entry, M_NETGRAPH); 521 break; 522 } 523 524 /* Successful, save info in our internal list. */ 525 entry->rdr.local_addr = rp->local_addr; 526 entry->rdr.alias_addr = rp->alias_addr; 527 entry->rdr.remote_addr = rp->remote_addr; 528 entry->rdr.proto = rp->proto; 529 bcopy(rp->description, entry->rdr.description, 530 NG_NAT_DESC_LENGTH); 531 532 /* Safety precaution. */ 533 entry->rdr.description[NG_NAT_DESC_LENGTH-1] = '\0'; 534 535 entry->rdr.id = priv->nextid++; 536 priv->rdrcount++; 537 538 /* Link to list of redirects. */ 539 STAILQ_INSERT_TAIL(&priv->redirhead, entry, entries); 540 541 /* Response with id of newly added entry. */ 542 NG_MKRESPONSE(resp, msg, sizeof(entry->rdr.id), M_NOWAIT); 543 if (resp == NULL) { 544 error = ENOMEM; 545 break; 546 } 547 bcopy(&entry->rdr.id, resp->data, sizeof(entry->rdr.id)); 548 } 549 break; 550 case NGM_NAT_REDIRECT_DYNAMIC: 551 case NGM_NAT_REDIRECT_DELETE: 552 { 553 struct ng_nat_rdr_lst *entry; 554 uint32_t *const id = (uint32_t *)msg->data; 555 556 if (msg->header.arglen < sizeof(*id)) { 557 error = EINVAL; 558 break; 559 } 560 561 /* Find entry with supplied id. */ 562 STAILQ_FOREACH(entry, &priv->redirhead, entries) { 563 if (entry->rdr.id == *id) 564 break; 565 } 566 567 /* Not found. */ 568 if (entry == NULL) { 569 error = ENOENT; 570 break; 571 } 572 573 if (msg->header.cmd == NGM_NAT_REDIRECT_DYNAMIC) { 574 if (LibAliasRedirectDynamic(priv->lib, 575 entry->lnk) == -1) { 576 error = ENOTTY; /* XXX Something better? */ 577 break; 578 } 579 } else { /* NGM_NAT_REDIRECT_DELETE */ 580 LibAliasRedirectDelete(priv->lib, entry->lnk); 581 } 582 583 /* Delete entry from our internal list. */ 584 priv->rdrcount--; 585 STAILQ_REMOVE(&priv->redirhead, entry, ng_nat_rdr_lst, entries); 586 FREE(entry, M_NETGRAPH); 587 } 588 break; 589 case NGM_NAT_ADD_SERVER: 590 { 591 struct ng_nat_rdr_lst *entry; 592 struct ng_nat_add_server *const as = 593 (struct ng_nat_add_server *)msg->data; 594 595 if (msg->header.arglen < sizeof(*as)) { 596 error = EINVAL; 597 break; 598 } 599 600 /* Find entry with supplied id. */ 601 STAILQ_FOREACH(entry, &priv->redirhead, entries) { 602 if (entry->rdr.id == as->id) 603 break; 604 } 605 606 /* Not found. */ 607 if (entry == NULL) { 608 error = ENOENT; 609 break; 610 } 611 612 if (LibAliasAddServer(priv->lib, entry->lnk, 613 as->addr, htons(as->port)) == -1) { 614 error = ENOMEM; 615 break; 616 } 617 618 entry->rdr.lsnat++; 619 } 620 break; 621 case NGM_NAT_LIST_REDIRECTS: 622 { 623 struct ng_nat_rdr_lst *entry; 624 struct ng_nat_list_redirects *ary; 625 int i = 0; 626 627 NG_MKRESPONSE(resp, msg, sizeof(*ary) + 628 (priv->rdrcount) * sizeof(*entry), M_NOWAIT); 629 if (resp == NULL) { 630 error = ENOMEM; 631 break; 632 } 633 634 ary = (struct ng_nat_list_redirects *)resp->data; 635 ary->total_count = priv->rdrcount; 636 637 STAILQ_FOREACH(entry, &priv->redirhead, entries) { 638 bcopy(&entry->rdr, &ary->redirects[i++], 639 sizeof(struct ng_nat_listrdrs_entry)); 640 } 641 } 642 break; 643 case NGM_NAT_PROXY_RULE: 644 { 645 char *cmd = (char *)msg->data; 646 647 if (msg->header.arglen < 6) { 648 error = EINVAL; 649 break; 650 } 651 652 if (LibAliasProxyRule(priv->lib, cmd) != 0) 653 error = ENOMEM; 654 } 655 break; |
|
235 default: 236 error = EINVAL; /* unknown command */ 237 break; 238 } 239 break; 240 default: 241 error = EINVAL; /* unknown cookie type */ 242 break; --- 111 unchanged lines hidden (view full) --- 354 355static int 356ng_nat_shutdown(node_p node) 357{ 358 const priv_p priv = NG_NODE_PRIVATE(node); 359 360 NG_NODE_SET_PRIVATE(node, NULL); 361 NG_NODE_UNREF(node); | 656 default: 657 error = EINVAL; /* unknown command */ 658 break; 659 } 660 break; 661 default: 662 error = EINVAL; /* unknown cookie type */ 663 break; --- 111 unchanged lines hidden (view full) --- 775 776static int 777ng_nat_shutdown(node_p node) 778{ 779 const priv_p priv = NG_NODE_PRIVATE(node); 780 781 NG_NODE_SET_PRIVATE(node, NULL); 782 NG_NODE_UNREF(node); |
783 784 /* Free redirects list. */ 785 while (!STAILQ_EMPTY(&priv->redirhead)) { 786 struct ng_nat_rdr_lst *entry = STAILQ_FIRST(&priv->redirhead); 787 STAILQ_REMOVE_HEAD(&priv->redirhead, entries); 788 FREE(entry, M_NETGRAPH); 789 }; 790 791 /* Final free. */ |
|
362 LibAliasUninit(priv->lib); 363 FREE(priv, M_NETGRAPH); 364 365 return (0); 366} 367 368static int 369ng_nat_disconnect(hook_p hook) --- 38 unchanged lines hidden --- | 792 LibAliasUninit(priv->lib); 793 FREE(priv, M_NETGRAPH); 794 795 return (0); 796} 797 798static int 799ng_nat_disconnect(hook_p hook) --- 38 unchanged lines hidden --- |