1fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu/* 2fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * m_nat.c NAT module 3fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * 4fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * This program is free software; you can distribute it and/or 5fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * modify it under the terms of the GNU General Public License 6fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * as published by the Free Software Foundation; either version 7fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * 2 of the License, or (at your option) any later version. 8fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * 9fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * Authors: Herbert Xu <herbert@gondor.apana.org.au> 10fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu * 11fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu */ 12fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 13fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <stdio.h> 14fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <stdlib.h> 15fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <unistd.h> 16fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <syslog.h> 17fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <fcntl.h> 18fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <sys/socket.h> 19fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <netinet/in.h> 20fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <arpa/inet.h> 21fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <string.h> 22fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include "utils.h" 23fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include "tc_util.h" 24fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu#include <linux/tc_act/tc_nat.h> 25fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 26fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xustatic void 27fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xuexplain(void) 28fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu{ 29fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu fprintf(stderr, "Usage: ... nat NAT\n" 30fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu "NAT := DIRECTION OLD NEW\n" 31fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu "DIRECTION := { ingress | egress }\n" 32fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu "OLD := PREFIX\n" 33fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu "NEW := ADDRESS\n"); 34fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu} 35fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 36fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xustatic void 37fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xuusage(void) 38fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu{ 39fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu explain(); 40fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu exit(-1); 41fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu} 42fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 43fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xustatic int 44fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xuparse_nat_args(int *argc_p, char ***argv_p,struct tc_nat *sel) 45fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu{ 46fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu int argc = *argc_p; 47fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu char **argv = *argv_p; 48fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu inet_prefix addr; 49fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 50fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (argc <= 0) 51fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return -1; 52fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 53fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (matches(*argv, "egress") == 0) 54fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel->flags |= TCA_NAT_FLAG_EGRESS; 55fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu else if (matches(*argv, "ingress") != 0) 56fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu goto bad_val; 57fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 58fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu NEXT_ARG(); 59fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 60fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (get_prefix_1(&addr, *argv, AF_INET)) 61fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu goto bad_val; 62fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 63fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel->old_addr = addr.data[0]; 64fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel->mask = htonl(~0u << (32 - addr.bitlen)); 65fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 66fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu NEXT_ARG(); 67fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 68fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (get_prefix_1(&addr, *argv, AF_INET)) 69fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu goto bad_val; 70fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 71fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel->new_addr = addr.data[0]; 72fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 73fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argc--; 74fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argv++; 75fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 76fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu *argc_p = argc; 77fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu *argv_p = argv; 78fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return 0; 79fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 80fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xubad_val: 81fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return -1; 82fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu} 83fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 84fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xustatic int 85fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xuparse_nat(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) 86fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu{ 87fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu struct tc_nat sel; 88fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 89fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu int argc = *argc_p; 90fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu char **argv = *argv_p; 91fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu int ok = 0; 92fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu struct rtattr *tail; 93fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 94fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu memset(&sel, 0, sizeof(sel)); 95fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 96fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu while (argc > 0) { 97fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (matches(*argv, "nat") == 0) { 98fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu NEXT_ARG(); 99fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (parse_nat_args(&argc, &argv, &sel)) { 100fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu fprintf(stderr, "Illegal nat construct (%s) \n", 101fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu *argv); 102fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu explain(); 103fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return -1; 104fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 105fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu ok++; 106fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu continue; 107fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } else if (matches(*argv, "help") == 0) { 108fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu usage(); 109fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } else { 110fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu break; 111fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 112fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 113fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 114fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 115fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (!ok) { 116fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu explain(); 117fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return -1; 118fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 119fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 120fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (argc) { 121fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (matches(*argv, "reclassify") == 0) { 122fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel.action = TC_ACT_RECLASSIFY; 123fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argc--; 124fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argv++; 125fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } else if (matches(*argv, "pipe") == 0) { 126fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel.action = TC_ACT_PIPE; 127fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argc--; 128fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argv++; 129fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } else if (matches(*argv, "drop") == 0 || 130fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu matches(*argv, "shot") == 0) { 131fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel.action = TC_ACT_SHOT; 132fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argc--; 133fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argv++; 134fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } else if (matches(*argv, "continue") == 0) { 135fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel.action = TC_ACT_UNSPEC; 136fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argc--; 137fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argv++; 138fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } else if (matches(*argv, "pass") == 0) { 139fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel.action = TC_ACT_OK; 140fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argc--; 141fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argv++; 142fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 143fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 144fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 145fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (argc) { 146fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (matches(*argv, "index") == 0) { 147fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu NEXT_ARG(); 148fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (get_u32(&sel.index, *argv, 10)) { 149fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu fprintf(stderr, "Pedit: Illegal \"index\"\n"); 150fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return -1; 151fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 152fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argc--; 153fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu argv++; 154fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 155fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 156fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 157fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu tail = NLMSG_TAIL(n); 158fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu addattr_l(n, MAX_MSG, tca_id, NULL, 0); 159fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu addattr_l(n, MAX_MSG, TCA_NAT_PARMS, &sel, sizeof(sel)); 160fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail; 161fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 162fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu *argc_p = argc; 163fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu *argv_p = argv; 164fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return 0; 165fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu} 166fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 167fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xustatic int 168fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xuprint_nat(struct action_util *au,FILE * f, struct rtattr *arg) 169fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu{ 170fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu struct tc_nat *sel; 171fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu struct rtattr *tb[TCA_NAT_MAX + 1]; 172fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu char buf1[256]; 173fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu char buf2[256]; 174fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu SPRINT_BUF(buf3); 175fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu int len; 176fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 177fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (arg == NULL) 178fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return -1; 179fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 180fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu parse_rtattr_nested(tb, TCA_NAT_MAX, arg); 181fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 182fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (tb[TCA_NAT_PARMS] == NULL) { 183fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu fprintf(f, "[NULL nat parameters]"); 184fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return -1; 185fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 186fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu sel = RTA_DATA(tb[TCA_NAT_PARMS]); 187fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 188fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu len = ffs(sel->mask); 189fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu len = len ? 33 - len : 0; 190fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 191fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu fprintf(f, " nat %s %s/%d %s %s", sel->flags & TCA_NAT_FLAG_EGRESS ? 192fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu "egress" : "ingress", 193fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu format_host(AF_INET, 4, &sel->old_addr, buf1, sizeof(buf1)), 194fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu len, 195fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu format_host(AF_INET, 4, &sel->new_addr, buf2, sizeof(buf2)), 196fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu action_n2a(sel->action, buf3, sizeof (buf3))); 197fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 198fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (show_stats) { 199fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu if (tb[TCA_NAT_TM]) { 200fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu struct tcf_t *tm = RTA_DATA(tb[TCA_NAT_TM]); 201fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu print_tm(f,tm); 202fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 203fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu } 204fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 205fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu return 0; 206fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu} 207fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu 208fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xustruct action_util nat_action_util = { 209fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu .id = "nat", 210fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu .parse_aopt = parse_nat, 211fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu .print_aopt = print_nat, 212fc2d02069b52e0e1fce9045572bd22d197dd91d5Herbert Xu}; 213