]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/ppp/alias_cmd.c
o Redesign the layering mechanism and make the aliasing code part of
[FreeBSD/FreeBSD.git] / usr.sbin / ppp / alias_cmd.c
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.23 1999/04/26 08:54:32 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 "layer.h"
28 #include "proto.h"
29 #include "defs.h"
30 #include "command.h"
31 #include "log.h"
32 #include "alias_cmd.h"
33 #include "descriptor.h"
34 #include "prompt.h"
35 #include "timer.h"
36 #include "fsm.h"
37 #include "slcompress.h"
38 #include "throughput.h"
39 #include "iplist.h"
40 #include "mbuf.h"
41 #include "lqr.h"
42 #include "hdlc.h"
43 #include "ipcp.h"
44 #include "lcp.h"
45 #include "ccp.h"
46 #include "link.h"
47 #include "mp.h"
48 #include "filter.h"
49 #ifndef NORADIUS
50 #include "radius.h"
51 #endif
52 #include "bundle.h"
53
54
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 *);
59
60
61 int
62 alias_RedirectPort(struct cmdargs const *arg)
63 {
64   if (!arg->bundle->AliasEnabled) {
65     prompt_Printf(arg->prompt, "Alias not enabled\n");
66     return 1;
67   } else if (arg->argc == arg->argn + 3) {
68     char proto_constant;
69     const char *proto;
70     u_short hlocalport;
71     u_short llocalport;
72     u_short haliasport;
73     u_short laliasport;
74     u_short port;
75     int error;
76     struct in_addr local_addr;
77     struct in_addr null_addr;
78     struct alias_link *link;
79
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;
85     } else {
86       prompt_Printf(arg->prompt, "port redirect: protocol must be"
87                     " tcp or udp\n");
88       return -1;
89     }
90
91     error = StrToAddrAndPort(arg->argv[arg->argn+1], &local_addr, &llocalport,
92                              &hlocalport, proto);
93     if (error) {
94       prompt_Printf(arg->prompt, "alias port: error reading localaddr:port\n");
95       return -1;
96     }
97     error = StrToPortRange(arg->argv[arg->argn+2], &laliasport, &haliasport,
98                            proto);
99     if (error) {
100       prompt_Printf(arg->prompt, "alias port: error reading alias port\n");
101       return -1;
102     }
103     null_addr.s_addr = INADDR_ANY;
104
105     if (llocalport > hlocalport) {
106       port = llocalport;
107       llocalport = hlocalport;
108       hlocalport = port;
109     }
110
111     if (laliasport > haliasport) {
112       port = laliasport;
113       laliasport = haliasport;
114       haliasport = port;
115     }
116
117     if (haliasport - laliasport != hlocalport - llocalport) {
118       prompt_Printf(arg->prompt, "alias port: Port ranges must be equal\n");
119       return -1;
120     }
121
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),
126                                      proto_constant);
127
128       if (link == NULL) {
129         prompt_Printf(arg->prompt, "alias port: %d: error %d\n", port, error);
130         return 1;
131       }
132     }
133   } else
134     return -1;
135
136   return 0;
137 }
138
139
140 int
141 alias_RedirectAddr(struct cmdargs const *arg)
142 {
143   if (!arg->bundle->AliasEnabled) {
144     prompt_Printf(arg->prompt, "alias not enabled\n");
145     return 1;
146   } else if (arg->argc == arg->argn+2) {
147     int error;
148     struct in_addr local_addr;
149     struct in_addr alias_addr;
150     struct alias_link *link;
151
152     error = StrToAddr(arg->argv[arg->argn], &local_addr);
153     if (error) {
154       prompt_Printf(arg->prompt, "address redirect: invalid local address\n");
155       return 1;
156     }
157     error = StrToAddr(arg->argv[arg->argn+1], &alias_addr);
158     if (error) {
159       prompt_Printf(arg->prompt, "address redirect: invalid alias address\n");
160       prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
161                     arg->cmd->syntax);
162       return 1;
163     }
164     link = PacketAliasRedirectAddr(local_addr, alias_addr);
165     if (link == NULL) {
166       prompt_Printf(arg->prompt, "address redirect: packet aliasing"
167                     " engine error\n");
168       prompt_Printf(arg->prompt, "Usage: alias %s %s\n", arg->cmd->name,
169                     arg->cmd->syntax);
170     }
171   } else
172     return -1;
173
174   return 0;
175 }
176
177
178 static int
179 StrToAddr(const char *str, struct in_addr *addr)
180 {
181   struct hostent *hp;
182
183   if (inet_aton(str, addr))
184     return 0;
185
186   hp = gethostbyname(str);
187   if (!hp) {
188     log_Printf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
189     return -1;
190   }
191   *addr = *((struct in_addr *) hp->h_addr);
192   return 0;
193 }
194
195
196 static int
197 StrToPort(const char *str, u_short *port, const char *proto)
198 {
199   struct servent *sp;
200   char *end;
201
202   *port = strtol(str, &end, 10);
203   if (*end != '\0') {
204     sp = getservbyname(str, proto);
205     if (sp == NULL) {
206       log_Printf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
207                 str, proto);
208       return -1;
209     }
210     *port = ntohs(sp->s_port);
211   }
212
213   return 0;
214 }
215
216 static int
217 StrToPortRange(const char *str, u_short *low, u_short *high, const char *proto)
218 {
219   char *minus;
220   int res;
221
222   minus = strchr(str, '-');
223   if (minus)
224     *minus = '\0';              /* Cheat the const-ness ! */
225
226   res = StrToPort(str, low, proto);
227
228   if (minus)
229     *minus = '-';               /* Cheat the const-ness ! */
230
231   if (res == 0) {
232     if (minus)
233       res = StrToPort(minus + 1, high, proto);
234     else
235       *high = *low;
236   }
237
238   return res;
239 }
240
241 static int
242 StrToAddrAndPort(const char *str, struct in_addr *addr, u_short *low,
243                  u_short *high, const char *proto)
244 {
245   char *colon;
246   int res;
247
248   colon = strchr(str, ':');
249   if (!colon) {
250     log_Printf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
251     return -1;
252   }
253
254   *colon = '\0';                /* Cheat the const-ness ! */
255   res = StrToAddr(str, addr);
256   *colon = ':';                 /* Cheat the const-ness ! */
257   if (res != 0)
258     return -1;
259
260   return StrToPortRange(colon + 1, low, high, proto);
261 }
262
263 int
264 alias_ProxyRule(struct cmdargs const *arg)
265 {
266   char cmd[LINE_LEN];
267   int f, pos;
268   size_t len;
269
270   if (arg->argn >= arg->argc)
271     return -1;
272
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))
276       break;
277     if (f)
278       cmd[pos++] = ' ';
279     strcpy(cmd + pos, arg->argv[f]);
280     pos += len;
281   }
282
283   return PacketAliasProxyRule(cmd);
284 }
285
286 int
287 alias_Pptp(struct cmdargs const *arg)
288 {
289   struct in_addr addr;
290
291   if (arg->argc == arg->argn) {
292     addr.s_addr = INADDR_NONE;
293     PacketAliasPptp(addr);
294     return 0;
295   }
296
297   if (arg->argc != arg->argn + 1)
298     return -1;
299
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]);
303     return 1;
304   }
305
306   PacketAliasPptp(addr);
307   return 0;
308 }
309
310 static struct mbuf *
311 alias_PadMbuf(struct mbuf *bp, int type)
312 {
313   struct mbuf **last;
314   int len;
315
316   for (last = &bp, len = 0; *last != NULL; last = &(*last)->next)
317     len += (*last)->cnt;
318
319   len = MAX_MRU - len;
320   *last = mbuf_Alloc(len, type);
321
322   return bp;
323 }
324
325 static struct mbuf *
326 alias_LayerPush(struct bundle *bundle, struct link *l, struct mbuf *bp,
327                 int pri, u_short *proto)
328 {
329   if (!bundle->AliasEnabled || *proto != PROTO_IP)
330     return bp;
331   
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);
335
336   return bp;
337 }
338
339 static struct mbuf *
340 alias_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
341                 u_short *proto)
342 {
343   struct ip *pip, *piip;
344   int ret;
345   struct mbuf **last;
346   char *fptr;
347
348   if (!bundle->AliasEnabled || *proto != PROTO_IP)
349     return bp;
350
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));
354
355   if (pip->ip_p == IPPROTO_IGMP ||
356       (pip->ip_p == IPPROTO_IPIP && IN_CLASSD(ntohl(piip->ip_dst.s_addr))))
357     return bp;
358
359   ret = PacketAliasIn(MBUF_CTOP(bp), bp->cnt);
360
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");
364     mbuf_Free(bp);
365     return NULL;
366   }
367
368   switch (ret) {
369     case PKT_ALIAS_OK:
370       break;
371
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);
377       break;
378
379     case PKT_ALIAS_FOUND_HEADER_FRAGMENT:
380       /* Fetch all the saved fragments and chain them on the end of `bp' */
381       last = &bp->pnext;
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);
386         free(fptr);
387         last = &(*last)->pnext;
388       }
389       break;
390
391     default:
392       mbuf_Free(bp);
393       bp = NULL;
394       break;
395   }
396
397   return bp;
398 }
399
400 struct layer aliaslayer =
401   { LAYER_ALIAS, "alias", alias_LayerPush, alias_LayerPull };