2 * The code in this file was written by Eivind Eklund <perhaps@yes.no>,
3 * who places it in the public domain without restriction.
5 * $Id: alias_cmd.c,v 1.23 1999/04/26 08:54:32 brian Exp $
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
12 #include <netinet/in_systm.h>
13 #include <netinet/in.h>
14 #include <netinet/ip.h>
32 #include "alias_cmd.h"
33 #include "descriptor.h"
37 #include "slcompress.h"
38 #include "throughput.h"
55 static int StrToAddr(const char *, struct in_addr *);
56 static int StrToPortRange(const char *, u_short *, u_short *, const char *);
57 static int StrToAddrAndPort(const char *, struct in_addr *, u_short *,
58 u_short *, const char *);
62 alias_RedirectPort(struct cmdargs const *arg)
64 if (!arg->bundle->AliasEnabled) {
65 prompt_Printf(arg->prompt, "Alias not enabled\n");
67 } else if (arg->argc == arg->argn + 3) {
76 struct in_addr local_addr;
77 struct in_addr null_addr;
78 struct alias_link *link;
80 proto = arg->argv[arg->argn];
81 if (strcmp(proto, "tcp") == 0) {
82 proto_constant = IPPROTO_TCP;
83 } else if (strcmp(proto, "udp") == 0) {
84 proto_constant = IPPROTO_UDP;
86 prompt_Printf(arg->prompt, "port redirect: protocol must be"
91 error = StrToAddrAndPort(arg->argv[arg->argn+1], &local_addr, &llocalport,
94 prompt_Printf(arg->prompt, "alias port: error reading localaddr:port\n");
97 error = StrToPortRange(arg->argv[arg->argn+2], &laliasport, &haliasport,
100 prompt_Printf(arg->prompt, "alias port: error reading alias port\n");
103 null_addr.s_addr = INADDR_ANY;
105 if (llocalport > hlocalport) {
107 llocalport = hlocalport;
111 if (laliasport > haliasport) {
113 laliasport = haliasport;
117 if (haliasport - laliasport != hlocalport - llocalport) {
118 prompt_Printf(arg->prompt, "alias port: Port ranges must be equal\n");
122 for (port = laliasport; port <= haliasport; port++) {
123 link = PacketAliasRedirectPort(local_addr,
124 htons(llocalport + (port - laliasport)),
125 null_addr, 0, null_addr, htons(port),
129 prompt_Printf(arg->prompt, "alias port: %d: error %d\n", port, error);
141 alias_RedirectAddr(struct cmdargs const *arg)
143 if (!arg->bundle->AliasEnabled) {
144 prompt_Printf(arg->prompt, "alias not enabled\n");
146 } else if (arg->argc == arg->argn+2) {
148 struct in_addr local_addr;
149 struct in_addr alias_addr;
150 struct alias_link *link;
152 error = StrToAddr(arg->argv[arg->argn], &local_addr);
154 prompt_Printf(arg->prompt, "address redirect: invalid local address\n");
157 error = StrToAddr(arg->argv[arg->argn+1], &alias_addr);
159 prompt_Printf(arg->prompt, "address redirect: invalid alias address\n");
160 prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
164 link = PacketAliasRedirectAddr(local_addr, alias_addr);
166 prompt_Printf(arg->prompt, "address redirect: packet aliasing"
168 prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
179 StrToAddr(const char *str, struct in_addr *addr)
183 if (inet_aton(str, addr))
186 hp = gethostbyname(str);
188 log_Printf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
191 *addr = *((struct in_addr *) hp->h_addr);
197 StrToPort(const char *str, u_short *port, const char *proto)
202 *port = strtol(str, &end, 10);
204 sp = getservbyname(str, proto);
206 log_Printf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
210 *port = ntohs(sp->s_port);
217 StrToPortRange(const char *str, u_short *low, u_short *high, const char *proto)
222 minus = strchr(str, '-');
224 *minus = '\0'; /* Cheat the const-ness ! */
226 res = StrToPort(str, low, proto);
229 *minus = '-'; /* Cheat the const-ness ! */
233 res = StrToPort(minus + 1, high, proto);
242 StrToAddrAndPort(const char *str, struct in_addr *addr, u_short *low,
243 u_short *high, const char *proto)
248 colon = strchr(str, ':');
250 log_Printf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
254 *colon = '\0'; /* Cheat the const-ness ! */
255 res = StrToAddr(str, addr);
256 *colon = ':'; /* Cheat the const-ness ! */
260 return StrToPortRange(colon + 1, low, high, proto);
264 alias_ProxyRule(struct cmdargs const *arg)
270 if (arg->argn >= arg->argc)
273 for (f = arg->argn, pos = 0; f < arg->argc; f++) {
274 len = strlen(arg->argv[f]);
275 if (sizeof cmd - pos < len + (f ? 1 : 0))
279 strcpy(cmd + pos, arg->argv[f]);
283 return PacketAliasProxyRule(cmd);
287 alias_Pptp(struct cmdargs const *arg)
291 if (arg->argc == arg->argn) {
292 addr.s_addr = INADDR_NONE;
293 PacketAliasPptp(addr);
297 if (arg->argc != arg->argn + 1)
300 addr = GetIpAddr(arg->argv[arg->argn]);
301 if (addr.s_addr == INADDR_NONE) {
302 log_Printf(LogWARN, "%s: invalid address\n", arg->argv[arg->argn]);
306 PacketAliasPptp(addr);
311 alias_PadMbuf(struct mbuf *bp, int type)
316 for (last = &bp, len = 0; *last != NULL; last = &(*last)->next)
320 *last = mbuf_Alloc(len, type);
326 alias_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp,
327 int pri, u_short *proto)
329 if (!bundle->AliasEnabled || *proto != PROTO_IP)
332 bp = mbuf_Contiguous(alias_PadMbuf(bp, MB_IPQ));
333 PacketAliasOut(MBUF_CTOP(bp), bp->cnt);
334 bp->cnt = ntohs(((struct ip *)MBUF_CTOP(bp))->ip_len);
340 alias_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
343 struct ip *pip, *piip;
348 if (!bundle->AliasEnabled || *proto != PROTO_IP)
351 bp = mbuf_Contiguous(alias_PadMbuf(bp, MB_IPIN));
352 pip = (struct ip *)MBUF_CTOP(bp);
353 piip = (struct ip *)((char *)pip + (pip->ip_hl << 2));
355 if (pip->ip_p == IPPROTO_IGMP ||
356 (pip->ip_p == IPPROTO_IPIP && IN_CLASSD(ntohl(piip->ip_dst.s_addr))))
359 ret = PacketAliasIn(MBUF_CTOP(bp), bp->cnt);
361 bp->cnt = ntohs(pip->ip_len);
362 if (bp->cnt > MAX_MRU) {
363 log_Printf(LogWARN, "alias_LayerPull: Problem with IP header length\n");
372 case PKT_ALIAS_UNRESOLVED_FRAGMENT:
373 /* Save the data for later */
374 fptr = malloc(bp->cnt);
375 mbuf_Read(bp, fptr, bp->cnt);
376 PacketAliasSaveFragment(fptr);
379 case PKT_ALIAS_FOUND_HEADER_FRAGMENT:
380 /* Fetch all the saved fragments and chain them on the end of `bp' */
382 while ((fptr = PacketAliasGetFragment(MBUF_CTOP(bp))) != NULL) {
383 PacketAliasFragmentIn(MBUF_CTOP(bp), fptr);
384 *last = mbuf_Alloc(ntohs(((struct ip *)fptr)->ip_len), MB_IPIN);
385 memcpy(MBUF_CTOP(*last), fptr, (*last)->cnt);
387 last = &(*last)->pnext;
400 struct layer aliaslayer =
401 { LAYER_ALIAS, "alias", alias_LayerPush, alias_LayerPull };