nat_cmd.c revision 46086
1/*-
2 * The code in this file was written by Eivind Eklund <perhaps@yes.no>,
3 * who places it in the public domain without restriction.
4 *
5 *	$Id: alias_cmd.c,v 1.22 1999/03/25 23:36:23 brian Exp $
6 */
7
8#include <sys/param.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11#include <netdb.h>
12#include <netinet/in_systm.h>
13#include <netinet/in.h>
14#include <netinet/ip.h>
15#include <sys/un.h>
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <termios.h>
21
22#ifdef __FreeBSD__
23#include <alias.h>
24#else
25#include "alias.h"
26#endif
27#include "defs.h"
28#include "command.h"
29#include "log.h"
30#include "alias_cmd.h"
31#include "descriptor.h"
32#include "prompt.h"
33#include "timer.h"
34#include "fsm.h"
35#include "slcompress.h"
36#include "throughput.h"
37#include "iplist.h"
38#include "mbuf.h"
39#include "lqr.h"
40#include "hdlc.h"
41#include "ipcp.h"
42#include "lcp.h"
43#include "ccp.h"
44#include "link.h"
45#include "mp.h"
46#include "filter.h"
47#ifndef NORADIUS
48#include "radius.h"
49#endif
50#include "bundle.h"
51
52
53static int StrToAddr(const char *, struct in_addr *);
54static int StrToPortRange(const char *, u_short *, u_short *, const char *);
55static int StrToAddrAndPort(const char *, struct in_addr *, u_short *,
56                            u_short *, const char *);
57
58
59int
60alias_RedirectPort(struct cmdargs const *arg)
61{
62  if (!arg->bundle->AliasEnabled) {
63    prompt_Printf(arg->prompt, "Alias not enabled\n");
64    return 1;
65  } else if (arg->argc == arg->argn + 3) {
66    char proto_constant;
67    const char *proto;
68    u_short hlocalport;
69    u_short llocalport;
70    u_short haliasport;
71    u_short laliasport;
72    u_short port;
73    int error;
74    struct in_addr local_addr;
75    struct in_addr null_addr;
76    struct alias_link *link;
77
78    proto = arg->argv[arg->argn];
79    if (strcmp(proto, "tcp") == 0) {
80      proto_constant = IPPROTO_TCP;
81    } else if (strcmp(proto, "udp") == 0) {
82      proto_constant = IPPROTO_UDP;
83    } else {
84      prompt_Printf(arg->prompt, "port redirect: protocol must be"
85                    " tcp or udp\n");
86      return -1;
87    }
88
89    error = StrToAddrAndPort(arg->argv[arg->argn+1], &local_addr, &llocalport,
90                             &hlocalport, proto);
91    if (error) {
92      prompt_Printf(arg->prompt, "alias port: error reading localaddr:port\n");
93      return -1;
94    }
95    error = StrToPortRange(arg->argv[arg->argn+2], &laliasport, &haliasport,
96                           proto);
97    if (error) {
98      prompt_Printf(arg->prompt, "alias port: error reading alias port\n");
99      return -1;
100    }
101    null_addr.s_addr = INADDR_ANY;
102
103    if (llocalport > hlocalport) {
104      port = llocalport;
105      llocalport = hlocalport;
106      hlocalport = port;
107    }
108
109    if (laliasport > haliasport) {
110      port = laliasport;
111      laliasport = haliasport;
112      haliasport = port;
113    }
114
115    if (haliasport - laliasport != hlocalport - llocalport) {
116      prompt_Printf(arg->prompt, "alias port: Port ranges must be equal\n");
117      return -1;
118    }
119
120    for (port = laliasport; port <= haliasport; port++) {
121      link = PacketAliasRedirectPort(local_addr,
122                                     htons(llocalport + (port - laliasport)),
123				     null_addr, 0, null_addr, htons(port),
124				     proto_constant);
125
126      if (link == NULL) {
127        prompt_Printf(arg->prompt, "alias port: %d: error %d\n", port, error);
128        return 1;
129      }
130    }
131  } else
132    return -1;
133
134  return 0;
135}
136
137
138int
139alias_RedirectAddr(struct cmdargs const *arg)
140{
141  if (!arg->bundle->AliasEnabled) {
142    prompt_Printf(arg->prompt, "alias not enabled\n");
143    return 1;
144  } else if (arg->argc == arg->argn+2) {
145    int error;
146    struct in_addr local_addr;
147    struct in_addr alias_addr;
148    struct alias_link *link;
149
150    error = StrToAddr(arg->argv[arg->argn], &local_addr);
151    if (error) {
152      prompt_Printf(arg->prompt, "address redirect: invalid local address\n");
153      return 1;
154    }
155    error = StrToAddr(arg->argv[arg->argn+1], &alias_addr);
156    if (error) {
157      prompt_Printf(arg->prompt, "address redirect: invalid alias address\n");
158      prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
159                    arg->cmd->syntax);
160      return 1;
161    }
162    link = PacketAliasRedirectAddr(local_addr, alias_addr);
163    if (link == NULL) {
164      prompt_Printf(arg->prompt, "address redirect: packet aliasing"
165                    " engine error\n");
166      prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
167                    arg->cmd->syntax);
168    }
169  } else
170    return -1;
171
172  return 0;
173}
174
175
176static int
177StrToAddr(const char *str, struct in_addr *addr)
178{
179  struct hostent *hp;
180
181  if (inet_aton(str, addr))
182    return 0;
183
184  hp = gethostbyname(str);
185  if (!hp) {
186    log_Printf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
187    return -1;
188  }
189  *addr = *((struct in_addr *) hp->h_addr);
190  return 0;
191}
192
193
194static int
195StrToPort(const char *str, u_short *port, const char *proto)
196{
197  struct servent *sp;
198  char *end;
199
200  *port = strtol(str, &end, 10);
201  if (*end != '\0') {
202    sp = getservbyname(str, proto);
203    if (sp == NULL) {
204      log_Printf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
205	        str, proto);
206      return -1;
207    }
208    *port = ntohs(sp->s_port);
209  }
210
211  return 0;
212}
213
214static int
215StrToPortRange(const char *str, u_short *low, u_short *high, const char *proto)
216{
217  char *minus;
218  int res;
219
220  minus = strchr(str, '-');
221  if (minus)
222    *minus = '\0';		/* Cheat the const-ness ! */
223
224  res = StrToPort(str, low, proto);
225
226  if (minus)
227    *minus = '-';		/* Cheat the const-ness ! */
228
229  if (res == 0) {
230    if (minus)
231      res = StrToPort(minus + 1, high, proto);
232    else
233      *high = *low;
234  }
235
236  return res;
237}
238
239static int
240StrToAddrAndPort(const char *str, struct in_addr *addr, u_short *low,
241                 u_short *high, const char *proto)
242{
243  char *colon;
244  int res;
245
246  colon = strchr(str, ':');
247  if (!colon) {
248    log_Printf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
249    return -1;
250  }
251
252  *colon = '\0';		/* Cheat the const-ness ! */
253  res = StrToAddr(str, addr);
254  *colon = ':';			/* Cheat the const-ness ! */
255  if (res != 0)
256    return -1;
257
258  return StrToPortRange(colon + 1, low, high, proto);
259}
260
261int
262alias_ProxyRule(struct cmdargs const *arg)
263{
264  char cmd[LINE_LEN];
265  int f, pos;
266  size_t len;
267
268  if (arg->argn >= arg->argc)
269    return -1;
270
271  for (f = arg->argn, pos = 0; f < arg->argc; f++) {
272    len = strlen(arg->argv[f]);
273    if (sizeof cmd - pos < len + (f ? 1 : 0))
274      break;
275    if (f)
276      cmd[pos++] = ' ';
277    strcpy(cmd + pos, arg->argv[f]);
278    pos += len;
279  }
280
281  return PacketAliasProxyRule(cmd);
282}
283
284int
285alias_Pptp(struct cmdargs const *arg)
286{
287  struct in_addr addr;
288
289  if (arg->argc == arg->argn) {
290    addr.s_addr = INADDR_NONE;
291    PacketAliasPptp(addr);
292    return 0;
293  }
294
295  if (arg->argc != arg->argn + 1)
296    return -1;
297
298  addr = GetIpAddr(arg->argv[arg->argn]);
299  if (addr.s_addr == INADDR_NONE) {
300    log_Printf(LogWARN, "%s: invalid address\n", arg->argv[arg->argn]);
301    return 1;
302  }
303
304  PacketAliasPptp(addr);
305  return 0;
306}
307