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