FreeBSD kernel IPv4 code
alias_sctp.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2008
5 * Swinburne University of Technology, Melbourne, Australia.
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 AUTHORS 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 AUTHORS 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/*
30 * Alias_sctp forms part of the libalias kernel module to handle
31 * Network Address Translation (NAT) for the SCTP protocol.
32 *
33 * This software was developed by David A. Hayes and Jason But
34 *
35 * The design is outlined in CAIA technical report number 080618A
36 * (D. Hayes and J. But, "Alias_sctp Version 0.1: SCTP NAT implementation in IPFW")
37 *
38 * Development is part of the CAIA SONATA project,
39 * proposed by Jason But and Grenville Armitage:
40 * http://caia.swin.edu.au/urp/sonata/
41 *
42 *
43 * This project has been made possible in part by a grant from
44 * the Cisco University Research Program Fund at Community
45 * Foundation Silicon Valley.
46 *
47 */
73/* $FreeBSD$ */
74
75#ifdef _KERNEL
76#include <machine/stdarg.h>
77#include <sys/param.h>
78#include <sys/gsb_crc32.h>
79#include <sys/systm.h>
80#include <sys/kernel.h>
81#include <sys/module.h>
82#include <sys/syslog.h>
86#include <netinet/sctp_crc32.h>
87#include <machine/in_cksum.h>
88#else
89#include "alias_sctp.h"
90#include <arpa/inet.h>
91#include "alias.h"
92#include "alias_local.h"
93#include <machine/in_cksum.h>
94#include <sys/libkern.h>
95#endif //#ifdef _KERNEL
96
97/* ----------------------------------------------------------------------
98 * FUNCTION PROTOTYPES
99 * ----------------------------------------------------------------------
100 */
101/* Packet Parsing Functions */
102static int sctp_PktParser(struct libalias *la, int direction, struct ip *pip,
103 struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc);
104static int GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm,
105 uint32_t *l_vtag, uint32_t *g_vtag, int direction);
106static int IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction);
107
108static void AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction);
109static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr);
110static void RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction);
111static int IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction);
112
113/* State Machine Functions */
114static int ProcessSctpMsg(struct libalias *la, int direction, \
115 struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc);
116
117static int ID_process(struct libalias *la, int direction,\
118 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
119static int INi_process(struct libalias *la, int direction,\
120 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
121static int INa_process(struct libalias *la, int direction,\
122 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
123static int UP_process(struct libalias *la, int direction,\
124 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
125static int CL_process(struct libalias *la, int direction,\
126 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
127static void TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm,\
128 struct sctp_nat_assoc *assoc, int sndrply, int direction);
129
130/* Hash Table Functions */
131static struct sctp_nat_assoc *
133static struct sctp_nat_assoc *
134FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match);
135static struct sctp_nat_assoc *
136FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc);
137static struct sctp_nat_assoc *
139static struct sctp_nat_assoc *
141
142static int AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_addr g_addr);
143static int AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc);
144static void RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc);
145static void freeGlobalAddressList(struct sctp_nat_assoc *assoc);
146
147/* Timer Queue Functions */
148static void sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc);
149static void sctp_RmTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc);
150static void sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp);
151void sctp_CheckTimers(struct libalias *la);
152
153/* Logging Functions */
154static void logsctperror(char *errormsg, uint32_t vtag, int error, int direction);
155static void logsctpparse(int direction, struct sctp_nat_msg *sm);
156static void logsctpassoc(struct sctp_nat_assoc *assoc, char *s);
157static void logTimerQ(struct libalias *la);
158static void logSctpGlobal(struct libalias *la);
159static void logSctpLocal(struct libalias *la);
160#ifdef _KERNEL
161static void SctpAliasLog(const char *format, ...);
162#endif
163
182void SctpShowAliasStats(struct libalias *la);
183
184#ifdef _KERNEL
185
186static MALLOC_DEFINE(M_SCTPNAT, "sctpnat", "sctp nat dbs");
187/* Use kernel allocator. */
188#ifdef _SYS_MALLOC_H_
189#define sn_malloc(x) malloc(x, M_SCTPNAT, M_NOWAIT|M_ZERO)
190#define sn_calloc(n,x) mallocarray((n), (x), M_SCTPNAT, M_NOWAIT|M_ZERO)
191#define sn_free(x) free(x, M_SCTPNAT)
192#endif// #ifdef _SYS_MALLOC_H_
193
194#else //#ifdef _KERNEL
195#define sn_malloc(x) malloc(x)
196#define sn_calloc(n, x) calloc(n, x)
197#define sn_free(x) free(x)
198
199#endif //#ifdef _KERNEL
200
209#define SN_SCTP_FIRSTCHUNK(sctphead) (struct sctp_chunkhdr *)(((char *)sctphead) + sizeof(struct sctphdr))
212#define SN_SCTP_NEXTCHUNK(chunkhead) (struct sctp_chunkhdr *)(((char *)chunkhead) + SCTP_SIZE32(ntohs(chunkhead->chunk_length)))
215#define SN_SCTP_NEXTPARAM(param) (struct sctp_paramhdr *)(((char *)param) + SCTP_SIZE32(ntohs(param->param_length)))
218#define SN_MIN_CHUNK_SIZE 4
219#define SN_MIN_PARAM_SIZE 4
220#define SN_VTAG_PARAM_SIZE 12
221#define SN_ASCONFACK_PARAM_SIZE 8
223/* Packet parsing return codes */
224#define SN_PARSE_OK 0
225#define SN_PARSE_ERROR_IPSHL 1
226#define SN_PARSE_ERROR_AS_MALLOC 2
227#define SN_PARSE_ERROR_CHHL 3
228#define SN_PARSE_ERROR_DIR 4
229#define SN_PARSE_ERROR_VTAG 5
230#define SN_PARSE_ERROR_CHUNK 6
231#define SN_PARSE_ERROR_PORT 7
232#define SN_PARSE_ERROR_LOOKUP 8
233#define SN_PARSE_ERROR_PARTIALLOOKUP 9
234#define SN_PARSE_ERROR_LOOKUP_ABORT 10
236/* Alias_sctp performs its processing based on a number of key messages */
237#define SN_SCTP_ABORT 0x0000
238#define SN_SCTP_INIT 0x0001
239#define SN_SCTP_INITACK 0x0002
240#define SN_SCTP_SHUTCOMP 0x0010
241#define SN_SCTP_SHUTACK 0x0020
242#define SN_SCTP_ASCONF 0x0100
243#define SN_SCTP_ASCONFACK 0x0200
244#define SN_SCTP_OTHER 0xFFFF
250#define SN_ID 0x0000
251#define SN_INi 0x0010
252#define SN_INa 0x0020
253#define SN_UP 0x0100
254#define SN_CL 0x1000
255#define SN_RM 0x2000
262#define SN_LOG_LOW 0
263#define SN_LOG_EVENT 1
264#define SN_LOG_INFO 2
265#define SN_LOG_DETAIL 3
266#define SN_LOG_DEBUG 4
267#define SN_LOG_DEBUG_MAX 5
269#define SN_LOG(level, action) if (sysctl_log_level >= level) { action; }
275#define SN_MIN_HASH_SIZE 101
276#define SN_MAX_HASH_SIZE 1000001
277#define SN_DEFAULT_HASH_SIZE 2003
279#define SN_LOCAL_TBL 0x01
280#define SN_GLOBAL_TBL 0x02
281#define SN_BOTH_TBL 0x03
282#define SN_WAIT_TOLOCAL 0x10
283#define SN_WAIT_TOGLOBAL 0x20
284#define SN_NULL_TBL 0x00
285#define SN_MAX_GLOBAL_ADDRESSES 100
287#define SN_ADD_OK 0
288#define SN_ADD_CLASH 1
290#define SN_TABLE_HASH(vtag, port, size) (((u_int) vtag + (u_int) port) % (u_int) size)
297#define SN_MIN_TIMER 1
298#define SN_MAX_TIMER 600
299#define SN_TIMER_QUEUE_SIZE SN_MAX_TIMER+2
301#define SN_I_T(la) (LibAliasTime + sysctl_init_timer)
302#define SN_U_T(la) (LibAliasTime + sysctl_up_timer)
303#define SN_C_T(la) (LibAliasTime + sysctl_shutdown_timer)
304#define SN_X_T(la) (LibAliasTime + sysctl_holddown_timer)
312/* Callbacks */
313int sysctl_chg_loglevel(SYSCTL_HANDLER_ARGS);
314int sysctl_chg_timer(SYSCTL_HANDLER_ARGS);
315int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS);
316int sysctl_chg_error_on_ootb(SYSCTL_HANDLER_ARGS);
317int sysctl_chg_accept_global_ootb_addip(SYSCTL_HANDLER_ARGS);
318int sysctl_chg_initialising_chunk_proc_limit(SYSCTL_HANDLER_ARGS);
319int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS);
320int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS);
321int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS);
322
323/* Sysctl variables */
325static u_int sysctl_log_level = 0;
327static u_int sysctl_init_timer = 15;
329static u_int sysctl_up_timer = 300;
331static u_int sysctl_shutdown_timer = 15;
333static u_int sysctl_holddown_timer = 0;
337static u_int sysctl_error_on_ootb = 1;
342static u_int sysctl_accept_global_ootb_addip = 0;
346static u_int sysctl_chunk_proc_limit = 5;
348static u_int sysctl_param_proc_limit = 25;
350static u_int sysctl_track_global_addresses = 0;
353#define SN_NO_ERROR_ON_OOTB 0
354#define SN_LOCAL_ERROR_ON_OOTB 1
355#define SN_LOCALandPARTIAL_ERROR_ON_OOTB 2
356#define SN_ERROR_ON_OOTB 3
358#ifdef SYSCTL_NODE
360SYSCTL_DECL(_net_inet);
361SYSCTL_DECL(_net_inet_ip);
362SYSCTL_DECL(_net_inet_ip_alias);
363
364static SYSCTL_NODE(_net_inet_ip_alias, OID_AUTO, sctp,
365 CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
366 "SCTP NAT");
367SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, log_level,
368 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
370 "Level of detail (0 - default, 1 - event, 2 - info, 3 - detail, 4 - debug, 5 - max debug)");
371SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, init_timer,
372 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
374 "Timeout value (s) while waiting for (INIT-ACK|AddIP-ACK)");
375SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, up_timer,
376 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
378 "Timeout value (s) to keep an association up with no traffic");
379SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, shutdown_timer,
380 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
382 "Timeout value (s) while waiting for SHUTDOWN-COMPLETE");
383SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, holddown_timer,
384 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
386 "Hold association in table for this many seconds after receiving a SHUTDOWN-COMPLETE");
387SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, hashtable_size,
388 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
390 "Size of hash tables used for NAT lookups (100 < prime_number > 1000001)");
391SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, error_on_ootb,
392 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
394 "ErrorM sent on receipt of ootb packet:\n\t0 - none,\n"
395 "\t1 - to local only,\n"
396 "\t2 - to local and global if a partial association match,\n"
397 "\t3 - to local and global (DoS risk)");
398SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, accept_global_ootb_addip,
399 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
401 "NAT response to receipt of global OOTB AddIP:\n"
402 "\t0 - No response,\n"
403 "\t1 - NAT will accept OOTB global AddIP messages for processing (Security risk)");
404SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, initialising_chunk_proc_limit,
405 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
408 "Number of chunks that should be processed if there is no current "
409 "association found:\n\t > 0 (A high value is a DoS risk)");
410SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, chunk_proc_limit,
411 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
413 "Number of chunks that should be processed to find key chunk:\n"
414 "\t>= initialising_chunk_proc_limit (A high value is a DoS risk)");
415SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, param_proc_limit,
416 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
418 "Number of parameters (in a chunk) that should be processed to find key "
419 "parameters:\n\t> 1 (A high value is a DoS risk)");
420SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, track_global_addresses,
421 CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
423 "Configures the global address tracking option within the NAT:\n"
424 "\t0 - Global tracking is disabled,\n"
425 "\t> 0 - enables tracking but limits the number of global IP addresses to this value");
426
427#endif /* SYSCTL_NODE */
435int sysctl_chg_loglevel(SYSCTL_HANDLER_ARGS)
436{
437 u_int level = *(u_int *)arg1;
438 int error;
439
440 error = sysctl_handle_int(oidp, &level, 0, req);
441 if (error)
442 return (error);
443
444 level = (level > SN_LOG_DEBUG_MAX) ? (SN_LOG_DEBUG_MAX) : (level);
445 level = (level < SN_LOG_LOW) ? (SN_LOG_LOW) : (level);
446 sysctl_log_level = level;
447 return (0);
448}
449
457int sysctl_chg_timer(SYSCTL_HANDLER_ARGS)
458{
459 u_int timer = *(u_int *)arg1;
460 int error;
461
462 error = sysctl_handle_int(oidp, &timer, 0, req);
463 if (error)
464 return (error);
465
466 timer = (timer > SN_MAX_TIMER) ? (SN_MAX_TIMER) : (timer);
467
468 if (((u_int *)arg1) != &sysctl_holddown_timer) {
469 timer = (timer < SN_MIN_TIMER) ? (SN_MIN_TIMER) : (timer);
470 }
471
472 *(u_int *)arg1 = timer;
473
474 return (0);
475}
476
486int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS)
487{
488 u_int size = *(u_int *)arg1;
489 int error;
490
491 error = sysctl_handle_int(oidp, &size, 0, req);
492 if (error)
493 return (error);
494
495 size = (size < SN_MIN_HASH_SIZE) ? (SN_MIN_HASH_SIZE) : ((size > SN_MAX_HASH_SIZE) ? (SN_MAX_HASH_SIZE) : (size));
496
497 size |= 0x00000001; /* make odd */
498
499 for (;(((size % 3) == 0) || ((size % 5) == 0) || ((size % 7) == 0) || ((size % 11) == 0)); size+=2);
501
502 return (0);
503}
504
515int sysctl_chg_error_on_ootb(SYSCTL_HANDLER_ARGS)
516{
517 u_int flag = *(u_int *)arg1;
518 int error;
519
520 error = sysctl_handle_int(oidp, &flag, 0, req);
521 if (error)
522 return (error);
523
525
526 return (0);
527}
528
535int sysctl_chg_accept_global_ootb_addip(SYSCTL_HANDLER_ARGS)
536{
537 u_int flag = *(u_int *)arg1;
538 int error;
539
540 error = sysctl_handle_int(oidp, &flag, 0, req);
541 if (error)
542 return (error);
543
544 sysctl_accept_global_ootb_addip = (flag == 1) ? 1: 0;
545
546 return (0);
547}
548
556int sysctl_chg_initialising_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
557{
558 u_int proclimit = *(u_int *)arg1;
559 int error;
560
561 error = sysctl_handle_int(oidp, &proclimit, 0, req);
562 if (error)
563 return (error);
564
565 sysctl_initialising_chunk_proc_limit = (proclimit < 1) ? 1: proclimit;
568
569 return (0);
570}
571
579int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
580{
581 u_int proclimit = *(u_int *)arg1;
582 int error;
583
584 error = sysctl_handle_int(oidp, &proclimit, 0, req);
585 if (error)
586 return (error);
587
590
591 return (0);
592}
593
601int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS)
602{
603 u_int proclimit = *(u_int *)arg1;
604 int error;
605
606 error = sysctl_handle_int(oidp, &proclimit, 0, req);
607 if (error)
608 return (error);
609
611 (proclimit < 2) ? 2 : proclimit;
612
613 return (0);
614}
615
623int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS)
624{
625 u_int num_to_track = *(u_int *)arg1;
626 int error;
627
628 error = sysctl_handle_int(oidp, &num_to_track, 0, req);
629 if (error)
630 return (error);
631
633
634 return (0);
635}
636
637/* ----------------------------------------------------------------------
638 * CODE BEGINS HERE
639 * ----------------------------------------------------------------------
640 */
649void
650AliasSctpInit(struct libalias *la)
651{
652 /* Initialise association tables*/
653 int i;
656 SctpAliasLog("Initialising SCTP NAT Instance (hash_table_size:%d)\n", la->sctpNatTableSize));
657 la->sctpTableLocal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableL));
658 la->sctpTableGlobal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableG));
659 la->sctpNatTimer.TimerQ = sn_calloc(SN_TIMER_QUEUE_SIZE, sizeof(struct sctpTimerQ));
660 /* Initialise hash table */
661 for (i = 0; i < la->sctpNatTableSize; i++) {
662 LIST_INIT(&la->sctpTableLocal[i]);
663 LIST_INIT(&la->sctpTableGlobal[i]);
664 }
665
666 /* Initialise circular timer Q*/
667 for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++)
668 LIST_INIT(&la->sctpNatTimer.TimerQ[i]);
669#ifdef _KERNEL
670 la->sctpNatTimer.loc_time=time_uptime; /* LibAliasTime is not set yet */
671#else
673#endif
674 la->sctpNatTimer.cur_loc = 0;
675 la->sctpLinkCount = 0;
676}
677
690void
691AliasSctpTerm(struct libalias *la)
692{
693 struct sctp_nat_assoc *assoc1, *assoc2;
694 int i;
695
698 SctpAliasLog("Removing SCTP NAT Instance\n"));
699 for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++) {
700 assoc1 = LIST_FIRST(&la->sctpNatTimer.TimerQ[i]);
701 while (assoc1 != NULL) {
702 freeGlobalAddressList(assoc1);
703 assoc2 = LIST_NEXT(assoc1, timer_Q);
704 sn_free(assoc1);
705 assoc1 = assoc2;
706 }
707 }
708
709 sn_free(la->sctpTableLocal);
710 sn_free(la->sctpTableGlobal);
711 sn_free(la->sctpNatTimer.TimerQ);
712}
713
737int
738SctpAlias(struct libalias *la, struct ip *pip, int direction)
739{
740 int rtnval;
742 struct sctp_nat_assoc *assoc = NULL;
743
744 if ((direction != SN_TO_LOCAL) && (direction != SN_TO_GLOBAL)) {
745 SctpAliasLog("ERROR: Invalid direction\n");
746 return (PKT_ALIAS_ERROR);
747 }
748
749 sctp_CheckTimers(la); /* Check timers */
750
751 /* Parse the packet */
752 rtnval = sctp_PktParser(la, direction, pip, &msg, &assoc); //using *char (change to mbuf when get code from paolo)
753 switch (rtnval) {
754 case SN_PARSE_OK:
755 break;
757 /* Not an error if there is a chunk length parsing error and this is a fragmented packet */
758 if (ntohs(pip->ip_off) & IP_MF) {
759 rtnval = SN_PARSE_OK;
760 break;
761 }
763 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
764 return (PKT_ALIAS_ERROR);
768 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
769 return (PKT_ALIAS_ERROR);
770 }
775 TxAbortErrorM(la, &msg, assoc, SN_REFLECT_ERROR, direction); /*NB assoc=NULL */
776 return (PKT_ALIAS_RESPOND);
777 }
778 default:
780 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
781 return (PKT_ALIAS_ERROR);
782 }
783
785 logsctpassoc(assoc, "*");
786 logsctpparse(direction, &msg);
787 );
788
789 /* Process the SCTP message */
790 rtnval = ProcessSctpMsg(la, direction, &msg, assoc);
791
793 logsctpassoc(assoc, "-");
794 logSctpLocal(la);
795 logSctpGlobal(la);
796 );
798
799 switch (rtnval) {
800 case SN_NAT_PKT:
801 switch (direction) {
802 case SN_TO_LOCAL:
803 DifferentialChecksum(&(msg.ip_hdr->ip_sum),
804 &(assoc->l_addr), &(msg.ip_hdr->ip_dst), 2);
805 msg.ip_hdr->ip_dst = assoc->l_addr; /* change dst address to local address*/
806 break;
807 case SN_TO_GLOBAL:
808 DifferentialChecksum(&(msg.ip_hdr->ip_sum),
809 &(assoc->a_addr), &(msg.ip_hdr->ip_src), 2);
810 msg.ip_hdr->ip_src = assoc->a_addr; /* change src to alias addr*/
811 break;
812 default:
813 rtnval = SN_DROP_PKT; /* shouldn't get here, but if it does drop packet */
814 SN_LOG(SN_LOG_LOW, logsctperror("ERROR: Invalid direction", msg.sctp_hdr->v_tag, rtnval, direction));
815 break;
816 }
817 break;
818 case SN_DROP_PKT:
819 SN_LOG(SN_LOG_DETAIL, logsctperror("SN_DROP_PKT", msg.sctp_hdr->v_tag, rtnval, direction));
820 break;
821 case SN_REPLY_ABORT:
822 case SN_REPLY_ERROR:
823 case SN_SEND_ABORT:
824 TxAbortErrorM(la, &msg, assoc, rtnval, direction);
825 break;
826 default:
827 // big error, remove association and go to idle and write log messages
828 SN_LOG(SN_LOG_LOW, logsctperror("SN_PROCESSING_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
829 assoc->state = SN_RM;/* Mark for removal*/
830 break;
831 }
832
833 /* Remove association if tagged for removal */
834 if (assoc->state == SN_RM) {
835 if (assoc->TableRegister) {
836 sctp_RmTimeOut(la, assoc);
837 RmSctpAssoc(la, assoc);
838 }
841 sn_free(assoc);
842 }
843 switch (rtnval) {
844 case SN_NAT_PKT:
845 return (PKT_ALIAS_OK);
846 case SN_SEND_ABORT:
847 return (PKT_ALIAS_OK);
848 case SN_REPLY_ABORT:
849 case SN_REPLY_ERROR:
850 case SN_REFLECT_ERROR:
851 return (PKT_ALIAS_RESPOND);
852 case SN_DROP_PKT:
853 default:
854 return (PKT_ALIAS_ERROR);
855 }
856}
857
891static uint32_t
893{
894 /* This routine is duplicated from SCTP
895 * we need to do that since it MAY be that SCTP
896 * is NOT compiled into the kernel. The CRC32C routines
897 * however are always available in libkern.
898 */
899 uint32_t result;
900#if BYTE_ORDER == BIG_ENDIAN
901 uint8_t byte0, byte1, byte2, byte3;
902
903#endif
904 /* Complement the result */
905 result = ~crc32c;
906#if BYTE_ORDER == BIG_ENDIAN
907 /*
908 * For BIG-ENDIAN.. aka Motorola byte order the result is in
909 * little-endian form. So we must manually swap the bytes. Then we
910 * can call htonl() which does nothing...
911 */
912 byte0 = result & 0x000000ff;
913 byte1 = (result >> 8) & 0x000000ff;
914 byte2 = (result >> 16) & 0x000000ff;
915 byte3 = (result >> 24) & 0x000000ff;
916 crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
917#else
918 /*
919 * For INTEL platforms the result comes out in network order. No
920 * htonl is required or the swap above. So we optimize out both the
921 * htonl and the manual swap above.
922 */
923 crc32c = result;
924#endif
925 return (crc32c);
926}
927
928static void
929TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int sndrply, int direction)
930{
931 int sctp_size = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_error_cause);
932 int ip_size = sizeof(struct ip) + sctp_size;
933 int include_error_cause = 1;
934 char tmp_ip[ip_size];
935 char addrbuf[INET_ADDRSTRLEN];
936
937 if (ntohs(sm->ip_hdr->ip_len) < ip_size) { /* short packet, cannot send error cause */
938 include_error_cause = 0;
939 ip_size = ip_size - sizeof(struct sctp_error_cause);
940 sctp_size = sctp_size - sizeof(struct sctp_error_cause);
941 }
942 /* Assign header pointers packet */
943 struct ip* ip = (struct ip *) tmp_ip;
944 struct sctphdr* sctp_hdr = (struct sctphdr *) ((char *) ip + sizeof(*ip));
945 struct sctp_chunkhdr* chunk_hdr = (struct sctp_chunkhdr *) ((char *) sctp_hdr + sizeof(*sctp_hdr));
946 struct sctp_error_cause* error_cause = (struct sctp_error_cause *) ((char *) chunk_hdr + sizeof(*chunk_hdr));
947
948 /* construct ip header */
949 ip->ip_v = sm->ip_hdr->ip_v;
950 ip->ip_hl = 5; /* 5*32 bit words */
951 ip->ip_tos = 0;
952 ip->ip_len = htons(ip_size);
953 ip->ip_id = sm->ip_hdr->ip_id;
954 ip->ip_off = 0;
955 ip->ip_ttl = 255;
957 /*
958 The definitions below should be removed when they make it into the SCTP stack
959 */
960#define SCTP_MIDDLEBOX_FLAG 0x02
961#define SCTP_NAT_TABLE_COLLISION 0x00b0
962#define SCTP_MISSING_NAT 0x00b1
964 chunk_hdr->chunk_flags = SCTP_MIDDLEBOX_FLAG;
965 if (include_error_cause) {
966 error_cause->code = htons((sndrply & SN_REFLECT_ERROR) ? SCTP_MISSING_NAT : SCTP_NAT_TABLE_COLLISION);
967 error_cause->length = htons(sizeof(struct sctp_error_cause));
968 chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr) + sizeof(struct sctp_error_cause));
969 } else {
970 chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr));
971 }
972
973 /* set specific values */
974 switch (sndrply) {
975 case SN_REFLECT_ERROR:
976 chunk_hdr->chunk_flags |= SCTP_HAD_NO_TCB; /* set Tbit */
977 sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
978 break;
979 case SN_REPLY_ERROR:
980 sctp_hdr->v_tag = (direction == SN_TO_LOCAL) ? assoc->g_vtag : assoc->l_vtag ;
981 break;
982 case SN_SEND_ABORT:
983 sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
984 break;
985 case SN_REPLY_ABORT:
986 sctp_hdr->v_tag = sm->sctpchnk.Init->initiate_tag;
987 break;
988 }
989
990 /* Set send/reply values */
991 if (sndrply == SN_SEND_ABORT) { /*pass through NAT */
992 ip->ip_src = (direction == SN_TO_LOCAL) ? sm->ip_hdr->ip_src : assoc->a_addr;
993 ip->ip_dst = (direction == SN_TO_LOCAL) ? assoc->l_addr : sm->ip_hdr->ip_dst;
994 sctp_hdr->src_port = sm->sctp_hdr->src_port;
995 sctp_hdr->dest_port = sm->sctp_hdr->dest_port;
996 } else { /* reply and reflect */
997 ip->ip_src = sm->ip_hdr->ip_dst;
998 ip->ip_dst = sm->ip_hdr->ip_src;
999 sctp_hdr->src_port = sm->sctp_hdr->dest_port;
1000 sctp_hdr->dest_port = sm->sctp_hdr->src_port;
1001 }
1002
1003 /* Calculate IP header checksum */
1005
1006 /* calculate SCTP header CRC32 */
1007 sctp_hdr->checksum = 0;
1008 sctp_hdr->checksum = local_sctp_finalize_crc32(calculate_crc32c(0xffffffff, (unsigned char *) sctp_hdr, sctp_size));
1009
1010 memcpy(sm->ip_hdr, ip, ip_size);
1011
1012 SN_LOG(SN_LOG_EVENT,SctpAliasLog("%s %s 0x%x (->%s:%u vtag=0x%x crc=0x%x)\n",
1013 ((sndrply == SN_SEND_ABORT) ? "Sending" : "Replying"),
1014 ((sndrply & SN_TX_ERROR) ? "ErrorM" : "AbortM"),
1015 (include_error_cause ? ntohs(error_cause->code) : 0),
1016 inet_ntoa_r(ip->ip_dst, INET_NTOA_BUF(addrbuf)),
1017 ntohs(sctp_hdr->dest_port),
1018 ntohl(sctp_hdr->v_tag), ntohl(sctp_hdr->checksum)));
1019}
1020
1021/* ----------------------------------------------------------------------
1022 * PACKET PARSER CODE
1023 * ----------------------------------------------------------------------
1024 */
1046static int
1047sctp_PktParser(struct libalias *la, int direction, struct ip *pip,
1048 struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc)
1049//sctp_PktParser(int direction, struct mbuf *ipak, int ip_hdr_len,struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
1051 struct sctphdr *sctp_hdr;
1052 struct sctp_chunkhdr *chunk_hdr;
1053 struct sctp_paramhdr *param_hdr;
1054 struct in_addr ipv4addr;
1055 int bytes_left; /* bytes left in ip packet */
1056 int chunk_length;
1057 int chunk_count;
1058 int partial_match = 0;
1059 // mbuf *mp;
1060 // int mlen;
1061
1062 // mlen = SCTP_HEADER_LEN(i_pak);
1063 // mp = SCTP_HEADER_TO_CHAIN(i_pak); /* does nothing in bsd since header and chain not separate */
1064
1065 /*
1066 * Note, that if the VTag is zero, it must be an INIT
1067 * Also, I am only interested in the content of INIT and ADDIP chunks
1068 */
1069
1070 // no mbuf stuff from Paolo yet so ...
1071 sm->ip_hdr = pip;
1072 /* remove ip header length from the bytes_left */
1073 bytes_left = ntohs(pip->ip_len) - (pip->ip_hl << 2);
1074
1075 /* Check SCTP header length and move to first chunk */
1076 if (bytes_left < sizeof(struct sctphdr)) {
1077 sm->sctp_hdr = NULL;
1078 return (SN_PARSE_ERROR_IPSHL); /* packet not long enough*/
1079 }
1080
1081 sm->sctp_hdr = sctp_hdr = (struct sctphdr *) ip_next(pip);
1082 bytes_left -= sizeof(struct sctphdr);
1083
1084 /* Check for valid ports (zero valued ports would find partially initialised associations */
1085 if (sctp_hdr->src_port == 0 || sctp_hdr->dest_port == 0)
1086 return (SN_PARSE_ERROR_PORT);
1087
1088 /* Check length of first chunk */
1089 if (bytes_left < SN_MIN_CHUNK_SIZE) /* malformed chunk - could cause endless loop*/
1090 return (SN_PARSE_ERROR_CHHL); /* packet not long enough for this chunk */
1091
1092 /* First chunk */
1093 chunk_hdr = SN_SCTP_FIRSTCHUNK(sctp_hdr);
1094
1095 chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
1096 if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left)) /* malformed chunk - could cause endless loop*/
1097 return (SN_PARSE_ERROR_CHHL);
1098
1099 if ((chunk_hdr->chunk_flags & SCTP_HAD_NO_TCB) &&
1100 ((chunk_hdr->chunk_type == SCTP_ABORT_ASSOCIATION) ||
1101 (chunk_hdr->chunk_type == SCTP_SHUTDOWN_COMPLETE))) {
1102 /* T-Bit set */
1103 if (direction == SN_TO_LOCAL)
1104 *passoc = FindSctpGlobalT(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
1105 else
1106 *passoc = FindSctpLocalT(la, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
1107 } else {
1108 /* Proper v_tag settings */
1109 if (direction == SN_TO_LOCAL)
1110 *passoc = FindSctpGlobal(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
1111 else
1112 *passoc = FindSctpLocal(la, pip->ip_src, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port);
1113 }
1114
1115 chunk_count = 1;
1116 /* Real packet parsing occurs below */
1117 sm->msg = SN_SCTP_OTHER;/* Initialise to largest value*/
1118 sm->chunk_length = 0; /* only care about length for key chunks */
1119 while (IS_SCTP_CONTROL(chunk_hdr)) {
1120 switch (chunk_hdr->chunk_type) {
1121 case SCTP_INITIATION:
1122 if (chunk_length < sizeof(struct sctp_init_chunk)) /* malformed chunk*/
1123 return (SN_PARSE_ERROR_CHHL);
1124 sm->msg = SN_SCTP_INIT;
1125 sm->sctpchnk.Init = (struct sctp_init *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
1127 /* if no existing association, create a new one */
1128 if (*passoc == NULL) {
1129 if (sctp_hdr->v_tag == 0) { //Init requires vtag=0
1130 *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
1131 if (*passoc == NULL) {/* out of resources */
1132 return (SN_PARSE_ERROR_AS_MALLOC);
1133 }
1134 /* Initialize association - sn_malloc initializes memory to zeros */
1135 (*passoc)->state = SN_ID;
1136 LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
1137 (*passoc)->TableRegister = SN_NULL_TBL;
1138 return (SN_PARSE_OK);
1139 }
1140 return (SN_PARSE_ERROR_VTAG);
1141 }
1142 return (SN_PARSE_ERROR_LOOKUP);
1144 if (chunk_length < sizeof(struct sctp_init_ack_chunk)) /* malformed chunk*/
1145 return (SN_PARSE_ERROR_CHHL);
1146 sm->msg = SN_SCTP_INITACK;
1147 sm->sctpchnk.InitAck = (struct sctp_init_ack *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
1149 return ((*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP) : (SN_PARSE_OK));
1150 case SCTP_ABORT_ASSOCIATION: /* access only minimum sized chunk */
1151 sm->msg = SN_SCTP_ABORT;
1153 return ((*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP_ABORT) : (SN_PARSE_OK));
1154 case SCTP_SHUTDOWN_ACK:
1155 if (chunk_length < sizeof(struct sctp_shutdown_ack_chunk)) /* malformed chunk*/
1156 return (SN_PARSE_ERROR_CHHL);
1157 if (sm->msg > SN_SCTP_SHUTACK) {
1158 sm->msg = SN_SCTP_SHUTACK;
1160 }
1161 break;
1162 case SCTP_SHUTDOWN_COMPLETE: /* minimum sized chunk */
1163 if (sm->msg > SN_SCTP_SHUTCOMP) {
1164 sm->msg = SN_SCTP_SHUTCOMP;
1166 }
1167 return ((*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP) : (SN_PARSE_OK));
1168 case SCTP_ASCONF:
1169 if (sm->msg > SN_SCTP_ASCONF) {
1170 if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param))) /* malformed chunk*/
1171 return (SN_PARSE_ERROR_CHHL);
1172 //leave parameter searching to later, if required
1173 param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + sizeof(struct sctp_asconf_chunk)); /*compulsory IP parameter*/
1174 if (ntohs(param_hdr->param_type) == SCTP_IPV4_ADDRESS) {
1175 if ((*passoc == NULL) && (direction == SN_TO_LOCAL)) { /* AddIP with no association */
1176 /* try look up with the ASCONF packet's alternative address */
1177 ipv4addr.s_addr = ((struct sctp_ipv4addr_param *) param_hdr)->addr;
1178 *passoc = FindSctpGlobal(la, ipv4addr, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
1179 }
1180 param_hdr = (struct sctp_paramhdr *)
1181 ((char *) param_hdr + sizeof(struct sctp_ipv4addr_param)); /*asconf's compulsory address parameter */
1182 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv4addr_param); /* rest of chunk */
1183 } else {
1184 if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv6addr_param))) /* malformed chunk*/
1185 return (SN_PARSE_ERROR_CHHL);
1186 param_hdr = (struct sctp_paramhdr *)
1187 ((char *) param_hdr + sizeof(struct sctp_ipv6addr_param)); /*asconf's compulsory address parameter */
1188 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv6addr_param); /* rest of chunk */
1189 }
1190 sm->msg = SN_SCTP_ASCONF;
1191 sm->sctpchnk.Asconf = param_hdr;
1192
1193 if (*passoc == NULL) { /* AddIP with no association */
1194 *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
1195 if (*passoc == NULL) {/* out of resources */
1196 return (SN_PARSE_ERROR_AS_MALLOC);
1197 }
1198 /* Initialize association - sn_malloc initializes memory to zeros */
1199 (*passoc)->state = SN_ID;
1200 LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
1201 (*passoc)->TableRegister = SN_NULL_TBL;
1202 return (SN_PARSE_OK);
1203 }
1204 }
1205 break;
1206 case SCTP_ASCONF_ACK:
1207 if (sm->msg > SN_SCTP_ASCONFACK) {
1208 if (chunk_length < sizeof(struct sctp_asconf_ack_chunk)) /* malformed chunk*/
1209 return (SN_PARSE_ERROR_CHHL);
1210 //leave parameter searching to later, if required
1211 param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr
1212 + sizeof(struct sctp_asconf_ack_chunk));
1213 sm->msg = SN_SCTP_ASCONFACK;
1214 sm->sctpchnk.Asconf = param_hdr;
1215 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_ack_chunk);
1216 }
1217 break;
1218 default:
1219 break; /* do nothing*/
1220 }
1221
1222 /* if no association is found exit - we need to find an Init or AddIP within sysctl_initialising_chunk_proc_limit */
1223 if ((*passoc == NULL) && (chunk_count >= sysctl_initialising_chunk_proc_limit))
1224 return (SN_PARSE_ERROR_LOOKUP);
1225
1226 /* finished with this chunk, on to the next chunk*/
1227 bytes_left-= chunk_length;
1228
1229 /* Is this the end of the packet ? */
1230 if (bytes_left == 0)
1231 return (*passoc == NULL) ? (SN_PARSE_ERROR_LOOKUP) : (SN_PARSE_OK);
1232
1233 /* Are there enough bytes in packet to at least retrieve length of next chunk ? */
1234 if (bytes_left < SN_MIN_CHUNK_SIZE)
1235 return (SN_PARSE_ERROR_CHHL);
1236
1237 chunk_hdr = SN_SCTP_NEXTCHUNK(chunk_hdr);
1238
1239 /* Is the chunk long enough to not cause endless look and are there enough bytes in packet to read the chunk ? */
1240 chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
1241 if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left))
1242 return (SN_PARSE_ERROR_CHHL);
1243 if (++chunk_count > sysctl_chunk_proc_limit)
1244 return (SN_PARSE_OK); /* limit for processing chunks, take what we get */
1245 }
1246
1247 if (*passoc == NULL)
1248 return (partial_match) ? (SN_PARSE_ERROR_PARTIALLOOKUP) : (SN_PARSE_ERROR_LOOKUP);
1249 else
1250 return (SN_PARSE_OK);
1251}
1252
1270static int
1271GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, uint32_t *g_vtag, int direction)
1272{
1273 /* To be removed when information is in the sctp headers */
1274#define SCTP_VTAG_PARAM 0xC007
1275 struct sctp_vtag_param {
1276 struct sctp_paramhdr ph;/* type=SCTP_VTAG_PARAM */
1277 uint32_t local_vtag;
1278 uint32_t remote_vtag;
1279 } __attribute__((packed));
1280
1281 struct sctp_vtag_param *vtag_param;
1282 struct sctp_paramhdr *param;
1283 int bytes_left;
1284 int param_size;
1285 int param_count;
1286
1287 param_count = 1;
1288 param = sm->sctpchnk.Asconf;
1289 param_size = SCTP_SIZE32(ntohs(param->param_length));
1290 bytes_left = sm->chunk_length;
1291 /* step through Asconf parameters */
1292 while((bytes_left >= param_size) && (bytes_left >= SN_VTAG_PARAM_SIZE)) {
1293 if (ntohs(param->param_type) == SCTP_VTAG_PARAM) {
1294 vtag_param = (struct sctp_vtag_param *) param;
1295 switch (direction) {
1296 /* The Internet draft is a little ambigious as to order of these vtags.
1297 We think it is this way around. If we are wrong, the order will need
1298 to be changed. */
1299 case SN_TO_GLOBAL:
1300 *g_vtag = vtag_param->local_vtag;
1301 *l_vtag = vtag_param->remote_vtag;
1302 break;
1303 case SN_TO_LOCAL:
1304 *g_vtag = vtag_param->remote_vtag;
1305 *l_vtag = vtag_param->local_vtag;
1306 break;
1307 }
1308 return (1); /* found */
1309 }
1310
1311 bytes_left -= param_size;
1312 if (bytes_left < SN_MIN_PARAM_SIZE)
1313 return (0);
1314
1315 param = SN_SCTP_NEXTPARAM(param);
1316 param_size = SCTP_SIZE32(ntohs(param->param_length));
1317 if (++param_count > sysctl_param_proc_limit) {
1319 logsctperror("Parameter parse limit exceeded (GetAsconfVtags)",
1320 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1321 return (0); /* not found limit exceeded*/
1322 }
1323 }
1324 return (0); /* not found */
1325}
1326
1338static void
1339AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
1340{
1341 struct sctp_ipv4addr_param *ipv4_param;
1342 struct sctp_paramhdr *param = NULL;
1343 struct sctp_GlobalAddress *G_Addr;
1344 struct in_addr g_addr = {0};
1345 int bytes_left = 0;
1346 int param_size;
1347 int param_count, addr_param_count = 0;
1348
1349 switch (direction) {
1350 case SN_TO_GLOBAL: /* does not contain global addresses */
1351 g_addr = sm->ip_hdr->ip_dst;
1352 bytes_left = 0; /* force exit */
1353 break;
1354 case SN_TO_LOCAL:
1355 g_addr = sm->ip_hdr->ip_src;
1356 param_count = 1;
1357 switch (sm->msg) {
1358 case SN_SCTP_INIT:
1359 bytes_left = sm->chunk_length - sizeof(struct sctp_init_chunk);
1360 param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.Init + sizeof(struct sctp_init));
1361 break;
1362 case SN_SCTP_INITACK:
1363 bytes_left = sm->chunk_length - sizeof(struct sctp_init_ack_chunk);
1364 param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.InitAck + sizeof(struct sctp_init_ack));
1365 break;
1366 case SN_SCTP_ASCONF:
1367 bytes_left = sm->chunk_length;
1368 param = sm->sctpchnk.Asconf;
1369 break;
1370 }
1371 }
1372 if (bytes_left >= SN_MIN_PARAM_SIZE)
1373 param_size = SCTP_SIZE32(ntohs(param->param_length));
1374 else
1375 param_size = bytes_left+1; /* force skip loop */
1376
1377 if ((assoc->state == SN_ID) && ((sm->msg == SN_SCTP_INIT) || (bytes_left < SN_MIN_PARAM_SIZE))) {/* add pkt address */
1378 G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
1379 if (G_Addr == NULL) {/* out of resources */
1381 logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
1382 sm->sctp_hdr->v_tag, 0, direction));
1383 assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
1385 return;
1386 }
1387 G_Addr->g_addr = g_addr;
1388 if (!Add_Global_Address_to_List(assoc, G_Addr))
1390 logsctperror("AddGlobalIPAddress: Address already in list",
1391 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1392 }
1393
1394 /* step through parameters */
1395 while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
1398 logsctperror("AddGlobalIPAddress: Maximum Number of addresses reached",
1399 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1400 return;
1401 }
1402 switch (ntohs(param->param_type)) {
1404 /* skip to address parameter - leave param_size so bytes left will be calculated properly*/
1405 param = (struct sctp_paramhdr *) &((struct sctp_asconf_addrv4_param *) param)->addrp;
1406 /* FALLTHROUGH */
1407 case SCTP_IPV4_ADDRESS:
1408 ipv4_param = (struct sctp_ipv4addr_param *) param;
1409 /* add addresses to association */
1410 G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
1411 if (G_Addr == NULL) {/* out of resources */
1413 logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
1414 sm->sctp_hdr->v_tag, 0, direction));
1415 assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
1417 return;
1418 }
1419 /* add address */
1420 addr_param_count++;
1421 if ((sm->msg == SN_SCTP_ASCONF) && (ipv4_param->addr == INADDR_ANY)) { /* use packet address */
1422 G_Addr->g_addr = g_addr;
1423 if (!Add_Global_Address_to_List(assoc, G_Addr))
1425 logsctperror("AddGlobalIPAddress: Address already in list",
1426 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1427 return; /*shouldn't be any other addresses if the zero address is given*/
1428 } else {
1429 G_Addr->g_addr.s_addr = ipv4_param->addr;
1430 if (!Add_Global_Address_to_List(assoc, G_Addr))
1432 logsctperror("AddGlobalIPAddress: Address already in list",
1433 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1434 }
1435 }
1436
1437 bytes_left -= param_size;
1438 if (bytes_left < SN_MIN_PARAM_SIZE)
1439 break;
1440
1441 param = SN_SCTP_NEXTPARAM(param);
1442 param_size = SCTP_SIZE32(ntohs(param->param_length));
1443 if (++param_count > sysctl_param_proc_limit) {
1445 logsctperror("Parameter parse limit exceeded (AddGlobalIPAddress)",
1446 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1447 break; /* limit exceeded*/
1448 }
1449 }
1450 if (addr_param_count == 0) {
1452 logsctperror("AddGlobalIPAddress: no address parameters to add",
1453 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1454 }
1455}
1456
1470static int
1472{
1473 struct sctp_GlobalAddress *iter_G_Addr = NULL, *first_G_Addr = NULL;
1474 first_G_Addr = LIST_FIRST(&(assoc->Gaddr));
1475 if (first_G_Addr == NULL) {
1476 LIST_INSERT_HEAD(&(assoc->Gaddr), G_addr, list_Gaddr); /* add new address to beginning of list*/
1477 } else {
1478 LIST_FOREACH(iter_G_Addr, &(assoc->Gaddr), list_Gaddr) {
1479 if (G_addr->g_addr.s_addr == iter_G_Addr->g_addr.s_addr)
1480 return (0); /* already exists, so don't add */
1481 }
1482 LIST_INSERT_AFTER(first_G_Addr, G_addr, list_Gaddr); /* add address to end of list*/
1483 }
1484 assoc->num_Gaddr++;
1485 return (1); /* success */
1486}
1487
1501static void
1502RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
1503{
1504 struct sctp_asconf_addrv4_param *asconf_ipv4_param;
1505 struct sctp_paramhdr *param;
1506 struct sctp_GlobalAddress *G_Addr, *G_Addr_tmp;
1507 struct in_addr g_addr;
1508 int bytes_left;
1509 int param_size;
1510 int param_count;
1511
1512 if (direction == SN_TO_GLOBAL)
1513 g_addr = sm->ip_hdr->ip_dst;
1514 else
1515 g_addr = sm->ip_hdr->ip_src;
1516
1517 bytes_left = sm->chunk_length;
1518 param_count = 1;
1519 param = sm->sctpchnk.Asconf;
1520 if (bytes_left >= SN_MIN_PARAM_SIZE) {
1521 param_size = SCTP_SIZE32(ntohs(param->param_length));
1522 } else {
1524 logsctperror("RmGlobalIPAddress: truncated packet - cannot remove IP addresses",
1525 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1526 return;
1527 }
1528
1529 /* step through Asconf parameters */
1530 while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
1531 if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) {
1532 asconf_ipv4_param = (struct sctp_asconf_addrv4_param *) param;
1533 if (asconf_ipv4_param->addrp.addr == INADDR_ANY) { /* remove all bar pkt address */
1534 LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
1535 if (G_Addr->g_addr.s_addr != sm->ip_hdr->ip_src.s_addr) {
1536 if (assoc->num_Gaddr > 1) { /* only delete if more than one */
1537 LIST_REMOVE(G_Addr, list_Gaddr);
1538 sn_free(G_Addr);
1539 assoc->num_Gaddr--;
1540 } else {
1542 logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
1543 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1544 }
1545 }
1546 }
1547 return; /*shouldn't be any other addresses if the zero address is given*/
1548 } else {
1549 LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
1550 if (G_Addr->g_addr.s_addr == asconf_ipv4_param->addrp.addr) {
1551 if (assoc->num_Gaddr > 1) { /* only delete if more than one */
1552 LIST_REMOVE(G_Addr, list_Gaddr);
1553 sn_free(G_Addr);
1554 assoc->num_Gaddr--;
1555 break; /* Since add only adds new addresses, there should be no double entries */
1556 } else {
1558 logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
1559 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1560 }
1561 }
1562 }
1563 }
1564 }
1565 bytes_left -= param_size;
1566 if (bytes_left == 0)
1567 return;
1568 else if (bytes_left < SN_MIN_PARAM_SIZE) {
1570 logsctperror("RmGlobalIPAddress: truncated packet - may not have removed all IP addresses",
1571 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1572 return;
1573 }
1574
1575 param = SN_SCTP_NEXTPARAM(param);
1576 param_size = SCTP_SIZE32(ntohs(param->param_length));
1577 if (++param_count > sysctl_param_proc_limit) {
1579 logsctperror("Parameter parse limit exceeded (RmGlobalIPAddress)",
1580 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1581 return; /* limit exceeded*/
1582 }
1583 }
1584}
1585
1608static int
1609IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction)
1610{
1611 struct sctp_paramhdr *param;
1612 int bytes_left;
1613 int param_size;
1614 int param_count;
1615
1616 param_count = 1;
1617 param = sm->sctpchnk.Asconf;
1618 param_size = SCTP_SIZE32(ntohs(param->param_length));
1619 if (param_size == 8)
1620 return (1); /*success - default acknowledgement of everything */
1621
1622 bytes_left = sm->chunk_length;
1623 if (bytes_left < param_size)
1624 return (0); /* not found */
1625 /* step through Asconf parameters */
1626 while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
1627 if (ntohs(param->param_type) == SCTP_SUCCESS_REPORT)
1628 return (1); /* success - but can't match correlation IDs - should only be one */
1629 /* check others just in case */
1630 bytes_left -= param_size;
1631 if (bytes_left >= SN_MIN_PARAM_SIZE)
1632 param = SN_SCTP_NEXTPARAM(param);
1633 else
1634 return (0);
1635
1636 param_size = SCTP_SIZE32(ntohs(param->param_length));
1637 if (bytes_left < param_size)
1638 return (0);
1639
1640 if (++param_count > sysctl_param_proc_limit) {
1642 logsctperror("Parameter parse limit exceeded (IsASCONFack)",
1643 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1644 return (0); /* not found limit exceeded*/
1645 }
1646 }
1647 return (0); /* not success */
1648}
1649
1662static int
1663IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction)
1664{
1665 struct sctp_paramhdr *param;
1666 int bytes_left;
1667 int param_size;
1668 int param_count;
1669
1670 param_count = 1;
1671 param = sm->sctpchnk.Asconf;
1672 param_size = SCTP_SIZE32(ntohs(param->param_length));
1673
1674 bytes_left = sm->chunk_length;
1675 if (bytes_left < param_size)
1676 return (0); /* not found */
1677 /* step through Asconf parameters */
1678 while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
1679 if (ntohs(param->param_type) == SCTP_ADD_IP_ADDRESS)
1680 return (SCTP_ADD_IP_ADDRESS);
1681 else if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS)
1682 return (SCTP_DEL_IP_ADDRESS);
1683 /* check others just in case */
1684 bytes_left -= param_size;
1685 if (bytes_left >= SN_MIN_PARAM_SIZE)
1686 param = SN_SCTP_NEXTPARAM(param);
1687 else
1688 return (0); /*Neither found */
1689
1690 param_size = SCTP_SIZE32(ntohs(param->param_length));
1691 if (bytes_left < param_size)
1692 return (0);
1693
1694 if (++param_count > sysctl_param_proc_limit) {
1696 logsctperror("Parameter parse limit exceeded IsADDorDEL)",
1697 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1698 return (0); /* not found limit exceeded*/
1699 }
1700 }
1701 return (0); /*Neither found */
1702}
1703
1704/* ----------------------------------------------------------------------
1705 * STATE MACHINE CODE
1706 * ----------------------------------------------------------------------
1707 */
1730static int
1731ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
1732{
1733 int rtnval;
1735 switch (assoc->state) {
1736 case SN_ID: /* Idle */
1737 rtnval = ID_process(la, direction, assoc, sm);
1738 if (rtnval != SN_NAT_PKT) {
1739 assoc->state = SN_RM;/* Mark for removal*/
1740 }
1741 return (rtnval);
1742 case SN_INi: /* Initialising - Init */
1743 return (INi_process(la, direction, assoc, sm));
1744 case SN_INa: /* Initialising - AddIP */
1745 return (INa_process(la, direction, assoc, sm));
1746 case SN_UP: /* Association UP */
1747 return (UP_process(la, direction, assoc, sm));
1748 case SN_CL: /* Association Closing */
1749 return (CL_process(la, direction, assoc, sm));
1750 }
1751 return (SN_PROCESSING_ERROR);
1752}
1753
1768static int
1769ID_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1770{
1771 switch (sm->msg) {
1772 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk with ADDIP */
1773 if (!sysctl_accept_global_ootb_addip && (direction == SN_TO_LOCAL))
1774 return (SN_DROP_PKT);
1775 /* if this Asconf packet does not contain the Vtag parameters it is of no use in Idle state */
1776 if (!GetAsconfVtags(la, sm, &(assoc->l_vtag), &(assoc->g_vtag), direction))
1777 return (SN_DROP_PKT);
1778 /* FALLTHROUGH */
1779 case SN_SCTP_INIT: /* a packet containing an INIT chunk or an ASCONF AddIP */
1781 AddGlobalIPAddresses(sm, assoc, direction);
1782 switch (direction) {
1783 case SN_TO_GLOBAL:
1784 assoc->l_addr = sm->ip_hdr->ip_src;
1785 assoc->a_addr = FindAliasAddress(la, assoc->l_addr);
1786 assoc->l_port = sm->sctp_hdr->src_port;
1787 assoc->g_port = sm->sctp_hdr->dest_port;
1788 if (sm->msg == SN_SCTP_INIT)
1789 assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
1790 if (AddSctpAssocGlobal(la, assoc)) /* DB clash: need to add dst address */
1791 return ((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
1792 if (sm->msg == SN_SCTP_ASCONF) {
1793 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_dst)) /* DB clash */
1794 return (SN_REPLY_ERROR);
1795 assoc->TableRegister |= SN_WAIT_TOLOCAL; /* wait for tolocal ack */
1796 }
1797 break;
1798 case SN_TO_LOCAL:
1799 assoc->l_addr = FindSctpRedirectAddress(la, sm);
1800 assoc->a_addr = sm->ip_hdr->ip_dst;
1801 assoc->l_port = sm->sctp_hdr->dest_port;
1802 assoc->g_port = sm->sctp_hdr->src_port;
1803 if (sm->msg == SN_SCTP_INIT)
1804 assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
1805 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) /* DB clash */
1806 return ((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
1807 if (sm->msg == SN_SCTP_ASCONF) {
1808 if (AddSctpAssocGlobal(la, assoc)) /* DB clash: need to add src address */
1809 return (SN_REPLY_ERROR);
1810 assoc->TableRegister |= SN_WAIT_TOGLOBAL; /* wait for toglobal ack */
1811 }
1812 break;
1813 }
1814 assoc->state = (sm->msg == SN_SCTP_INIT) ? SN_INi : SN_INa;
1815 assoc->exp = SN_I_T(la);
1816 sctp_AddTimeOut(la,assoc);
1817 return (SN_NAT_PKT);
1818 default: /* Any other type of SCTP message is not valid in Idle */
1819 return (SN_DROP_PKT);
1820 }
1821 return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1822}
1823
1837static int
1838INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1839{
1840 switch (sm->msg) {
1841 case SN_SCTP_INIT: /* a packet containing a retransmitted INIT chunk */
1842 sctp_ResetTimeOut(la, assoc, SN_I_T(la));
1843 return (SN_NAT_PKT);
1844 case SN_SCTP_INITACK: /* a packet containing an INIT-ACK chunk */
1845 switch (direction) {
1846 case SN_TO_LOCAL:
1847 if (assoc->num_Gaddr) /*If tracking global addresses for this association */
1848 AddGlobalIPAddresses(sm, assoc, direction);
1849 assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
1850 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) { /* DB clash */
1851 assoc->state = SN_RM;/* Mark for removal*/
1852 return (SN_SEND_ABORT);
1853 }
1854 break;
1855 case SN_TO_GLOBAL:
1856 assoc->l_addr = sm->ip_hdr->ip_src; // Only if not set in Init! *
1857 assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
1858 if (AddSctpAssocGlobal(la, assoc)) { /* DB clash */
1859 assoc->state = SN_RM;/* Mark for removal*/
1860 return (SN_SEND_ABORT);
1861 }
1862 break;
1863 }
1864 assoc->state = SN_UP;/* association established for NAT */
1865 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1866 return (SN_NAT_PKT);
1867 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1868 assoc->state = SN_RM;/* Mark for removal*/
1869 return (SN_NAT_PKT);
1870 default:
1871 return (SN_DROP_PKT);
1872 }
1873 return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1874}
1875
1889static int
1890INa_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1891{
1892 switch (sm->msg) {
1893 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
1894 sctp_ResetTimeOut(la,assoc, SN_I_T(la));
1895 return (SN_NAT_PKT);
1896 case SN_SCTP_ASCONFACK: /* a packet containing an ASCONF chunk with a ADDIP-ACK */
1897 switch (direction) {
1898 case SN_TO_LOCAL:
1899 if (!(assoc->TableRegister & SN_WAIT_TOLOCAL)) /* wrong direction */
1900 return (SN_DROP_PKT);
1901 break;
1902 case SN_TO_GLOBAL:
1903 if (!(assoc->TableRegister & SN_WAIT_TOGLOBAL)) /* wrong direction */
1904 return (SN_DROP_PKT);
1905 }
1906 if (IsASCONFack(la,sm,direction)) {
1907 assoc->TableRegister &= SN_BOTH_TBL; /* remove wait flags */
1908 assoc->state = SN_UP; /* association established for NAT */
1909 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1910 return (SN_NAT_PKT);
1911 } else {
1912 assoc->state = SN_RM;/* Mark for removal*/
1913 return (SN_NAT_PKT);
1914 }
1915 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1916 assoc->state = SN_RM;/* Mark for removal*/
1917 return (SN_NAT_PKT);
1918 default:
1919 return (SN_DROP_PKT);
1920 }
1921 return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1922}
1923
1937static int
1938UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1939{
1940 switch (sm->msg) {
1941 case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
1942 assoc->state = SN_CL;
1943 sctp_ResetTimeOut(la,assoc, SN_C_T(la));
1944 return (SN_NAT_PKT);
1945 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1946 assoc->state = SN_RM;/* Mark for removal*/
1947 return (SN_NAT_PKT);
1948 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
1949 if ((direction == SN_TO_LOCAL) && assoc->num_Gaddr) /*If tracking global addresses for this association & from global side */
1950 switch (IsADDorDEL(la,sm,direction)) {
1952 AddGlobalIPAddresses(sm, assoc, direction);
1953 break;
1955 RmGlobalIPAddresses(sm, assoc, direction);
1956 break;
1957 }
1958 /* fall through to default */
1959 default:
1960 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1961 return (SN_NAT_PKT); /* forward packet */
1962 }
1963 return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1964}
1965
1981static int
1982CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1983{
1984 switch (sm->msg) {
1985 case SN_SCTP_SHUTCOMP: /* a packet containing a SHUTDOWN-COMPLETE chunk */
1986 assoc->state = SN_CL; /* Stay in Close state until timeout */
1987 if (sysctl_holddown_timer > 0)
1988 sctp_ResetTimeOut(la, assoc, SN_X_T(la));/* allow to stay open for Tbit packets*/
1989 else
1990 assoc->state = SN_RM;/* Mark for removal*/
1991 return (SN_NAT_PKT);
1992 case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
1993 assoc->state = SN_CL; /* Stay in Close state until timeout */
1994 sctp_ResetTimeOut(la, assoc, SN_C_T(la));
1995 return (SN_NAT_PKT);
1996 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1997 assoc->state = SN_RM;/* Mark for removal*/
1998 return (SN_NAT_PKT);
1999 default:
2000 return (SN_DROP_PKT);
2001 }
2002 return (SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
2003}
2004
2005/* ----------------------------------------------------------------------
2006 * HASH TABLE CODE
2007 * ----------------------------------------------------------------------
2008 */
2029static struct sctp_nat_assoc *
2031{
2032 u_int i;
2033 struct sctp_nat_assoc *assoc = NULL;
2034 struct sctp_GlobalAddress *G_Addr = NULL;
2035
2036 if (l_vtag != 0) { /* an init packet, vtag==0 */
2037 i = SN_TABLE_HASH(l_vtag, l_port, la->sctpNatTableSize);
2038 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
2039 if ((assoc->l_vtag == l_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)\
2040 && (assoc->l_addr.s_addr == l_addr.s_addr)) {
2041 if (assoc->num_Gaddr) {
2042 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2043 if (G_Addr->g_addr.s_addr == g_addr.s_addr)
2044 return (assoc);
2045 }
2046 } else {
2047 return (assoc);
2048 }
2049 }
2050 }
2051 }
2052 return (NULL);
2053}
2054
2066static struct sctp_nat_assoc *
2067FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc)
2068{
2069 u_int i;
2070 struct sctp_nat_assoc *assoc = NULL;
2071 struct sctp_GlobalAddress *G_Addr = NULL;
2072 struct sctp_GlobalAddress *G_AddrC = NULL;
2073
2074 if (Cassoc->g_vtag != 0) { /* an init packet, vtag==0 */
2075 i = SN_TABLE_HASH(Cassoc->g_vtag, Cassoc->g_port, la->sctpNatTableSize);
2076 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2077 if ((assoc->g_vtag == Cassoc->g_vtag) && (assoc->g_port == Cassoc->g_port) && (assoc->l_port == Cassoc->l_port)) {
2078 if (assoc->num_Gaddr) {
2079 LIST_FOREACH(G_AddrC, &(Cassoc->Gaddr), list_Gaddr) {
2080 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2081 if (G_Addr->g_addr.s_addr == G_AddrC->g_addr.s_addr)
2082 return (assoc);
2083 }
2084 }
2085 } else {
2086 return (assoc);
2087 }
2088 }
2089 }
2090 }
2091 return (NULL);
2092}
2093
2113static struct sctp_nat_assoc *
2114FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match)
2115{
2116 u_int i;
2117 struct sctp_nat_assoc *assoc = NULL;
2118 struct sctp_GlobalAddress *G_Addr = NULL;
2119
2120 *partial_match = 0;
2121 if (g_vtag != 0) { /* an init packet, vtag==0 */
2122 i = SN_TABLE_HASH(g_vtag, g_port, la->sctpNatTableSize);
2123 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2124 if ((assoc->g_vtag == g_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
2125 *partial_match = 1;
2126 if (assoc->num_Gaddr) {
2127 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2128 if (G_Addr->g_addr.s_addr == g_addr.s_addr)
2129 return (assoc);
2130 }
2131 } else {
2132 return (assoc);
2133 }
2134 }
2135 }
2136 }
2137 return (NULL);
2138}
2139
2154static struct sctp_nat_assoc *
2156{
2157 u_int i;
2158 struct sctp_nat_assoc *assoc = NULL, *lastmatch = NULL;
2159 struct sctp_GlobalAddress *G_Addr = NULL;
2160 int cnt = 0;
2161
2162 if (l_vtag != 0) { /* an init packet, vtag==0 */
2163 i = SN_TABLE_HASH(l_vtag, g_port, la->sctpNatTableSize);
2164 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2165 if ((assoc->g_vtag == l_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
2166 if (assoc->num_Gaddr) {
2167 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2168 if (G_Addr->g_addr.s_addr == g_addr.s_addr)
2169 return (assoc); /* full match */
2170 }
2171 } else {
2172 if (++cnt > 1)
2173 return (NULL);
2174 lastmatch = assoc;
2175 }
2176 }
2177 }
2178 }
2179 /* If there is more than one match we do not know which local address to send to */
2180 return (cnt ? lastmatch : NULL);
2181}
2182
2197static struct sctp_nat_assoc *
2199{
2200 u_int i;
2201 struct sctp_nat_assoc *assoc = NULL;
2202 struct sctp_GlobalAddress *G_Addr = NULL;
2203
2204 if (g_vtag != 0) { /* an init packet, vtag==0 */
2205 i = SN_TABLE_HASH(g_vtag, l_port, la->sctpNatTableSize);
2206 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
2207 if ((assoc->l_vtag == g_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)) {
2208 if (assoc->num_Gaddr) {
2209 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2210 if (G_Addr->g_addr.s_addr == g_addr.s_addr)
2211 return (assoc);
2212 }
2213 } else {
2214 return (assoc);
2215 }
2216 }
2217 }
2218 }
2219 return (NULL);
2220}
2221
2238static int
2239AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_addr g_addr)
2240{
2241 struct sctp_nat_assoc *found;
2244 found = FindSctpLocal(la, assoc->l_addr, g_addr, assoc->l_vtag, assoc->l_port, assoc->g_port);
2245 /*
2246 * Note that if a different global address initiated this Init,
2247 * ie it wasn't resent as presumed:
2248 * - the local receiver if receiving it for the first time will establish
2249 * an association with the new global host
2250 * - if receiving an init from a different global address after sending a
2251 * lost initack it will send an initack to the new global host, the first
2252 * association attempt will then be blocked if retried.
2253 */
2254 if (found != NULL) {
2255 if ((found->TableRegister == SN_LOCAL_TBL) && (found->g_port == assoc->g_port)) { /* resent message */
2256 RmSctpAssoc(la, found);
2257 sctp_RmTimeOut(la, found);
2258 freeGlobalAddressList(found);
2259 sn_free(found);
2260 } else
2261 return (SN_ADD_CLASH);
2262 }
2263
2264 LIST_INSERT_HEAD(&la->sctpTableLocal[SN_TABLE_HASH(assoc->l_vtag, assoc->l_port, la->sctpNatTableSize)],
2265 assoc, list_L);
2266 assoc->TableRegister |= SN_LOCAL_TBL;
2267 la->sctpLinkCount++; //increment link count
2268
2269 if (assoc->TableRegister == SN_BOTH_TBL) {
2270 /* libalias log -- controlled by libalias */
2273
2274 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
2275 }
2276
2277 return (SN_ADD_OK);
2278}
2279
2295static int
2296AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc)
2297{
2298 struct sctp_nat_assoc *found;
2301 found = FindSctpGlobalClash(la, assoc);
2302 if (found != NULL) {
2303 if ((found->TableRegister == SN_GLOBAL_TBL) &&
2304 (found->l_addr.s_addr == assoc->l_addr.s_addr) &&
2305 (found->l_port == assoc->l_port)) { /* resent message */
2306 RmSctpAssoc(la, found);
2307 sctp_RmTimeOut(la, found);
2308 freeGlobalAddressList(found);
2309 sn_free(found);
2310 } else
2311 return (SN_ADD_CLASH);
2312 }
2313
2314 LIST_INSERT_HEAD(&la->sctpTableGlobal[SN_TABLE_HASH(assoc->g_vtag, assoc->g_port, la->sctpNatTableSize)],
2315 assoc, list_G);
2316 assoc->TableRegister |= SN_GLOBAL_TBL;
2317 la->sctpLinkCount++; //increment link count
2318
2319 if (assoc->TableRegister == SN_BOTH_TBL) {
2320 /* libalias log -- controlled by libalias */
2323
2324 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
2325 }
2326
2327 return (SN_ADD_OK);
2328}
2329
2344static void
2345RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc)
2346{
2347 // struct sctp_nat_assoc *found;
2348 if (assoc == NULL) {
2349 /* very bad, log and die*/
2351 logsctperror("ERROR: alias_sctp:RmSctpAssoc(NULL)\n", 0, 0, SN_TO_NODIR));
2352 return;
2353 }
2354 /* log if association is fully up and now closing */
2355 if (assoc->TableRegister == SN_BOTH_TBL) {
2356 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "$"));
2357 }
2359 if (assoc->TableRegister & SN_LOCAL_TBL) {
2360 assoc->TableRegister ^= SN_LOCAL_TBL;
2361 la->sctpLinkCount--; //decrement link count
2362 LIST_REMOVE(assoc, list_L);
2363 }
2364
2365 if (assoc->TableRegister & SN_GLOBAL_TBL) {
2366 assoc->TableRegister ^= SN_GLOBAL_TBL;
2367 la->sctpLinkCount--; //decrement link count
2368 LIST_REMOVE(assoc, list_G);
2369 }
2370 // sn_free(assoc); //Don't remove now, remove if needed later
2371 /* libalias logging -- controlled by libalias log definition */
2374}
2375
2385static void freeGlobalAddressList(struct sctp_nat_assoc *assoc)
2386{
2387 struct sctp_GlobalAddress *gaddr1=NULL,*gaddr2=NULL;
2388 /*free global address list*/
2389 gaddr1 = LIST_FIRST(&(assoc->Gaddr));
2390 while (gaddr1 != NULL) {
2391 gaddr2 = LIST_NEXT(gaddr1, list_Gaddr);
2392 sn_free(gaddr1);
2393 gaddr1 = gaddr2;
2394 }
2395}
2396/* ----------------------------------------------------------------------
2397 * TIMER QUEUE CODE
2398 * ----------------------------------------------------------------------
2399 */
2423static void
2424sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
2425{
2426 int add_loc;
2428 add_loc = assoc->exp - la->sctpNatTimer.loc_time + la->sctpNatTimer.cur_loc;
2429 if (add_loc >= SN_TIMER_QUEUE_SIZE)
2430 add_loc -= SN_TIMER_QUEUE_SIZE;
2431 LIST_INSERT_HEAD(&la->sctpNatTimer.TimerQ[add_loc], assoc, timer_Q);
2432 assoc->exp_loc = add_loc;
2433}
2434
2444static void
2445sctp_RmTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
2446{
2448 LIST_REMOVE(assoc, timer_Q);/* Note this is O(1) */
2449}
2450
2462static void
2463sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp)
2464{
2465 if (newexp < assoc->exp) {
2466 sctp_RmTimeOut(la, assoc);
2467 assoc->exp = newexp;
2468 sctp_AddTimeOut(la, assoc);
2469 } else {
2470 assoc->exp = newexp;
2471 }
2472}
2473
2490void
2491sctp_CheckTimers(struct libalias *la)
2492{
2493 struct sctp_nat_assoc *assoc;
2496 while(LibAliasTime >= la->sctpNatTimer.loc_time) {
2497 while (!LIST_EMPTY(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc])) {
2498 assoc = LIST_FIRST(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc]);
2499 //SLIST_REMOVE_HEAD(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc], timer_Q);
2500 LIST_REMOVE(assoc, timer_Q);
2501 if (LibAliasTime >= assoc->exp) { /* state expired */
2502 SN_LOG(((assoc->state == SN_CL) ? (SN_LOG_DEBUG) : (SN_LOG_INFO)),
2503 logsctperror("Timer Expired", assoc->g_vtag, assoc->state, SN_TO_NODIR));
2504 RmSctpAssoc(la, assoc);
2505 freeGlobalAddressList(assoc);
2506 sn_free(assoc);
2507 } else {/* state not expired, reschedule timer*/
2508 sctp_AddTimeOut(la, assoc);
2509 }
2510 }
2511 /* Goto next location in the timer queue*/
2512 ++la->sctpNatTimer.loc_time;
2514 la->sctpNatTimer.cur_loc = 0;
2515 }
2516}
2517
2518/* ----------------------------------------------------------------------
2519 * LOGGING CODE
2520 * ----------------------------------------------------------------------
2521 */
2536static void
2537logsctperror(char *errormsg, uint32_t vtag, int error, int direction)
2538{
2539 char dir;
2540 switch (direction) {
2541 case SN_TO_LOCAL:
2542 dir = 'L';
2543 break;
2544 case SN_TO_GLOBAL:
2545 dir = 'G';
2546 break;
2547 default:
2548 dir = '*';
2549 break;
2550 }
2551 SctpAliasLog("->%c %s (vt=%u) %d\n", dir, errormsg, ntohl(vtag), error);
2552}
2553
2560static void
2561logsctpparse(int direction, struct sctp_nat_msg *sm)
2562{
2563 char *ploc, *pstate;
2564 switch (direction) {
2565 case SN_TO_LOCAL:
2566 ploc = "TO_LOCAL -";
2567 break;
2568 case SN_TO_GLOBAL:
2569 ploc = "TO_GLOBAL -";
2570 break;
2571 default:
2572 ploc = "";
2573 }
2574 switch (sm->msg) {
2575 case SN_SCTP_INIT:
2576 pstate = "Init";
2577 break;
2578 case SN_SCTP_INITACK:
2579 pstate = "InitAck";
2580 break;
2581 case SN_SCTP_ABORT:
2582 pstate = "Abort";
2583 break;
2584 case SN_SCTP_SHUTACK:
2585 pstate = "ShutAck";
2586 break;
2587 case SN_SCTP_SHUTCOMP:
2588 pstate = "ShutComp";
2589 break;
2590 case SN_SCTP_ASCONF:
2591 pstate = "Asconf";
2592 break;
2593 case SN_SCTP_ASCONFACK:
2594 pstate = "AsconfAck";
2595 break;
2596 case SN_SCTP_OTHER:
2597 pstate = "Other";
2598 break;
2599 default:
2600 pstate = "***ERROR***";
2601 break;
2602 }
2603 SctpAliasLog("Parsed: %s %s\n", ploc, pstate);
2604}
2605
2612static void logsctpassoc(struct sctp_nat_assoc *assoc, char *s)
2613{
2614 struct sctp_GlobalAddress *G_Addr = NULL;
2615 char *sp;
2616 char addrbuf[INET_ADDRSTRLEN];
2617
2618 switch (assoc->state) {
2619 case SN_ID:
2620 sp = "ID ";
2621 break;
2622 case SN_INi:
2623 sp = "INi ";
2624 break;
2625 case SN_INa:
2626 sp = "INa ";
2627 break;
2628 case SN_UP:
2629 sp = "UP ";
2630 break;
2631 case SN_CL:
2632 sp = "CL ";
2633 break;
2634 case SN_RM:
2635 sp = "RM ";
2636 break;
2637 default:
2638 sp = "***ERROR***";
2639 break;
2640 }
2641 SctpAliasLog("%sAssoc: %s exp=%u la=%s lv=%u lp=%u gv=%u gp=%u tbl=%d\n",
2642 s, sp, assoc->exp, inet_ntoa_r(assoc->l_addr, addrbuf),
2643 ntohl(assoc->l_vtag), ntohs(assoc->l_port),
2644 ntohl(assoc->g_vtag), ntohs(assoc->g_port),
2645 assoc->TableRegister);
2646 /* list global addresses */
2647 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2648 SctpAliasLog("\t\tga=%s\n",
2649 inet_ntoa_r(G_Addr->g_addr, addrbuf));
2650 }
2651}
2652
2658static void logSctpGlobal(struct libalias *la)
2659{
2660 u_int i;
2661 struct sctp_nat_assoc *assoc = NULL;
2662
2663 SctpAliasLog("G->\n");
2664 for (i = 0; i < la->sctpNatTableSize; i++) {
2665 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2666 logsctpassoc(assoc, " ");
2667 }
2668 }
2669}
2670
2676static void logSctpLocal(struct libalias *la)
2677{
2678 u_int i;
2679 struct sctp_nat_assoc *assoc = NULL;
2680
2681 SctpAliasLog("L->\n");
2682 for (i = 0; i < la->sctpNatTableSize; i++) {
2683 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
2684 logsctpassoc(assoc, " ");
2685 }
2686 }
2687}
2688
2694static void logTimerQ(struct libalias *la)
2695{
2696 static char buf[50];
2697 u_int i;
2698 struct sctp_nat_assoc *assoc = NULL;
2699
2700 SctpAliasLog("t->\n");
2701 for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++) {
2702 LIST_FOREACH(assoc, &la->sctpNatTimer.TimerQ[i], timer_Q) {
2703 snprintf(buf, 50, " l=%u ",i);
2704 //SctpAliasLog(la->logDesc," l=%d ",i);
2705 logsctpassoc(assoc, buf);
2706 }
2707 }
2708}
2709
2718#ifdef _KERNEL
2719static void
2720SctpAliasLog(const char *format, ...)
2721{
2722 char buffer[LIBALIAS_BUF_SIZE];
2723 va_list ap;
2724 va_start(ap, format);
2725 vsnprintf(buffer, LIBALIAS_BUF_SIZE, format, ap);
2726 va_end(ap);
2727 log(LOG_SECURITY | LOG_INFO, "alias_sctp: %s", buffer);
2728}
2729#else
2730static void
2731SctpAliasLog(FILE *stream, const char *format, ...)
2732{
2733 va_list ap;
2734
2735 va_start(ap, format);
2736 vfprintf(stream, format, ap);
2737 va_end(ap);
2738 fflush(stream);
2739}
2740#endif
static SYSCTL_NODE(_net_inet_accf, OID_AUTO, http, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "HTTP accept filter")
#define PKT_ALIAS_OK
Definition: alias.h:234
#define PKT_ALIAS_LOG
Definition: alias.h:147
#define LIBALIAS_BUF_SIZE
Definition: alias.h:48
#define PKT_ALIAS_ERROR
Definition: alias.h:233
struct in_addr FindAliasAddress(struct libalias *la, struct in_addr original_addr)
Definition: alias_db.c:1363
struct in_addr FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm)
Definition: alias_db.c:2459
#define LIBALIAS_LOCK_ASSERT(l)
Definition: alias_local.h:174
int LibAliasTime
#define INET_NTOA_BUF(buf)
Definition: alias_local.h:74
void DifferentialChecksum(u_short *_cksum, void *_new, void *_old, int _n)
Definition: alias_util.c:154
static MALLOC_DEFINE(M_SCTPNAT, "sctpnat", "sctp nat dbs")
#define SCTP_VTAG_PARAM
int SctpAlias(struct libalias *la, struct ip *pip, int direction)
Handles SCTP packets passed from libalias.
Definition: alias_sctp.c:741
static uint32_t local_sctp_finalize_crc32(uint32_t crc32c)
Send an AbortM or ErrorM.
Definition: alias_sctp.c:895
#define SCTP_NAT_TABLE_COLLISION
static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr)
Add_Global_Address_to_List.
Definition: alias_sctp.c:1474
void AliasSctpTerm(struct libalias *la)
Cleans-up the SCTP NAT Implementation prior to unloading.
Definition: alias_sctp.c:694
#define SCTP_MIDDLEBOX_FLAG
static void TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int sndrply, int direction)
Definition: alias_sctp.c:932
#define SCTP_MISSING_NAT
void AliasSctpInit(struct libalias *la)
Initialises the SCTP NAT Implementation.
Definition: alias_sctp.c:653
#define SN_TO_LOCAL
Definition: alias_sctp.h:100
#define SN_TX_ABORT
Definition: alias_sctp.h:109
#define SN_NAT_PKT
Definition: alias_sctp.h:104
#define SN_DROP_PKT
Definition: alias_sctp.h:105
#define PKT_ALIAS_RESPOND
Definition: alias_sctp.h:114
#define SN_TX_ERROR
Definition: alias_sctp.h:112
#define SN_REFLECT_ERROR
Definition: alias_sctp.h:110
#define SN_PROCESSING_ERROR
Definition: alias_sctp.h:106
#define SN_SEND_ABORT
Definition: alias_sctp.h:108
#define SN_REPLY_ERROR
Definition: alias_sctp.h:111
#define SN_REPLY_ABORT
Definition: alias_sctp.h:107
#define SN_TO_GLOBAL
Definition: alias_sctp.h:101
#define SN_TO_NODIR
Definition: alias_sctp.h:102
SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, algorithm, CTLFLAG_VNET|CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE, NULL, 0, cc_default_algo, "A", "Default congestion control algorithm")
SYSCTL_DECL(_net_inet_tcp_cc)
static struct sctp_nat_assoc * FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc)
Check for Global Clash.
Definition: alias_sctp.c:2070
static struct sctp_nat_assoc * FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uint16_t g_port, uint16_t l_port)
Find the SCTP association for a T-Flag message (given the global port and local vtag)
Definition: alias_sctp.c:2158
#define SN_BOTH_TBL
Definition: alias_sctp.c:284
#define SN_WAIT_TOGLOBAL
Definition: alias_sctp.c:286
static void RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc)
Remove the sctp association information from the look up table.
Definition: alias_sctp.c:2348
#define SN_WAIT_TOLOCAL
Definition: alias_sctp.c:285
#define SN_MIN_HASH_SIZE
Definition: alias_sctp.c:278
#define SN_MAX_HASH_SIZE
Definition: alias_sctp.c:279
#define SN_ADD_CLASH
Definition: alias_sctp.c:291
static struct sctp_nat_assoc * FindSctpGlobalT(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t l_port, uint16_t g_port)
Find the SCTP association for a T-Flag message (given the local port and global vtag)
Definition: alias_sctp.c:2201
#define SN_ADD_OK
Definition: alias_sctp.c:290
#define SN_MAX_GLOBAL_ADDRESSES
Definition: alias_sctp.c:288
#define SN_DEFAULT_HASH_SIZE
Definition: alias_sctp.c:280
#define SN_NULL_TBL
Definition: alias_sctp.c:287
#define SN_LOCAL_TBL
Definition: alias_sctp.c:282
#define SN_TABLE_HASH(vtag, port, size)
Definition: alias_sctp.c:293
static struct sctp_nat_assoc * FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match)
Find the SCTP association given the global port and vtag.
Definition: alias_sctp.c:2117
static int AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc)
Add the sctp association information to the global look up table.
Definition: alias_sctp.c:2299
static int AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_addr g_addr)
Add the sctp association information to the local look up table.
Definition: alias_sctp.c:2242
#define SN_GLOBAL_TBL
Definition: alias_sctp.c:283
static struct sctp_nat_assoc * FindSctpLocal(struct libalias *la, struct in_addr l_addr, struct in_addr g_addr, uint32_t l_vtag, uint16_t l_port, uint16_t g_port)
Find the SCTP association given the local address, port and vtag.
Definition: alias_sctp.c:2033
static void freeGlobalAddressList(struct sctp_nat_assoc *assoc)
free the Global Address List memory
Definition: alias_sctp.c:2388
static void logsctpassoc(struct sctp_nat_assoc *assoc, char *s)
Log an SCTP association's details.
Definition: alias_sctp.c:2615
static void logTimerQ(struct libalias *la)
Output timer queue to log.
Definition: alias_sctp.c:2697
#define SN_LOG(level, action)
Definition: alias_sctp.c:272
#define SN_LOG_DEBUG
Definition: alias_sctp.c:269
#define SN_LOG_INFO
Definition: alias_sctp.c:267
static void logsctperror(char *errormsg, uint32_t vtag, int error, int direction)
Log sctp nat errors.
Definition: alias_sctp.c:2540
#define SN_LOG_LOW
Definition: alias_sctp.c:265
#define SN_LOG_EVENT
Definition: alias_sctp.c:266
#define SN_LOG_DEBUG_MAX
Definition: alias_sctp.c:270
#define SN_LOG_DETAIL
Definition: alias_sctp.c:268
static void logsctpparse(int direction, struct sctp_nat_msg *sm)
Log what the parser parsed.
Definition: alias_sctp.c:2564
static void SctpAliasLog(const char *format,...)
Sctp NAT logging function.
Definition: alias_sctp.c:2723
static void logSctpLocal(struct libalias *la)
Output Local table to log.
Definition: alias_sctp.c:2679
static void logSctpGlobal(struct libalias *la)
Output Global table to log.
Definition: alias_sctp.c:2661
static void sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
Add an association timeout to the timer queue.
Definition: alias_sctp.c:2427
static void sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp)
Reset timer in timer queue.
Definition: alias_sctp.c:2466
static void sctp_RmTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
Remove an association from timer queue.
Definition: alias_sctp.c:2448
#define SN_U_T(la)
Definition: alias_sctp.c:305
#define SN_TIMER_QUEUE_SIZE
Definition: alias_sctp.c:302
#define SN_C_T(la)
Definition: alias_sctp.c:306
#define SN_I_T(la)
Definition: alias_sctp.c:304
void sctp_CheckTimers(struct libalias *la)
Check timer Q against current time.
Definition: alias_sctp.c:2494
#define SN_MAX_TIMER
Definition: alias_sctp.c:301
#define SN_MIN_TIMER
Definition: alias_sctp.c:300
#define SN_X_T(la)
Definition: alias_sctp.c:307
void SctpShowAliasStats(struct libalias *la)
Log current statistics for the libalias instance.
Definition: alias_db.c:185
#define SN_VTAG_PARAM_SIZE
Definition: alias_sctp.c:223
#define SN_PARSE_ERROR_PORT
Definition: alias_sctp.c:234
#define SN_SCTP_ASCONF
Definition: alias_sctp.c:245
#define SN_PARSE_ERROR_PARTIALLOOKUP
Definition: alias_sctp.c:236
#define SN_SCTP_NEXTPARAM(param)
Definition: alias_sctp.c:217
static int IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction)
Check to see if ASCONF contains an Add IP or Del IP parameter.
Definition: alias_sctp.c:1666
#define SN_PARSE_ERROR_LOOKUP
Definition: alias_sctp.c:235
#define SN_PARSE_ERROR_CHHL
Definition: alias_sctp.c:230
static int IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction)
Check that ASCONF was successful.
Definition: alias_sctp.c:1612
#define SN_PARSE_ERROR_IPSHL
Definition: alias_sctp.c:228
#define SN_MIN_CHUNK_SIZE
Definition: alias_sctp.c:221
#define SN_SCTP_NEXTCHUNK(chunkhead)
Definition: alias_sctp.c:213
static int GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, uint32_t *g_vtag, int direction)
Extract Vtags from Asconf Chunk.
Definition: alias_sctp.c:1274
#define SN_SCTP_INITACK
Definition: alias_sctp.c:242
#define SN_PARSE_ERROR_VTAG
Definition: alias_sctp.c:232
#define SN_ASCONFACK_PARAM_SIZE
Definition: alias_sctp.c:224
#define SN_SCTP_OTHER
Definition: alias_sctp.c:247
static void RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
RmGlobalIPAddresses from DelIP packets.
Definition: alias_sctp.c:1505
static void AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
AddGlobalIPAddresses from Init,InitAck,or AddIP packets.
Definition: alias_sctp.c:1342
#define SN_PARSE_ERROR_LOOKUP_ABORT
Definition: alias_sctp.c:237
#define SN_PARSE_ERROR_AS_MALLOC
Definition: alias_sctp.c:229
#define SN_SCTP_ASCONFACK
Definition: alias_sctp.c:246
#define SN_SCTP_INIT
Definition: alias_sctp.c:241
#define SN_MIN_PARAM_SIZE
Definition: alias_sctp.c:222
#define SN_SCTP_FIRSTCHUNK(sctphead)
Definition: alias_sctp.c:209
static int sctp_PktParser(struct libalias *la, int direction, struct ip *pip, struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc)
Parses SCTP packets for the key SCTP chunk that will be processed.
Definition: alias_sctp.c:1050
#define SN_SCTP_SHUTCOMP
Definition: alias_sctp.c:243
#define SN_SCTP_ABORT
Definition: alias_sctp.c:240
#define SN_SCTP_SHUTACK
Definition: alias_sctp.c:244
#define SN_PARSE_OK
Definition: alias_sctp.c:227
static int INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
Process SCTP message while waiting for an INIT-ACK message.
Definition: alias_sctp.c:1841
static int ID_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
Process SCTP message while in the Idle state.
Definition: alias_sctp.c:1772
#define SN_UP
Definition: alias_sctp.c:256
static int ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
Process SCTP message.
Definition: alias_sctp.c:1734
#define SN_ID
Definition: alias_sctp.c:253
static int CL_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
Process SCTP message while association is in the process of closing.
Definition: alias_sctp.c:1985
#define SN_CL
Definition: alias_sctp.c:257
#define SN_INa
Definition: alias_sctp.c:255
#define SN_INi
Definition: alias_sctp.c:254
static int INa_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
Process SCTP message while waiting for an AddIp-ACK message.
Definition: alias_sctp.c:1893
static int UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
Process SCTP messages while association is UP redirecting packets.
Definition: alias_sctp.c:1941
#define SN_RM
Definition: alias_sctp.c:258
int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.alias.sctp.chunk_proc_limit
Definition: alias_sctp.c:582
static u_int sysctl_error_on_ootb
net.inet.ip.alias.sctp.error_on_ootb
Definition: alias_sctp.c:340
static u_int sysctl_holddown_timer
net.inet.ip.alias.sctp.holddown_timer
Definition: alias_sctp.c:336
static u_int sysctl_chunk_proc_limit
net.inet.ip.alias.sctp.param_proc_limit
Definition: alias_sctp.c:349
static u_int sysctl_param_proc_limit
net.inet.ip.alias.sctp.param_proc_limit
Definition: alias_sctp.c:351
static u_int sysctl_log_level
net.inet.ip.alias.sctp.log_level
Definition: alias_sctp.c:328
int sysctl_chg_timer(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.fw.sctp.(init_timer|up_timer|shutdown_timer)
Definition: alias_sctp.c:460
#define SN_LOCAL_ERROR_ON_OOTB
Definition: alias_sctp.c:357
int sysctl_chg_accept_global_ootb_addip(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.alias.sctp.accept_global_ootb_addip
Definition: alias_sctp.c:538
static u_int sysctl_up_timer
net.inet.ip.alias.sctp.up_timer
Definition: alias_sctp.c:332
int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.alias.sctp.track_global_addresses
Definition: alias_sctp.c:626
#define SN_ERROR_ON_OOTB
Definition: alias_sctp.c:359
static u_int sysctl_track_global_addresses
net.inet.ip.alias.sctp.track_global_addresses
Definition: alias_sctp.c:353
int sysctl_chg_error_on_ootb(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.alias.sctp.error_on_ootb
Definition: alias_sctp.c:518
int sysctl_chg_loglevel(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.fw.sctp.log_level
Definition: alias_sctp.c:438
#define SN_LOCALandPARTIAL_ERROR_ON_OOTB
Definition: alias_sctp.c:358
int sysctl_chg_initialising_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.alias.sctp.initialising_chunk_proc_limit
Definition: alias_sctp.c:559
static u_int sysctl_init_timer
net.inet.ip.alias.sctp.init_timer
Definition: alias_sctp.c:330
int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.alias.sctp.hashtable_size
Definition: alias_sctp.c:489
static u_int sysctl_shutdown_timer
net.inet.ip.alias.sctp.shutdown_timer
Definition: alias_sctp.c:334
int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS)
sysctl callback for changing net.inet.ip.alias.sctp.param_proc_limit
Definition: alias_sctp.c:604
static u_int sysctl_initialising_chunk_proc_limit
net.inet.ip.alias.sctp.initialising_chunk_proc_limit
Definition: alias_sctp.c:347
static u_int sysctl_accept_global_ootb_addip
net.inet.ip.alias.sctp.accept_global_ootb_addip
Definition: alias_sctp.c:345
static u_int sysctl_hashtable_size
net.inet.ip.alias.sctp.hashtable_size
Definition: alias_sctp.c:338
__uint32_t uint32_t
Definition: in.h:62
__uint16_t uint16_t
Definition: in.h:57
__uint8_t uint8_t
Definition: in.h:52
char * inet_ntoa_r(struct in_addr ina, char *buf)
#define INADDR_ANY
Definition: in.h:48
u_int in_cksum_hdr(const struct ip *ip)
Definition: in_cksum.c:249
#define IP_MF
Definition: ip.h:14
#define SCTP_ASCONF_ACK
Definition: sctp.h:454
#define SCTP_INITIATION_ACK
Definition: sctp.h:433
#define SCTP_ASCONF
Definition: sctp.h:466
#define SCTP_OPERATION_ERROR
Definition: sctp.h:440
#define SCTP_HAD_NO_TCB
Definition: sctp.h:470
#define SCTP_SHUTDOWN_ACK
Definition: sctp.h:439
#define SCTP_SHUTDOWN_COMPLETE
Definition: sctp.h:445
#define SCTP_ABORT_ASSOCIATION
Definition: sctp.h:437
#define SCTP_INITIATION
Definition: sctp.h:432
#define SCTP_ADD_IP_ADDRESS
#define SCTP_SIZE32(x)
#define SCTP_SUCCESS_REPORT
#define SCTP_DEL_IP_ADDRESS
#define SCTP_IPV4_ADDRESS
#define IS_SCTP_CONTROL(a)
#define IPPROTO_SCTP
#define sctp_init_ack_chunk
Definition: sctp_header.h:235
#define sctp_init_ack
Definition: sctp_header.h:234
Definition: in.h:83
in_addr_t s_addr
Definition: in.h:84
Definition: ip.h:51
u_char ip_p
Definition: ip.h:69
u_short ip_id
Definition: ip.h:62
struct in_addr ip_src ip_dst
Definition: ip.h:71
u_char ip_tos
Definition: ip.h:60
u_char ip_hl
Definition: ip.h:53
u_short ip_sum
Definition: ip.h:70
u_short ip_len
Definition: ip.h:61
u_char ip_v
Definition: ip.h:54
u_char ip_ttl
Definition: ip.h:68
u_short ip_off
Definition: ip.h:63
int packetAliasMode
Definition: alias_local.h:92
struct sctp_nat_timer sctpNatTimer
Definition: alias_local.h:156
u_int sctpNatTableSize
Definition: alias_local.h:158
int sctpLinkCount
Definition: alias_local.h:153
struct in_addr g_addr
Definition: alias_sctp.h:146
struct sctp_ipv4addr_param addrp
Definition: sctp_header.h:125
uint8_t chunk_type
Definition: sctp.h:60
uint8_t chunk_flags
Definition: sctp.h:61
uint16_t chunk_length
Definition: sctp.h:62
uint16_t length
Definition: sctp.h:382
uint16_t code
Definition: sctp.h:381
uint32_t initiate_tag
Definition: sctp_header.h:174
sctp association information
Definition: alias_sctp.h:126
struct in_addr a_addr
Definition: alias_sctp.h:132
uint16_t g_port
Definition: alias_sctp.h:130
struct in_addr l_addr
Definition: alias_sctp.h:131
uint32_t l_vtag
Definition: alias_sctp.h:127
uint16_t l_port
Definition: alias_sctp.h:128
uint32_t g_vtag
Definition: alias_sctp.h:129
SCTP message.
Definition: alias_sctp.h:166
int chunk_length
Definition: alias_sctp.h:175
union sctpChunkOfInt sctpchnk
Definition: alias_sctp.h:174
uint16_t msg
Definition: alias_sctp.h:167
struct ip * ip_hdr
Definition: alias_sctp.h:171
struct sctphdr * sctp_hdr
Definition: alias_sctp.h:173
uint16_t param_length
Definition: sctp.h:71
uint16_t param_type
Definition: sctp.h:70
Definition: sctp.h:48
uint16_t src_port
Definition: sctp.h:49
uint32_t v_tag
Definition: sctp.h:51
uint32_t checksum
Definition: sctp.h:52
uint16_t dest_port
Definition: sctp.h:50
struct sctp_init_ack * InitAck
Definition: alias_sctp.h:157
struct sctp_paramhdr * Asconf
Definition: alias_sctp.h:158
struct sctp_init * Init
Definition: alias_sctp.h:156