1706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh/*-
2706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *                    Brian Somers <brian@Awfulhak.org>
4706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * All rights reserved.
5706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
6706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Redistribution and use in source and binary forms, with or without
7706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * modification, are permitted provided that the following conditions
8706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * are met:
9706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 1. Redistributions of source code must retain the above copyright
10706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer.
11706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 2. Redistributions in binary form must reproduce the above copyright
12706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer in the
13706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    documentation and/or other materials provided with the distribution.
14706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
15706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * SUCH DAMAGE.
26706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
27706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * $FreeBSD: src/usr.sbin/ppp/nat_cmd.c,v 1.62.10.1.4.1 2010/12/21 17:10:29 kensmith Exp $
28706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh */
29706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
30706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/param.h>
31706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in.h>
32706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <arpa/inet.h>
33706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netdb.h>
34706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in_systm.h>
35706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in.h>
36706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/ip.h>
37706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/socket.h>
38706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/un.h>
39706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
40706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdarg.h>
41706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdio.h>
42706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <stdlib.h>
43706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <string.h>
44706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <termios.h>
45706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
46706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifdef LOCALNAT
47706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "alias.h"
48706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#else
49706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <alias.h>
50706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
51706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
52706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "layer.h"
53706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "proto.h"
54706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "defs.h"
55706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "command.h"
56706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "log.h"
57706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "nat_cmd.h"
58706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "descriptor.h"
59706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "prompt.h"
60706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "timer.h"
61706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "fsm.h"
62706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "slcompress.h"
63706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "throughput.h"
64706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "iplist.h"
65706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mbuf.h"
66706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lqr.h"
67706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "hdlc.h"
68706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncpaddr.h"
69706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ip.h"
70706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipcp.h"
71706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipv6cp.h"
72706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lcp.h"
73706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ccp.h"
74706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "link.h"
75706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mp.h"
76706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "filter.h"
77706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
78706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "radius.h"
79706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
80706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncp.h"
81706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "bundle.h"
82706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
83706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
84706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#define NAT_EXTRABUF (13)
85706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
86706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int StrToAddr(const char *, struct in_addr *);
87706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int StrToPortRange(const char *, u_short *, u_short *, const char *);
88706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int StrToAddrAndPort(const char *, struct in_addr *, u_short *,
89706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                            u_short *, const char *);
90706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
91706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
92706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehlowhigh(u_short *a, u_short *b)
93706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
94706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (a > b) {
95706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    u_short c;
96706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
97706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    c = *b;
98706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    *b = *a;
99706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    *a = c;
100706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
101706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
102706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
103706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
104706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_RedirectPort(struct cmdargs const *arg)
105706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
106706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!arg->bundle->NatEnabled) {
107706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "Alias not enabled\n");
108706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
109706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (arg->argc == arg->argn + 3 || arg->argc == arg->argn + 4) {
110706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    char proto_constant;
111706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    const char *proto;
112706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct in_addr localaddr;
113706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    u_short hlocalport, llocalport;
114706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct in_addr aliasaddr;
115706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    u_short haliasport, laliasport;
116706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct in_addr remoteaddr;
117706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    u_short hremoteport, lremoteport;
118706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct alias_link *link;
119706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int error;
120706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
121706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    proto = arg->argv[arg->argn];
122706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (strcmp(proto, "tcp") == 0) {
123706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      proto_constant = IPPROTO_TCP;
124706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else if (strcmp(proto, "udp") == 0) {
125706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      proto_constant = IPPROTO_UDP;
126706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else {
127706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "port redirect: protocol must be"
128706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    " tcp or udp\n");
129706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return -1;
130706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
131706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
132706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    error = StrToAddrAndPort(arg->argv[arg->argn+1], &localaddr, &llocalport,
133706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                             &hlocalport, proto);
134706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (error) {
135706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "nat port: error reading localaddr:port\n");
136706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return -1;
137706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
138706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
139706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    error = StrToPortRange(arg->argv[arg->argn+2], &laliasport, &haliasport,
140706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                           proto);
141706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (error) {
142706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "nat port: error reading alias port\n");
143706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return -1;
144706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
145706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    aliasaddr.s_addr = INADDR_ANY;
146706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
147706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (arg->argc == arg->argn + 4) {
148706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      error = StrToAddrAndPort(arg->argv[arg->argn+3], &remoteaddr,
149706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                               &lremoteport, &hremoteport, proto);
150706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (error) {
151706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        prompt_Printf(arg->prompt, "nat port: error reading "
152706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                      "remoteaddr:port\n");
153706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return -1;
154706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
155706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else {
156706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      remoteaddr.s_addr = INADDR_ANY;
157706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      lremoteport = hremoteport = 0;
158706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
159706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
160706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    lowhigh(&llocalport, &hlocalport);
161706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    lowhigh(&laliasport, &haliasport);
162706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    lowhigh(&lremoteport, &hremoteport);
163706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
164706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (haliasport - laliasport != hlocalport - llocalport) {
165706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "nat port: local & alias port ranges "
166706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    "are not equal\n");
167706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return -1;
168706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
169706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
170706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (hremoteport && hremoteport - lremoteport != hlocalport - llocalport) {
171706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "nat port: local & remote port ranges "
172706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    "are not equal\n");
173706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return -1;
174706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
175706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
176706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    do {
177706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      link = PacketAliasRedirectPort(localaddr, htons(llocalport),
178706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh				     remoteaddr, htons(lremoteport),
179706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                                     aliasaddr, htons(laliasport),
180706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh				     proto_constant);
181706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
182706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (link == NULL) {
183706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        prompt_Printf(arg->prompt, "nat port: %d: error %d\n", laliasport,
184706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                      error);
185706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return 1;
186706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
187706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      llocalport++;
188706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (hremoteport)
189706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        lremoteport++;
190706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } while (laliasport++ < haliasport);
191706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
192706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
193706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
194706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
195706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return -1;
196706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
197706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
198706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
199706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
200706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_RedirectAddr(struct cmdargs const *arg)
201706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
202706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!arg->bundle->NatEnabled) {
203706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "nat not enabled\n");
204706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
205706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (arg->argc == arg->argn+2) {
206706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int error;
207706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct in_addr localaddr, aliasaddr;
208706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct alias_link *link;
209706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
210706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    error = StrToAddr(arg->argv[arg->argn], &localaddr);
211706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (error) {
212706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "address redirect: invalid local address\n");
213706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
214706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
215706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    error = StrToAddr(arg->argv[arg->argn+1], &aliasaddr);
216706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (error) {
217706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "address redirect: invalid alias address\n");
218706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
219706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    arg->cmd->syntax);
220706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
221706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
222706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    link = PacketAliasRedirectAddr(localaddr, aliasaddr);
223706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (link == NULL) {
224706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "address redirect: packet aliasing"
225706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    " engine error\n");
226706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
227706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    arg->cmd->syntax);
228706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
229706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else
230706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
231706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
232706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
233706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
234706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
235706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
236706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
237706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_RedirectProto(struct cmdargs const *arg)
238706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
239706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!arg->bundle->NatEnabled) {
240706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    prompt_Printf(arg->prompt, "nat not enabled\n");
241706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
242706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else if (arg->argc >= arg->argn + 2 && arg->argc <= arg->argn + 4) {
243706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct in_addr localIP, publicIP, remoteIP;
244706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct alias_link *link;
245706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    struct protoent *pe;
246706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    int error;
247706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    unsigned len;
248706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
249706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    len = strlen(arg->argv[arg->argn]);
250706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (len == 0) {
251706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "proto redirect: invalid protocol\n");
252706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
253706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
254706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (strspn(arg->argv[arg->argn], "01234567") == len)
255706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      pe = getprotobynumber(atoi(arg->argv[arg->argn]));
256706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
257706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      pe = getprotobyname(arg->argv[arg->argn]);
258706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (pe == NULL) {
259706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "proto redirect: invalid protocol\n");
260706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
261706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
262706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
263706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    error = StrToAddr(arg->argv[arg->argn + 1], &localIP);
264706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (error) {
265706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "proto redirect: invalid src address\n");
266706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return 1;
267706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
268706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
269706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (arg->argc >= arg->argn + 3) {
270706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      error = StrToAddr(arg->argv[arg->argn + 2], &publicIP);
271706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (error) {
272706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        prompt_Printf(arg->prompt, "proto redirect: invalid alias address\n");
273706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
274706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                      arg->cmd->syntax);
275706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return 1;
276706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
277706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else
278706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      publicIP.s_addr = INADDR_ANY;
279706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
280706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (arg->argc == arg->argn + 4) {
281706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      error = StrToAddr(arg->argv[arg->argn + 2], &remoteIP);
282706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (error) {
283706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        prompt_Printf(arg->prompt, "proto redirect: invalid dst address\n");
284706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
285706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                      arg->cmd->syntax);
286706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        return 1;
287706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
288706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    } else
289706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      remoteIP.s_addr = INADDR_ANY;
290706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
291706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    link = PacketAliasRedirectProto(localIP, remoteIP, publicIP, pe->p_proto);
292706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (link == NULL) {
293706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "proto redirect: packet aliasing"
294706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    " engine error\n");
295706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
296706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    arg->cmd->syntax);
297706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
298706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else
299706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
300706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
301706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
302706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
303706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
304706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
305706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
306706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi YehStrToAddr(const char *str, struct in_addr *addr)
307706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
308706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct hostent *hp;
309706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
310706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (inet_aton(str, addr))
311706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
312706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
313706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  hp = gethostbyname(str);
314706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!hp) {
315706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
316706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
317706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
318706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *addr = *((struct in_addr *) hp->h_addr);
319706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
320706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
321706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
322706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
323706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
324706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi YehStrToPort(const char *str, u_short *port, const char *proto)
325706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
326706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct servent *sp;
327706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char *end;
328706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
329706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *port = strtol(str, &end, 10);
330706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (*end != '\0') {
331706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    sp = getservbyname(str, proto);
332706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (sp == NULL) {
333706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
334706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	        str, proto);
335706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      return -1;
336706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
337706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    *port = ntohs(sp->s_port);
338706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
339706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
340706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
341706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
342706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
343706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
344706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi YehStrToPortRange(const char *str, u_short *low, u_short *high, const char *proto)
345706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
346706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char *minus;
347706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int res;
348706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
349706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  minus = strchr(str, '-');
350706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (minus)
351706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    *minus = '\0';		/* Cheat the const-ness ! */
352706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
353706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  res = StrToPort(str, low, proto);
354706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
355706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (minus)
356706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    *minus = '-';		/* Cheat the const-ness ! */
357706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
358706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (res == 0) {
359706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (minus)
360706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      res = StrToPort(minus + 1, high, proto);
361706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else
362706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      *high = *low;
363706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
364706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
365706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return res;
366706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
367706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
368706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic int
369706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi YehStrToAddrAndPort(const char *str, struct in_addr *addr, u_short *low,
370706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 u_short *high, const char *proto)
371706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
372706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char *colon;
373706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int res;
374706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
375706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  colon = strchr(str, ':');
376706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!colon) {
377706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
378706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
379706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
380706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
381706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *colon = '\0';		/* Cheat the const-ness ! */
382706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  res = StrToAddr(str, addr);
383706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  *colon = ':';			/* Cheat the const-ness ! */
384706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (res != 0)
385706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
386706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
387706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return StrToPortRange(colon + 1, low, high, proto);
388706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
389706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
390706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
391706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_ProxyRule(struct cmdargs const *arg)
392706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
393706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char cmd[LINE_LEN];
394706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int f, pos;
395706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  size_t len;
396706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
397706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->argn >= arg->argc)
398706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
399706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
400706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (f = arg->argn, pos = 0; f < arg->argc; f++) {
401706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    len = strlen(arg->argv[f]);
402706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (sizeof cmd - pos < len + (len ? 1 : 0))
403706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
404706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (len)
405706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      cmd[pos++] = ' ';
406706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    strcpy(cmd + pos, arg->argv[f]);
407706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    pos += len;
408706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
409706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
410706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return PacketAliasProxyRule(cmd);
411706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
412706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
413706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
414706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_SetTarget(struct cmdargs const *arg)
415706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
416706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct in_addr addr;
417706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
418706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->argc == arg->argn) {
419706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    addr.s_addr = INADDR_ANY;
420706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    PacketAliasSetTarget(addr);
421706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
422706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
423706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
424706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->argc != arg->argn + 1)
425706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
426706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
427706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!strcasecmp(arg->argv[arg->argn], "MYADDR")) {
428706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    addr.s_addr = INADDR_ANY;
429706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    PacketAliasSetTarget(addr);
430706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
431706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
432706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
433706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  addr = GetIpAddr(arg->argv[arg->argn]);
434706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (addr.s_addr == INADDR_NONE) {
435706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogWARN, "%s: invalid address\n", arg->argv[arg->argn]);
436706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 1;
437706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
438706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
439706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  PacketAliasSetTarget(addr);
440706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
441706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
442706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
443706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NO_FW_PUNCH
444706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
445706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_PunchFW(struct cmdargs const *arg)
446706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
447706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char *end;
448706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  long base, count;
449706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
450706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->argc == arg->argn) {
451706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    PacketAliasSetMode(0, PKT_ALIAS_PUNCH_FW);
452706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
453706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
454706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
455706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->argc != arg->argn + 2)
456706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
457706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
458706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  base = strtol(arg->argv[arg->argn], &end, 10);
459706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (*end != '\0' || base < 0)
460706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
461706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
462706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  count = strtol(arg->argv[arg->argn + 1], &end, 10);
463706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (*end != '\0' || count < 0)
464706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
465706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
466706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  PacketAliasSetFWBase(base, count);
467706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  PacketAliasSetMode(PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW);
468706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
469706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
470706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
471706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
472706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
473706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehint
474706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_SkinnyPort(struct cmdargs const *arg)
475706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
476706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char *end;
477706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  long port;
478706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
479706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->argc == arg->argn) {
480706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    PacketAliasSetSkinnyPort(0);
481706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return 0;
482706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
483706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
484706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (arg->argc != arg->argn + 1)
485706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
486706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
487706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  port = strtol(arg->argv[arg->argn], &end, 10);
488706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (*end != '\0' || port < 0)
489706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return -1;
490706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
491706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  PacketAliasSetSkinnyPort(port);
492706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
493706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return 0;
494706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
495706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
496706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic struct mbuf *
497706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_LayerPush(struct bundle *bundle, struct link *l __unused, struct mbuf *bp,
498706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                int pri __unused, u_short *proto)
499706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
500706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!bundle->NatEnabled || *proto != PROTO_IP)
501706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return bp;
502706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
503706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogDEBUG, "nat_LayerPush: PROTO_IP -> PROTO_IP\n");
504706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  m_settype(bp, MB_NATOUT);
505706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Ensure there's a bit of extra buffer for the NAT code... */
506706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bp = m_pullup(m_append(bp, NULL, NAT_EXTRABUF));
507706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  PacketAliasOut(MBUF_CTOP(bp), bp->m_len);
508706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bp->m_len = ntohs(((struct ip *)MBUF_CTOP(bp))->ip_len);
509706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
510706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return bp;
511706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
512706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
513706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic struct mbuf *
514706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehnat_LayerPull(struct bundle *bundle, struct link *l __unused, struct mbuf *bp,
515706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                u_short *proto)
516706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
517706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  static int gfrags;
518706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int ret, len, nfrags;
519706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct mbuf **last;
520706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  char *fptr;
521706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
522706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!bundle->NatEnabled || *proto != PROTO_IP)
523706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return bp;
524706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
525706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  log_Printf(LogDEBUG, "nat_LayerPull: PROTO_IP -> PROTO_IP\n");
526706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  m_settype(bp, MB_NATIN);
527706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Ensure there's a bit of extra buffer for the NAT code... */
528706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bp = m_pullup(m_append(bp, NULL, NAT_EXTRABUF));
529706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  ret = PacketAliasIn(MBUF_CTOP(bp), bp->m_len);
530706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
531706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bp->m_len = ntohs(((struct ip *)MBUF_CTOP(bp))->ip_len);
532706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (bp->m_len > MAX_MRU) {
533706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    log_Printf(LogWARN, "nat_LayerPull: Problem with IP header length (%lu)\n",
534706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               (unsigned long)bp->m_len);
535706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    m_freem(bp);
536706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return NULL;
537706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
538706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
539706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  switch (ret) {
540706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case PKT_ALIAS_OK:
541706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
542706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
543706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case PKT_ALIAS_UNRESOLVED_FRAGMENT:
544706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* Save the data for later */
545706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if ((fptr = malloc(bp->m_len)) == NULL) {
546706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	log_Printf(LogWARN, "nat_LayerPull: Dropped unresolved fragment -"
547706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		   " out of memory!\n");
548706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	m_freem(bp);
549706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	bp = NULL;
550706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else {
551706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	bp = mbuf_Read(bp, fptr, bp->m_len);
552706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	PacketAliasSaveFragment(fptr);
553706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	log_Printf(LogDEBUG, "Store another frag (%lu) - now %d\n",
554706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		   (unsigned long)((struct ip *)fptr)->ip_id, ++gfrags);
555706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
556706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
557706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
558706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case PKT_ALIAS_FOUND_HEADER_FRAGMENT:
559706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      /* Fetch all the saved fragments and chain them on the end of `bp' */
560706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      last = &bp->m_nextpkt;
561706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      nfrags = 0;
562706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      while ((fptr = PacketAliasGetFragment(MBUF_CTOP(bp))) != NULL) {
563706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        nfrags++;
564706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        PacketAliasFragmentIn(MBUF_CTOP(bp), fptr);
565706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        len = ntohs(((struct ip *)fptr)->ip_len);
566706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        *last = m_get(len, MB_NATIN);
567706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        memcpy(MBUF_CTOP(*last), fptr, len);
568706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        free(fptr);
569706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        last = &(*last)->m_nextpkt;
570706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
571706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      gfrags -= nfrags;
572706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogDEBUG, "Found a frag header (%lu) - plus %d more frags (no"
573706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 "w %d)\n", (unsigned long)((struct ip *)MBUF_CTOP(bp))->ip_id,
574706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                 nfrags, gfrags);
575706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
576706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
577706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    case PKT_ALIAS_IGNORED:
578706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (PacketAliasSetMode(0, 0) & PKT_ALIAS_DENY_INCOMING) {
579706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogTCPIP, "NAT engine denied data:\n");
580706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        m_freem(bp);
581706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        bp = NULL;
582706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      } else if (log_IsKept(LogTCPIP)) {
583706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        log_Printf(LogTCPIP, "NAT engine ignored data:\n");
584706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        PacketCheck(bundle, AF_INET, MBUF_CTOP(bp), bp->m_len, NULL,
585706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh                    NULL, NULL);
586706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
587706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
588706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
589706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    default:
590706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      log_Printf(LogWARN, "nat_LayerPull: Dropped a packet (%d)....\n", ret);
591706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      m_freem(bp);
592706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      bp = NULL;
593706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
594706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
595706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
596706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return bp;
597706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
598706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
599706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstruct layer natlayer =
600706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  { LAYER_NAT, "nat", nat_LayerPush, nat_LayerPull };
601