FreeBSD kernel IPv4 code
alias_db.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#ifdef _KERNEL
33#include <machine/stdarg.h>
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/systm.h>
37#include <sys/lock.h>
38#include <sys/module.h>
39#include <sys/rwlock.h>
40#include <sys/syslog.h>
41#else
42#include <stdarg.h>
43#include <stdlib.h>
44#include <stdio.h>
45#include <sys/errno.h>
46#include <sys/time.h>
47#include <unistd.h>
48#endif
49
50#include <sys/socket.h>
51#include <netinet/tcp.h>
52
53#ifdef _KERNEL
57#include <net/if.h>
58#else
59#include "alias.h"
60#include "alias_local.h"
61#include "alias_mod.h"
62#endif
63
64#include "alias_db.h"
65
66static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
67int LibAliasTime;
68
69/* Kernel module definition. */
70#ifdef _KERNEL
71MALLOC_DEFINE(M_ALIAS, "libalias", "packet aliasing");
72
74
75static int
76alias_mod_handler(module_t mod, int type, void *data)
77{
78 switch (type) {
79 case MOD_QUIESCE:
80 case MOD_UNLOAD:
81 finishoff();
82 case MOD_LOAD:
83 return (0);
84 default:
85 return (EINVAL);
86 }
87}
88
89static moduledata_t alias_mod = {
90 "alias", alias_mod_handler, NULL
91};
92
93DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
94#endif
95
96SPLAY_GENERATE(splay_out, alias_link, all.out, cmp_out);
98
99static struct group_in *
101 struct in_addr alias_addr, u_short alias_port, int link_type,
102 int create)
103{
104 struct group_in *grp;
105 struct group_in needle = {
107 .alias_port = alias_port,
108 .link_type = link_type
109 };
110
111 grp = SPLAY_FIND(splay_in, &la->linkSplayIn, &needle);
112 if (grp != NULL || !create || (grp = malloc(sizeof(*grp))) == NULL)
113 return (grp);
114 grp->alias_addr = alias_addr;
115 grp->alias_port = alias_port;
116 grp->link_type = link_type;
117 LIST_INIT(&grp->full);
118 LIST_INIT(&grp->partial);
119 SPLAY_INSERT(splay_in, &la->linkSplayIn, grp);
120 return (grp);
121}
122
123static int
124SeqDiff(u_long x, u_long y)
125{
126/* Return the difference between two TCP sequence numbers
127 * This function is encapsulated in case there are any unusual
128 * arithmetic conditions that need to be considered.
129 */
130 return (ntohl(y) - ntohl(x));
131}
132
133#ifdef _KERNEL
134static void
135AliasLog(char *str, const char *format, ...)
136{
137 va_list ap;
138
139 va_start(ap, format);
140 vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
141 va_end(ap);
142}
143#else
144static void
145AliasLog(FILE *stream, const char *format, ...)
146{
147 va_list ap;
148
149 va_start(ap, format);
150 vfprintf(stream, format, ap);
151 va_end(ap);
152 fflush(stream);
153}
154#endif
155
156static void
158{
160 /* Used for debugging */
161 if (la->logDesc) {
162 int tot = la->icmpLinkCount + la->udpLinkCount +
163 (la->sctpLinkCount>>1) + /* sctp counts half associations */
164 la->tcpLinkCount + la->pptpLinkCount +
167
168 AliasLog(la->logDesc,
169 "icmp=%u, udp=%u, tcp=%u, sctp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
170 la->icmpLinkCount,
171 la->udpLinkCount,
172 la->tcpLinkCount,
173 la->sctpLinkCount>>1, /* sctp counts half associations */
174 la->pptpLinkCount,
175 la->protoLinkCount,
178 tot);
179#ifndef _KERNEL
180 AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
181#endif
182 }
183}
184
186{
187 ShowAliasStats(la);
188}
189
190/* get random port in network byte order */
191static u_short
193 u_short port;
194
195 port = la->aliasPortLower +
196 arc4random_uniform(la->aliasPortLength);
197
198 return ntohs(port);
199}
200
201/* GetNewPort() allocates port numbers. Note that if a port number
202 is already in use, that does not mean that it cannot be used by
203 another link concurrently. This is because GetNewPort() looks for
204 unused triplets: (dest addr, dest port, alias port). */
205
206static int
207GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
208{
209 int i;
210 int max_trials;
211 u_short port;
212
214 /*
215 * Description of alias_port_param for GetNewPort(). When
216 * this parameter is zero or positive, it precisely specifies
217 * the port number. GetNewPort() will return this number
218 * without check that it is in use.
219 *
220 * The aliasing port is automatically selected by one of
221 * two methods below:
222 *
223 * When this parameter is GET_ALIAS_PORT, it indicates to get
224 * a randomly selected port number.
225 */
226 if (alias_port_param >= 0 && alias_port_param < 0x10000) {
227 lnk->alias_port = (u_short) alias_port_param;
228 return (0);
229 }
230 if (alias_port_param != GET_ALIAS_PORT) {
231#ifdef LIBALIAS_DEBUG
232 fprintf(stderr, "PacketAlias/GetNewPort(): ");
233 fprintf(stderr, "input parameter error\n");
234#endif
235 return (-1);
236 }
237
238 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
239
240 /*
241 * When the PKT_ALIAS_SAME_PORTS option is chosen,
242 * the first try will be the actual source port. If
243 * this is already in use, the remainder of the
244 * trials will be random.
245 */
247 ? lnk->src_port
248 : _RandomPort(la);
249
250 /* Port number search */
251 for (i = 0; i < max_trials; i++, port = _RandomPort(la)) {
252 struct group_in *grp;
253 struct alias_link *search_result;
254
255 grp = StartPointIn(la, lnk->alias_addr, port, lnk->link_type, 0);
256 if (grp == NULL)
257 break;
258
259 LIST_FOREACH(search_result, &grp->full, all.in) {
260 if (lnk->dst_addr.s_addr == search_result->dst_addr.s_addr &&
261 lnk->dst_port == search_result->dst_port)
262 break; /* found match */
263 }
264 if (search_result == NULL)
265 break;
266 }
267
268 if (i >= max_trials) {
269#ifdef LIBALIAS_DEBUG
270 fprintf(stderr, "PacketAlias/GetNewPort(): ");
271 fprintf(stderr, "could not find free port\n");
272#endif
273 return (-1);
274 }
275
276#ifndef NO_USE_SOCKETS
277 if ((la->packetAliasMode & PKT_ALIAS_USE_SOCKETS) &&
279 ((lnk->link_type == LINK_TCP) ||
280 (lnk->link_type == LINK_UDP))) {
281 if (!GetSocket(la, port, &lnk->sockfd, lnk->link_type)) {
282 return (-1);
283 }
284 }
285#endif
286 lnk->alias_port = port;
287
288 return (0);
289}
290
291#ifndef NO_USE_SOCKETS
292static u_short
293GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
294{
295 int err;
296 int sock;
297 struct sockaddr_in sock_addr;
298
300 if (link_type == LINK_TCP)
301 sock = socket(AF_INET, SOCK_STREAM, 0);
302 else if (link_type == LINK_UDP)
303 sock = socket(AF_INET, SOCK_DGRAM, 0);
304 else {
305#ifdef LIBALIAS_DEBUG
306 fprintf(stderr, "PacketAlias/GetSocket(): ");
307 fprintf(stderr, "incorrect link type\n");
308#endif
309 return (0);
310 }
311
312 if (sock < 0) {
313#ifdef LIBALIAS_DEBUG
314 fprintf(stderr, "PacketAlias/GetSocket(): ");
315 fprintf(stderr, "socket() error %d\n", *sockfd);
316#endif
317 return (0);
318 }
319 sock_addr.sin_family = AF_INET;
320 sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);
321 sock_addr.sin_port = port_net;
322
323 err = bind(sock,
324 (struct sockaddr *)&sock_addr,
325 sizeof(sock_addr));
326 if (err == 0) {
327 la->sockCount++;
328 *sockfd = sock;
329 return (1);
330 } else {
331 close(sock);
332 return (0);
333 }
334}
335#endif
336
337/* FindNewPortGroup() returns a base port number for an available
338 range of contiguous port numbers. Note that if a port number
339 is already in use, that does not mean that it cannot be used by
340 another link concurrently. This is because FindNewPortGroup()
341 looks for unused triplets: (dest addr, dest port, alias port). */
342
343int
345 struct in_addr dst_addr,
346 struct in_addr alias_addr,
347 u_short src_port,
348 u_short dst_port,
349 u_short port_count,
350 u_char proto,
351 u_char align)
352{
353 int i, j;
354 int max_trials;
355 u_short port;
356 int link_type;
357
359 /*
360 * Get link_type from protocol
361 */
362
363 switch (proto) {
364 case IPPROTO_UDP:
365 link_type = LINK_UDP;
366 break;
367 case IPPROTO_TCP:
368 link_type = LINK_TCP;
369 break;
370 default:
371 return (0);
372 break;
373 }
374
375 /*
376 * The aliasing port is automatically selected by one of two
377 * methods below:
378 */
379 max_trials = GET_NEW_PORT_MAX_ATTEMPTS;
380
382 /*
383 * When the ALIAS_SAME_PORTS option is chosen, the first
384 * try will be the actual source port. If this is already
385 * in use, the remainder of the trials will be random.
386 */
387 port = src_port;
388
389 } else {
390 port = _RandomPort(la);
391 }
392
393 /* Port number search */
394 for (i = 0; i < max_trials; i++, port = _RandomPort(la)) {
395 struct alias_link *search_result;
396
397 if (align)
398 port &= htons(0xfffe);
399
400 for (j = 0; j < port_count; j++) {
401 u_short port_j = ntohs(port) + j;
402
403 if ((search_result = FindLinkIn(la, dst_addr,
404 alias_addr, dst_port, htons(port_j),
405 link_type, 0)) != NULL)
406 break;
407 }
408
409 /* Found a good range, return base */
410 if (j == port_count)
411 return (port);
412 }
413
414#ifdef LIBALIAS_DEBUG
415 fprintf(stderr, "PacketAlias/FindNewPortGroup(): ");
416 fprintf(stderr, "could not find free port(s)\n");
417#endif
418
419 return (0);
420}
421
422static void
423CleanupAliasData(struct libalias *la, int deletePermanent)
424{
425 struct alias_link *lnk, *lnk_tmp;
426
428
429 /* permanent entries may stay */
430 TAILQ_FOREACH_SAFE(lnk, &la->checkExpire, expire.list, lnk_tmp)
431 DeleteLink(&lnk, deletePermanent);
432}
433static void
434CleanupLink(struct libalias *la, struct alias_link **lnk, int deletePermanent)
435{
437
438 if (lnk == NULL || *lnk == NULL)
439 return;
440
441 if (LibAliasTime - (*lnk)->timestamp > (*lnk)->expire.time) {
442 DeleteLink(lnk, deletePermanent);
443 if ((*lnk) == NULL)
444 return;
445 }
446
447 /* move to end, swap may fail on a single entry list */
448 TAILQ_REMOVE(&la->checkExpire, (*lnk), expire.list);
449 TAILQ_INSERT_TAIL(&la->checkExpire, (*lnk), expire.list);
450}
451
452static struct alias_link *
453UseLink(struct libalias *la, struct alias_link *lnk)
454{
455 CleanupLink(la, &lnk, 0);
456 if (lnk != NULL)
457 lnk->timestamp = LibAliasTime;
458 return (lnk);
459}
460
461static void
462DeleteLink(struct alias_link **plnk, int deletePermanent)
463{
464 struct alias_link *lnk = *plnk;
465 struct libalias *la = lnk->la;
466
468 /* Don't do anything if the link is marked permanent */
469 if (!deletePermanent && (lnk->flags & LINK_PERMANENT))
470 return;
471
472#ifndef NO_FW_PUNCH
473 /* Delete associated firewall hole, if any */
474 ClearFWHole(lnk);
475#endif
476
477 switch (lnk->link_type) {
478 case LINK_PPTP:
479 LIST_REMOVE(lnk, pptp.list);
480 break;
481 default: {
482 struct group_in *grp;
483
484 /* Free memory allocated for LSNAT server pool */
485 if (lnk->server != NULL) {
486 struct server *head, *curr, *next;
487
488 head = curr = lnk->server;
489 do {
490 next = curr->next;
491 free(curr);
492 } while ((curr = next) != head);
493 } else {
494 /* Adjust output table pointers */
495 SPLAY_REMOVE(splay_out, &la->linkSplayOut, lnk);
496 }
497
498 /* Adjust input table pointers */
499 LIST_REMOVE(lnk, all.in);
500
501 /* Remove intermediate node, if empty */
502 grp = StartPointIn(la, lnk->alias_addr, lnk->alias_port, lnk->link_type, 0);
503 if (grp != NULL &&
504 LIST_EMPTY(&grp->full) &&
505 LIST_EMPTY(&grp->partial)) {
506 SPLAY_REMOVE(splay_in, &la->linkSplayIn, grp);
507 free(grp);
508 }
509 }
510 break;
511 }
512
513 /* remove from housekeeping */
514 TAILQ_REMOVE(&la->checkExpire, lnk, expire.list);
515
516#ifndef NO_USE_SOCKETS
517 /* Close socket, if one has been allocated */
518 if (lnk->sockfd != -1) {
519 la->sockCount--;
520 close(lnk->sockfd);
521 }
522#endif
523 /* Link-type dependent cleanup */
524 switch (lnk->link_type) {
525 case LINK_ICMP:
526 la->icmpLinkCount--;
527 break;
528 case LINK_UDP:
529 la->udpLinkCount--;
530 break;
531 case LINK_TCP:
532 la->tcpLinkCount--;
533 free(lnk->data.tcp);
534 break;
535 case LINK_PPTP:
536 la->pptpLinkCount--;
537 break;
538 case LINK_FRAGMENT_ID:
540 break;
543 if (lnk->data.frag_ptr != NULL)
544 free(lnk->data.frag_ptr);
545 break;
546 case LINK_ADDR:
547 break;
548 default:
549 la->protoLinkCount--;
550 break;
551 }
552
553 /* Free memory */
554 free(lnk);
555 *plnk = NULL;
556
557 /* Write statistics, if logging enabled */
558 if (la->packetAliasMode & PKT_ALIAS_LOG) {
559 ShowAliasStats(la);
560 }
561}
562
563struct alias_link *
565 struct in_addr alias_addr, u_short src_port, u_short dst_port,
566 int alias_port_param, int link_type)
567{
568 struct alias_link *lnk;
569
571
572 lnk = malloc(sizeof(struct alias_link));
573 if (lnk == NULL) {
574#ifdef LIBALIAS_DEBUG
575 fprintf(stderr, "PacketAlias/AddLink(): ");
576 fprintf(stderr, "malloc() call failed.\n");
577#endif
578 return (NULL);
579 }
580 /* Basic initialization */
581 lnk->la = la;
582 lnk->src_addr = src_addr;
583 lnk->dst_addr = dst_addr;
584 lnk->alias_addr = alias_addr;
586 lnk->src_port = src_port;
587 lnk->dst_port = dst_port;
588 lnk->proxy_port = 0;
589 lnk->server = NULL;
590 lnk->link_type = link_type;
591#ifndef NO_USE_SOCKETS
592 lnk->sockfd = -1;
593#endif
594 lnk->flags = 0;
595 lnk->pflags = 0;
596 lnk->timestamp = LibAliasTime;
597
598 /* Expiration time */
599 switch (link_type) {
600 case LINK_ICMP:
602 break;
603 case LINK_UDP:
605 break;
606 case LINK_TCP:
608 break;
609 case LINK_FRAGMENT_ID:
611 break;
614 break;
615 default:
617 break;
618 }
619
620 /* Determine alias flags */
623 if (dst_port == 0)
625
626 /* Determine alias port */
627 if (GetNewPort(la, lnk, alias_port_param) != 0) {
628 free(lnk);
629 return (NULL);
630 }
631 /* Link-type dependent initialization */
632 switch (link_type) {
633 case LINK_ICMP:
634 la->icmpLinkCount++;
635 break;
636 case LINK_UDP:
637 la->udpLinkCount++;
638 break;
639 case LINK_TCP: {
640 struct tcp_dat *aux_tcp;
641 int i;
642
643 aux_tcp = malloc(sizeof(struct tcp_dat));
644 if (aux_tcp == NULL) {
645#ifdef LIBALIAS_DEBUG
646 fprintf(stderr, "PacketAlias/AddLink: ");
647 fprintf(stderr, " cannot allocate auxiliary TCP data\n");
648#endif
649 free(lnk);
650 return (NULL);
651 }
652
653 la->tcpLinkCount++;
656 aux_tcp->state.index = 0;
657 aux_tcp->state.ack_modified = 0;
658 for (i = 0; i < N_LINK_TCP_DATA; i++)
659 aux_tcp->ack[i].active = 0;
660 aux_tcp->fwhole = -1;
661 lnk->data.tcp = aux_tcp;
662 }
663 break;
664 case LINK_PPTP:
665 la->pptpLinkCount++;
666 break;
667 case LINK_FRAGMENT_ID:
669 break;
672 break;
673 case LINK_ADDR:
674 break;
675 default:
676 la->protoLinkCount++;
677 break;
678 }
679
680 switch (link_type) {
681 case LINK_PPTP:
682 LIST_INSERT_HEAD(&la->pptpList, lnk, pptp.list);
683 break;
684 default: {
685 struct group_in *grp;
686
687 grp = StartPointIn(la, alias_addr, lnk->alias_port, link_type, 1);
688 if (grp == NULL) {
689 free(lnk);
690 return (NULL);
691 }
692
693 /* Set up pointers for output lookup table */
694 SPLAY_INSERT(splay_out, &la->linkSplayOut, lnk);
695
696 /* Set up pointers for input lookup table */
698 LIST_INSERT_HEAD(&grp->partial, lnk, all.in);
699 else
700 LIST_INSERT_HEAD(&grp->full, lnk, all.in);
701 }
702 break;
703 }
704
705 /* Include the element into the housekeeping list */
706 TAILQ_INSERT_TAIL(&la->checkExpire, lnk, expire.list);
707
709 ShowAliasStats(la);
710
711 return (lnk);
712}
713
714/*
715 * If alias_port_param is less than zero, alias port will be automatically
716 * chosen. If greater than zero, equal to alias port
717 */
718static struct alias_link *
719ReLink(struct alias_link *old_lnk,
720 struct in_addr src_addr,
721 struct in_addr dst_addr,
722 struct in_addr alias_addr,
723 u_short src_port,
724 u_short dst_port,
725 int alias_port_param,
726 int link_type,
727 int deletePermanent)
728{
729 struct alias_link *new_lnk;
730 struct libalias *la = old_lnk->la;
731
733 new_lnk = AddLink(la, src_addr, dst_addr, alias_addr,
734 src_port, dst_port, alias_port_param,
735 link_type);
736#ifndef NO_FW_PUNCH
737 if (new_lnk != NULL &&
738 old_lnk->link_type == LINK_TCP &&
739 old_lnk->data.tcp->fwhole > 0) {
740 PunchFWHole(new_lnk);
741 }
742#endif
743 DeleteLink(&old_lnk, deletePermanent);
744 return (new_lnk);
745}
746
747static struct alias_link *
749 struct in_addr dst_addr,
750 u_short src_port,
751 u_short dst_port,
752 int link_type) {
753 struct alias_link *lnk;
754 struct alias_link needle = {
756 .dst_addr = dst_addr,
757 .src_port = src_port,
758 .dst_port = dst_port,
759 .link_type = link_type
760 };
761
762 lnk = SPLAY_FIND(splay_out, &la->linkSplayOut, &needle);
763 return (UseLink(la, lnk));
764}
765
766static struct alias_link *
768 struct in_addr dst_addr,
769 u_short src_port,
770 u_short dst_port,
771 int link_type,
772 int replace_partial_links)
773{
774 struct alias_link *lnk;
775
778 if (lnk != NULL || !replace_partial_links)
779 return (lnk);
780
781 /* Search for partially specified links. */
782 if (dst_port != 0 && dst_addr.s_addr != INADDR_ANY) {
784 link_type);
785 if (lnk == NULL)
788 }
789 if (lnk == NULL &&
790 (dst_port != 0 || dst_addr.s_addr != INADDR_ANY)) {
792 link_type);
793 }
794 if (lnk != NULL) {
795 lnk = ReLink(lnk,
798 link_type, 0);
799 }
800 return (lnk);
801}
802
803static struct alias_link *
805 struct in_addr dst_addr,
806 u_short src_port,
807 u_short dst_port,
808 int link_type,
809 int replace_partial_links)
810{
811 struct alias_link *lnk;
812
815 link_type, replace_partial_links);
816
817 if (lnk == NULL) {
818 /*
819 * The following allows permanent links to be specified as
820 * using the default source address (i.e. device interface
821 * address) without knowing in advance what that address
822 * is.
823 */
827 link_type, replace_partial_links);
828 }
829 }
830 return (lnk);
831}
832
833static struct alias_link *
835 struct in_addr alias_addr,
836 u_short dst_port,
837 u_short alias_port,
838 int link_type,
839 int replace_partial_links)
840{
841 int flags_in;
842 struct group_in *grp;
843 struct alias_link *lnk;
844 struct alias_link *lnk_unknown_all;
845 struct alias_link *lnk_unknown_dst_addr;
846 struct alias_link *lnk_unknown_dst_port;
847 struct in_addr src_addr;
848 u_short src_port;
849
851 /* Initialize pointers */
852 lnk_unknown_all = NULL;
853 lnk_unknown_dst_addr = NULL;
854 lnk_unknown_dst_port = NULL;
855
856 /* If either the dest addr or port is unknown, the search
857 * loop will have to know about this. */
858 flags_in = 0;
859 if (dst_addr.s_addr == INADDR_ANY)
860 flags_in |= LINK_UNKNOWN_DEST_ADDR;
861 if (dst_port == 0)
862 flags_in |= LINK_UNKNOWN_DEST_PORT;
863
864 /* Search loop */
865 grp = StartPointIn(la, alias_addr, alias_port, link_type, 0);
866 if (grp == NULL)
867 return (NULL);
868
869 switch (flags_in) {
870 case 0:
871 LIST_FOREACH(lnk, &grp->full, all.in) {
872 if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
873 lnk->dst_port == dst_port)
874 return (UseLink(la, lnk));
875 }
876 break;
878 LIST_FOREACH(lnk, &grp->full, all.in) {
879 if(lnk->dst_addr.s_addr == dst_addr.s_addr) {
880 lnk_unknown_dst_port = lnk;
881 break;
882 }
883 }
884 break;
886 LIST_FOREACH(lnk, &grp->full, all.in) {
887 if(lnk->dst_port == dst_port) {
888 lnk_unknown_dst_addr = lnk;
889 break;
890 }
891 }
892 break;
894 lnk_unknown_all = LIST_FIRST(&grp->full);
895 break;
896 }
897
898 if (lnk_unknown_dst_port == NULL) {
899 LIST_FOREACH(lnk, &grp->partial, all.in) {
900 int flags = (flags_in | lnk->flags) & LINK_PARTIALLY_SPECIFIED;
901
902 if (flags == LINK_PARTIALLY_SPECIFIED &&
903 lnk_unknown_all == NULL)
904 lnk_unknown_all = lnk;
905 if (flags == LINK_UNKNOWN_DEST_ADDR &&
906 lnk->dst_port == dst_port &&
907 lnk_unknown_dst_addr == NULL)
908 lnk_unknown_dst_addr = lnk;
909 if (flags == LINK_UNKNOWN_DEST_PORT &&
910 lnk->dst_addr.s_addr == dst_addr.s_addr) {
911 lnk_unknown_dst_port = lnk;
912 break;
913 }
914 }
915 }
916
917 lnk = (lnk_unknown_dst_port != NULL) ? lnk_unknown_dst_port
918 : (lnk_unknown_dst_addr != NULL) ? lnk_unknown_dst_addr
919 : lnk_unknown_all;
920
921 if (lnk == NULL || !replace_partial_links)
922 return (lnk);
923
924 if (lnk->server != NULL) { /* LSNAT link */
925 src_addr = lnk->server->addr;
926 src_port = lnk->server->port;
927 lnk->server = lnk->server->next;
928 } else {
929 src_addr = lnk->src_addr;
930 src_port = lnk->src_port;
931 }
932
933 if (link_type == LINK_SCTP) {
934 lnk->src_addr = src_addr;
935 lnk->src_port = src_port;
936 } else {
937 lnk = ReLink(lnk,
938 src_addr, dst_addr, alias_addr,
939 src_port, dst_port, alias_port,
940 link_type, 0);
941 }
942 return (lnk);
943}
944
945static struct alias_link *
947 struct in_addr alias_addr,
948 u_short dst_port,
949 u_short alias_port,
950 int link_type,
951 int replace_partial_links)
952{
953 struct alias_link *lnk;
954
957 link_type, replace_partial_links);
958
959 if (lnk == NULL) {
960 /*
961 * The following allows permanent links to be specified as
962 * using the default aliasing address (i.e. device
963 * interface address) without knowing in advance what that
964 * address is.
965 */
969 link_type, replace_partial_links);
970 }
971 }
972 return (lnk);
973}
974
975/* External routines for finding/adding links
976
977-- "external" means outside alias_db.c, but within alias*.c --
978
979 FindIcmpIn(), FindIcmpOut()
980 FindFragmentIn1(), FindFragmentIn2()
981 AddFragmentPtrLink(), FindFragmentPtr()
982 FindProtoIn(), FindProtoOut()
983 FindUdpTcpIn(), FindUdpTcpOut()
984 AddPptp(), FindPptpOutByCallId(), FindPptpInByCallId(),
985 FindPptpOutByPeerCallId(), FindPptpInByPeerCallId()
986 FindOriginalAddress(), FindAliasAddress()
987
988(prototypes in alias_local.h)
989*/
990
991struct alias_link *
993 struct in_addr alias_addr,
994 u_short id_alias,
995 int create)
996{
997 struct alias_link *lnk;
998
1001 NO_DEST_PORT, id_alias,
1002 LINK_ICMP, 0);
1003 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1004 struct in_addr target_addr;
1005
1006 target_addr = FindOriginalAddress(la, alias_addr);
1007 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1008 id_alias, NO_DEST_PORT, id_alias,
1009 LINK_ICMP);
1010 }
1011 return (lnk);
1012}
1013
1014struct alias_link *
1016 struct in_addr dst_addr,
1017 u_short id,
1018 int create)
1019{
1020 struct alias_link *lnk;
1021
1024 id, NO_DEST_PORT,
1025 LINK_ICMP, 0);
1026 if (lnk == NULL && create) {
1027 struct in_addr alias_addr;
1028
1029 alias_addr = FindAliasAddress(la, src_addr);
1030 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1032 LINK_ICMP);
1033 }
1034 return (lnk);
1035}
1036
1037struct alias_link *
1039 struct in_addr alias_addr,
1040 u_short ip_id)
1041{
1042 struct alias_link *lnk;
1043
1047 LINK_FRAGMENT_ID, 0);
1048
1049 if (lnk == NULL) {
1053 }
1054 return (lnk);
1055}
1056
1057/* Doesn't add a link if one is not found. */
1058struct alias_link *
1060 struct in_addr alias_addr, u_short ip_id)
1061{
1065 LINK_FRAGMENT_ID, 0);
1066}
1067
1068struct alias_link *
1070 u_short ip_id)
1071{
1076}
1077
1078struct alias_link *
1080 u_short ip_id)
1081{
1083 return FindLinkIn(la, dst_addr, ANY_ADDR,
1086}
1087
1088struct alias_link *
1090 struct in_addr alias_addr,
1091 u_char proto)
1092{
1093 struct alias_link *lnk;
1094
1097 NO_DEST_PORT, 0,
1098 proto, 1);
1099
1100 if (lnk == NULL && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1101 struct in_addr target_addr;
1102
1103 target_addr = FindOriginalAddress(la, alias_addr);
1104 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1106 proto);
1107 }
1108 return (lnk);
1109}
1110
1111struct alias_link *
1113 struct in_addr dst_addr,
1114 u_char proto)
1115{
1116 struct alias_link *lnk;
1117
1121 proto, 1);
1122
1123 if (lnk == NULL) {
1124 struct in_addr alias_addr;
1125
1126 alias_addr = FindAliasAddress(la, src_addr);
1127 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1129 proto);
1130 }
1131 return (lnk);
1132}
1133
1134struct alias_link *
1136 struct in_addr alias_addr,
1137 u_short dst_port,
1138 u_short alias_port,
1139 u_char proto,
1140 int create)
1141{
1142 int link_type;
1143 struct alias_link *lnk;
1144
1146 switch (proto) {
1147 case IPPROTO_UDP:
1149 break;
1150 case IPPROTO_TCP:
1152 break;
1153 default:
1154 return (NULL);
1155 break;
1156 }
1157
1160 link_type, create);
1161
1162 if (lnk == NULL && create && !(la->packetAliasMode & PKT_ALIAS_DENY_INCOMING)) {
1163 struct in_addr target_addr;
1164
1165 target_addr = FindOriginalAddress(la, alias_addr);
1166 lnk = AddLink(la, target_addr, dst_addr, alias_addr,
1167 alias_port, dst_port, alias_port,
1168 link_type);
1169 }
1170 return (lnk);
1171}
1172
1173struct alias_link *
1175 struct in_addr dst_addr,
1176 u_short src_port,
1177 u_short dst_port,
1178 u_char proto,
1179 int create)
1180{
1181 int link_type;
1182 struct alias_link *lnk;
1183
1185 switch (proto) {
1186 case IPPROTO_UDP:
1188 break;
1189 case IPPROTO_TCP:
1191 break;
1192 default:
1193 return (NULL);
1194 break;
1195 }
1196
1198
1199 if (lnk == NULL && create) {
1200 struct in_addr alias_addr;
1201
1202 alias_addr = FindAliasAddress(la, src_addr);
1203 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1204 src_port, dst_port, GET_ALIAS_PORT,
1205 link_type);
1206 }
1207 return (lnk);
1208}
1209
1210struct alias_link *
1212 struct in_addr dst_addr,
1213 struct in_addr alias_addr,
1214 u_int16_t src_call_id)
1215{
1216 struct alias_link *lnk;
1217
1220 src_call_id, 0, GET_ALIAS_PORT,
1221 LINK_PPTP);
1222
1223 return (lnk);
1224}
1225
1226struct alias_link *
1228 struct in_addr dst_addr,
1229 u_int16_t src_call_id)
1230{
1231 struct alias_link *lnk;
1232
1234 LIST_FOREACH(lnk, &la->pptpList, pptp.list)
1235 if (lnk->src_addr.s_addr == src_addr.s_addr &&
1236 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1237 lnk->src_port == src_call_id)
1238 break;
1239
1240 return (UseLink(la, lnk));
1241}
1242
1243struct alias_link *
1245 struct in_addr dst_addr,
1246 u_int16_t dst_call_id)
1247{
1248 struct alias_link *lnk;
1249
1251 LIST_FOREACH(lnk, &la->pptpList, pptp.list)
1252 if (lnk->src_addr.s_addr == src_addr.s_addr &&
1253 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1254 lnk->dst_port == dst_call_id)
1255 break;
1256
1257 return (UseLink(la, lnk));
1258}
1259
1260struct alias_link *
1262 struct in_addr alias_addr,
1263 u_int16_t dst_call_id)
1264{
1265 struct alias_link *lnk;
1266
1268
1269 LIST_FOREACH(lnk, &la->pptpList, pptp.list)
1270 if (lnk->dst_port == dst_call_id &&
1271 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1273 break;
1274
1275 return (UseLink(la, lnk));
1276}
1277
1278struct alias_link *
1280 struct in_addr alias_addr,
1281 u_int16_t alias_call_id)
1282{
1283 struct alias_link *lnk;
1284
1286 LIST_FOREACH(lnk, &la->pptpList, pptp.list)
1287 if (lnk->alias_port == alias_call_id &&
1288 lnk->dst_addr.s_addr == dst_addr.s_addr &&
1290 break;
1291
1292 return (lnk);
1293}
1294
1295struct alias_link *
1297 struct in_addr dst_addr,
1298 u_short src_port,
1299 u_short alias_port,
1300 u_char proto)
1301{
1302 int link_type;
1303 struct alias_link *lnk;
1304
1306 switch (proto) {
1307 case IPPROTO_UDP:
1309 break;
1310 case IPPROTO_TCP:
1312 break;
1313 default:
1314 return (NULL);
1315 break;
1316 }
1317
1319
1320 if (lnk == NULL) {
1321 struct in_addr alias_addr;
1322
1323 alias_addr = FindAliasAddress(la, src_addr);
1324 lnk = AddLink(la, src_addr, dst_addr, alias_addr,
1325 src_port, 0, alias_port,
1326 link_type);
1327 }
1328 return (lnk);
1329}
1330
1331struct in_addr
1332FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
1333{
1334 struct alias_link *lnk;
1335
1338 0, 0, LINK_ADDR, 0);
1339 if (lnk == NULL) {
1341 return (alias_addr);
1342 else if (la->targetAddress.s_addr == INADDR_NONE)
1343 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1345 else
1346 return (la->targetAddress);
1347 } else {
1348 if (lnk->server != NULL) { /* LSNAT link */
1349 struct in_addr src_addr;
1350
1351 src_addr = lnk->server->addr;
1352 lnk->server = lnk->server->next;
1353 return (src_addr);
1354 } else if (lnk->src_addr.s_addr == INADDR_ANY)
1355 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1356 la->aliasAddress : alias_addr;
1357 else
1358 return (lnk->src_addr);
1359 }
1360}
1361
1362struct in_addr
1363FindAliasAddress(struct libalias *la, struct in_addr original_addr)
1364{
1365 struct alias_link *lnk;
1366
1368 lnk = FindLinkOut(la, original_addr, ANY_ADDR,
1369 0, 0, LINK_ADDR, 0);
1370 if (lnk == NULL) {
1371 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1372 la->aliasAddress : original_addr;
1373 } else {
1374 if (lnk->alias_addr.s_addr == INADDR_ANY)
1375 return (la->aliasAddress.s_addr != INADDR_ANY) ?
1376 la->aliasAddress : original_addr;
1377 else
1378 return (lnk->alias_addr);
1379 }
1380}
1381
1382/* External routines for getting or changing link data
1383 (external to alias_db.c, but internal to alias*.c)
1384
1385 SetFragmentData(), GetFragmentData()
1386 SetFragmentPtr(), GetFragmentPtr()
1387 SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut()
1388 GetOriginalAddress(), GetDestAddress(), GetAliasAddress()
1389 GetOriginalPort(), GetAliasPort()
1390 SetAckModified(), GetAckModified()
1391 GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq()
1392 SetProtocolFlags(), GetProtocolFlags()
1393 SetDestCallId()
1394*/
1395
1396void
1398{
1399 lnk->data.frag_addr = src_addr;
1400}
1401
1402void
1404{
1405 *src_addr = lnk->data.frag_addr;
1406}
1407
1408void
1409SetFragmentPtr(struct alias_link *lnk, void *fptr)
1410{
1411 lnk->data.frag_ptr = fptr;
1412}
1413
1414void
1415GetFragmentPtr(struct alias_link *lnk, void **fptr)
1416{
1417 *fptr = lnk->data.frag_ptr;
1418}
1419
1420void
1421SetStateIn(struct alias_link *lnk, int state)
1422{
1423 /* TCP input state */
1424 switch (state) {
1428 else
1430 break;
1434 break;
1435 default:
1436#ifdef _KERNEL
1437 panic("libalias:SetStateIn() unknown state");
1438#else
1439 abort();
1440#endif
1441 }
1442 lnk->data.tcp->state.in = state;
1443}
1444
1445void
1447{
1448 /* TCP output state */
1449 switch (state) {
1453 else
1455 break;
1459 break;
1460 default:
1461#ifdef _KERNEL
1462 panic("libalias:SetStateOut() unknown state");
1463#else
1464 abort();
1465#endif
1466 }
1467 lnk->data.tcp->state.out = state;
1468}
1469
1470int
1472{
1473 /* TCP input state */
1474 return (lnk->data.tcp->state.in);
1475}
1476
1477int
1479{
1480 /* TCP output state */
1481 return (lnk->data.tcp->state.out);
1482}
1483
1484struct in_addr
1486{
1487 if (lnk->src_addr.s_addr == INADDR_ANY)
1488 return (lnk->la->aliasAddress);
1489 else
1490 return (lnk->src_addr);
1491}
1492
1493struct in_addr
1495{
1496 return (lnk->dst_addr);
1497}
1498
1499struct in_addr
1501{
1502 if (lnk->alias_addr.s_addr == INADDR_ANY)
1503 return (lnk->la->aliasAddress);
1504 else
1505 return (lnk->alias_addr);
1506}
1507
1508struct in_addr
1510{
1512 return (la->aliasAddress);
1513}
1514
1515void
1516SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
1517{
1519 la->aliasAddress = alias_addr;
1520}
1521
1522u_short
1524{
1525 return (lnk->src_port);
1526}
1527
1528u_short
1530{
1531 return (lnk->alias_port);
1532}
1533
1534#ifndef NO_FW_PUNCH
1535static u_short
1537{
1538 return (lnk->dst_port);
1539}
1540
1541#endif
1542
1543/* Indicate that ACK numbers have been modified in a TCP connection */
1544void
1546{
1547 lnk->data.tcp->state.ack_modified = 1;
1548}
1549
1550struct in_addr
1552{
1553 return (lnk->proxy_addr);
1554}
1555
1556void
1557SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
1558{
1559 lnk->proxy_addr = addr;
1560}
1561
1562u_short
1564{
1565 return (lnk->proxy_port);
1566}
1567
1568void
1569SetProxyPort(struct alias_link *lnk, u_short port)
1570{
1571 lnk->proxy_port = port;
1572}
1573
1574/* See if ACK numbers have been modified */
1575int
1577{
1578 return (lnk->data.tcp->state.ack_modified);
1579}
1580
1581/*
1582 * Find out how much the ACK number has been altered for an
1583 * incoming TCP packet. To do this, a circular list of ACK
1584 * numbers where the TCP packet size was altered is searched.
1585 */
1586// XXX ip free
1587int
1588GetDeltaAckIn(u_long ack, struct alias_link *lnk)
1589{
1590 int i, j;
1591 int delta, ack_diff_min;
1592
1593 delta = 0;
1594 ack_diff_min = -1;
1595 i = lnk->data.tcp->state.index;
1596 for (j = 0; j < N_LINK_TCP_DATA; j++) {
1597 struct ack_data_record x;
1598
1599 if (i == 0)
1600 i = N_LINK_TCP_DATA;
1601 i--;
1602 x = lnk->data.tcp->ack[i];
1603 if (x.active == 1) {
1604 int ack_diff;
1605
1606 ack_diff = SeqDiff(x.ack_new, ack);
1607 if (ack_diff >= 0) {
1608 if (ack_diff_min >= 0) {
1609 if (ack_diff < ack_diff_min) {
1610 delta = x.delta;
1611 ack_diff_min = ack_diff;
1612 }
1613 } else {
1614 delta = x.delta;
1615 ack_diff_min = ack_diff;
1616 }
1617 }
1618 }
1619 }
1620 return (delta);
1621}
1622
1623/*
1624 * Find out how much the sequence number has been altered for an
1625 * outgoing TCP packet. To do this, a circular list of ACK numbers
1626 * where the TCP packet size was altered is searched.
1627 */
1628// XXX ip free
1629int
1630GetDeltaSeqOut(u_long seq, struct alias_link *lnk)
1631{
1632 int i, j;
1633 int delta, seq_diff_min;
1634
1635 delta = 0;
1636 seq_diff_min = -1;
1637 i = lnk->data.tcp->state.index;
1638 for (j = 0; j < N_LINK_TCP_DATA; j++) {
1639 struct ack_data_record x;
1640
1641 if (i == 0)
1642 i = N_LINK_TCP_DATA;
1643 i--;
1644 x = lnk->data.tcp->ack[i];
1645 if (x.active == 1) {
1646 int seq_diff;
1647
1648 seq_diff = SeqDiff(x.ack_old, seq);
1649 if (seq_diff >= 0) {
1650 if (seq_diff_min >= 0) {
1651 if (seq_diff < seq_diff_min) {
1652 delta = x.delta;
1653 seq_diff_min = seq_diff;
1654 }
1655 } else {
1656 delta = x.delta;
1657 seq_diff_min = seq_diff;
1658 }
1659 }
1660 }
1661 }
1662 return (delta);
1663}
1664
1665/*
1666 * When a TCP packet has been altered in length, save this
1667 * information in a circular list. If enough packets have been
1668 * altered, then this list will begin to overwrite itself.
1669 */
1670// XXX ip free
1671void
1672AddSeq(struct alias_link *lnk, int delta, u_int ip_hl, u_short ip_len,
1673 u_long th_seq, u_int th_off)
1674{
1675 struct ack_data_record x;
1676 int hlen, tlen, dlen;
1677 int i;
1678
1679 hlen = (ip_hl + th_off) << 2;
1680 tlen = ntohs(ip_len);
1681 dlen = tlen - hlen;
1682
1683 x.ack_old = htonl(ntohl(th_seq) + dlen);
1684 x.ack_new = htonl(ntohl(th_seq) + dlen + delta);
1685 x.delta = delta;
1686 x.active = 1;
1687
1688 i = lnk->data.tcp->state.index;
1689 lnk->data.tcp->ack[i] = x;
1690
1691 i++;
1692 if (i == N_LINK_TCP_DATA)
1693 lnk->data.tcp->state.index = 0;
1694 else
1695 lnk->data.tcp->state.index = i;
1696}
1697
1698void
1699SetExpire(struct alias_link *lnk, int expire)
1700{
1701 if (expire == 0) {
1702 lnk->flags &= ~LINK_PERMANENT;
1703 DeleteLink(&lnk, 0);
1704 } else if (expire == -1) {
1705 lnk->flags |= LINK_PERMANENT;
1706 } else if (expire > 0) {
1707 lnk->expire.time = expire;
1708 } else {
1709#ifdef LIBALIAS_DEBUG
1710 fprintf(stderr, "PacketAlias/SetExpire(): ");
1711 fprintf(stderr, "error in expire parameter\n");
1712#endif
1713 }
1714}
1715
1716void
1717SetProtocolFlags(struct alias_link *lnk, int pflags)
1718{
1719 lnk->pflags = pflags;
1720}
1721
1722int
1724{
1725 return (lnk->pflags);
1726}
1727
1728void
1729SetDestCallId(struct alias_link *lnk, u_int16_t cid)
1730{
1732 ReLink(lnk, lnk->src_addr, lnk->dst_addr, lnk->alias_addr,
1733 lnk->src_port, cid, lnk->alias_port, lnk->link_type, 1);
1734}
1735
1736/* Miscellaneous Functions
1737
1738 HouseKeeping()
1739 InitPacketAliasLog()
1740 UninitPacketAliasLog()
1741*/
1742
1743/*
1744 Whenever an outgoing or incoming packet is handled, HouseKeeping()
1745 is called to find and remove timed-out aliasing links. Logic exists
1746 to sweep through the entire table and linked list structure
1747 every 60 seconds.
1748
1749 (prototype in alias_local.h)
1750*/
1751
1752void
1754{
1755 static unsigned int packets = 0;
1756 static unsigned int packet_limit = 1000;
1757
1759 packets++;
1760
1761 /*
1762 * User space time/gettimeofday/... is very expensive.
1763 * Kernel space cache trashing is unnecessary.
1764 *
1765 * Save system time (seconds) in global variable LibAliasTime
1766 * for use by other functions. This is done so as not to
1767 * unnecessarily waste timeline by making system calls.
1768 *
1769 * Reduce the amount of house keeping work substantially by
1770 * sampling over the packets.
1771 */
1772 if (packet_limit <= 1 || packets % packet_limit == 0) {
1773 time_t now;
1774
1775#ifdef _KERNEL
1776 now = time_uptime;
1777#else
1778 now = time(NULL);
1779#endif
1780 if (now != LibAliasTime) {
1781 /* retry three times a second */
1782 packet_limit = packets / 3;
1783 packets = 0;
1784 LibAliasTime = now;
1785 }
1786
1787 }
1788 /* Do a cleanup for the first packets of the new second only */
1789 if (packets < (la->udpLinkCount + la->tcpLinkCount)) {
1790 struct alias_link * lnk = TAILQ_FIRST(&la->checkExpire);
1791
1792 CleanupLink(la, &lnk, 0);
1793 }
1794}
1795
1796/* Init the log file and enable logging */
1797static int
1799{
1802#ifdef _KERNEL
1803 if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
1804 ;
1805#else
1806 if ((la->logDesc = fopen("/var/log/alias.log", "w")))
1807 fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
1808#endif
1809 else
1810 return (ENOMEM); /* log initialization failed */
1812 }
1813
1814 return (1);
1815}
1816
1817/* Close the log-file and disable logging. */
1818static void
1820{
1822 if (la->logDesc) {
1823#ifdef _KERNEL
1824 free(la->logDesc);
1825#else
1826 fclose(la->logDesc);
1827#endif
1828 la->logDesc = NULL;
1829 }
1830 la->packetAliasMode &= ~PKT_ALIAS_LOG;
1831}
1832
1833/* Outside world interfaces
1834
1835-- "outside world" means other than alias*.c routines --
1836
1837 PacketAliasRedirectPort()
1838 PacketAliasAddServer()
1839 PacketAliasRedirectProto()
1840 PacketAliasRedirectAddr()
1841 PacketAliasRedirectDynamic()
1842 PacketAliasRedirectDelete()
1843 PacketAliasSetAddress()
1844 PacketAliasInit()
1845 PacketAliasUninit()
1846 PacketAliasSetMode()
1847
1848(prototypes in alias.h)
1849*/
1850
1851/* Redirection from a specific public addr:port to a
1852 private addr:port */
1853struct alias_link *
1855 struct in_addr dst_addr, u_short dst_port,
1856 struct in_addr alias_addr, u_short alias_port,
1857 u_char proto)
1858{
1859 int link_type;
1860 struct alias_link *lnk;
1861
1863 switch (proto) {
1864 case IPPROTO_UDP:
1866 break;
1867 case IPPROTO_TCP:
1869 break;
1870 case IPPROTO_SCTP:
1872 break;
1873 default:
1874#ifdef LIBALIAS_DEBUG
1875 fprintf(stderr, "PacketAliasRedirectPort(): ");
1876 fprintf(stderr, "only SCTP, TCP and UDP protocols allowed\n");
1877#endif
1878 lnk = NULL;
1879 goto getout;
1880 }
1881
1884 link_type);
1885
1886 if (lnk != NULL) {
1887 lnk->flags |= LINK_PERMANENT;
1888 }
1889#ifdef LIBALIAS_DEBUG
1890 else {
1891 fprintf(stderr, "PacketAliasRedirectPort(): "
1892 "call to AddLink() failed\n");
1893 }
1894#endif
1895
1896getout:
1898 return (lnk);
1899}
1900
1901/* Add server to the pool of servers */
1902int
1903LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
1904{
1905 struct server *server;
1906 int res;
1907
1908 LIBALIAS_LOCK(la);
1909 (void)la;
1910
1911 switch (lnk->link_type) {
1912 case LINK_PPTP:
1913 server = NULL;
1914 break;
1915 default:
1916 server = malloc(sizeof(struct server));
1917 break;
1918 }
1919
1920 if (server != NULL) {
1921 struct server *head;
1922
1923 server->addr = addr;
1924 server->port = port;
1925
1926 head = lnk->server;
1927 if (head == NULL) {
1928 server->next = server;
1929 /* not usable for outgoing connections */
1930 SPLAY_REMOVE(splay_out, &la->linkSplayOut, lnk);
1931 } else {
1932 struct server *s;
1933
1934 for (s = head; s->next != head; s = s->next)
1935 ;
1936 s->next = server;
1937 server->next = head;
1938 }
1939 lnk->server = server;
1940 res = 0;
1941 } else
1942 res = -1;
1943
1944 LIBALIAS_UNLOCK(la);
1945 return (res);
1946}
1947
1948/* Redirect packets of a given IP protocol from a specific
1949 public address to a private address */
1950struct alias_link *
1952 struct in_addr dst_addr,
1953 struct in_addr alias_addr,
1954 u_char proto)
1955{
1956 struct alias_link *lnk;
1957
1961 proto);
1962
1963 if (lnk != NULL) {
1964 lnk->flags |= LINK_PERMANENT;
1965 }
1966#ifdef LIBALIAS_DEBUG
1967 else {
1968 fprintf(stderr, "PacketAliasRedirectProto(): "
1969 "call to AddLink() failed\n");
1970 }
1971#endif
1972
1974 return (lnk);
1975}
1976
1977/* Static address translation */
1978struct alias_link *
1980 struct in_addr alias_addr)
1981{
1982 struct alias_link *lnk;
1983
1986 0, 0, 0,
1987 LINK_ADDR);
1988
1989 if (lnk != NULL) {
1990 lnk->flags |= LINK_PERMANENT;
1991 }
1992#ifdef LIBALIAS_DEBUG
1993 else {
1994 fprintf(stderr, "PacketAliasRedirectAddr(): "
1995 "call to AddLink() failed\n");
1996 }
1997#endif
1998
2000 return (lnk);
2001}
2002
2003/* Mark the aliasing link dynamic */
2004int
2006{
2007 int res;
2008
2010 (void)la;
2011
2013 res = -1;
2014 else {
2015 lnk->flags &= ~LINK_PERMANENT;
2016 res = 0;
2017 }
2019 return (res);
2020}
2021
2022/* This is a dangerous function to put in the API,
2023 because an invalid pointer can crash the program. */
2024void
2026{
2028 (void)la;
2029 DeleteLink(&lnk, 1);
2031}
2032
2033void
2035{
2038 && la->aliasAddress.s_addr != addr.s_addr)
2039 CleanupAliasData(la, 0);
2040
2041 la->aliasAddress = addr;
2043}
2044
2045void
2046LibAliasSetAliasPortRange(struct libalias *la, u_short port_low,
2047 u_short port_high)
2048{
2050 if (port_low) {
2051 la->aliasPortLower = port_low;
2052 /* Add 1 to the aliasPortLength as modulo has range of 1 to n-1 */
2053 la->aliasPortLength = port_high - port_low + 1;
2054 } else {
2055 /* Set default values */
2056 la->aliasPortLower = 0x8000;
2057 la->aliasPortLength = 0x8000;
2058 }
2060}
2061
2062void
2063LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
2064{
2066 la->targetAddress = target_addr;
2068}
2069
2070static void
2072{
2073 while (!LIST_EMPTY(&instancehead))
2074 LibAliasUninit(LIST_FIRST(&instancehead));
2075}
2076
2077struct libalias *
2079{
2080 if (la == NULL) {
2081#ifdef _KERNEL
2082#undef malloc /* XXX: ugly */
2083 la = malloc(sizeof *la, M_ALIAS, M_WAITOK | M_ZERO);
2084#else
2085 la = calloc(sizeof *la, 1);
2086 if (la == NULL)
2087 return (la);
2088#endif
2089
2090#ifndef _KERNEL
2091 /* kernel cleans up on module unload */
2092 if (LIST_EMPTY(&instancehead))
2093 atexit(finishoff);
2094#endif
2095 LIST_INSERT_HEAD(&instancehead, la, instancelist);
2096
2097#ifdef _KERNEL
2098 LibAliasTime = time_uptime;
2099#else
2100 LibAliasTime = time(NULL);
2101#endif
2102
2103 SPLAY_INIT(&la->linkSplayIn);
2104 SPLAY_INIT(&la->linkSplayOut);
2105 LIST_INIT(&la->pptpList);
2106 TAILQ_INIT(&la->checkExpire);
2107#ifdef _KERNEL
2108 AliasSctpInit(la);
2109#endif
2111 LIBALIAS_LOCK(la);
2112 } else {
2113 LIBALIAS_LOCK(la);
2114 CleanupAliasData(la, 1);
2115#ifdef _KERNEL
2116 AliasSctpTerm(la);
2117 AliasSctpInit(la);
2118#endif
2119 }
2120
2123 la->aliasPortLower = 0x8000;
2124 la->aliasPortLength = 0x8000;
2125
2126 la->icmpLinkCount = 0;
2127 la->udpLinkCount = 0;
2128 la->tcpLinkCount = 0;
2129 la->sctpLinkCount = 0;
2130 la->pptpLinkCount = 0;
2131 la->protoLinkCount = 0;
2132 la->fragmentIdLinkCount = 0;
2133 la->fragmentPtrLinkCount = 0;
2134 la->sockCount = 0;
2135
2137#ifndef NO_USE_SOCKETS
2138 | PKT_ALIAS_USE_SOCKETS
2139#endif
2141#ifndef NO_FW_PUNCH
2142 la->fireWallFD = -1;
2143#endif
2144#ifndef _KERNEL
2146#endif
2147 LIBALIAS_UNLOCK(la);
2148 return (la);
2149}
2150
2151void
2153{
2154 LIBALIAS_LOCK(la);
2155#ifdef _KERNEL
2156 AliasSctpTerm(la);
2157#endif
2158 CleanupAliasData(la, 1);
2160#ifndef NO_FW_PUNCH
2161 UninitPunchFW(la);
2162#endif
2163 LIST_REMOVE(la, instancelist);
2164 LIBALIAS_UNLOCK(la);
2166 free(la);
2167}
2168
2169/* Change mode for some operations */
2170unsigned int
2172 struct libalias *la,
2173 unsigned int flags, /* Which state to bring flags to */
2174 unsigned int mask /* Mask of which flags to affect (use 0 to
2175 * do a probe for flag values) */
2176)
2177{
2178 int res = -1;
2179
2180 LIBALIAS_LOCK(la);
2181 if (flags & mask & PKT_ALIAS_LOG) {
2182 /* Enable logging */
2183 if (InitPacketAliasLog(la) == ENOMEM)
2184 goto getout;
2185 } else if (~flags & mask & PKT_ALIAS_LOG)
2186 /* _Disable_ logging */
2188
2189#ifndef NO_FW_PUNCH
2190 if (flags & mask & PKT_ALIAS_PUNCH_FW)
2191 /* Start punching holes in the firewall? */
2192 InitPunchFW(la);
2193 else if (~flags & mask & PKT_ALIAS_PUNCH_FW)
2194 /* Stop punching holes in the firewall? */
2195 UninitPunchFW(la);
2196#endif
2197
2198 /* Other flags can be set/cleared without special action */
2199 la->packetAliasMode = (flags & mask) | (la->packetAliasMode & ~mask);
2200 res = la->packetAliasMode;
2201getout:
2202 LIBALIAS_UNLOCK(la);
2203 return (res);
2204}
2205
2206#ifndef NO_FW_PUNCH
2207
2208/*****************
2209 Code to support firewall punching. This shouldn't really be in this
2210 file, but making variables global is evil too.
2211 ****************/
2212
2213/* Firewall include files */
2214#include <net/if.h>
2215#include <netinet/ip_fw.h>
2216#include <string.h>
2217#include <err.h>
2218
2219/*
2220 * helper function, updates the pointer to cmd with the length
2221 * of the current command, and also cleans up the first word of
2222 * the new command in case it has been clobbered before.
2223 */
2224static ipfw_insn *
2226{
2227 cmd += F_LEN(cmd);
2228 bzero(cmd, sizeof(*cmd));
2229 return (cmd);
2230}
2231
2232/*
2233 * A function to fill simple commands of size 1.
2234 * Existing flags are preserved.
2235 */
2236static ipfw_insn *
2237fill_cmd(ipfw_insn * cmd, enum ipfw_opcodes opcode, int size,
2238 int flags, u_int16_t arg)
2239{
2240 cmd->opcode = opcode;
2241 cmd->len = ((cmd->len | flags) & (F_NOT | F_OR)) | (size & F_LEN_MASK);
2242 cmd->arg1 = arg;
2243 return next_cmd(cmd);
2244}
2245
2246static ipfw_insn *
2247fill_ip(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
2248{
2249 ipfw_insn_ip *cmd = (ipfw_insn_ip *)cmd1;
2250
2251 cmd->addr.s_addr = addr;
2252 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u32), 0, 0);
2253}
2254
2255static ipfw_insn *
2256fill_one_port(ipfw_insn * cmd1, enum ipfw_opcodes opcode, u_int16_t port)
2257{
2258 ipfw_insn_u16 *cmd = (ipfw_insn_u16 *)cmd1;
2259
2260 cmd->ports[0] = cmd->ports[1] = port;
2261 return fill_cmd(cmd1, opcode, F_INSN_SIZE(ipfw_insn_u16), 0, 0);
2262}
2263
2264static int
2265fill_rule(void *buf, int bufsize, int rulenum,
2266 enum ipfw_opcodes action, int proto,
2267 struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
2268{
2269 struct ip_fw *rule = (struct ip_fw *)buf;
2270 ipfw_insn *cmd = (ipfw_insn *)rule->cmd;
2271
2272 bzero(buf, bufsize);
2273 rule->rulenum = rulenum;
2274
2275 cmd = fill_cmd(cmd, O_PROTO, F_INSN_SIZE(ipfw_insn), 0, proto);
2276 cmd = fill_ip(cmd, O_IP_SRC, sa.s_addr);
2277 cmd = fill_one_port(cmd, O_IP_SRCPORT, sp);
2278 cmd = fill_ip(cmd, O_IP_DST, da.s_addr);
2279 cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
2280
2281 rule->act_ofs = (u_int32_t *)cmd - (u_int32_t *)rule->cmd;
2282 cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
2283
2284 rule->cmd_len = (u_int32_t *)cmd - (u_int32_t *)rule->cmd;
2285
2286 return ((char *)cmd - (char *)buf);
2287}
2288
2289static void
2291{
2292 la->fireWallField = malloc(la->fireWallNumNums);
2293 if (la->fireWallField) {
2294 memset(la->fireWallField, 0, la->fireWallNumNums);
2295 if (la->fireWallFD < 0) {
2296 la->fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
2297 }
2298 ClearAllFWHoles(la);
2300 }
2301}
2302
2303static void
2305{
2306 ClearAllFWHoles(la);
2307 if (la->fireWallFD >= 0)
2308 close(la->fireWallFD);
2309 la->fireWallFD = -1;
2310 if (la->fireWallField)
2311 free(la->fireWallField);
2312 la->fireWallField = NULL;
2313 la->packetAliasMode &= ~PKT_ALIAS_PUNCH_FW;
2314}
2315
2316/* Make a certain link go through the firewall */
2317void
2319{
2320 struct libalias *la;
2321 int r; /* Result code */
2322 struct ip_fw rule; /* On-the-fly built rule */
2323 int fwhole; /* Where to punch hole */
2324
2325 la = lnk->la;
2326
2327 /* Don't do anything unless we are asked to */
2328 if (!(la->packetAliasMode & PKT_ALIAS_PUNCH_FW) ||
2329 la->fireWallFD < 0 ||
2330 lnk->link_type != LINK_TCP)
2331 return;
2332
2333 memset(&rule, 0, sizeof rule);
2334
2337 /* Find empty slot */
2338 for (fwhole = la->fireWallActiveNum;
2339 fwhole < la->fireWallBaseNum + la->fireWallNumNums &&
2340 fw_tstfield(la, la->fireWallField, fwhole);
2341 fwhole++);
2342 if (fwhole == la->fireWallBaseNum + la->fireWallNumNums) {
2343 for (fwhole = la->fireWallBaseNum;
2344 fwhole < la->fireWallActiveNum &&
2345 fw_tstfield(la, la->fireWallField, fwhole);
2346 fwhole++);
2347 if (fwhole == la->fireWallActiveNum) {
2348 /* No rule point empty - we can't punch more holes. */
2350#ifdef LIBALIAS_DEBUG
2351 fprintf(stderr, "libalias: Unable to create firewall hole!\n");
2352#endif
2353 return;
2354 }
2355 }
2356 /* Start next search at next position */
2357 la->fireWallActiveNum = fwhole + 1;
2358
2359 /*
2360 * generate two rules of the form
2361 *
2362 * add fwhole accept tcp from OAddr OPort to DAddr DPort add fwhole
2363 * accept tcp from DAddr DPort to OAddr OPort
2364 */
2365 if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
2366 u_int32_t rulebuf[255];
2367 int i;
2368
2369 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2371 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
2372 GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
2373 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2374 if (r)
2375 err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
2376
2377 i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
2379 GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
2380 GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
2381 r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
2382 if (r)
2383 err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)");
2384 }
2385
2386 /* Indicate hole applied */
2387 lnk->data.tcp->fwhole = fwhole;
2388 fw_setfield(la, la->fireWallField, fwhole);
2389}
2390
2391/* Remove a hole in a firewall associated with a particular alias
2392 lnk. Calling this too often is harmless. */
2393static void
2395{
2396 struct libalias *la;
2397
2398 la = lnk->la;
2399 if (lnk->link_type == LINK_TCP) {
2400 int fwhole = lnk->data.tcp->fwhole; /* Where is the firewall hole? */
2401 struct ip_fw rule;
2402
2403 if (fwhole < 0)
2404 return;
2405
2406 memset(&rule, 0, sizeof rule); /* useless for ipfw2 */
2407 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL,
2408 &fwhole, sizeof fwhole));
2409 fw_clrfield(la, la->fireWallField, fwhole);
2410 lnk->data.tcp->fwhole = -1;
2411 }
2412}
2413
2414/* Clear out the entire range dedicated to firewall holes. */
2415static void
2417{
2418 struct ip_fw rule; /* On-the-fly built rule */
2419 int i;
2420
2421 if (la->fireWallFD < 0)
2422 return;
2423
2424 memset(&rule, 0, sizeof rule);
2425 for (i = la->fireWallBaseNum; i < la->fireWallBaseNum + la->fireWallNumNums; i++) {
2426 int r = i;
2427
2428 while (!setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_DEL, &r, sizeof r));
2429 }
2430 /* XXX: third arg correct here ? /phk */
2431 memset(la->fireWallField, 0, la->fireWallNumNums);
2432}
2433
2434#endif /* !NO_FW_PUNCH */
2435
2436void
2437LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
2438{
2439 LIBALIAS_LOCK(la);
2440#ifndef NO_FW_PUNCH
2441 la->fireWallBaseNum = base;
2442 la->fireWallNumNums = num;
2443#endif
2444 LIBALIAS_UNLOCK(la);
2445}
2446
2447void
2448LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
2449{
2450 LIBALIAS_LOCK(la);
2451 la->skinnyPort = port;
2452 LIBALIAS_UNLOCK(la);
2453}
2454
2455/*
2456 * Find the address to redirect incoming packets
2457 */
2458struct in_addr
2460{
2461 struct alias_link *lnk;
2462 struct in_addr redir;
2463
2465 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2466 sm->sctp_hdr->dest_port,sm->sctp_hdr->dest_port, LINK_SCTP, 1);
2467 if (lnk != NULL) {
2468 /* port redirect */
2469 return (lnk->src_addr);
2470 } else {
2471 redir = FindOriginalAddress(la,sm->ip_hdr->ip_dst);
2472 if (redir.s_addr == la->aliasAddress.s_addr ||
2473 redir.s_addr == la->targetAddress.s_addr) {
2474 /* No address found */
2475 lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst,
2476 NO_DEST_PORT, 0, LINK_SCTP, 1);
2477 if (lnk != NULL)
2478 /* redirect proto */
2479 return (lnk->src_addr);
2480 }
2481 return (redir); /* address redirect */
2482 }
2483}
#define PKT_ALIAS_LOG
Definition: alias.h:147
int LibAliasRefreshModules(void)
#define PKT_ALIAS_DENY_INCOMING
Definition: alias.h:153
#define LIBALIAS_BUF_SIZE
Definition: alias.h:48
#define PKT_ALIAS_RESET_ON_ADDR_CHANGE
Definition: alias.h:193
#define PKT_ALIAS_SAME_PORTS
Definition: alias.h:162
struct in_addr FindOriginalAddress(struct libalias *la, struct in_addr alias_addr)
Definition: alias_db.c:1332
void LibAliasSetTarget(struct libalias *la, struct in_addr target_addr)
Definition: alias_db.c:2063
struct alias_link * FindUdpTcpIn(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_short dst_port, u_short alias_port, u_char proto, int create)
Definition: alias_db.c:1135
static struct alias_link * _FindLinkIn(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_short dst_port, u_short alias_port, int link_type, int replace_partial_links)
Definition: alias_db.c:834
unsigned int LibAliasSetMode(struct libalias *la, unsigned int flags, unsigned int mask)
Definition: alias_db.c:2171
void SetFragmentAddr(struct alias_link *lnk, struct in_addr src_addr)
Definition: alias_db.c:1397
struct alias_link * LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_port, struct in_addr dst_addr, u_short dst_port, struct in_addr alias_addr, u_short alias_port, u_char proto)
Definition: alias_db.c:1854
void LibAliasRedirectDelete(struct libalias *la, struct alias_link *lnk)
Definition: alias_db.c:2025
static void UninitPacketAliasLog(struct libalias *la)
Definition: alias_db.c:1819
u_short GetAliasPort(struct alias_link *lnk)
Definition: alias_db.c:1529
struct alias_link * FindProtoIn(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_char proto)
Definition: alias_db.c:1089
void SetProxyAddress(struct alias_link *lnk, struct in_addr addr)
Definition: alias_db.c:1557
void SetFragmentPtr(struct alias_link *lnk, void *fptr)
Definition: alias_db.c:1409
int GetAckModified(struct alias_link *lnk)
Definition: alias_db.c:1576
void PunchFWHole(struct alias_link *lnk)
Definition: alias_db.c:2318
static struct alias_link * ReLink(struct alias_link *old_lnk, struct in_addr src_addr, struct in_addr dst_addr, struct in_addr alias_addr, u_short src_port, u_short dst_port, int alias_port_param, int link_type, int deletePermanent)
Definition: alias_db.c:719
struct alias_link * LibAliasRedirectAddr(struct libalias *la, struct in_addr src_addr, struct in_addr alias_addr)
Definition: alias_db.c:1979
void SetStateIn(struct alias_link *lnk, int state)
Definition: alias_db.c:1421
u_short GetProxyPort(struct alias_link *lnk)
Definition: alias_db.c:1563
static moduledata_t alias_mod
Definition: alias_db.c:89
static void UninitPunchFW(struct libalias *la)
Definition: alias_db.c:2304
struct libalias * LibAliasInit(struct libalias *la)
Definition: alias_db.c:2078
void LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
Definition: alias_db.c:2448
int GetDeltaAckIn(u_long ack, struct alias_link *lnk)
Definition: alias_db.c:1588
static void CleanupLink(struct libalias *la, struct alias_link **lnk, int deletePermanent)
Definition: alias_db.c:434
static int fill_rule(void *buf, int bufsize, int rulenum, enum ipfw_opcodes action, int proto, struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
Definition: alias_db.c:2265
void SetStateOut(struct alias_link *lnk, int state)
Definition: alias_db.c:1446
struct in_addr GetAliasAddress(struct alias_link *lnk)
Definition: alias_db.c:1500
static int GetNewPort(struct libalias *la, struct alias_link *lnk, int alias_port_param)
Definition: alias_db.c:207
void SetDefaultAliasAddress(struct libalias *la, struct in_addr alias_addr)
Definition: alias_db.c:1516
static void ShowAliasStats(struct libalias *la)
Definition: alias_db.c:157
void LibAliasSetAliasPortRange(struct libalias *la, u_short port_low, u_short port_high)
Definition: alias_db.c:2046
struct alias_link * FindPptpOutByPeerCallId(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_int16_t dst_call_id)
Definition: alias_db.c:1244
struct alias_link * FindIcmpIn(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_short id_alias, int create)
Definition: alias_db.c:992
static void ClearAllFWHoles(struct libalias *la)
Definition: alias_db.c:2416
SPLAY_GENERATE(splay_out, alias_link, all.out, cmp_out)
static ipfw_insn * next_cmd(ipfw_insn *cmd)
Definition: alias_db.c:2225
void LibAliasSetFWBase(struct libalias *la, unsigned int base, unsigned int num)
Definition: alias_db.c:2437
static u_short _RandomPort(struct libalias *la)
Definition: alias_db.c:192
static void ClearFWHole(struct alias_link *lnk)
Definition: alias_db.c:2394
struct in_addr GetDestAddress(struct alias_link *lnk)
Definition: alias_db.c:1494
void GetFragmentAddr(struct alias_link *lnk, struct in_addr *src_addr)
Definition: alias_db.c:1403
int LibAliasAddServer(struct libalias *la, struct alias_link *lnk, struct in_addr addr, u_short port)
Definition: alias_db.c:1903
struct in_addr FindAliasAddress(struct libalias *la, struct in_addr original_addr)
Definition: alias_db.c:1363
struct alias_link * FindFragmentIn2(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_short ip_id)
Definition: alias_db.c:1059
struct alias_link * FindFragmentIn1(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_short ip_id)
Definition: alias_db.c:1038
void SetExpire(struct alias_link *lnk, int expire)
Definition: alias_db.c:1699
struct alias_link * FindPptpInByPeerCallId(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_int16_t alias_call_id)
Definition: alias_db.c:1279
struct alias_link * FindPptpOutByCallId(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_int16_t src_call_id)
Definition: alias_db.c:1227
struct in_addr GetProxyAddress(struct alias_link *lnk)
Definition: alias_db.c:1551
struct alias_link * AddPptp(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, struct in_addr alias_addr, u_int16_t src_call_id)
Definition: alias_db.c:1211
struct alias_link * FindIcmpOut(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_short id, int create)
Definition: alias_db.c:1015
struct alias_link * FindProtoOut(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_char proto)
Definition: alias_db.c:1112
static struct alias_link * UseLink(struct libalias *la, struct alias_link *lnk)
Definition: alias_db.c:453
int GetProtocolFlags(struct alias_link *lnk)
Definition: alias_db.c:1723
__FBSDID("$FreeBSD$")
struct alias_link * FindPptpInByCallId(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_int16_t dst_call_id)
Definition: alias_db.c:1261
int GetStateOut(struct alias_link *lnk)
Definition: alias_db.c:1478
void GetFragmentPtr(struct alias_link *lnk, void **fptr)
Definition: alias_db.c:1415
static void finishoff(void)
Definition: alias_db.c:2071
struct alias_link * AddFragmentPtrLink(struct libalias *la, struct in_addr dst_addr, u_short ip_id)
Definition: alias_db.c:1069
struct alias_link * FindRtspOut(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_short src_port, u_short alias_port, u_char proto)
Definition: alias_db.c:1296
static ipfw_insn * fill_one_port(ipfw_insn *cmd1, enum ipfw_opcodes opcode, u_int16_t port)
Definition: alias_db.c:2256
void HouseKeeping(struct libalias *la)
Definition: alias_db.c:1753
int LibAliasRedirectDynamic(struct libalias *la, struct alias_link *lnk)
Definition: alias_db.c:2005
void LibAliasUninit(struct libalias *la)
Definition: alias_db.c:2152
static ipfw_insn * fill_cmd(ipfw_insn *cmd, enum ipfw_opcodes opcode, int size, int flags, u_int16_t arg)
Definition: alias_db.c:2237
static void AliasLog(char *str, const char *format,...)
Definition: alias_db.c:135
static struct alias_link * FindLinkOut(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_short src_port, u_short dst_port, int link_type, int replace_partial_links)
Definition: alias_db.c:804
static int SeqDiff(u_long x, u_long y)
Definition: alias_db.c:124
int GetStateIn(struct alias_link *lnk)
Definition: alias_db.c:1471
static int InitPacketAliasLog(struct libalias *la)
Definition: alias_db.c:1798
static void DeleteLink(struct alias_link **plnk, int deletePermanent)
Definition: alias_db.c:462
struct in_addr GetOriginalAddress(struct alias_link *lnk)
Definition: alias_db.c:1485
static u_short GetDestPort(struct alias_link *lnk)
Definition: alias_db.c:1536
static void CleanupAliasData(struct libalias *la, int deletePermanent)
Definition: alias_db.c:423
static void InitPunchFW(struct libalias *la)
Definition: alias_db.c:2290
static LIST_HEAD(MODULE_VERSION(libalias)
Definition: alias_db.c:66
void SetAckModified(struct alias_link *lnk)
Definition: alias_db.c:1545
static struct alias_link * FindLinkIn(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_short dst_port, u_short alias_port, int link_type, int replace_partial_links)
Definition: alias_db.c:946
void SetDestCallId(struct alias_link *lnk, u_int16_t cid)
Definition: alias_db.c:1729
static ipfw_insn * fill_ip(ipfw_insn *cmd1, enum ipfw_opcodes opcode, u_int32_t addr)
Definition: alias_db.c:2247
struct in_addr FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm)
Definition: alias_db.c:2459
struct alias_link * LibAliasRedirectProto(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, struct in_addr alias_addr, u_char proto)
Definition: alias_db.c:1951
static struct group_in * StartPointIn(struct libalias *la, struct in_addr alias_addr, u_short alias_port, int link_type, int create)
Definition: alias_db.c:100
static struct alias_link * _FindLinkOut(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_short src_port, u_short dst_port, int link_type, int replace_partial_links)
Definition: alias_db.c:767
struct alias_link * AddLink(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, struct in_addr alias_addr, u_short src_port, u_short dst_port, int alias_port_param, int link_type)
Definition: alias_db.c:564
void SetProxyPort(struct alias_link *lnk, u_short port)
Definition: alias_db.c:1569
static struct alias_link * _SearchLinkOut(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_short src_port, u_short dst_port, int link_type)
Definition: alias_db.c:748
void LibAliasSetAddress(struct libalias *la, struct in_addr addr)
Definition: alias_db.c:2034
DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND)
u_short GetOriginalPort(struct alias_link *lnk)
Definition: alias_db.c:1523
static u_short GetSocket(struct libalias *la, u_short port_net, int *sockfd, int link_type)
Definition: alias_db.c:293
struct alias_link * FindFragmentPtr(struct libalias *la, struct in_addr dst_addr, u_short ip_id)
Definition: alias_db.c:1079
void SetProtocolFlags(struct alias_link *lnk, int pflags)
Definition: alias_db.c:1717
int FindNewPortGroup(struct libalias *la, struct in_addr dst_addr, struct in_addr alias_addr, u_short src_port, u_short dst_port, u_short port_count, u_char proto, u_char align)
Definition: alias_db.c:344
struct in_addr GetDefaultAliasAddress(struct libalias *la)
Definition: alias_db.c:1509
void AddSeq(struct alias_link *lnk, int delta, u_int ip_hl, u_short ip_len, u_long th_seq, u_int th_off)
Definition: alias_db.c:1672
int GetDeltaSeqOut(u_long seq, struct alias_link *lnk)
Definition: alias_db.c:1630
struct alias_link * FindUdpTcpOut(struct libalias *la, struct in_addr src_addr, struct in_addr dst_addr, u_short src_port, u_short dst_port, u_char proto, int create)
Definition: alias_db.c:1174
#define LINK_FRAGMENT_ID
Definition: alias_db.h:272
#define ICMP_EXPIRE_TIME
Definition: alias_db.h:153
#define GET_NEW_PORT_MAX_ATTEMPTS
Definition: alias_db.h:422
#define TCP_EXPIRE_SINGLEDEAD
Definition: alias_db.h:169
#define LINK_UNKNOWN_DEST_ADDR
Definition: alias_db.h:281
#define TCP_EXPIRE_CONNECTED
Definition: alias_db.h:179
#define LINK_UDP
Definition: alias_db.h:270
#define LINK_PPTP
Definition: alias_db.h:275
#define NO_SRC_PORT
Definition: alias_db.h:187
#define LINK_TCP
Definition: alias_db.h:271
static struct in_addr const ANY_ADDR
Definition: alias_db.h:190
static int cmp_out(struct alias_link *a, struct alias_link *b)
Definition: alias_db.h:351
#define LINK_ADDR
Definition: alias_db.h:274
static int cmp_in(struct group_in *a, struct group_in *b)
Definition: alias_db.h:366
#define LINK_ICMP
Definition: alias_db.h:269
#define LINK_UNKNOWN_DEST_PORT
Definition: alias_db.h:280
#define LINK_FRAGMENT_PTR
Definition: alias_db.h:273
#define LINK_PERMANENT
Definition: alias_db.h:282
#define FRAGMENT_PTR_EXPIRE_TIME
Definition: alias_db.h:157
#define UDP_EXPIRE_TIME
Definition: alias_db.h:154
#define fw_clrfield(la, field, num)
Definition: alias_db.h:434
#define FRAGMENT_ID_EXPIRE_TIME
Definition: alias_db.h:156
#define TCP_EXPIRE_DEAD
Definition: alias_db.h:163
#define N_LINK_TCP_DATA
Definition: alias_db.h:238
#define fw_tstfield(la, field, num)
Definition: alias_db.h:439
#define LINK_PARTIALLY_SPECIFIED
Definition: alias_db.h:283
#define TCP_EXPIRE_INITIAL
Definition: alias_db.h:174
#define NO_DEST_PORT
Definition: alias_db.h:186
#define fw_setfield(la, field, num)
Definition: alias_db.h:429
#define PROTO_EXPIRE_TIME
Definition: alias_db.h:155
#define LIBALIAS_LOCK_ASSERT(l)
Definition: alias_local.h:174
#define GET_ALIAS_PORT
Definition: alias_local.h:70
#define GET_ALIAS_ID
Definition: alias_local.h:71
#define INADDR_NONE
Definition: alias_local.h:62
int LibAliasTime
void AliasSctpTerm(struct libalias *la)
Cleans-up the SCTP NAT Implementation prior to unloading.
Definition: alias_sctp.c:694
#define LIBALIAS_LOCK_DESTROY(l)
Definition: alias_local.h:177
#define LIBALIAS_LOCK_INIT(l)
Definition: alias_local.h:172
#define LIBALIAS_LOCK(l)
Definition: alias_local.h:175
#define LIBALIAS_UNLOCK(l)
Definition: alias_local.h:176
void AliasSctpInit(struct libalias *la)
Initialises the SCTP NAT Implementation.
Definition: alias_sctp.c:653
@ ALIAS_TCP_STATE_NOT_CONNECTED
Definition: alias_local.h:351
@ ALIAS_TCP_STATE_CONNECTED
Definition: alias_local.h:352
@ ALIAS_TCP_STATE_DISCONNECTED
Definition: alias_local.h:353
#define LINK_SCTP
Definition: alias_sctp.h:98
MALLOC_DEFINE(M_CC_MEM, "CC Mem", "Congestion Control State memory")
MODULE_VERSION(cdg, 2)
void SctpShowAliasStats(struct libalias *la)
Log current statistics for the libalias instance.
Definition: alias_db.c:185
#define INADDR_ANY
Definition: in.h:48
#define IPPROTO_TCP
Definition: in.h:45
#define IPPROTO_UDP
Definition: in.h:46
#define IPPROTO_IP
Definition: in.h:43
u_char ip_hl
Definition: ip.h:1
u_short ip_len
Definition: ip.h:9
u_short ip_id
Definition: ip.h:10
struct ip_fw * rule
Definition: ip_fw.h:1
#define F_LEN(cmd)
Definition: ip_fw.h:347
ipfw_dyn_rule * next
Definition: ip_fw.h:0
#define F_OR
Definition: ip_fw.h:345
ipfw_opcodes
Definition: ip_fw.h:166
@ O_IP_DST
Definition: ip_fw.h:174
@ O_IP_SRC
Definition: ip_fw.h:169
@ O_IP_SRCPORT
Definition: ip_fw.h:179
@ O_IP_DSTPORT
Definition: ip_fw.h:180
@ O_ACCEPT
Definition: ip_fw.h:229
@ O_PROTO
Definition: ip_fw.h:181
#define F_INSN_SIZE(t)
Definition: ip_fw.h:356
u_int32_t expire
Definition: ip_fw.h:8
#define F_LEN_MASK
Definition: ip_fw.h:346
u_int32_t state
Definition: ip_fw.h:10
#define F_NOT
Definition: ip_fw.h:344
#define IPPROTO_SCTP
struct in_addr addr
Definition: ip_fw.h:380
u_int16_t ports[2]
Definition: ip_fw.h:363
u_int8_t len
Definition: ip_fw.h:343
u_int16_t arg1
Definition: ip_fw.h:349
u_long ack_new
Definition: alias_db.h:222
u_long ack_old
Definition: alias_db.h:221
u_short alias_port
Definition: alias_local.h:83
struct in_addr alias_addr
Definition: alias_local.h:82
int link_type
Definition: alias_local.h:84
Definition: in.h:83
in_addr_t s_addr
Definition: in.h:84
u_short aliasPortLower
Definition: alias_local.h:145
char * fireWallField
Definition: alias_local.h:134
int fireWallNumNums
Definition: alias_local.h:130
unsigned int fragmentIdLinkCount
Definition: alias_local.h:112
unsigned int pptpLinkCount
Definition: alias_local.h:110
unsigned int skinnyPort
Definition: alias_local.h:137
char * logDesc
Definition: alias_local.h:117
int fireWallFD
Definition: alias_local.h:126
int packetAliasMode
Definition: alias_local.h:92
int fireWallBaseNum
Definition: alias_local.h:128
u_short aliasPortLength
Definition: alias_local.h:146
unsigned int tcpLinkCount
Definition: alias_local.h:109
unsigned int udpLinkCount
Definition: alias_local.h:108
unsigned int protoLinkCount
Definition: alias_local.h:111
struct in_addr targetAddress
Definition: alias_local.h:97
int fireWallActiveNum
Definition: alias_local.h:132
struct in_addr aliasAddress
Definition: alias_local.h:94
unsigned int icmpLinkCount
Definition: alias_local.h:107
unsigned int fragmentPtrLinkCount
Definition: alias_local.h:113
int sctpLinkCount
Definition: alias_local.h:153
unsigned int sockCount
Definition: alias_local.h:114
SCTP message.
Definition: alias_sctp.h:166
struct in_addr addr
Definition: alias_db.h:248
u_short port
Definition: alias_db.h:249
struct server * next
Definition: alias_db.h:250
Definition: in.h:97
struct in_addr sin_addr
Definition: in.h:101
sa_family_t sin_family
Definition: in.h:99
in_port_t sin_port
Definition: in.h:100
int fwhole
Definition: alias_db.h:243
struct ack_data_record ack[N_LINK_TCP_DATA]
Definition: alias_db.h:241
struct tcp_state state
Definition: alias_db.h:240
int index
Definition: alias_db.h:231
int in
Definition: alias_db.h:229
int out
Definition: alias_db.h:230
int ack_modified
Definition: alias_db.h:233