1142293Sglebius/*-
2142293Sglebius * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3142293Sglebius *                    Brian Somers <brian@Awfulhak.org>
4228571Sglebius * All rights reserved.
5142293Sglebius *
6142293Sglebius * Redistribution and use in source and binary forms, with or without
7142293Sglebius * modification, are permitted provided that the following conditions
8142293Sglebius * are met:
9142293Sglebius * 1. Redistributions of source code must retain the above copyright
10142293Sglebius *    notice, this list of conditions and the following disclaimer.
11142293Sglebius * 2. Redistributions in binary form must reproduce the above copyright
12142293Sglebius *    notice, this list of conditions and the following disclaimer in the
13142293Sglebius *    documentation and/or other materials provided with the distribution.
14142293Sglebius *
15142293Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16142293Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17142293Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18142293Sglebius * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19142293Sglebius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20142293Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21142293Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22142293Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23142293Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24142293Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25142293Sglebius * SUCH DAMAGE.
26142293Sglebius *
27142372Sglebius * $FreeBSD$
28142293Sglebius */
29247102Spluknet
30142293Sglebius#include <sys/param.h>
31142293Sglebius#include <netinet/in.h>
32142293Sglebius#include <arpa/inet.h>
33142293Sglebius#include <netdb.h>
34142293Sglebius#include <netinet/in_systm.h>
35142293Sglebius#include <netinet/ip.h>
36142293Sglebius#include <sys/socket.h>
37142293Sglebius#include <sys/un.h>
38228571Sglebius
39228571Sglebius#include <stdarg.h>
40142293Sglebius#include <stdio.h>
41228571Sglebius#include <stdlib.h>
42142293Sglebius#include <string.h>
43142293Sglebius#include <termios.h>
44142293Sglebius
45234953Sbjk#ifdef LOCALNAT
46234953Sbjk#include "alias.h"
47228571Sglebius#else
48228571Sglebius#include <alias.h>
49142293Sglebius#endif
50142293Sglebius
51142293Sglebius#include "layer.h"
52142293Sglebius#include "proto.h"
53142293Sglebius#include "defs.h"
54142293Sglebius#include "command.h"
55142372Sglebius#include "log.h"
56142372Sglebius#include "nat_cmd.h"
57142372Sglebius#include "descriptor.h"
58144743Sglebius#include "prompt.h"
59144743Sglebius#include "timer.h"
60144743Sglebius#include "fsm.h"
61147432Sru#include "slcompress.h"
62149207Skeramida#include "throughput.h"
63144743Sglebius#include "iplist.h"
64144743Sglebius#include "mbuf.h"
65144743Sglebius#include "lqr.h"
66147432Sru#include "hdlc.h"
67144743Sglebius#include "ncpaddr.h"
68144743Sglebius#include "ip.h"
69144743Sglebius#include "ipcp.h"
70144743Sglebius#include "ipv6cp.h"
71144743Sglebius#include "lcp.h"
72144743Sglebius#include "ccp.h"
73144743Sglebius#include "link.h"
74147432Sru#include "mp.h"
75234953Sbjk#include "filter.h"
76142293Sglebius#ifndef NORADIUS
77142293Sglebius#include "radius.h"
78142293Sglebius#endif
79142372Sglebius#include "ncp.h"
80142293Sglebius#include "bundle.h"
81234953Sbjk
82228571Sglebius
83228571Sglebius#define NAT_EXTRABUF (13)
84228571Sglebius
85228571Sglebiusstatic int StrToAddr(const char *, struct in_addr *);
86228571Sglebiusstatic int StrToPortRange(const char *, u_short *, u_short *, const char *);
87228571Sglebiusstatic int StrToAddrAndPort(const char *, struct in_addr *, u_short *,
88228571Sglebius                            u_short *, const char *);
89228571Sglebius
90228571Sglebiusextern struct libalias *la;
91228571Sglebius
92142293Sglebiusstatic void
93142293Sglebiuslowhigh(u_short *a, u_short *b)
94234953Sbjk{
95142372Sglebius  if (a > b) {
96142293Sglebius    u_short c;
97142293Sglebius
98142293Sglebius    c = *b;
99142293Sglebius    *b = *a;
100142372Sglebius    *a = c;
101142293Sglebius  }
102230594Sglebius}
103230594Sglebius
104142293Sglebiusint
105142372Sglebiusnat_RedirectPort(struct cmdargs const *arg)
106234953Sbjk{
107142293Sglebius  if (!arg->bundle->NatEnabled) {
108236294Sbjk    prompt_Printf(arg->prompt, "Alias not enabled\n");
109234953Sbjk    return 1;
110234953Sbjk  } else if (arg->argc == arg->argn + 3 || arg->argc == arg->argn + 4) {
111234953Sbjk    char proto_constant;
112230594Sglebius    const char *proto;
113201801Sru    struct in_addr localaddr;
114201801Sru    u_short hlocalport, llocalport;
115142293Sglebius    struct in_addr aliasaddr;
116234953Sbjk    u_short haliasport, laliasport;
117228736Sglebius    struct in_addr remoteaddr;
118228736Sglebius    u_short hremoteport, lremoteport;
119228736Sglebius    struct alias_link *link;
120228736Sglebius    int error;
121228736Sglebius
122228736Sglebius    proto = arg->argv[arg->argn];
123228736Sglebius    if (strcmp(proto, "tcp") == 0) {
124228736Sglebius      proto_constant = IPPROTO_TCP;
125228736Sglebius    } else if (strcmp(proto, "udp") == 0) {
126146227Sglebius      proto_constant = IPPROTO_UDP;
127146227Sglebius    } else {
128244681Sglebius      prompt_Printf(arg->prompt, "port redirect: protocol must be"
129244681Sglebius                    " tcp or udp\n");
130244681Sglebius      return -1;
131244681Sglebius    }
132244681Sglebius
133228736Sglebius    error = StrToAddrAndPort(arg->argv[arg->argn+1], &localaddr, &llocalport,
134244681Sglebius                             &hlocalport, proto);
135244681Sglebius    if (error) {
136228736Sglebius      prompt_Printf(arg->prompt, "nat port: error reading localaddr:port\n");
137234953Sbjk      return -1;
138228736Sglebius    }
139234953Sbjk
140234953Sbjk    error = StrToPortRange(arg->argv[arg->argn+2], &laliasport, &haliasport,
141228736Sglebius                           proto);
142234953Sbjk    if (error) {
143228736Sglebius      prompt_Printf(arg->prompt, "nat port: error reading alias port\n");
144228736Sglebius      return -1;
145228736Sglebius    }
146228736Sglebius    aliasaddr.s_addr = INADDR_ANY;
147234953Sbjk
148142293Sglebius    if (arg->argc == arg->argn + 4) {
149228571Sglebius      error = StrToAddrAndPort(arg->argv[arg->argn+3], &remoteaddr,
150234953Sbjk                               &lremoteport, &hremoteport, proto);
151228571Sglebius      if (error) {
152234953Sbjk        prompt_Printf(arg->prompt, "nat port: error reading "
153234953Sbjk                      "remoteaddr:port\n");
154234953Sbjk        return -1;
155228571Sglebius      }
156228571Sglebius    } else {
157228571Sglebius      remoteaddr.s_addr = INADDR_ANY;
158234953Sbjk      lremoteport = hremoteport = 0;
159234953Sbjk    }
160234953Sbjk
161234953Sbjk    lowhigh(&llocalport, &hlocalport);
162234953Sbjk    lowhigh(&laliasport, &haliasport);
163228571Sglebius    lowhigh(&lremoteport, &hremoteport);
164228571Sglebius
165228571Sglebius    if (haliasport - laliasport != hlocalport - llocalport) {
166228571Sglebius      prompt_Printf(arg->prompt, "nat port: local & alias port ranges "
167234953Sbjk                    "are not equal\n");
168234953Sbjk      return -1;
169234953Sbjk    }
170228571Sglebius
171228571Sglebius    if (hremoteport && hremoteport - lremoteport != hlocalport - llocalport) {
172228571Sglebius      prompt_Printf(arg->prompt, "nat port: local & remote port ranges "
173228571Sglebius                    "are not equal\n");
174228571Sglebius      return -1;
175228571Sglebius    }
176228571Sglebius
177228571Sglebius    do {
178228571Sglebius      link = LibAliasRedirectPort(la, localaddr, htons(llocalport),
179234953Sbjk				     remoteaddr, htons(lremoteport),
180228571Sglebius                                     aliasaddr, htons(laliasport),
181228571Sglebius				     proto_constant);
182234953Sbjk
183234953Sbjk      if (link == NULL) {
184224879Sglebius        prompt_Printf(arg->prompt, "nat port: %d: error %d\n", laliasport,
185224879Sglebius                      error);
186224879Sglebius        return 1;
187224879Sglebius      }
188224879Sglebius      llocalport++;
189224879Sglebius      if (hremoteport)
190224879Sglebius        lremoteport++;
191228571Sglebius    } while (laliasport++ < haliasport);
192228571Sglebius
193234953Sbjk    return 0;
194234953Sbjk  }
195234953Sbjk
196224879Sglebius  return -1;
197224879Sglebius}
198234953Sbjk
199224879Sglebius
200224879Sglebiusint
201142293Sglebiusnat_RedirectAddr(struct cmdargs const *arg)
202142293Sglebius{
203230594Sglebius  if (!arg->bundle->NatEnabled) {
204142293Sglebius    prompt_Printf(arg->prompt, "nat not enabled\n");
205230594Sglebius    return 1;
206234953Sbjk  } else if (arg->argc == arg->argn+2) {
207234953Sbjk    int error;
208142293Sglebius    struct in_addr localaddr, aliasaddr;
209142372Sglebius    struct alias_link *link;
210142293Sglebius
211228571Sglebius    error = StrToAddr(arg->argv[arg->argn], &localaddr);
212228571Sglebius    if (error) {
213266859Smarck      prompt_Printf(arg->prompt, "address redirect: invalid local address\n");
214266859Smarck      return 1;
215142293Sglebius    }
216266859Smarck    error = StrToAddr(arg->argv[arg->argn+1], &aliasaddr);
217266859Smarck    if (error) {
218142293Sglebius      prompt_Printf(arg->prompt, "address redirect: invalid alias address\n");
219142293Sglebius      prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
220142372Sglebius                    arg->cmd->syntax);
221142372Sglebius      return 1;
222142293Sglebius    }
223266859Smarck    link = LibAliasRedirectAddr(la, localaddr, aliasaddr);
224266859Smarck    if (link == NULL) {
225142293Sglebius      prompt_Printf(arg->prompt, "address redirect: packet aliasing"
226142293Sglebius                    " engine error\n");
227230594Sglebius      prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
228142372Sglebius                    arg->cmd->syntax);
229230594Sglebius    }
230142293Sglebius  } else
231230594Sglebius    return -1;
232230594Sglebius
233230594Sglebius  return 0;
234228571Sglebius}
235228571Sglebius
236228571Sglebius
237228571Sglebiusint
238228571Sglebiusnat_RedirectProto(struct cmdargs const *arg)
239228571Sglebius{
240228571Sglebius  if (!arg->bundle->NatEnabled) {
241228571Sglebius    prompt_Printf(arg->prompt, "nat not enabled\n");
242228571Sglebius    return 1;
243228571Sglebius  } else if (arg->argc >= arg->argn + 2 && arg->argc <= arg->argn + 4) {
244228571Sglebius    struct in_addr localIP, publicIP, remoteIP;
245228571Sglebius    struct alias_link *link;
246228571Sglebius    struct protoent *pe;
247228571Sglebius    int error;
248228571Sglebius    unsigned len;
249228571Sglebius
250266859Smarck    len = strlen(arg->argv[arg->argn]);
251228571Sglebius    if (len == 0) {
252266859Smarck      prompt_Printf(arg->prompt, "proto redirect: invalid protocol\n");
253228571Sglebius      return 1;
254228571Sglebius    }
255228571Sglebius    if (strspn(arg->argv[arg->argn], "01234567") == len)
256228571Sglebius      pe = getprotobynumber(atoi(arg->argv[arg->argn]));
257228571Sglebius    else
258228571Sglebius      pe = getprotobyname(arg->argv[arg->argn]);
259228571Sglebius    if (pe == NULL) {
260266859Smarck      prompt_Printf(arg->prompt, "proto redirect: invalid protocol\n");
261228571Sglebius      return 1;
262266859Smarck    }
263228571Sglebius
264228571Sglebius    error = StrToAddr(arg->argv[arg->argn + 1], &localIP);
265228571Sglebius    if (error) {
266228571Sglebius      prompt_Printf(arg->prompt, "proto redirect: invalid src address\n");
267228571Sglebius      return 1;
268228571Sglebius    }
269228571Sglebius
270228571Sglebius    if (arg->argc >= arg->argn + 3) {
271228571Sglebius      error = StrToAddr(arg->argv[arg->argn + 2], &publicIP);
272228571Sglebius      if (error) {
273228571Sglebius        prompt_Printf(arg->prompt, "proto redirect: invalid alias address\n");
274228571Sglebius        prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
275228571Sglebius                      arg->cmd->syntax);
276228571Sglebius        return 1;
277228571Sglebius      }
278142293Sglebius    } else
279224879Sglebius      publicIP.s_addr = INADDR_ANY;
280224879Sglebius
281228571Sglebius    if (arg->argc == arg->argn + 4) {
282224879Sglebius      error = StrToAddr(arg->argv[arg->argn + 2], &remoteIP);
283224879Sglebius      if (error) {
284228571Sglebius        prompt_Printf(arg->prompt, "proto redirect: invalid dst address\n");
285247102Spluknet        prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
286228571Sglebius                      arg->cmd->syntax);
287228571Sglebius        return 1;
288224879Sglebius      }
289224879Sglebius    } else
290241045Sglebius      remoteIP.s_addr = INADDR_ANY;
291241045Sglebius
292241045Sglebius    link = LibAliasRedirectProto(la, localIP, remoteIP, publicIP, pe->p_proto);
293241045Sglebius    if (link == NULL) {
294296198Strasz      prompt_Printf(arg->prompt, "proto redirect: packet aliasing"
295241045Sglebius                    " engine error\n");
296241045Sglebius      prompt_Printf(arg->prompt, "usage: nat %s %s\n", arg->cmd->name,
297241045Sglebius                    arg->cmd->syntax);
298296198Strasz    }
299241045Sglebius  } else
300241045Sglebius    return -1;
301241045Sglebius
302241045Sglebius  return 0;
303142293Sglebius}
304296198Strasz
305142293Sglebius
306146227Sglebiusstatic int
307276259SbaptStrToAddr(const char *str, struct in_addr *addr)
308142293Sglebius{
309147432Sru  struct hostent *hp;
310296198Strasz
311142293Sglebius  if (inet_aton(str, addr))
312142293Sglebius    return 0;
313142293Sglebius
314142293Sglebius  hp = gethostbyname(str);
315142293Sglebius  if (!hp) {
316142293Sglebius    log_Printf(LogWARN, "StrToAddr: Unknown host %s.\n", str);
317142293Sglebius    return -1;
318142372Sglebius  }
319142293Sglebius  *addr = *((struct in_addr *) hp->h_addr);
320228571Sglebius  return 0;
321234953Sbjk}
322228571Sglebius
323228571Sglebius
324static int
325StrToPort(const char *str, u_short *port, const char *proto)
326{
327  struct servent *sp;
328  char *end;
329
330  *port = strtol(str, &end, 10);
331  if (*end != '\0') {
332    sp = getservbyname(str, proto);
333    if (sp == NULL) {
334      log_Printf(LogWARN, "StrToAddr: Unknown port or service %s/%s.\n",
335	        str, proto);
336      return -1;
337    }
338    *port = ntohs(sp->s_port);
339  }
340
341  return 0;
342}
343
344static int
345StrToPortRange(const char *str, u_short *low, u_short *high, const char *proto)
346{
347  char *minus;
348  int res;
349
350  minus = strchr(str, '-');
351  if (minus)
352    *minus = '\0';		/* Cheat the const-ness ! */
353
354  res = StrToPort(str, low, proto);
355
356  if (minus)
357    *minus = '-';		/* Cheat the const-ness ! */
358
359  if (res == 0) {
360    if (minus)
361      res = StrToPort(minus + 1, high, proto);
362    else
363      *high = *low;
364  }
365
366  return res;
367}
368
369static int
370StrToAddrAndPort(const char *str, struct in_addr *addr, u_short *low,
371                 u_short *high, const char *proto)
372{
373  char *colon;
374  int res;
375
376  colon = strchr(str, ':');
377  if (!colon) {
378    log_Printf(LogWARN, "StrToAddrAndPort: %s is missing port number.\n", str);
379    return -1;
380  }
381
382  *colon = '\0';		/* Cheat the const-ness ! */
383  res = StrToAddr(str, addr);
384  *colon = ':';			/* Cheat the const-ness ! */
385  if (res != 0)
386    return -1;
387
388  return StrToPortRange(colon + 1, low, high, proto);
389}
390
391int
392nat_ProxyRule(struct cmdargs const *arg)
393{
394  char cmd[LINE_LEN];
395  int f, pos;
396  size_t len;
397
398  if (arg->argn >= arg->argc)
399    return -1;
400
401  for (f = arg->argn, pos = 0; f < arg->argc; f++) {
402    len = strlen(arg->argv[f]);
403    if (sizeof cmd - pos < len + (len ? 1 : 0))
404      break;
405    if (len)
406      cmd[pos++] = ' ';
407    strcpy(cmd + pos, arg->argv[f]);
408    pos += len;
409  }
410
411  return LibAliasProxyRule(la, cmd);
412}
413
414int
415nat_SetTarget(struct cmdargs const *arg)
416{
417  struct in_addr addr;
418
419  if (arg->argc == arg->argn) {
420    addr.s_addr = INADDR_ANY;
421    LibAliasSetTarget(la, addr);
422    return 0;
423  }
424
425  if (arg->argc != arg->argn + 1)
426    return -1;
427
428  if (!strcasecmp(arg->argv[arg->argn], "MYADDR")) {
429    addr.s_addr = INADDR_ANY;
430    LibAliasSetTarget(la, addr);
431    return 0;
432  }
433
434  addr = GetIpAddr(arg->argv[arg->argn]);
435  if (addr.s_addr == INADDR_NONE) {
436    log_Printf(LogWARN, "%s: invalid address\n", arg->argv[arg->argn]);
437    return 1;
438  }
439
440  LibAliasSetTarget(la, addr);
441  return 0;
442}
443
444#ifndef NO_FW_PUNCH
445int
446nat_PunchFW(struct cmdargs const *arg)
447{
448  char *end;
449  long base, count;
450
451  if (arg->argc == arg->argn) {
452    LibAliasSetMode(la, 0, PKT_ALIAS_PUNCH_FW);
453    return 0;
454  }
455
456  if (arg->argc != arg->argn + 2)
457    return -1;
458
459  base = strtol(arg->argv[arg->argn], &end, 10);
460  if (*end != '\0' || base < 0)
461    return -1;
462
463  count = strtol(arg->argv[arg->argn + 1], &end, 10);
464  if (*end != '\0' || count < 0)
465    return -1;
466
467  LibAliasSetFWBase(la, base, count);
468  LibAliasSetMode(la, PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW);
469
470  return 0;
471}
472#endif
473
474int
475nat_SkinnyPort(struct cmdargs const *arg)
476{
477  char *end;
478  long port;
479
480  if (arg->argc == arg->argn) {
481    LibAliasSetSkinnyPort(la, 0);
482    return 0;
483  }
484
485  if (arg->argc != arg->argn + 1)
486    return -1;
487
488  port = strtol(arg->argv[arg->argn], &end, 10);
489  if (*end != '\0' || port < 0)
490    return -1;
491
492  LibAliasSetSkinnyPort(la, port);
493
494  return 0;
495}
496
497static struct mbuf *
498nat_LayerPush(struct bundle *bundle, struct link *l __unused, struct mbuf *bp,
499                int pri __unused, u_short *proto)
500{
501  if (!bundle->NatEnabled || *proto != PROTO_IP)
502    return bp;
503
504  log_Printf(LogDEBUG, "nat_LayerPush: PROTO_IP -> PROTO_IP\n");
505  m_settype(bp, MB_NATOUT);
506  /* Ensure there's a bit of extra buffer for the NAT code... */
507  bp = m_pullup(m_append(bp, NULL, NAT_EXTRABUF));
508  LibAliasOut(la, MBUF_CTOP(bp), bp->m_len);
509  bp->m_len = ntohs(((struct ip *)MBUF_CTOP(bp))->ip_len);
510
511  return bp;
512}
513
514static struct mbuf *
515nat_LayerPull(struct bundle *bundle, struct link *l __unused, struct mbuf *bp,
516                u_short *proto)
517{
518  static int gfrags;
519  int ret, len, nfrags;
520  struct mbuf **last;
521  char *fptr;
522
523  if (!bundle->NatEnabled || *proto != PROTO_IP)
524    return bp;
525
526  log_Printf(LogDEBUG, "nat_LayerPull: PROTO_IP -> PROTO_IP\n");
527  m_settype(bp, MB_NATIN);
528  /* Ensure there's a bit of extra buffer for the NAT code... */
529  bp = m_pullup(m_append(bp, NULL, NAT_EXTRABUF));
530  ret = LibAliasIn(la, MBUF_CTOP(bp), bp->m_len);
531
532  bp->m_len = ntohs(((struct ip *)MBUF_CTOP(bp))->ip_len);
533  if (bp->m_len > MAX_MRU) {
534    log_Printf(LogWARN, "nat_LayerPull: Problem with IP header length (%lu)\n",
535               (unsigned long)bp->m_len);
536    m_freem(bp);
537    return NULL;
538  }
539
540  switch (ret) {
541    case PKT_ALIAS_OK:
542      break;
543
544    case PKT_ALIAS_UNRESOLVED_FRAGMENT:
545      /* Save the data for later */
546      if ((fptr = malloc(bp->m_len)) == NULL) {
547	log_Printf(LogWARN, "nat_LayerPull: Dropped unresolved fragment -"
548		   " out of memory!\n");
549	m_freem(bp);
550	bp = NULL;
551      } else {
552	bp = mbuf_Read(bp, fptr, bp->m_len);
553	LibAliasSaveFragment(la, fptr);
554	log_Printf(LogDEBUG, "Store another frag (%lu) - now %d\n",
555		   (unsigned long)((struct ip *)fptr)->ip_id, ++gfrags);
556      }
557      break;
558
559    case PKT_ALIAS_FOUND_HEADER_FRAGMENT:
560      /* Fetch all the saved fragments and chain them on the end of `bp' */
561      last = &bp->m_nextpkt;
562      nfrags = 0;
563      while ((fptr = LibAliasGetFragment(la, MBUF_CTOP(bp))) != NULL) {
564        nfrags++;
565        LibAliasFragmentIn(la, MBUF_CTOP(bp), fptr);
566        len = ntohs(((struct ip *)fptr)->ip_len);
567        *last = m_get(len, MB_NATIN);
568        memcpy(MBUF_CTOP(*last), fptr, len);
569        free(fptr);
570        last = &(*last)->m_nextpkt;
571      }
572      gfrags -= nfrags;
573      log_Printf(LogDEBUG, "Found a frag header (%lu) - plus %d more frags (no"
574                 "w %d)\n", (unsigned long)((struct ip *)MBUF_CTOP(bp))->ip_id,
575                 nfrags, gfrags);
576      break;
577
578    case PKT_ALIAS_IGNORED:
579      if (LibAliasSetMode(la, 0, 0) & PKT_ALIAS_DENY_INCOMING) {
580        log_Printf(LogTCPIP, "NAT engine denied data:\n");
581        m_freem(bp);
582        bp = NULL;
583      } else if (log_IsKept(LogTCPIP)) {
584        log_Printf(LogTCPIP, "NAT engine ignored data:\n");
585        PacketCheck(bundle, AF_INET, MBUF_CTOP(bp), bp->m_len, NULL,
586                    NULL, NULL);
587      }
588      break;
589
590    default:
591      log_Printf(LogWARN, "nat_LayerPull: Dropped a packet (%d)....\n", ret);
592      m_freem(bp);
593      bp = NULL;
594      break;
595  }
596
597  return bp;
598}
599
600struct layer natlayer =
601  { LAYER_NAT, "nat", nat_LayerPush, nat_LayerPull };
602