nat_cmd.c revision 28679
1#include <limits.h>
2#include <netdb.h>
3#include <stdlib.h>
4#include <stdio.h>
5#include <string.h>
6
7#include <sys/types.h>
8#include <sys/socket.h>
9#include <netinet/in.h>
10#include <arpa/inet.h>
11
12#include "defs.h"
13#include "command.h"
14#include "loadalias.h"
15#include "vars.h"
16
17static int
18    StrToAddr(char *, struct in_addr * addr);
19
20static int
21    StrToPort(char *, u_short * port, char *proto);
22
23static int
24    StrToAddrAndPort(char *, struct in_addr * addr, u_short * port, char *proto);
25
26
27int
28AliasRedirectPort(struct cmdtab * list,
29		  int argc,
30		  char **argv,
31		  void *param)
32{
33  if (!(mode & MODE_ALIAS)) {
34    if (VarTerm)
35      fprintf(VarTerm, "Alias not enabled\n");
36  } else if (argc == 3) {
37    char proto_constant;
38    char *proto;
39    u_short local_port;
40    u_short alias_port;
41    int error;
42    struct in_addr local_addr;
43    struct in_addr null_addr;
44    struct alias_link *link;
45
46    proto = argv[0];
47    if (strcmp(proto, "tcp") == 0) {
48      proto_constant = IPPROTO_TCP;
49    } else if (strcmp(proto, "udp") == 0) {
50      proto_constant = IPPROTO_UDP;
51    } else {
52      if (VarTerm) {
53	fprintf(VarTerm, "port redirect: protocol must be tcp or udp\n");
54	fprintf(VarTerm, "Usage: alias %s %s\n", list->name,
55		list->syntax);
56      }
57      return 1;
58    }
59
60    error = StrToAddrAndPort(argv[1], &local_addr, &local_port, proto);
61    if (error) {
62      if (VarTerm) {
63	fprintf(VarTerm, "port redirect: error reading local addr:port\n");
64	fprintf(VarTerm, "Usage: alias %s %s\n", list->name, list->syntax);
65      }
66      return 1;
67    }
68    error = StrToPort(argv[2], &alias_port, proto);
69    if (error) {
70      if (VarTerm) {
71	fprintf(VarTerm, "port redirect: error reading alias port\n");
72	fprintf(VarTerm, "Usage: alias %s %s\n", list->name, list->syntax);
73      }
74      return 1;
75    }
76    null_addr.s_addr = 0;
77
78    link = VarPacketAliasRedirectPort(local_addr, local_port,
79				      null_addr, 0,
80				      null_addr, alias_port,
81				      proto_constant);
82
83    if (link == NULL && VarTerm)
84      fprintf(VarTerm, "port redirect: error returned by packed"
85	      " aliasing engine (code=%d)\n", error);
86  } else if (VarTerm)
87    fprintf(VarTerm, "Usage: alias %s %s\n", list->name, list->syntax);
88
89  return 1;
90}
91
92
93int
94AliasRedirectAddr(struct cmdtab * list,
95		  int argc,
96		  char **argv,
97		  void *param)
98{
99  if (!(mode & MODE_ALIAS)) {
100    if (VarTerm)
101      fprintf(VarTerm, "alias not enabled\n");
102  } else if (argc == 2) {
103    int error;
104    struct in_addr local_addr;
105    struct in_addr alias_addr;
106    struct alias_link *link;
107
108    error = StrToAddr(argv[0], &local_addr);
109    if (error) {
110      if (VarTerm)
111	fprintf(VarTerm, "address redirect: invalid local address\n");
112      return 1;
113    }
114    error = StrToAddr(argv[1], &alias_addr);
115    if (error) {
116      if (VarTerm) {
117	fprintf(VarTerm, "address redirect: invalid alias address\n");
118	fprintf(VarTerm, "Usage: alias %s %s\n", list->name, list->syntax);
119      }
120      return 1;
121    }
122    link = VarPacketAliasRedirectAddr(local_addr, alias_addr);
123    if (link == NULL && VarTerm) {
124      fprintf(VarTerm, "address redirect: packet aliasing engine error\n");
125      fprintf(VarTerm, "Usage: alias %s %s\n", list->name, list->syntax);
126    }
127  } else if (VarTerm)
128    fprintf(VarTerm, "Usage: alias %s %s\n", list->name, list->syntax);
129
130  return 1;
131}
132
133
134static int
135StrToAddr(char *str,
136	  struct in_addr * addr)
137{
138  struct hostent *hp;
139
140  if (inet_aton(str, addr))
141    return 0;
142
143  hp = gethostbyname(str);
144  if (!hp) {
145    LogPrintf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
146    return -1;
147  }
148  *addr = *((struct in_addr *) hp->h_addr);
149  return 0;
150}
151
152
153static int
154StrToPort(char *str,
155	  u_short * port,
156	  char *proto)
157{
158  int iport;
159  struct servent *sp;
160  char *end;
161
162  iport = strtol(str, &end, 10);
163  if (end != str) {
164    *port = htons(iport);
165    return 0;
166  }
167  sp = getservbyname(str, proto);
168  if (!sp) {
169    LogPrintf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
170	      str, proto);
171    return -1;
172  }
173  *port = sp->s_port;
174  return 0;
175}
176
177
178int
179StrToAddrAndPort(char *str,
180		 struct in_addr * addr,
181		 u_short * port,
182		 char *proto)
183{
184  char *ptr;
185
186  ptr = strchr(str, ':');
187  if (!ptr) {
188    LogPrintf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n",
189	      str);
190    return -1;
191  }
192  *ptr = '\0';
193  ++ptr;
194
195  if (StrToAddr(str, addr) != 0)
196    return -1;
197
198  return StrToPort(ptr, port, proto);
199}
200