Deleted Added
full compact
alias_sctp.c (186543) alias_sctp.c (188294)
1//* $Id$ */
2//#ifndef lint
3//static char vcid[] = "$Id$";
4//#endif /* lint */
5/**
6 * @file alias_sctp.c
7 * Copyright (c) 2008, Centre for Advanced Internet Architectures
8 * Swinburne University of Technology, Melbourne, Australia
9 * (CRICOS number 00111D).
10 *
1/**
2 * @file alias_sctp.c
3 * Copyright (c) 2008, Centre for Advanced Internet Architectures
4 * Swinburne University of Technology, Melbourne, Australia
5 * (CRICOS number 00111D).
6 *
11 * Alias_sctp forms part of the libalias kernel module to handle
12 * Network Address Translation (NAT) for the SCTP protocol.
13 *
14 * This software was developed by David A. Hayes and Jason But
15 *
16 * The design is outlined in CAIA technical report number 080618A
17 * (D. Hayes and J. But, "Alias_sctp Version 0.1: SCTP NAT implementation in IPFW")
18 *
19 * Development is part of the CAIA SONATA project,
20 * proposed by Jason But and Grenville Armitage:
21 * http://caia.swin.edu.au/urp/sonata/
22 *
23 *
24 * This project has been made possible in part by a grant from
25 * the Cisco University Research Program Fund at Community
26 * Foundation Silicon Valley.
27 *
28 *
29 *
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.

--- 9 unchanged lines hidden (view full) ---

49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
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.

--- 9 unchanged lines hidden (view full) ---

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * Alias_sctp forms part of the libalias kernel module to handle
33 * Network Address Translation (NAT) for the SCTP protocol.
34 *
35 * This software was developed by David A. Hayes and Jason But
36 *
37 * The design is outlined in CAIA technical report number 080618A
38 * (D. Hayes and J. But, "Alias_sctp Version 0.1: SCTP NAT implementation in IPFW")
39 *
40 * Development is part of the CAIA SONATA project,
41 * proposed by Jason But and Grenville Armitage:
42 * http://caia.swin.edu.au/urp/sonata/
43 *
44 *
45 * This project has been made possible in part by a grant from
46 * the Cisco University Research Program Fund at Community
47 * Foundation Silicon Valley.
48 *
57 */
58/** @mainpage
59 * Alias_sctp is part of the SONATA (http://caia.swin.edu.au/urp/sonata) project
60 * to develop and release a BSD licensed implementation of a Network Address
61 * Translation (NAT) module that supports the Stream Control Transmission
62 * Protocol (SCTP).
63 *
64 * Traditional address and port number look ups are inadequate for SCTP's

--- 10 unchanged lines hidden (view full) ---

75 * - Generation and delivery of AbortM/ErrorM packets upon detection of NAT
76 * collisions
77 * - Per-port forwarding rules
78 * - Dynamically controllable logging and statistics
79 * - Dynamic management of timers
80 * - Dynamic control of hash-table size
81 */
82
49 */
50/** @mainpage
51 * Alias_sctp is part of the SONATA (http://caia.swin.edu.au/urp/sonata) project
52 * to develop and release a BSD licensed implementation of a Network Address
53 * Translation (NAT) module that supports the Stream Control Transmission
54 * Protocol (SCTP).
55 *
56 * Traditional address and port number look ups are inadequate for SCTP's

--- 10 unchanged lines hidden (view full) ---

67 * - Generation and delivery of AbortM/ErrorM packets upon detection of NAT
68 * collisions
69 * - Per-port forwarding rules
70 * - Dynamically controllable logging and statistics
71 * - Dynamic management of timers
72 * - Dynamic control of hash-table size
73 */
74
75/* $FreeBSD: head/sys/netinet/libalias/alias_sctp.c 188294 2009-02-07 18:49:42Z piso $ */
76
83#ifdef _KERNEL
84#include <machine/stdarg.h>
85#include <sys/param.h>
86#include <sys/systm.h>
87#include <sys/kernel.h>
88#include <sys/module.h>
89#include <sys/syslog.h>
90#include <netinet/libalias/alias_sctp.h>

--- 11 unchanged lines hidden (view full) ---

102#endif //#ifdef _KERNEL
103
104/* ----------------------------------------------------------------------
105 * FUNCTION PROTOTYPES
106 * ----------------------------------------------------------------------
107 */
108/* Packet Parsing Functions */
109static int sctp_PktParser(struct libalias *la, int direction, struct ip *pip,
77#ifdef _KERNEL
78#include <machine/stdarg.h>
79#include <sys/param.h>
80#include <sys/systm.h>
81#include <sys/kernel.h>
82#include <sys/module.h>
83#include <sys/syslog.h>
84#include <netinet/libalias/alias_sctp.h>

--- 11 unchanged lines hidden (view full) ---

96#endif //#ifdef _KERNEL
97
98/* ----------------------------------------------------------------------
99 * FUNCTION PROTOTYPES
100 * ----------------------------------------------------------------------
101 */
102/* Packet Parsing Functions */
103static int sctp_PktParser(struct libalias *la, int direction, struct ip *pip,
110 struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc);
104 struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc);
111static int GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm,
105static int GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm,
112 uint32_t *l_vtag, uint32_t *g_vtag, int direction);
106 uint32_t *l_vtag, uint32_t *g_vtag, int direction);
113static int IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction);
114
115static void AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction);
116static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr);
117static void RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction);
118static int IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction);
119
120/* State Machine Functions */
121static int ProcessSctpMsg(struct libalias *la, int direction, \
107static int IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction);
108
109static void AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction);
110static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr);
111static void RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction);
112static int IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction);
113
114/* State Machine Functions */
115static int ProcessSctpMsg(struct libalias *la, int direction, \
122 struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc);
116 struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc);
123
124static int ID_process(struct libalias *la, int direction,\
117
118static int ID_process(struct libalias *la, int direction,\
125 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
119 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
126static int INi_process(struct libalias *la, int direction,\
120static int INi_process(struct libalias *la, int direction,\
127 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
121 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
128static int INa_process(struct libalias *la, int direction,\
122static int INa_process(struct libalias *la, int direction,\
129 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
123 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
130static int UP_process(struct libalias *la, int direction,\
124static int UP_process(struct libalias *la, int direction,\
131 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
125 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
132static int CL_process(struct libalias *la, int direction,\
126static int CL_process(struct libalias *la, int direction,\
133 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
127 struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm);
134static void TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm,\
128static void TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm,\
135 struct sctp_nat_assoc *assoc, int sndrply, int direction);
129 struct sctp_nat_assoc *assoc, int sndrply, int direction);
136
137/* Hash Table Functions */
138static struct sctp_nat_assoc*
139FindSctpLocal(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);
140static struct sctp_nat_assoc*
141FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match);
142static struct sctp_nat_assoc*
143FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc);

--- 40 unchanged lines hidden (view full) ---

184 *
185 * Calls the higher level ShowAliasStats() in alias_db.c which logs all current
186 * statistics about the libalias instance - including SCTP statistics
187 *
188 * @param la Pointer to the libalias instance
189 */
190void SctpShowAliasStats(struct libalias *la);
191
130
131/* Hash Table Functions */
132static struct sctp_nat_assoc*
133FindSctpLocal(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);
134static struct sctp_nat_assoc*
135FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match);
136static struct sctp_nat_assoc*
137FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc);

--- 40 unchanged lines hidden (view full) ---

178 *
179 * Calls the higher level ShowAliasStats() in alias_db.c which logs all current
180 * statistics about the libalias instance - including SCTP statistics
181 *
182 * @param la Pointer to the libalias instance
183 */
184void SctpShowAliasStats(struct libalias *la);
185
192/** @ingroup external
193 * @brief Find the address to redirect incoming packets
194 *
195 * This function is defined in alias_db.c, since it calls static functions in
196 * this file
197 *
198 * Given a destination port for incoming packets to the NAT, discover what
199 * (if any) internal IP address this packet should be re-directed to
200 *
201 * @param la Pointer to the libalias instance
202 * @param sm Pointer to the incoming message
203 *
204 * @return Address to redirect an incoming INIT to
205 */
206struct in_addr FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm);
207
208#ifdef _KERNEL
209
210MALLOC_DEFINE(M_SCTPNAT, "sctpnat", "sctp nat dbs");
211/* Use kernel allocator. */
212#ifdef _SYS_MALLOC_H_
213#define sn_malloc(x) malloc(x, M_SCTPNAT, M_NOWAIT|M_ZERO)
214#define sn_calloc(n,x) sn_malloc(x * n)
215#define sn_free(x) free(x, M_SCTPNAT)

--- 143 unchanged lines hidden (view full) ---

359/** @brief net.inet.ip.alias.sctp.shutdown_timer */
360static u_int sysctl_shutdown_timer = 15; /**< Seconds to hold an association in the table waiting for a SHUTDOWN-COMPLETE */
361/** @brief net.inet.ip.alias.sctp.holddown_timer */
362static u_int sysctl_holddown_timer = 0; /**< Seconds to hold an association in the table after it has been shutdown (to allow for lost SHUTDOWN-COMPLETEs) */
363/** @brief net.inet.ip.alias.sctp.hashtable_size */
364static u_int sysctl_hashtable_size = SN_DEFAULT_HASH_SIZE; /**< Sets the hash table size for any NEW NAT instances (existing instances retain their existing Hash Table */
365/** @brief net.inet.ip.alias.sctp.error_on_ootb */
366static u_int sysctl_error_on_ootb = 1; /**< NAT response to receipt of OOTB packet
186#ifdef _KERNEL
187
188MALLOC_DEFINE(M_SCTPNAT, "sctpnat", "sctp nat dbs");
189/* Use kernel allocator. */
190#ifdef _SYS_MALLOC_H_
191#define sn_malloc(x) malloc(x, M_SCTPNAT, M_NOWAIT|M_ZERO)
192#define sn_calloc(n,x) sn_malloc(x * n)
193#define sn_free(x) free(x, M_SCTPNAT)

--- 143 unchanged lines hidden (view full) ---

337/** @brief net.inet.ip.alias.sctp.shutdown_timer */
338static u_int sysctl_shutdown_timer = 15; /**< Seconds to hold an association in the table waiting for a SHUTDOWN-COMPLETE */
339/** @brief net.inet.ip.alias.sctp.holddown_timer */
340static u_int sysctl_holddown_timer = 0; /**< Seconds to hold an association in the table after it has been shutdown (to allow for lost SHUTDOWN-COMPLETEs) */
341/** @brief net.inet.ip.alias.sctp.hashtable_size */
342static u_int sysctl_hashtable_size = SN_DEFAULT_HASH_SIZE; /**< Sets the hash table size for any NEW NAT instances (existing instances retain their existing Hash Table */
343/** @brief net.inet.ip.alias.sctp.error_on_ootb */
344static u_int sysctl_error_on_ootb = 1; /**< NAT response to receipt of OOTB packet
367 (0 - No response, 1 - NAT will send ErrorM only to local side,
368 2 - NAT will send local ErrorM and global ErrorM if there was a partial association match
369 3 - NAT will send ErrorM to both local and global) */
345 (0 - No response, 1 - NAT will send ErrorM only to local side,
346 2 - NAT will send local ErrorM and global ErrorM if there was a partial association match
347 3 - NAT will send ErrorM to both local and global) */
370/** @brief net.inet.ip.alias.sctp.accept_global_ootb_addip */
371static u_int sysctl_accept_global_ootb_addip = 0; /**<NAT responset to receipt of global OOTB AddIP (0 - No response, 1 - NAT will accept OOTB global AddIP messages for processing (Security risk)) */
372/** @brief net.inet.ip.alias.sctp.initialising_chunk_proc_limit */
373static u_int sysctl_initialising_chunk_proc_limit = 2; /**< A limit on the number of chunks that should be searched if there is no matching association (DoS prevention) */
374/** @brief net.inet.ip.alias.sctp.param_proc_limit */
375static u_int sysctl_chunk_proc_limit = 5; /**< A limit on the number of chunks that should be searched (DoS prevention) */
376/** @brief net.inet.ip.alias.sctp.param_proc_limit */
377static u_int sysctl_param_proc_limit = 25; /**< A limit on the number of parameters (in chunks) that should be searched (DoS prevention) */
378/** @brief net.inet.ip.alias.sctp.track_global_addresses */
379static u_int sysctl_track_global_addresses = 0; /**< Configures the global address tracking option within the NAT (0 - Global tracking is disabled, > 0 - enables tracking but limits the number of global IP addresses to this value)
348/** @brief net.inet.ip.alias.sctp.accept_global_ootb_addip */
349static u_int sysctl_accept_global_ootb_addip = 0; /**<NAT responset to receipt of global OOTB AddIP (0 - No response, 1 - NAT will accept OOTB global AddIP messages for processing (Security risk)) */
350/** @brief net.inet.ip.alias.sctp.initialising_chunk_proc_limit */
351static u_int sysctl_initialising_chunk_proc_limit = 2; /**< A limit on the number of chunks that should be searched if there is no matching association (DoS prevention) */
352/** @brief net.inet.ip.alias.sctp.param_proc_limit */
353static u_int sysctl_chunk_proc_limit = 5; /**< A limit on the number of chunks that should be searched (DoS prevention) */
354/** @brief net.inet.ip.alias.sctp.param_proc_limit */
355static u_int sysctl_param_proc_limit = 25; /**< A limit on the number of parameters (in chunks) that should be searched (DoS prevention) */
356/** @brief net.inet.ip.alias.sctp.track_global_addresses */
357static u_int sysctl_track_global_addresses = 0; /**< Configures the global address tracking option within the NAT (0 - Global tracking is disabled, > 0 - enables tracking but limits the number of global IP addresses to this value)
380 If set to >=1 the NAT will track that many global IP addresses. This may reduce look up table conflicts, but increases processing */
358 If set to >=1 the NAT will track that many global IP addresses. This may reduce look up table conflicts, but increases processing */
381
382#define SN_NO_ERROR_ON_OOTB 0 /**< Send no errorM on out of the blue packets */
383#define SN_LOCAL_ERROR_ON_OOTB 1 /**< Send only local errorM on out of the blue packets */
384#define SN_LOCALandPARTIAL_ERROR_ON_OOTB 2 /**< Send local errorM and global errorM for out of the blue packets only if partial match found */
385#define SN_ERROR_ON_OOTB 3 /**< Send errorM on out of the blue packets */
386
387#ifdef SYSCTL_NODE
388
389SYSCTL_DECL(_net_inet);
390SYSCTL_DECL(_net_inet_ip);
391SYSCTL_DECL(_net_inet_ip_alias);
392
393SYSCTL_NODE(_net_inet_ip_alias, OID_AUTO, sctp, CTLFLAG_RW, NULL, "SCTP NAT");
394
395SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, log_level, CTLTYPE_UINT | CTLFLAG_RW,
359
360#define SN_NO_ERROR_ON_OOTB 0 /**< Send no errorM on out of the blue packets */
361#define SN_LOCAL_ERROR_ON_OOTB 1 /**< Send only local errorM on out of the blue packets */
362#define SN_LOCALandPARTIAL_ERROR_ON_OOTB 2 /**< Send local errorM and global errorM for out of the blue packets only if partial match found */
363#define SN_ERROR_ON_OOTB 3 /**< Send errorM on out of the blue packets */
364
365#ifdef SYSCTL_NODE
366
367SYSCTL_DECL(_net_inet);
368SYSCTL_DECL(_net_inet_ip);
369SYSCTL_DECL(_net_inet_ip_alias);
370
371SYSCTL_NODE(_net_inet_ip_alias, OID_AUTO, sctp, CTLFLAG_RW, NULL, "SCTP NAT");
372
373SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, log_level, CTLTYPE_UINT | CTLFLAG_RW,
396 &sysctl_log_level, 0, sysctl_chg_loglevel, "IU",
397 "Level of detail (0 - default, 1 - event, 2 - info, 3 - detail, 4 - debug, 5 - max debug)");
374 &sysctl_log_level, 0, sysctl_chg_loglevel, "IU",
375 "Level of detail (0 - default, 1 - event, 2 - info, 3 - detail, 4 - debug, 5 - max debug)");
398SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, init_timer, CTLTYPE_UINT | CTLFLAG_RW,
376SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, init_timer, CTLTYPE_UINT | CTLFLAG_RW,
399 &sysctl_init_timer, 0, sysctl_chg_timer, "IU",
400 "Timeout value (s) while waiting for (INIT-ACK|AddIP-ACK)");
377 &sysctl_init_timer, 0, sysctl_chg_timer, "IU",
378 "Timeout value (s) while waiting for (INIT-ACK|AddIP-ACK)");
401SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, up_timer, CTLTYPE_UINT | CTLFLAG_RW,
379SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, up_timer, CTLTYPE_UINT | CTLFLAG_RW,
402 &sysctl_up_timer, 0, sysctl_chg_timer, "IU",
403 "Timeout value (s) to keep an association up with no traffic");
380 &sysctl_up_timer, 0, sysctl_chg_timer, "IU",
381 "Timeout value (s) to keep an association up with no traffic");
404SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, shutdown_timer, CTLTYPE_UINT | CTLFLAG_RW,
382SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, shutdown_timer, CTLTYPE_UINT | CTLFLAG_RW,
405 &sysctl_shutdown_timer, 0, sysctl_chg_timer, "IU",
406 "Timeout value (s) while waiting for SHUTDOWN-COMPLETE");
383 &sysctl_shutdown_timer, 0, sysctl_chg_timer, "IU",
384 "Timeout value (s) while waiting for SHUTDOWN-COMPLETE");
407SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, holddown_timer, CTLTYPE_UINT | CTLFLAG_RW,
385SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, holddown_timer, CTLTYPE_UINT | CTLFLAG_RW,
408 &sysctl_holddown_timer, 0, sysctl_chg_timer, "IU",
409 "Hold association in table for this many seconds after receiving a SHUTDOWN-COMPLETE");
386 &sysctl_holddown_timer, 0, sysctl_chg_timer, "IU",
387 "Hold association in table for this many seconds after receiving a SHUTDOWN-COMPLETE");
410SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, hashtable_size, CTLTYPE_UINT | CTLFLAG_RW,
388SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, hashtable_size, CTLTYPE_UINT | CTLFLAG_RW,
411 &sysctl_hashtable_size, 0, sysctl_chg_hashtable_size, "IU",
412 "Size of hash tables used for NAT lookups (100 < prime_number > 1000001)");
389 &sysctl_hashtable_size, 0, sysctl_chg_hashtable_size, "IU",
390 "Size of hash tables used for NAT lookups (100 < prime_number > 1000001)");
413SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, error_on_ootb, CTLTYPE_UINT | CTLFLAG_RW,
391SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, error_on_ootb, CTLTYPE_UINT | CTLFLAG_RW,
414 &sysctl_error_on_ootb, 0, sysctl_chg_error_on_ootb, "IU",
415 "ErrorM sent on receipt of ootb packet:\n\t0 - none,\n\t1 - to local only,\n\t2 - to local and global if a partial association match,\n\t3 - to local and global (DoS risk)");
392 &sysctl_error_on_ootb, 0, sysctl_chg_error_on_ootb, "IU",
393 "ErrorM sent on receipt of ootb packet:\n\t0 - none,\n\t1 - to local only,\n\t2 - to local and global if a partial association match,\n\t3 - to local and global (DoS risk)");
416SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, accept_global_ootb_addip, CTLTYPE_UINT | CTLFLAG_RW,
394SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, accept_global_ootb_addip, CTLTYPE_UINT | CTLFLAG_RW,
417 &sysctl_accept_global_ootb_addip, 0, sysctl_chg_accept_global_ootb_addip, "IU",
418 "NAT response to receipt of global OOTB AddIP:\n\t0 - No response,\n\t1 - NAT will accept OOTB global AddIP messages for processing (Security risk)");
395 &sysctl_accept_global_ootb_addip, 0, sysctl_chg_accept_global_ootb_addip, "IU",
396 "NAT response to receipt of global OOTB AddIP:\n\t0 - No response,\n\t1 - NAT will accept OOTB global AddIP messages for processing (Security risk)");
419SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, initialising_chunk_proc_limit, CTLTYPE_UINT | CTLFLAG_RW,
397SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, initialising_chunk_proc_limit, CTLTYPE_UINT | CTLFLAG_RW,
420 &sysctl_initialising_chunk_proc_limit, 0, sysctl_chg_initialising_chunk_proc_limit, "IU",
421 "Number of chunks that should be processed if there is no current association found:\n\t > 0 (A high value is a DoS risk)");
398 &sysctl_initialising_chunk_proc_limit, 0, sysctl_chg_initialising_chunk_proc_limit, "IU",
399 "Number of chunks that should be processed if there is no current association found:\n\t > 0 (A high value is a DoS risk)");
422SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, chunk_proc_limit, CTLTYPE_UINT | CTLFLAG_RW,
400SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, chunk_proc_limit, CTLTYPE_UINT | CTLFLAG_RW,
423 &sysctl_chunk_proc_limit, 0, sysctl_chg_chunk_proc_limit, "IU",
424 "Number of chunks that should be processed to find key chunk:\n\t>= initialising_chunk_proc_limit (A high value is a DoS risk)");
401 &sysctl_chunk_proc_limit, 0, sysctl_chg_chunk_proc_limit, "IU",
402 "Number of chunks that should be processed to find key chunk:\n\t>= initialising_chunk_proc_limit (A high value is a DoS risk)");
425SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, param_proc_limit, CTLTYPE_UINT | CTLFLAG_RW,
403SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, param_proc_limit, CTLTYPE_UINT | CTLFLAG_RW,
426 &sysctl_param_proc_limit, 0, sysctl_chg_param_proc_limit, "IU",
427 "Number of parameters (in a chunk) that should be processed to find key parameters:\n\t> 1 (A high value is a DoS risk)");
404 &sysctl_param_proc_limit, 0, sysctl_chg_param_proc_limit, "IU",
405 "Number of parameters (in a chunk) that should be processed to find key parameters:\n\t> 1 (A high value is a DoS risk)");
428SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, track_global_addresses, CTLTYPE_UINT | CTLFLAG_RW,
406SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, track_global_addresses, CTLTYPE_UINT | CTLFLAG_RW,
429 &sysctl_track_global_addresses, 0, sysctl_chg_track_global_addresses, "IU",
430 "Configures the global address tracking option within the NAT:\n\t0 - Global tracking is disabled,\n\t> 0 - enables tracking but limits the number of global IP addresses to this value");
407 &sysctl_track_global_addresses, 0, sysctl_chg_track_global_addresses, "IU",
408 "Configures the global address tracking option within the NAT:\n\t0 - Global tracking is disabled,\n\t> 0 - enables tracking but limits the number of global IP addresses to this value");
431
432#endif /* SYSCTL_NODE */
433
434/** @}
435 * @ingroup sysctl
436 * @brief sysctl callback for changing net.inet.ip.fw.sctp.log_level
437 *
438 * Updates the variable sysctl_log_level to the provided value and ensures
439 * it is in the valid range (SN_LOG_LOW -> SN_LOG_DEBUG)
440 */
441int sysctl_chg_loglevel(SYSCTL_HANDLER_ARGS)
442{
409
410#endif /* SYSCTL_NODE */
411
412/** @}
413 * @ingroup sysctl
414 * @brief sysctl callback for changing net.inet.ip.fw.sctp.log_level
415 *
416 * Updates the variable sysctl_log_level to the provided value and ensures
417 * it is in the valid range (SN_LOG_LOW -> SN_LOG_DEBUG)
418 */
419int sysctl_chg_loglevel(SYSCTL_HANDLER_ARGS)
420{
443 u_int level = *(u_int *)arg1;
444 int error;
421 u_int level = *(u_int *)arg1;
422 int error;
445
423
446 error = sysctl_handle_int(oidp, &level, 0, req);
447 if (error) return (error);
424 error = sysctl_handle_int(oidp, &level, 0, req);
425 if (error) return (error);
448
426
449 sysctl_log_level = (level > SN_LOG_DEBUG_MAX)?(SN_LOG_DEBUG_MAX):(level);
450 sysctl_log_level = (level < SN_LOG_LOW)?(SN_LOG_LOW):(level);
427 sysctl_log_level = (level > SN_LOG_DEBUG_MAX)?(SN_LOG_DEBUG_MAX):(level);
428 sysctl_log_level = (level < SN_LOG_LOW)?(SN_LOG_LOW):(level);
451
429
452 return (0);
430 return (0);
453}
454
455/** @ingroup sysctl
456 * @brief sysctl callback for changing net.inet.ip.fw.sctp.(init_timer|up_timer|shutdown_timer)
457 *
458 * Updates the timer-based sysctl variables. The new values are sanity-checked
459 * to make sure that they are within the range SN_MIN_TIMER-SN_MAX_TIMER. The
460 * holddown timer is allowed to be 0
461 */
462int sysctl_chg_timer(SYSCTL_HANDLER_ARGS)
463{
431}
432
433/** @ingroup sysctl
434 * @brief sysctl callback for changing net.inet.ip.fw.sctp.(init_timer|up_timer|shutdown_timer)
435 *
436 * Updates the timer-based sysctl variables. The new values are sanity-checked
437 * to make sure that they are within the range SN_MIN_TIMER-SN_MAX_TIMER. The
438 * holddown timer is allowed to be 0
439 */
440int sysctl_chg_timer(SYSCTL_HANDLER_ARGS)
441{
464 u_int timer = *(u_int *)arg1;
465 int error;
442 u_int timer = *(u_int *)arg1;
443 int error;
466
444
467 error = sysctl_handle_int(oidp, &timer, 0, req);
468 if (error) return (error);
445 error = sysctl_handle_int(oidp, &timer, 0, req);
446 if (error) return (error);
469
447
470 timer = (timer > SN_MAX_TIMER)?(SN_MAX_TIMER):(timer);
448 timer = (timer > SN_MAX_TIMER)?(SN_MAX_TIMER):(timer);
471
449
472 if (((u_int *)arg1) != &sysctl_holddown_timer)
473 {
474 timer = (timer < SN_MIN_TIMER)?(SN_MIN_TIMER):(timer);
475 }
450 if (((u_int *)arg1) != &sysctl_holddown_timer)
451 {
452 timer = (timer < SN_MIN_TIMER)?(SN_MIN_TIMER):(timer);
453 }
476
454
477 *(u_int *)arg1 = timer;
455 *(u_int *)arg1 = timer;
478
456
479 return (0);
457 return (0);
480}
481
482/** @ingroup sysctl
483 * @brief sysctl callback for changing net.inet.ip.alias.sctp.hashtable_size
484 *
485 * Updates the hashtable_size sysctl variable. The new value should be a prime
486 * number. We sanity check to ensure that the size is within the range
487 * SN_MIN_HASH_SIZE-SN_MAX_HASH_SIZE. We then check the provided number to see
488 * if it is prime. We approximate by checking that (2,3,5,7,11) are not factors,
489 * incrementing the user provided value until we find a suitable number.
490 */
491int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS)
492{
458}
459
460/** @ingroup sysctl
461 * @brief sysctl callback for changing net.inet.ip.alias.sctp.hashtable_size
462 *
463 * Updates the hashtable_size sysctl variable. The new value should be a prime
464 * number. We sanity check to ensure that the size is within the range
465 * SN_MIN_HASH_SIZE-SN_MAX_HASH_SIZE. We then check the provided number to see
466 * if it is prime. We approximate by checking that (2,3,5,7,11) are not factors,
467 * incrementing the user provided value until we find a suitable number.
468 */
469int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS)
470{
493 u_int size = *(u_int *)arg1;
494 int error;
471 u_int size = *(u_int *)arg1;
472 int error;
495
473
496 error = sysctl_handle_int(oidp, &size, 0, req);
497 if (error) return (error);
474 error = sysctl_handle_int(oidp, &size, 0, req);
475 if (error) return (error);
498
476
499 size = (size < SN_MIN_HASH_SIZE)?(SN_MIN_HASH_SIZE):((size > SN_MAX_HASH_SIZE)?(SN_MAX_HASH_SIZE):(size));
477 size = (size < SN_MIN_HASH_SIZE)?(SN_MIN_HASH_SIZE):((size > SN_MAX_HASH_SIZE)?(SN_MAX_HASH_SIZE):(size));
500
478
501 size |= 0x00000001; /* make odd */
479 size |= 0x00000001; /* make odd */
502
480
503 for(;(((size % 3) == 0) || ((size % 5) == 0) || ((size % 7) == 0) || ((size % 11) == 0)); size+=2);
504 sysctl_hashtable_size = size;
481 for(;(((size % 3) == 0) || ((size % 5) == 0) || ((size % 7) == 0) || ((size % 11) == 0)); size+=2);
482 sysctl_hashtable_size = size;
505
483
506 return (0);
484 return (0);
507}
508
509/** @ingroup sysctl
510 * @brief sysctl callback for changing net.inet.ip.alias.sctp.error_on_ootb
511 *
512 * Updates the error_on_clash sysctl variable.
513 * If set to 0, no ErrorM will be sent if there is a look up table clash
514 * If set to 1, an ErrorM is sent only to the local side
515 * If set to 2, an ErrorM is sent to the local side and global side if there is
516 * a partial association match
517 * If set to 3, an ErrorM is sent to both local and global sides (DoS) risk.
518 */
519int sysctl_chg_error_on_ootb(SYSCTL_HANDLER_ARGS)
520{
485}
486
487/** @ingroup sysctl
488 * @brief sysctl callback for changing net.inet.ip.alias.sctp.error_on_ootb
489 *
490 * Updates the error_on_clash sysctl variable.
491 * If set to 0, no ErrorM will be sent if there is a look up table clash
492 * If set to 1, an ErrorM is sent only to the local side
493 * If set to 2, an ErrorM is sent to the local side and global side if there is
494 * a partial association match
495 * If set to 3, an ErrorM is sent to both local and global sides (DoS) risk.
496 */
497int sysctl_chg_error_on_ootb(SYSCTL_HANDLER_ARGS)
498{
521 u_int flag = *(u_int *)arg1;
522 int error;
499 u_int flag = *(u_int *)arg1;
500 int error;
523
501
524 error = sysctl_handle_int(oidp, &flag, 0, req);
525 if (error) return (error);
502 error = sysctl_handle_int(oidp, &flag, 0, req);
503 if (error) return (error);
526
504
527 sysctl_error_on_ootb = (flag > SN_ERROR_ON_OOTB) ? SN_ERROR_ON_OOTB: flag;
505 sysctl_error_on_ootb = (flag > SN_ERROR_ON_OOTB) ? SN_ERROR_ON_OOTB: flag;
528
506
529 return (0);
507 return (0);
530}
531
532/** @ingroup sysctl
533 * @brief sysctl callback for changing net.inet.ip.alias.sctp.accept_global_ootb_addip
534 *
535 * If set to 1 the NAT will accept ootb global addip messages for processing (Security risk)
536 * Default is 0, only responding to local ootb AddIP messages
537 */
538int sysctl_chg_accept_global_ootb_addip(SYSCTL_HANDLER_ARGS)
539{
508}
509
510/** @ingroup sysctl
511 * @brief sysctl callback for changing net.inet.ip.alias.sctp.accept_global_ootb_addip
512 *
513 * If set to 1 the NAT will accept ootb global addip messages for processing (Security risk)
514 * Default is 0, only responding to local ootb AddIP messages
515 */
516int sysctl_chg_accept_global_ootb_addip(SYSCTL_HANDLER_ARGS)
517{
540 u_int flag = *(u_int *)arg1;
541 int error;
518 u_int flag = *(u_int *)arg1;
519 int error;
542
520
543 error = sysctl_handle_int(oidp, &flag, 0, req);
544 if (error) return (error);
521 error = sysctl_handle_int(oidp, &flag, 0, req);
522 if (error) return (error);
545
523
546 sysctl_accept_global_ootb_addip = (flag == 1) ? 1: 0;
524 sysctl_accept_global_ootb_addip = (flag == 1) ? 1: 0;
547
525
548 return (0);
526 return (0);
549}
550
551/** @ingroup sysctl
552 * @brief sysctl callback for changing net.inet.ip.alias.sctp.initialising_chunk_proc_limit
553 *
554 * Updates the initialising_chunk_proc_limit sysctl variable. Number of chunks
555 * that should be processed if there is no current association found: > 0 (A
556 * high value is a DoS risk)
557 */
558int sysctl_chg_initialising_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
559{
527}
528
529/** @ingroup sysctl
530 * @brief sysctl callback for changing net.inet.ip.alias.sctp.initialising_chunk_proc_limit
531 *
532 * Updates the initialising_chunk_proc_limit sysctl variable. Number of chunks
533 * that should be processed if there is no current association found: > 0 (A
534 * high value is a DoS risk)
535 */
536int sysctl_chg_initialising_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
537{
560 u_int proclimit = *(u_int *)arg1;
561 int error;
538 u_int proclimit = *(u_int *)arg1;
539 int error;
562
540
563 error = sysctl_handle_int(oidp, &proclimit, 0, req);
564 if (error) return (error);
541 error = sysctl_handle_int(oidp, &proclimit, 0, req);
542 if (error) return (error);
565
543
566 sysctl_initialising_chunk_proc_limit = (proclimit < 1) ? 1: proclimit;
567 sysctl_chunk_proc_limit =
568 (sysctl_chunk_proc_limit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : sysctl_chunk_proc_limit;
544 sysctl_initialising_chunk_proc_limit = (proclimit < 1) ? 1: proclimit;
545 sysctl_chunk_proc_limit =
546 (sysctl_chunk_proc_limit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : sysctl_chunk_proc_limit;
569
547
570 return (0);
548 return (0);
571}
572
573/** @ingroup sysctl
574 * @brief sysctl callback for changing net.inet.ip.alias.sctp.chunk_proc_limit
575 *
576 * Updates the chunk_proc_limit sysctl variable.
577 * Number of chunks that should be processed to find key chunk:
578 * >= initialising_chunk_proc_limit (A high value is a DoS risk)
579 */
580int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
581{
549}
550
551/** @ingroup sysctl
552 * @brief sysctl callback for changing net.inet.ip.alias.sctp.chunk_proc_limit
553 *
554 * Updates the chunk_proc_limit sysctl variable.
555 * Number of chunks that should be processed to find key chunk:
556 * >= initialising_chunk_proc_limit (A high value is a DoS risk)
557 */
558int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS)
559{
582 u_int proclimit = *(u_int *)arg1;
583 int error;
560 u_int proclimit = *(u_int *)arg1;
561 int error;
584
562
585 error = sysctl_handle_int(oidp, &proclimit, 0, req);
586 if (error) return (error);
563 error = sysctl_handle_int(oidp, &proclimit, 0, req);
564 if (error) return (error);
587
565
588 sysctl_chunk_proc_limit =
589 (proclimit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : proclimit;
566 sysctl_chunk_proc_limit =
567 (proclimit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : proclimit;
590
568
591 return (0);
569 return (0);
592}
593
594
595/** @ingroup sysctl
596 * @brief sysctl callback for changing net.inet.ip.alias.sctp.param_proc_limit
597 *
598 * Updates the param_proc_limit sysctl variable.
599 * Number of parameters that should be processed to find key parameters:
600 * > 1 (A high value is a DoS risk)
601 */
602int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS)
603{
570}
571
572
573/** @ingroup sysctl
574 * @brief sysctl callback for changing net.inet.ip.alias.sctp.param_proc_limit
575 *
576 * Updates the param_proc_limit sysctl variable.
577 * Number of parameters that should be processed to find key parameters:
578 * > 1 (A high value is a DoS risk)
579 */
580int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS)
581{
604 u_int proclimit = *(u_int *)arg1;
605 int error;
582 u_int proclimit = *(u_int *)arg1;
583 int error;
606
584
607 error = sysctl_handle_int(oidp, &proclimit, 0, req);
608 if (error) return (error);
585 error = sysctl_handle_int(oidp, &proclimit, 0, req);
586 if (error) return (error);
609
587
610 sysctl_param_proc_limit =
611 (proclimit < 2) ? 2 : proclimit;
588 sysctl_param_proc_limit =
589 (proclimit < 2) ? 2 : proclimit;
612
590
613 return (0);
591 return (0);
614}
615
616/** @ingroup sysctl
617 * @brief sysctl callback for changing net.inet.ip.alias.sctp.track_global_addresses
618 *
619 *Configures the global address tracking option within the NAT (0 - Global
620 *tracking is disabled, > 0 - enables tracking but limits the number of global
621 *IP addresses to this value)
622 */
623int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS)
624{
592}
593
594/** @ingroup sysctl
595 * @brief sysctl callback for changing net.inet.ip.alias.sctp.track_global_addresses
596 *
597 *Configures the global address tracking option within the NAT (0 - Global
598 *tracking is disabled, > 0 - enables tracking but limits the number of global
599 *IP addresses to this value)
600 */
601int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS)
602{
625 u_int num_to_track = *(u_int *)arg1;
626 int error;
603 u_int num_to_track = *(u_int *)arg1;
604 int error;
627
605
628 error = sysctl_handle_int(oidp, &num_to_track, 0, req);
629 if (error) return (error);
606 error = sysctl_handle_int(oidp, &num_to_track, 0, req);
607 if (error) return (error);
630
608
631 sysctl_track_global_addresses = (num_to_track > SN_MAX_GLOBAL_ADDRESSES) ? SN_MAX_GLOBAL_ADDRESSES : num_to_track;
609 sysctl_track_global_addresses = (num_to_track > SN_MAX_GLOBAL_ADDRESSES) ? SN_MAX_GLOBAL_ADDRESSES : num_to_track;
632
610
633 return (0);
611 return (0);
634}
635
636
637/* ----------------------------------------------------------------------
638 * CODE BEGINS HERE
639 * ----------------------------------------------------------------------
640 */
641/**
642 * @brief Initialises the SCTP NAT Implementation
643 *
644 * Creates the look-up tables and the timer queue and initialises all state
645 * variables
646 *
647 * @param la Pointer to the relevant libalias instance
648 */
649void AliasSctpInit(struct libalias *la)
650{
612}
613
614
615/* ----------------------------------------------------------------------
616 * CODE BEGINS HERE
617 * ----------------------------------------------------------------------
618 */
619/**
620 * @brief Initialises the SCTP NAT Implementation
621 *
622 * Creates the look-up tables and the timer queue and initialises all state
623 * variables
624 *
625 * @param la Pointer to the relevant libalias instance
626 */
627void AliasSctpInit(struct libalias *la)
628{
651 /* Initialise association tables*/
652 int i;
653 la->sctpNatTableSize = sysctl_hashtable_size;
654 SN_LOG(SN_LOG_EVENT,
655 SctpAliasLog("Initialising SCTP NAT Instance (hash_table_size:%d)\n", la->sctpNatTableSize));
656 la->sctpTableLocal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableL));
657 la->sctpTableGlobal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableG));
658 la->sctpNatTimer.TimerQ = sn_calloc(SN_TIMER_QUEUE_SIZE, sizeof(struct sctpTimerQ));
659 /* Initialise hash table */
660 for (i = 0; i < la->sctpNatTableSize; i++) {
661 LIST_INIT(&la->sctpTableLocal[i]);
662 LIST_INIT(&la->sctpTableGlobal[i]);
663 }
629 /* Initialise association tables*/
630 int i;
631 la->sctpNatTableSize = sysctl_hashtable_size;
632 SN_LOG(SN_LOG_EVENT,
633 SctpAliasLog("Initialising SCTP NAT Instance (hash_table_size:%d)\n", la->sctpNatTableSize));
634 la->sctpTableLocal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableL));
635 la->sctpTableGlobal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableG));
636 la->sctpNatTimer.TimerQ = sn_calloc(SN_TIMER_QUEUE_SIZE, sizeof(struct sctpTimerQ));
637 /* Initialise hash table */
638 for (i = 0; i < la->sctpNatTableSize; i++) {
639 LIST_INIT(&la->sctpTableLocal[i]);
640 LIST_INIT(&la->sctpTableGlobal[i]);
641 }
664
642
665 /* Initialise circular timer Q*/
666 for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++)
667 LIST_INIT(&la->sctpNatTimer.TimerQ[i]);
643 /* Initialise circular timer Q*/
644 for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++)
645 LIST_INIT(&la->sctpNatTimer.TimerQ[i]);
668#ifdef _KERNEL
646#ifdef _KERNEL
669 la->sctpNatTimer.loc_time=time_uptime; /* la->timeStamp is not set yet */
647 la->sctpNatTimer.loc_time=time_uptime; /* la->timeStamp is not set yet */
670#else
648#else
671 la->sctpNatTimer.loc_time=la->timeStamp;
649 la->sctpNatTimer.loc_time=la->timeStamp;
672#endif
650#endif
673 la->sctpNatTimer.cur_loc = 0;
674 la->sctpLinkCount = 0;
651 la->sctpNatTimer.cur_loc = 0;
652 la->sctpLinkCount = 0;
675}
676
677/**
678 * @brief Cleans-up the SCTP NAT Implementation prior to unloading
679 *
680 * Removes all entries from the timer queue, freeing associations as it goes.
681 * We then free memory allocated to the look-up tables and the time queue
682 *
683 * NOTE: We do not need to traverse the look-up tables as each association
684 * will always have an entry in the timer queue, freeing this memory
685 * once will free all memory allocated to entries in the look-up tables
686 *
687 * @param la Pointer to the relevant libalias instance
688 */
689void AliasSctpTerm(struct libalias *la)
690{
653}
654
655/**
656 * @brief Cleans-up the SCTP NAT Implementation prior to unloading
657 *
658 * Removes all entries from the timer queue, freeing associations as it goes.
659 * We then free memory allocated to the look-up tables and the time queue
660 *
661 * NOTE: We do not need to traverse the look-up tables as each association
662 * will always have an entry in the timer queue, freeing this memory
663 * once will free all memory allocated to entries in the look-up tables
664 *
665 * @param la Pointer to the relevant libalias instance
666 */
667void AliasSctpTerm(struct libalias *la)
668{
691 struct sctp_nat_assoc *assoc1, *assoc2;
692 int i;
669 struct sctp_nat_assoc *assoc1, *assoc2;
670 int i;
693
671
694 LIBALIAS_LOCK_ASSERT(la);
695 SN_LOG(SN_LOG_EVENT,
696 SctpAliasLog("Removing SCTP NAT Instance\n"));
697 for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++) {
698 assoc1 = LIST_FIRST(&la->sctpNatTimer.TimerQ[i]);
699 while (assoc1 != NULL) {
700 freeGlobalAddressList(assoc1);
701 assoc2 = LIST_NEXT(assoc1, timer_Q);
702 sn_free(assoc1);
703 assoc1 = assoc2;
704 }
705 }
672 LIBALIAS_LOCK_ASSERT(la);
673 SN_LOG(SN_LOG_EVENT,
674 SctpAliasLog("Removing SCTP NAT Instance\n"));
675 for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++) {
676 assoc1 = LIST_FIRST(&la->sctpNatTimer.TimerQ[i]);
677 while (assoc1 != NULL) {
678 freeGlobalAddressList(assoc1);
679 assoc2 = LIST_NEXT(assoc1, timer_Q);
680 sn_free(assoc1);
681 assoc1 = assoc2;
682 }
683 }
706
684
707 sn_free(la->sctpTableLocal);
708 sn_free(la->sctpTableGlobal);
709 sn_free(la->sctpNatTimer.TimerQ);
685 sn_free(la->sctpTableLocal);
686 sn_free(la->sctpTableGlobal);
687 sn_free(la->sctpNatTimer.TimerQ);
710}
711
712/**
713 * @brief Handles SCTP packets passed from libalias
714 *
715 * This function needs to actually NAT/drop packets and possibly create and
716 * send AbortM or ErrorM packets in response. The process involves:
717 * - Validating the direction parameter passed by the caller

--- 12 unchanged lines hidden (view full) ---

730 * @param pip Pointer to IP packet to process
731 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
732 *
733 * @return PKT_ALIAS_OK | PKT_ALIAS_IGNORE | PKT_ALIAS_ERROR
734 */
735int
736SctpAlias(struct libalias *la, struct ip *pip, int direction)
737{
688}
689
690/**
691 * @brief Handles SCTP packets passed from libalias
692 *
693 * This function needs to actually NAT/drop packets and possibly create and
694 * send AbortM or ErrorM packets in response. The process involves:
695 * - Validating the direction parameter passed by the caller

--- 12 unchanged lines hidden (view full) ---

708 * @param pip Pointer to IP packet to process
709 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
710 *
711 * @return PKT_ALIAS_OK | PKT_ALIAS_IGNORE | PKT_ALIAS_ERROR
712 */
713int
714SctpAlias(struct libalias *la, struct ip *pip, int direction)
715{
738 int rtnval;
739 struct sctp_nat_msg msg;
740 struct sctp_nat_assoc *assoc = NULL;
716 int rtnval;
717 struct sctp_nat_msg msg;
718 struct sctp_nat_assoc *assoc = NULL;
741
719
742 if ((direction != SN_TO_LOCAL) && (direction != SN_TO_GLOBAL)) {
743 SctpAliasLog("ERROR: Invalid direction\n");
744 return(PKT_ALIAS_ERROR);
745 }
720 if ((direction != SN_TO_LOCAL) && (direction != SN_TO_GLOBAL)) {
721 SctpAliasLog("ERROR: Invalid direction\n");
722 return(PKT_ALIAS_ERROR);
723 }
746
724
747 sctp_CheckTimers(la); /* Check timers */
725 sctp_CheckTimers(la); /* Check timers */
748
726
749 /* Parse the packet */
750 rtnval = sctp_PktParser(la, direction, pip, &msg, &assoc); //using *char (change to mbuf when get code from paolo)
751 switch (rtnval) {
752 case SN_PARSE_OK:
753 break;
754 case SN_PARSE_ERROR_CHHL:
755 /* Not an error if there is a chunk length parsing error and this is a fragmented packet */
756 if (ntohs(pip->ip_off) & IP_MF) {
757 rtnval = SN_PARSE_OK;
758 break;
759 }
760 SN_LOG(SN_LOG_EVENT,
761 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
762 return(PKT_ALIAS_ERROR);
763 case SN_PARSE_ERROR_PARTIALLOOKUP:
764 if (sysctl_error_on_ootb > SN_LOCALandPARTIAL_ERROR_ON_OOTB) {
765 SN_LOG(SN_LOG_EVENT,
766 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
767 return(PKT_ALIAS_ERROR);
768 }
769 case SN_PARSE_ERROR_LOOKUP:
770 if (sysctl_error_on_ootb == SN_ERROR_ON_OOTB ||
771 (sysctl_error_on_ootb == SN_LOCALandPARTIAL_ERROR_ON_OOTB && direction == SN_TO_LOCAL) ||
772 (sysctl_error_on_ootb == SN_LOCAL_ERROR_ON_OOTB && direction == SN_TO_GLOBAL)) {
773 TxAbortErrorM(la, &msg, assoc, SN_REFLECT_ERROR, direction); /*NB assoc=NULL */
774 return(PKT_ALIAS_RESPOND);
775 }
776 default:
777 SN_LOG(SN_LOG_EVENT,
778 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
779 return(PKT_ALIAS_ERROR);
780 }
727 /* Parse the packet */
728 rtnval = sctp_PktParser(la, direction, pip, &msg, &assoc); //using *char (change to mbuf when get code from paolo)
729 switch (rtnval) {
730 case SN_PARSE_OK:
731 break;
732 case SN_PARSE_ERROR_CHHL:
733 /* Not an error if there is a chunk length parsing error and this is a fragmented packet */
734 if (ntohs(pip->ip_off) & IP_MF) {
735 rtnval = SN_PARSE_OK;
736 break;
737 }
738 SN_LOG(SN_LOG_EVENT,
739 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
740 return(PKT_ALIAS_ERROR);
741 case SN_PARSE_ERROR_PARTIALLOOKUP:
742 if (sysctl_error_on_ootb > SN_LOCALandPARTIAL_ERROR_ON_OOTB) {
743 SN_LOG(SN_LOG_EVENT,
744 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
745 return(PKT_ALIAS_ERROR);
746 }
747 case SN_PARSE_ERROR_LOOKUP:
748 if (sysctl_error_on_ootb == SN_ERROR_ON_OOTB ||
749 (sysctl_error_on_ootb == SN_LOCALandPARTIAL_ERROR_ON_OOTB && direction == SN_TO_LOCAL) ||
750 (sysctl_error_on_ootb == SN_LOCAL_ERROR_ON_OOTB && direction == SN_TO_GLOBAL)) {
751 TxAbortErrorM(la, &msg, assoc, SN_REFLECT_ERROR, direction); /*NB assoc=NULL */
752 return(PKT_ALIAS_RESPOND);
753 }
754 default:
755 SN_LOG(SN_LOG_EVENT,
756 logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
757 return(PKT_ALIAS_ERROR);
758 }
781
759
782 SN_LOG(SN_LOG_DETAIL,
783 logsctpassoc(assoc, "*");
784 logsctpparse(direction, &msg);
785 );
760 SN_LOG(SN_LOG_DETAIL,
761 logsctpassoc(assoc, "*");
762 logsctpparse(direction, &msg);
763 );
786
764
787 /* Process the SCTP message */
788 rtnval = ProcessSctpMsg(la, direction, &msg, assoc);
765 /* Process the SCTP message */
766 rtnval = ProcessSctpMsg(la, direction, &msg, assoc);
789
767
790 SN_LOG(SN_LOG_DEBUG_MAX,
791 logsctpassoc(assoc, "-");
792 logSctpLocal(la);
793 logSctpGlobal(la);
794 );
795 SN_LOG(SN_LOG_DEBUG, logTimerQ(la));
768 SN_LOG(SN_LOG_DEBUG_MAX,
769 logsctpassoc(assoc, "-");
770 logSctpLocal(la);
771 logSctpGlobal(la);
772 );
773 SN_LOG(SN_LOG_DEBUG, logTimerQ(la));
796
774
797 switch(rtnval){
798 case SN_NAT_PKT:
799 switch(direction) {
800 case SN_TO_LOCAL:
801 DifferentialChecksum(&(msg.ip_hdr->ip_sum),
802 &(assoc->l_addr), &(msg.ip_hdr->ip_dst), 2);
803 msg.ip_hdr->ip_dst = assoc->l_addr; /* change dst address to local address*/
804 break;
805 case SN_TO_GLOBAL:
806 DifferentialChecksum(&(msg.ip_hdr->ip_sum),
807 &(assoc->a_addr), &(msg.ip_hdr->ip_src), 2);
808 msg.ip_hdr->ip_src = assoc->a_addr; /* change src to alias addr*/
809 break;
810 default:
811 rtnval = SN_DROP_PKT; /* shouldn't get here, but if it does drop packet */
812 SN_LOG(SN_LOG_LOW, logsctperror("ERROR: Invalid direction", msg.sctp_hdr->v_tag, rtnval, direction));
813 break;
814 }
815 break;
816 case SN_DROP_PKT:
817 SN_LOG(SN_LOG_DETAIL, logsctperror("SN_DROP_PKT", msg.sctp_hdr->v_tag, rtnval, direction));
818 break;
819 case SN_REPLY_ABORT:
820 case SN_REPLY_ERROR:
821 case SN_SEND_ABORT:
822 TxAbortErrorM(la, &msg, assoc, rtnval, direction);
823 break;
824 default:
825 // big error, remove association and go to idle and write log messages
826 SN_LOG(SN_LOG_LOW, logsctperror("SN_PROCESSING_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
827 assoc->state=SN_RM;/* Mark for removal*/
828 break;
829 }
775 switch(rtnval){
776 case SN_NAT_PKT:
777 switch(direction) {
778 case SN_TO_LOCAL:
779 DifferentialChecksum(&(msg.ip_hdr->ip_sum),
780 &(assoc->l_addr), &(msg.ip_hdr->ip_dst), 2);
781 msg.ip_hdr->ip_dst = assoc->l_addr; /* change dst address to local address*/
782 break;
783 case SN_TO_GLOBAL:
784 DifferentialChecksum(&(msg.ip_hdr->ip_sum),
785 &(assoc->a_addr), &(msg.ip_hdr->ip_src), 2);
786 msg.ip_hdr->ip_src = assoc->a_addr; /* change src to alias addr*/
787 break;
788 default:
789 rtnval = SN_DROP_PKT; /* shouldn't get here, but if it does drop packet */
790 SN_LOG(SN_LOG_LOW, logsctperror("ERROR: Invalid direction", msg.sctp_hdr->v_tag, rtnval, direction));
791 break;
792 }
793 break;
794 case SN_DROP_PKT:
795 SN_LOG(SN_LOG_DETAIL, logsctperror("SN_DROP_PKT", msg.sctp_hdr->v_tag, rtnval, direction));
796 break;
797 case SN_REPLY_ABORT:
798 case SN_REPLY_ERROR:
799 case SN_SEND_ABORT:
800 TxAbortErrorM(la, &msg, assoc, rtnval, direction);
801 break;
802 default:
803 // big error, remove association and go to idle and write log messages
804 SN_LOG(SN_LOG_LOW, logsctperror("SN_PROCESSING_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
805 assoc->state=SN_RM;/* Mark for removal*/
806 break;
807 }
830
808
831 /* Remove association if tagged for removal */
832 if (assoc->state == SN_RM) {
833 if (assoc->TableRegister) {
834 sctp_RmTimeOut(la, assoc);
835 RmSctpAssoc(la, assoc);
836 }
837 LIBALIAS_LOCK_ASSERT(la);
838 freeGlobalAddressList(assoc);
839 sn_free(assoc);
840 }
841 switch(rtnval) {
842 case SN_NAT_PKT:
843 return(PKT_ALIAS_OK);
844 case SN_SEND_ABORT:
845 return(PKT_ALIAS_OK);
846 case SN_REPLY_ABORT:
847 case SN_REPLY_ERROR:
848 case SN_REFLECT_ERROR:
849 return(PKT_ALIAS_RESPOND);
850 case SN_DROP_PKT:
851 default:
852 return(PKT_ALIAS_ERROR);
853 }
809 /* Remove association if tagged for removal */
810 if (assoc->state == SN_RM) {
811 if (assoc->TableRegister) {
812 sctp_RmTimeOut(la, assoc);
813 RmSctpAssoc(la, assoc);
814 }
815 LIBALIAS_LOCK_ASSERT(la);
816 freeGlobalAddressList(assoc);
817 sn_free(assoc);
818 }
819 switch(rtnval) {
820 case SN_NAT_PKT:
821 return(PKT_ALIAS_OK);
822 case SN_SEND_ABORT:
823 return(PKT_ALIAS_OK);
824 case SN_REPLY_ABORT:
825 case SN_REPLY_ERROR:
826 case SN_REFLECT_ERROR:
827 return(PKT_ALIAS_RESPOND);
828 case SN_DROP_PKT:
829 default:
830 return(PKT_ALIAS_ERROR);
831 }
854}
855
856/**
857 * @brief Send an AbortM or ErrorM
858 *
859 * We construct the new SCTP packet to send in place of the existing packet we
860 * have been asked to NAT. This function can only be called if the original
861 * packet was successfully parsed as a valid SCTP packet.

--- 22 unchanged lines hidden (view full) ---

884 * @param sm Pointer to sctp message information
885 * @param assoc Pointer to current association details
886 * @param sndrply SN_SEND_ABORT | SN_REPLY_ABORT | SN_REPLY_ERROR
887 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
888 */
889static void
890TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int sndrply, int direction)
891{
832}
833
834/**
835 * @brief Send an AbortM or ErrorM
836 *
837 * We construct the new SCTP packet to send in place of the existing packet we
838 * have been asked to NAT. This function can only be called if the original
839 * packet was successfully parsed as a valid SCTP packet.

--- 22 unchanged lines hidden (view full) ---

862 * @param sm Pointer to sctp message information
863 * @param assoc Pointer to current association details
864 * @param sndrply SN_SEND_ABORT | SN_REPLY_ABORT | SN_REPLY_ERROR
865 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
866 */
867static void
868TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int sndrply, int direction)
869{
892 int sctp_size = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_error_cause);
893 int ip_size = sizeof(struct ip) + sctp_size;
894 int include_error_cause = 1;
895 char tmp_ip[ip_size];
870 int sctp_size = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_error_cause);
871 int ip_size = sizeof(struct ip) + sctp_size;
872 int include_error_cause = 1;
873 char tmp_ip[ip_size];
896
874
897 if (ntohs(sm->ip_hdr->ip_len) < ip_size) { /* short packet, cannot send error cause */
898 include_error_cause = 0;
899 ip_size = ip_size - sizeof(struct sctp_error_cause);
900 sctp_size = sctp_size - sizeof(struct sctp_error_cause);
901 }
902 /* Assign header pointers packet */
903 struct ip* ip = (struct ip *) tmp_ip;
904 struct sctphdr* sctp_hdr = (struct sctphdr *) ((char *) ip + sizeof(*ip));
905 struct sctp_chunkhdr* chunk_hdr = (struct sctp_chunkhdr *) ((char *) sctp_hdr + sizeof(*sctp_hdr));
906 struct sctp_error_cause* error_cause = (struct sctp_error_cause *) ((char *) chunk_hdr + sizeof(*chunk_hdr));
875 if (ntohs(sm->ip_hdr->ip_len) < ip_size) { /* short packet, cannot send error cause */
876 include_error_cause = 0;
877 ip_size = ip_size - sizeof(struct sctp_error_cause);
878 sctp_size = sctp_size - sizeof(struct sctp_error_cause);
879 }
880 /* Assign header pointers packet */
881 struct ip* ip = (struct ip *) tmp_ip;
882 struct sctphdr* sctp_hdr = (struct sctphdr *) ((char *) ip + sizeof(*ip));
883 struct sctp_chunkhdr* chunk_hdr = (struct sctp_chunkhdr *) ((char *) sctp_hdr + sizeof(*sctp_hdr));
884 struct sctp_error_cause* error_cause = (struct sctp_error_cause *) ((char *) chunk_hdr + sizeof(*chunk_hdr));
907
885
908 /* construct ip header */
909 ip->ip_v = sm->ip_hdr->ip_v;
910 ip->ip_hl = 5; /* 5*32 bit words */
911 ip->ip_tos = 0;
912 ip->ip_len = htons(ip_size);
913 ip->ip_id = sm->ip_hdr->ip_id;
914 ip->ip_off = 0;
915 ip->ip_ttl = 255;
916 ip->ip_p = IPPROTO_SCTP;
917 /*
918 The definitions below should be removed when they make it into the SCTP stack
919 */
886 /* construct ip header */
887 ip->ip_v = sm->ip_hdr->ip_v;
888 ip->ip_hl = 5; /* 5*32 bit words */
889 ip->ip_tos = 0;
890 ip->ip_len = htons(ip_size);
891 ip->ip_id = sm->ip_hdr->ip_id;
892 ip->ip_off = 0;
893 ip->ip_ttl = 255;
894 ip->ip_p = IPPROTO_SCTP;
895 /*
896 The definitions below should be removed when they make it into the SCTP stack
897 */
920#define SCTP_MIDDLEBOX_FLAG 0x02
921#define SCTP_NAT_TABLE_COLLISION 0x00b0
922#define SCTP_MISSING_NAT 0x00b1
898#define SCTP_MIDDLEBOX_FLAG 0x02
899#define SCTP_NAT_TABLE_COLLISION 0x00b0
900#define SCTP_MISSING_NAT 0x00b1
923 chunk_hdr->chunk_type = (sndrply & SN_TX_ABORT) ? SCTP_ABORT_ASSOCIATION : SCTP_OPERATION_ERROR;
924 chunk_hdr->chunk_flags = SCTP_MIDDLEBOX_FLAG;
925 if (include_error_cause) {
926 error_cause->code = htons((sndrply & SN_REFLECT_ERROR) ? SCTP_MISSING_NAT : SCTP_NAT_TABLE_COLLISION);
927 error_cause->length = htons(sizeof(struct sctp_error_cause));
928 chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr) + sizeof(struct sctp_error_cause));
929 } else {
930 chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr));
931 }
901 chunk_hdr->chunk_type = (sndrply & SN_TX_ABORT) ? SCTP_ABORT_ASSOCIATION : SCTP_OPERATION_ERROR;
902 chunk_hdr->chunk_flags = SCTP_MIDDLEBOX_FLAG;
903 if (include_error_cause) {
904 error_cause->code = htons((sndrply & SN_REFLECT_ERROR) ? SCTP_MISSING_NAT : SCTP_NAT_TABLE_COLLISION);
905 error_cause->length = htons(sizeof(struct sctp_error_cause));
906 chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr) + sizeof(struct sctp_error_cause));
907 } else {
908 chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr));
909 }
932
910
933 /* set specific values */
934 switch(sndrply) {
935 case SN_REFLECT_ERROR:
936 chunk_hdr->chunk_flags |= SCTP_HAD_NO_TCB; /* set Tbit */
937 sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
938 break;
939 case SN_REPLY_ERROR:
940 sctp_hdr->v_tag = (direction == SN_TO_LOCAL) ? assoc->g_vtag : assoc->l_vtag ;
941 break;
942 case SN_SEND_ABORT:
943 sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
944 break;
945 case SN_REPLY_ABORT:
946 sctp_hdr->v_tag = sm->sctpchnk.Init->initiate_tag;
947 break;
948 }
911 /* set specific values */
912 switch(sndrply) {
913 case SN_REFLECT_ERROR:
914 chunk_hdr->chunk_flags |= SCTP_HAD_NO_TCB; /* set Tbit */
915 sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
916 break;
917 case SN_REPLY_ERROR:
918 sctp_hdr->v_tag = (direction == SN_TO_LOCAL) ? assoc->g_vtag : assoc->l_vtag ;
919 break;
920 case SN_SEND_ABORT:
921 sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
922 break;
923 case SN_REPLY_ABORT:
924 sctp_hdr->v_tag = sm->sctpchnk.Init->initiate_tag;
925 break;
926 }
949
927
950 /* Set send/reply values */
951 if (sndrply == SN_SEND_ABORT) { /*pass through NAT */
952 ip->ip_src = (direction == SN_TO_LOCAL) ? sm->ip_hdr->ip_src : assoc->a_addr;
953 ip->ip_dst = (direction == SN_TO_LOCAL) ? assoc->l_addr : sm->ip_hdr->ip_dst;
954 sctp_hdr->src_port = sm->sctp_hdr->src_port;
955 sctp_hdr->dest_port = sm->sctp_hdr->dest_port;
956 } else { /* reply and reflect */
957 ip->ip_src = sm->ip_hdr->ip_dst;
958 ip->ip_dst = sm->ip_hdr->ip_src;
959 sctp_hdr->src_port = sm->sctp_hdr->dest_port;
960 sctp_hdr->dest_port = sm->sctp_hdr->src_port;
961 }
928 /* Set send/reply values */
929 if (sndrply == SN_SEND_ABORT) { /*pass through NAT */
930 ip->ip_src = (direction == SN_TO_LOCAL) ? sm->ip_hdr->ip_src : assoc->a_addr;
931 ip->ip_dst = (direction == SN_TO_LOCAL) ? assoc->l_addr : sm->ip_hdr->ip_dst;
932 sctp_hdr->src_port = sm->sctp_hdr->src_port;
933 sctp_hdr->dest_port = sm->sctp_hdr->dest_port;
934 } else { /* reply and reflect */
935 ip->ip_src = sm->ip_hdr->ip_dst;
936 ip->ip_dst = sm->ip_hdr->ip_src;
937 sctp_hdr->src_port = sm->sctp_hdr->dest_port;
938 sctp_hdr->dest_port = sm->sctp_hdr->src_port;
939 }
962
940
963 /* Calculate IP header checksum */
964 ip->ip_sum = in_cksum_hdr(ip);
941 /* Calculate IP header checksum */
942 ip->ip_sum = in_cksum_hdr(ip);
965
943
966 /* calculate SCTP header CRC32 */
967 sctp_hdr->checksum = 0;
968 sctp_hdr->checksum = sctp_csum_finalize(update_crc32(0xffffffff, (unsigned char *) sctp_hdr, sctp_size));
944 /* calculate SCTP header CRC32 */
945 sctp_hdr->checksum = 0;
946 sctp_hdr->checksum = sctp_finalize_crc32(update_crc32(0xffffffff, (unsigned char *) sctp_hdr, sctp_size));
969
947
970 memcpy(sm->ip_hdr, ip, ip_size);
948 memcpy(sm->ip_hdr, ip, ip_size);
971
949
972 SN_LOG(SN_LOG_EVENT,SctpAliasLog("%s %s 0x%x (->%s:%u vtag=0x%x crc=0x%x)\n",
973 ((sndrply == SN_SEND_ABORT) ? "Sending" : "Replying"),
974 ((sndrply & SN_TX_ERROR) ? "ErrorM" : "AbortM"),
975 (include_error_cause ? ntohs(error_cause->code) : 0),
976 inet_ntoa(ip->ip_dst),ntohs(sctp_hdr->dest_port),
977 ntohl(sctp_hdr->v_tag), ntohl(sctp_hdr->checksum)));
950 SN_LOG(SN_LOG_EVENT,SctpAliasLog("%s %s 0x%x (->%s:%u vtag=0x%x crc=0x%x)\n",
951 ((sndrply == SN_SEND_ABORT) ? "Sending" : "Replying"),
952 ((sndrply & SN_TX_ERROR) ? "ErrorM" : "AbortM"),
953 (include_error_cause ? ntohs(error_cause->code) : 0),
954 inet_ntoa(ip->ip_dst),ntohs(sctp_hdr->dest_port),
955 ntohl(sctp_hdr->v_tag), ntohl(sctp_hdr->checksum)));
978}
979
980/* ----------------------------------------------------------------------
981 * PACKET PARSER CODE
982 * ----------------------------------------------------------------------
983 */
984/** @addtogroup packet_parser
985 *

--- 13 unchanged lines hidden (view full) ---

999 * @param pip
1000 * @param sm Pointer to sctp message information
1001 * @param passoc Pointer to the association this SCTP Message belongs to
1002 *
1003 * @return SN_PARSE_OK | SN_PARSE_ERROR_*
1004 */
1005static int
1006sctp_PktParser(struct libalias *la, int direction, struct ip *pip,
956}
957
958/* ----------------------------------------------------------------------
959 * PACKET PARSER CODE
960 * ----------------------------------------------------------------------
961 */
962/** @addtogroup packet_parser
963 *

--- 13 unchanged lines hidden (view full) ---

977 * @param pip
978 * @param sm Pointer to sctp message information
979 * @param passoc Pointer to the association this SCTP Message belongs to
980 *
981 * @return SN_PARSE_OK | SN_PARSE_ERROR_*
982 */
983static int
984sctp_PktParser(struct libalias *la, int direction, struct ip *pip,
1007 struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc)
985 struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc)
1008//sctp_PktParser(int direction, struct mbuf *ipak, int ip_hdr_len,struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
1009{
986//sctp_PktParser(int direction, struct mbuf *ipak, int ip_hdr_len,struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
987{
1010 struct sctphdr *sctp_hdr;
1011 struct sctp_chunkhdr *chunk_hdr;
1012 struct sctp_paramhdr *param_hdr;
1013 struct in_addr ipv4addr;
1014 int bytes_left; /* bytes left in ip packet */
1015 int chunk_length;
1016 int chunk_count;
1017 int partial_match = 0;
1018 // mbuf *mp;
1019 // int mlen;
988 struct sctphdr *sctp_hdr;
989 struct sctp_chunkhdr *chunk_hdr;
990 struct sctp_paramhdr *param_hdr;
991 struct in_addr ipv4addr;
992 int bytes_left; /* bytes left in ip packet */
993 int chunk_length;
994 int chunk_count;
995 int partial_match = 0;
996 // mbuf *mp;
997 // int mlen;
1020
998
1021 // mlen = SCTP_HEADER_LEN(i_pak);
1022 // mp = SCTP_HEADER_TO_CHAIN(i_pak); /* does nothing in bsd since header and chain not separate */
999 // mlen = SCTP_HEADER_LEN(i_pak);
1000 // mp = SCTP_HEADER_TO_CHAIN(i_pak); /* does nothing in bsd since header and chain not separate */
1023
1001
1024 /*
1025 * Note, that if the VTag is zero, it must be an INIT
1026 * Also, I am only interested in the content of INIT and ADDIP chunks
1027 */
1002 /*
1003 * Note, that if the VTag is zero, it must be an INIT
1004 * Also, I am only interested in the content of INIT and ADDIP chunks
1005 */
1028
1006
1029 // no mbuf stuff from Paolo yet so ...
1030 sm->ip_hdr = pip;
1031 /* remove ip header length from the bytes_left */
1032 bytes_left = ntohs(pip->ip_len) - (pip->ip_hl << 2);
1007 // no mbuf stuff from Paolo yet so ...
1008 sm->ip_hdr = pip;
1009 /* remove ip header length from the bytes_left */
1010 bytes_left = ntohs(pip->ip_len) - (pip->ip_hl << 2);
1033
1011
1034 /* Check SCTP header length and move to first chunk */
1035 if (bytes_left < sizeof(struct sctphdr)) {
1036 sm->sctp_hdr = NULL;
1037 return(SN_PARSE_ERROR_IPSHL); /* packet not long enough*/
1038 }
1012 /* Check SCTP header length and move to first chunk */
1013 if (bytes_left < sizeof(struct sctphdr)) {
1014 sm->sctp_hdr = NULL;
1015 return(SN_PARSE_ERROR_IPSHL); /* packet not long enough*/
1016 }
1039
1017
1040 sm->sctp_hdr = sctp_hdr = (struct sctphdr *) ip_next(pip);
1041 bytes_left -= sizeof(struct sctphdr);
1018 sm->sctp_hdr = sctp_hdr = (struct sctphdr *) ip_next(pip);
1019 bytes_left -= sizeof(struct sctphdr);
1042
1020
1043 /* Check for valid ports (zero valued ports would find partially initialised associations */
1044 if (sctp_hdr->src_port == 0 || sctp_hdr->dest_port == 0)
1045 return(SN_PARSE_ERROR_PORT);
1021 /* Check for valid ports (zero valued ports would find partially initialised associations */
1022 if (sctp_hdr->src_port == 0 || sctp_hdr->dest_port == 0)
1023 return(SN_PARSE_ERROR_PORT);
1046
1024
1047 /* Check length of first chunk */
1048 if (bytes_left < SN_MIN_CHUNK_SIZE) /* malformed chunk - could cause endless loop*/
1049 return(SN_PARSE_ERROR_CHHL); /* packet not long enough for this chunk */
1025 /* Check length of first chunk */
1026 if (bytes_left < SN_MIN_CHUNK_SIZE) /* malformed chunk - could cause endless loop*/
1027 return(SN_PARSE_ERROR_CHHL); /* packet not long enough for this chunk */
1050
1028
1051 /* First chunk */
1052 chunk_hdr = SN_SCTP_FIRSTCHUNK(sctp_hdr);
1029 /* First chunk */
1030 chunk_hdr = SN_SCTP_FIRSTCHUNK(sctp_hdr);
1053
1031
1054 chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
1055 if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left)) /* malformed chunk - could cause endless loop*/
1056 return(SN_PARSE_ERROR_CHHL);
1032 chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
1033 if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left)) /* malformed chunk - could cause endless loop*/
1034 return(SN_PARSE_ERROR_CHHL);
1057
1035
1058 if ((chunk_hdr->chunk_flags & SCTP_HAD_NO_TCB) &&
1059 ((chunk_hdr->chunk_type == SCTP_ABORT_ASSOCIATION) ||
1060 (chunk_hdr->chunk_type == SCTP_SHUTDOWN_COMPLETE))) {
1061 /* T-Bit set */
1062 if (direction == SN_TO_LOCAL)
1063 *passoc = FindSctpGlobalT(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
1064 else
1065 *passoc = FindSctpLocalT(la, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
1066 } else {
1067 /* Proper v_tag settings */
1068 if (direction == SN_TO_LOCAL)
1069 *passoc = FindSctpGlobal(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
1070 else
1071 *passoc = FindSctpLocal(la, pip->ip_src, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port);
1072 }
1073
1074 chunk_count = 1;
1075 /* Real packet parsing occurs below */
1076 sm->msg = SN_SCTP_OTHER;/* Initialise to largest value*/
1077 sm->chunk_length = 0; /* only care about length for key chunks */
1078 while (IS_SCTP_CONTROL(chunk_hdr)) {
1079 switch(chunk_hdr->chunk_type) {
1080 case SCTP_INITIATION:
1081 if (chunk_length < sizeof(struct sctp_init_chunk)) /* malformed chunk*/
1082 return(SN_PARSE_ERROR_CHHL);
1083 sm->msg = SN_SCTP_INIT;
1084 sm->sctpchnk.Init = (struct sctp_init *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
1085 sm->chunk_length = chunk_length;
1086 /* if no existing association, create a new one */
1087 if (*passoc == NULL) {
1088 if (sctp_hdr->v_tag == 0){ //Init requires vtag=0
1089 *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
1090 if (*passoc == NULL) {/* out of resources */
1091 return(SN_PARSE_ERROR_AS_MALLOC);
1092 }
1093 /* Initialise association - malloc initialises memory to zeros */
1094 (*passoc)->state = SN_ID;
1095 LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
1096 (*passoc)->TableRegister = SN_NULL_TBL;
1097 return(SN_PARSE_OK);
1098 }
1099 return(SN_PARSE_ERROR_VTAG);
1100 }
1101 return(SN_PARSE_ERROR_LOOKUP);
1102 case SCTP_INITIATION_ACK:
1103 if (chunk_length < sizeof(struct sctp_init_ack_chunk)) /* malformed chunk*/
1104 return(SN_PARSE_ERROR_CHHL);
1105 sm->msg = SN_SCTP_INITACK;
1106 sm->sctpchnk.InitAck = (struct sctp_init_ack *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
1107 sm->chunk_length = chunk_length;
1108 return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
1109 case SCTP_ABORT_ASSOCIATION: /* access only minimum sized chunk */
1110 sm->msg = SN_SCTP_ABORT;
1111 sm->chunk_length = chunk_length;
1112 return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP_ABORT):(SN_PARSE_OK));
1113 case SCTP_SHUTDOWN_ACK:
1114 if (chunk_length < sizeof(struct sctp_shutdown_ack_chunk)) /* malformed chunk*/
1115 return(SN_PARSE_ERROR_CHHL);
1116 if (sm->msg > SN_SCTP_SHUTACK) {
1117 sm->msg = SN_SCTP_SHUTACK;
1118 sm->chunk_length = chunk_length;
1119 }
1120 break;
1121 case SCTP_SHUTDOWN_COMPLETE: /* minimum sized chunk */
1122 if (sm->msg > SN_SCTP_SHUTCOMP) {
1123 sm->msg = SN_SCTP_SHUTCOMP;
1124 sm->chunk_length = chunk_length;
1125 }
1126 return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
1127 case SCTP_ASCONF:
1128 if (sm->msg > SN_SCTP_ASCONF) {
1129 if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param))) /* malformed chunk*/
1130 return(SN_PARSE_ERROR_CHHL);
1131 //leave parameter searching to later, if required
1132 param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + sizeof(struct sctp_asconf_chunk)); /*compulsory IP parameter*/
1133 if (ntohs(param_hdr->param_type) == SCTP_IPV4_ADDRESS) {
1134 if ((*passoc == NULL) && (direction == SN_TO_LOCAL)) { /* AddIP with no association */
1135 /* try look up with the ASCONF packet's alternative address */
1136 ipv4addr.s_addr = ((struct sctp_ipv4addr_param *) param_hdr)->addr;
1137 *passoc = FindSctpGlobal(la, ipv4addr, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
1138 }
1139 param_hdr = (struct sctp_paramhdr *)
1140 ((char *) param_hdr + sizeof(struct sctp_ipv4addr_param)); /*asconf's compulsory address parameter */
1141 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv4addr_param); /* rest of chunk */
1036 if ((chunk_hdr->chunk_flags & SCTP_HAD_NO_TCB) &&
1037 ((chunk_hdr->chunk_type == SCTP_ABORT_ASSOCIATION) ||
1038 (chunk_hdr->chunk_type == SCTP_SHUTDOWN_COMPLETE))) {
1039 /* T-Bit set */
1040 if (direction == SN_TO_LOCAL)
1041 *passoc = FindSctpGlobalT(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
1042 else
1043 *passoc = FindSctpLocalT(la, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
1142 } else {
1044 } else {
1143 if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv6addr_param))) /* malformed chunk*/
1144 return(SN_PARSE_ERROR_CHHL);
1145 param_hdr = (struct sctp_paramhdr *)
1146 ((char *) param_hdr + sizeof(struct sctp_ipv6addr_param)); /*asconf's compulsory address parameter */
1147 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv6addr_param); /* rest of chunk */
1045 /* Proper v_tag settings */
1046 if (direction == SN_TO_LOCAL)
1047 *passoc = FindSctpGlobal(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
1048 else
1049 *passoc = FindSctpLocal(la, pip->ip_src, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port);
1148 }
1050 }
1149 sm->msg = SN_SCTP_ASCONF;
1150 sm->sctpchnk.Asconf = param_hdr;
1051
1052 chunk_count = 1;
1053 /* Real packet parsing occurs below */
1054 sm->msg = SN_SCTP_OTHER;/* Initialise to largest value*/
1055 sm->chunk_length = 0; /* only care about length for key chunks */
1056 while (IS_SCTP_CONTROL(chunk_hdr)) {
1057 switch(chunk_hdr->chunk_type) {
1058 case SCTP_INITIATION:
1059 if (chunk_length < sizeof(struct sctp_init_chunk)) /* malformed chunk*/
1060 return(SN_PARSE_ERROR_CHHL);
1061 sm->msg = SN_SCTP_INIT;
1062 sm->sctpchnk.Init = (struct sctp_init *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
1063 sm->chunk_length = chunk_length;
1064 /* if no existing association, create a new one */
1065 if (*passoc == NULL) {
1066 if (sctp_hdr->v_tag == 0){ //Init requires vtag=0
1067 *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
1068 if (*passoc == NULL) {/* out of resources */
1069 return(SN_PARSE_ERROR_AS_MALLOC);
1070 }
1071 /* Initialise association - malloc initialises memory to zeros */
1072 (*passoc)->state = SN_ID;
1073 LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
1074 (*passoc)->TableRegister = SN_NULL_TBL;
1075 return(SN_PARSE_OK);
1076 }
1077 return(SN_PARSE_ERROR_VTAG);
1078 }
1079 return(SN_PARSE_ERROR_LOOKUP);
1080 case SCTP_INITIATION_ACK:
1081 if (chunk_length < sizeof(struct sctp_init_ack_chunk)) /* malformed chunk*/
1082 return(SN_PARSE_ERROR_CHHL);
1083 sm->msg = SN_SCTP_INITACK;
1084 sm->sctpchnk.InitAck = (struct sctp_init_ack *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
1085 sm->chunk_length = chunk_length;
1086 return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
1087 case SCTP_ABORT_ASSOCIATION: /* access only minimum sized chunk */
1088 sm->msg = SN_SCTP_ABORT;
1089 sm->chunk_length = chunk_length;
1090 return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP_ABORT):(SN_PARSE_OK));
1091 case SCTP_SHUTDOWN_ACK:
1092 if (chunk_length < sizeof(struct sctp_shutdown_ack_chunk)) /* malformed chunk*/
1093 return(SN_PARSE_ERROR_CHHL);
1094 if (sm->msg > SN_SCTP_SHUTACK) {
1095 sm->msg = SN_SCTP_SHUTACK;
1096 sm->chunk_length = chunk_length;
1097 }
1098 break;
1099 case SCTP_SHUTDOWN_COMPLETE: /* minimum sized chunk */
1100 if (sm->msg > SN_SCTP_SHUTCOMP) {
1101 sm->msg = SN_SCTP_SHUTCOMP;
1102 sm->chunk_length = chunk_length;
1103 }
1104 return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
1105 case SCTP_ASCONF:
1106 if (sm->msg > SN_SCTP_ASCONF) {
1107 if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param))) /* malformed chunk*/
1108 return(SN_PARSE_ERROR_CHHL);
1109 //leave parameter searching to later, if required
1110 param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + sizeof(struct sctp_asconf_chunk)); /*compulsory IP parameter*/
1111 if (ntohs(param_hdr->param_type) == SCTP_IPV4_ADDRESS) {
1112 if ((*passoc == NULL) && (direction == SN_TO_LOCAL)) { /* AddIP with no association */
1113 /* try look up with the ASCONF packet's alternative address */
1114 ipv4addr.s_addr = ((struct sctp_ipv4addr_param *) param_hdr)->addr;
1115 *passoc = FindSctpGlobal(la, ipv4addr, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
1116 }
1117 param_hdr = (struct sctp_paramhdr *)
1118 ((char *) param_hdr + sizeof(struct sctp_ipv4addr_param)); /*asconf's compulsory address parameter */
1119 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv4addr_param); /* rest of chunk */
1120 } else {
1121 if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv6addr_param))) /* malformed chunk*/
1122 return(SN_PARSE_ERROR_CHHL);
1123 param_hdr = (struct sctp_paramhdr *)
1124 ((char *) param_hdr + sizeof(struct sctp_ipv6addr_param)); /*asconf's compulsory address parameter */
1125 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv6addr_param); /* rest of chunk */
1126 }
1127 sm->msg = SN_SCTP_ASCONF;
1128 sm->sctpchnk.Asconf = param_hdr;
1151
1129
1152 if (*passoc == NULL) { /* AddIP with no association */
1153 *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
1154 if (*passoc == NULL) {/* out of resources */
1155 return(SN_PARSE_ERROR_AS_MALLOC);
1156 }
1157 /* Initialise association - malloc initialises memory to zeros */
1158 (*passoc)->state = SN_ID;
1159 LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
1160 (*passoc)->TableRegister = SN_NULL_TBL;
1161 return(SN_PARSE_OK);
1162 }
1163 }
1164 break;
1165 case SCTP_ASCONF_ACK:
1166 if (sm->msg > SN_SCTP_ASCONFACK) {
1167 if (chunk_length < sizeof(struct sctp_asconf_ack_chunk)) /* malformed chunk*/
1168 return(SN_PARSE_ERROR_CHHL);
1169 //leave parameter searching to later, if required
1170 param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr
1171 + sizeof(struct sctp_asconf_ack_chunk));
1172 sm->msg = SN_SCTP_ASCONFACK;
1173 sm->sctpchnk.Asconf = param_hdr;
1174 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_ack_chunk);
1175 }
1176 break;
1177 default:
1178 break; /* do nothing*/
1179 }
1130 if (*passoc == NULL) { /* AddIP with no association */
1131 *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
1132 if (*passoc == NULL) {/* out of resources */
1133 return(SN_PARSE_ERROR_AS_MALLOC);
1134 }
1135 /* Initialise association - malloc initialises memory to zeros */
1136 (*passoc)->state = SN_ID;
1137 LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
1138 (*passoc)->TableRegister = SN_NULL_TBL;
1139 return(SN_PARSE_OK);
1140 }
1141 }
1142 break;
1143 case SCTP_ASCONF_ACK:
1144 if (sm->msg > SN_SCTP_ASCONFACK) {
1145 if (chunk_length < sizeof(struct sctp_asconf_ack_chunk)) /* malformed chunk*/
1146 return(SN_PARSE_ERROR_CHHL);
1147 //leave parameter searching to later, if required
1148 param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr
1149 + sizeof(struct sctp_asconf_ack_chunk));
1150 sm->msg = SN_SCTP_ASCONFACK;
1151 sm->sctpchnk.Asconf = param_hdr;
1152 sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_ack_chunk);
1153 }
1154 break;
1155 default:
1156 break; /* do nothing*/
1157 }
1180
1158
1181 /* if no association is found exit - we need to find an Init or AddIP within sysctl_initialising_chunk_proc_limit */
1182 if ((*passoc == NULL) && (chunk_count >= sysctl_initialising_chunk_proc_limit))
1183 return(SN_PARSE_ERROR_LOOKUP);
1159 /* if no association is found exit - we need to find an Init or AddIP within sysctl_initialising_chunk_proc_limit */
1160 if ((*passoc == NULL) && (chunk_count >= sysctl_initialising_chunk_proc_limit))
1161 return(SN_PARSE_ERROR_LOOKUP);
1184
1162
1185 /* finished with this chunk, on to the next chunk*/
1186 bytes_left-= chunk_length;
1163 /* finished with this chunk, on to the next chunk*/
1164 bytes_left-= chunk_length;
1187
1165
1188 /* Is this the end of the packet ? */
1189 if (bytes_left == 0)
1190 return(SN_PARSE_OK);
1166 /* Is this the end of the packet ? */
1167 if (bytes_left == 0)
1168 return (*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK);
1191
1169
1192 /* Are there enough bytes in packet to at least retrieve length of next chunk ? */
1193 if (bytes_left < SN_MIN_CHUNK_SIZE)
1194 return(SN_PARSE_ERROR_CHHL);
1170 /* Are there enough bytes in packet to at least retrieve length of next chunk ? */
1171 if (bytes_left < SN_MIN_CHUNK_SIZE)
1172 return(SN_PARSE_ERROR_CHHL);
1195
1173
1196 chunk_hdr = SN_SCTP_NEXTCHUNK(chunk_hdr);
1174 chunk_hdr = SN_SCTP_NEXTCHUNK(chunk_hdr);
1197
1175
1198 /* Is the chunk long enough to not cause endless look and are there enough bytes in packet to read the chunk ? */
1199 chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
1200 if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left))
1201 return(SN_PARSE_ERROR_CHHL);
1202 if(++chunk_count > sysctl_chunk_proc_limit)
1203 return(SN_PARSE_OK); /* limit for processing chunks, take what we get */
1204 }
1176 /* Is the chunk long enough to not cause endless look and are there enough bytes in packet to read the chunk ? */
1177 chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
1178 if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left))
1179 return(SN_PARSE_ERROR_CHHL);
1180 if(++chunk_count > sysctl_chunk_proc_limit)
1181 return(SN_PARSE_OK); /* limit for processing chunks, take what we get */
1182 }
1205
1183
1206 if (*passoc == NULL)
1207 return (partial_match)?(SN_PARSE_ERROR_PARTIALLOOKUP):(SN_PARSE_ERROR_LOOKUP);
1208 else
1209 return(SN_PARSE_OK);
1184 if (*passoc == NULL)
1185 return (partial_match)?(SN_PARSE_ERROR_PARTIALLOOKUP):(SN_PARSE_ERROR_LOOKUP);
1186 else
1187 return(SN_PARSE_OK);
1210}
1211
1212/** @ingroup packet_parser
1213 * @brief Extract Vtags from Asconf Chunk
1214 *
1215 * GetAsconfVtags scans an Asconf Chunk for the vtags parameter, and then
1216 * extracts the vtags.
1217 *

--- 6 unchanged lines hidden (view full) ---

1224 * @param g_vtag Pointer to the local vtag in the association this SCTP Message belongs to
1225 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1226 *
1227 * @return 1 - success | 0 - fail
1228 */
1229static int
1230GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, uint32_t *g_vtag, int direction)
1231{
1188}
1189
1190/** @ingroup packet_parser
1191 * @brief Extract Vtags from Asconf Chunk
1192 *
1193 * GetAsconfVtags scans an Asconf Chunk for the vtags parameter, and then
1194 * extracts the vtags.
1195 *

--- 6 unchanged lines hidden (view full) ---

1202 * @param g_vtag Pointer to the local vtag in the association this SCTP Message belongs to
1203 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1204 *
1205 * @return 1 - success | 0 - fail
1206 */
1207static int
1208GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, uint32_t *g_vtag, int direction)
1209{
1232 /* To be removed when information is in the sctp headers */
1210 /* To be removed when information is in the sctp headers */
1233#define SCTP_VTAG_PARAM 0xC007
1211#define SCTP_VTAG_PARAM 0xC007
1234 struct sctp_vtag_param {
1235 struct sctp_paramhdr ph;/* type=SCTP_VTAG_PARAM */
1236 uint32_t local_vtag;
1237 uint32_t remote_vtag;
1238 } __attribute__((packed));
1212 struct sctp_vtag_param {
1213 struct sctp_paramhdr ph;/* type=SCTP_VTAG_PARAM */
1214 uint32_t local_vtag;
1215 uint32_t remote_vtag;
1216 } __attribute__((packed));
1239
1217
1240 struct sctp_vtag_param *vtag_param;
1241 struct sctp_paramhdr *param;
1242 int bytes_left;
1243 int param_size;
1244 int param_count;
1218 struct sctp_vtag_param *vtag_param;
1219 struct sctp_paramhdr *param;
1220 int bytes_left;
1221 int param_size;
1222 int param_count;
1245
1223
1246 param_count = 1;
1247 param = sm->sctpchnk.Asconf;
1248 param_size = SCTP_SIZE32(ntohs(param->param_length));
1249 bytes_left = sm->chunk_length;
1250 /* step through Asconf parameters */
1251 while((bytes_left >= param_size) && (bytes_left >= SN_VTAG_PARAM_SIZE)) {
1252 if (ntohs(param->param_type) == SCTP_VTAG_PARAM) {
1253 vtag_param = (struct sctp_vtag_param *) param;
1254 switch(direction) {
1255 /* The Internet draft is a little ambigious as to order of these vtags.
1256 We think it is this way around. If we are wrong, the order will need
1257 to be changed. */
1258 case SN_TO_GLOBAL:
1259 *g_vtag = vtag_param->local_vtag;
1260 *l_vtag = vtag_param->remote_vtag;
1261 break;
1262 case SN_TO_LOCAL:
1263 *g_vtag = vtag_param->remote_vtag;
1264 *l_vtag = vtag_param->local_vtag;
1265 break;
1266 }
1267 return(1); /* found */
1268 }
1224 param_count = 1;
1225 param = sm->sctpchnk.Asconf;
1226 param_size = SCTP_SIZE32(ntohs(param->param_length));
1227 bytes_left = sm->chunk_length;
1228 /* step through Asconf parameters */
1229 while((bytes_left >= param_size) && (bytes_left >= SN_VTAG_PARAM_SIZE)) {
1230 if (ntohs(param->param_type) == SCTP_VTAG_PARAM) {
1231 vtag_param = (struct sctp_vtag_param *) param;
1232 switch(direction) {
1233 /* The Internet draft is a little ambigious as to order of these vtags.
1234 We think it is this way around. If we are wrong, the order will need
1235 to be changed. */
1236 case SN_TO_GLOBAL:
1237 *g_vtag = vtag_param->local_vtag;
1238 *l_vtag = vtag_param->remote_vtag;
1239 break;
1240 case SN_TO_LOCAL:
1241 *g_vtag = vtag_param->remote_vtag;
1242 *l_vtag = vtag_param->local_vtag;
1243 break;
1244 }
1245 return(1); /* found */
1246 }
1269
1247
1270 bytes_left -= param_size;
1271 if (bytes_left < SN_MIN_PARAM_SIZE) return(0);
1248 bytes_left -= param_size;
1249 if (bytes_left < SN_MIN_PARAM_SIZE) return(0);
1272
1250
1273 param = SN_SCTP_NEXTPARAM(param);
1274 param_size = SCTP_SIZE32(ntohs(param->param_length));
1275 if (++param_count > sysctl_param_proc_limit) {
1276 SN_LOG(SN_LOG_EVENT,
1277 logsctperror("Parameter parse limit exceeded (GetAsconfVtags)",
1278 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1279 return(0); /* not found limit exceeded*/
1280 }
1281 }
1282 return(0); /* not found */
1251 param = SN_SCTP_NEXTPARAM(param);
1252 param_size = SCTP_SIZE32(ntohs(param->param_length));
1253 if (++param_count > sysctl_param_proc_limit) {
1254 SN_LOG(SN_LOG_EVENT,
1255 logsctperror("Parameter parse limit exceeded (GetAsconfVtags)",
1256 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1257 return(0); /* not found limit exceeded*/
1258 }
1259 }
1260 return(0); /* not found */
1283}
1284
1285/** @ingroup packet_parser
1286 * @brief AddGlobalIPAddresses from Init,InitAck,or AddIP packets
1287 *
1288 * AddGlobalIPAddresses scans an SCTP chunk (in sm) for Global IP addresses, and
1289 * adds them.
1290 *
1291 * @param sm Pointer to sctp message information
1292 * @param assoc Pointer to the association this SCTP Message belongs to
1293 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1294 *
1295 */
1296static void
1297AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
1298{
1261}
1262
1263/** @ingroup packet_parser
1264 * @brief AddGlobalIPAddresses from Init,InitAck,or AddIP packets
1265 *
1266 * AddGlobalIPAddresses scans an SCTP chunk (in sm) for Global IP addresses, and
1267 * adds them.
1268 *
1269 * @param sm Pointer to sctp message information
1270 * @param assoc Pointer to the association this SCTP Message belongs to
1271 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1272 *
1273 */
1274static void
1275AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
1276{
1299 struct sctp_ipv4addr_param *ipv4_param;
1300 struct sctp_paramhdr *param = NULL;
1301 struct sctp_GlobalAddress *G_Addr;
1302 struct in_addr g_addr = {0};
1303 int bytes_left = 0;
1304 int param_size;
1305 int param_count, addr_param_count = 0;
1277 struct sctp_ipv4addr_param *ipv4_param;
1278 struct sctp_paramhdr *param = NULL;
1279 struct sctp_GlobalAddress *G_Addr;
1280 struct in_addr g_addr = {0};
1281 int bytes_left = 0;
1282 int param_size;
1283 int param_count, addr_param_count = 0;
1306
1284
1307 switch(direction) {
1308 case SN_TO_GLOBAL: /* does not contain global addresses */
1309 g_addr = sm->ip_hdr->ip_dst;
1310 bytes_left = 0; /* force exit */
1311 break;
1312 case SN_TO_LOCAL:
1313 g_addr = sm->ip_hdr->ip_src;
1314 param_count = 1;
1315 switch(sm->msg) {
1316 case SN_SCTP_INIT:
1317 bytes_left = sm->chunk_length - sizeof(struct sctp_init_chunk);
1318 param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.Init + sizeof(struct sctp_init));
1319 break;
1320 case SN_SCTP_INITACK:
1321 bytes_left = sm->chunk_length - sizeof(struct sctp_init_ack_chunk);
1322 param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.InitAck + sizeof(struct sctp_init_ack));
1323 break;
1324 case SN_SCTP_ASCONF:
1325 bytes_left = sm->chunk_length;
1326 param = sm->sctpchnk.Asconf;
1327 break;
1328 }
1329 }
1330 if (bytes_left >= SN_MIN_PARAM_SIZE)
1331 param_size = SCTP_SIZE32(ntohs(param->param_length));
1332 else
1333 param_size = bytes_left+1; /* force skip loop */
1285 switch(direction) {
1286 case SN_TO_GLOBAL: /* does not contain global addresses */
1287 g_addr = sm->ip_hdr->ip_dst;
1288 bytes_left = 0; /* force exit */
1289 break;
1290 case SN_TO_LOCAL:
1291 g_addr = sm->ip_hdr->ip_src;
1292 param_count = 1;
1293 switch(sm->msg) {
1294 case SN_SCTP_INIT:
1295 bytes_left = sm->chunk_length - sizeof(struct sctp_init_chunk);
1296 param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.Init + sizeof(struct sctp_init));
1297 break;
1298 case SN_SCTP_INITACK:
1299 bytes_left = sm->chunk_length - sizeof(struct sctp_init_ack_chunk);
1300 param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.InitAck + sizeof(struct sctp_init_ack));
1301 break;
1302 case SN_SCTP_ASCONF:
1303 bytes_left = sm->chunk_length;
1304 param = sm->sctpchnk.Asconf;
1305 break;
1306 }
1307 }
1308 if (bytes_left >= SN_MIN_PARAM_SIZE)
1309 param_size = SCTP_SIZE32(ntohs(param->param_length));
1310 else
1311 param_size = bytes_left+1; /* force skip loop */
1334
1312
1335 if ((assoc->state == SN_ID) && ((sm->msg == SN_SCTP_INIT) || (bytes_left < SN_MIN_PARAM_SIZE))) {/* add pkt address */
1336 G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
1337 if (G_Addr == NULL) {/* out of resources */
1338 SN_LOG(SN_LOG_EVENT,
1339 logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
1340 sm->sctp_hdr->v_tag, 0, direction));
1341 assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
1342 sysctl_track_global_addresses=0;
1343 return;
1344 }
1345 G_Addr->g_addr = g_addr;
1346 if (!Add_Global_Address_to_List(assoc, G_Addr))
1347 SN_LOG(SN_LOG_EVENT,
1348 logsctperror("AddGlobalIPAddress: Address already in list",
1349 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1350 }
1313 if ((assoc->state == SN_ID) && ((sm->msg == SN_SCTP_INIT) || (bytes_left < SN_MIN_PARAM_SIZE))) {/* add pkt address */
1314 G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
1315 if (G_Addr == NULL) {/* out of resources */
1316 SN_LOG(SN_LOG_EVENT,
1317 logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
1318 sm->sctp_hdr->v_tag, 0, direction));
1319 assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
1320 sysctl_track_global_addresses=0;
1321 return;
1322 }
1323 G_Addr->g_addr = g_addr;
1324 if (!Add_Global_Address_to_List(assoc, G_Addr))
1325 SN_LOG(SN_LOG_EVENT,
1326 logsctperror("AddGlobalIPAddress: Address already in list",
1327 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1328 }
1351
1329
1352 /* step through parameters */
1353 while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
1354 if (assoc->num_Gaddr >= sysctl_track_global_addresses) {
1355 SN_LOG(SN_LOG_EVENT,
1356 logsctperror("AddGlobalIPAddress: Maximum Number of addresses reached",
1357 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1358 return;
1359 }
1360 switch(ntohs(param->param_type)) {
1361 case SCTP_ADD_IP_ADDRESS:
1362 /* skip to address parameter - leave param_size so bytes left will be calculated properly*/
1363 param = (struct sctp_paramhdr *) &((struct sctp_asconf_addrv4_param *) param)->addrp;
1364 case SCTP_IPV4_ADDRESS:
1365 ipv4_param = (struct sctp_ipv4addr_param *) param;
1366 /* add addresses to association */
1367 G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
1368 if (G_Addr == NULL) {/* out of resources */
1369 SN_LOG(SN_LOG_EVENT,
1370 logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
1371 sm->sctp_hdr->v_tag, 0, direction));
1372 assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
1373 sysctl_track_global_addresses=0;
1374 return;
1375 }
1376 /* add address */
1377 addr_param_count++;
1378 if ((sm->msg == SN_SCTP_ASCONF) && (ipv4_param->addr == INADDR_ANY)) { /* use packet address */
1379 G_Addr->g_addr = g_addr;
1380 if (!Add_Global_Address_to_List(assoc, G_Addr))
1381 SN_LOG(SN_LOG_EVENT,
1382 logsctperror("AddGlobalIPAddress: Address already in list",
1383 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1384 return; /*shouldn't be any other addresses if the zero address is given*/
1385 } else {
1386 G_Addr->g_addr.s_addr = ipv4_param->addr;
1387 if (!Add_Global_Address_to_List(assoc, G_Addr))
1388 SN_LOG(SN_LOG_EVENT,
1389 logsctperror("AddGlobalIPAddress: Address already in list",
1390 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1391 }
1392 }
1330 /* step through parameters */
1331 while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
1332 if (assoc->num_Gaddr >= sysctl_track_global_addresses) {
1333 SN_LOG(SN_LOG_EVENT,
1334 logsctperror("AddGlobalIPAddress: Maximum Number of addresses reached",
1335 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1336 return;
1337 }
1338 switch(ntohs(param->param_type)) {
1339 case SCTP_ADD_IP_ADDRESS:
1340 /* skip to address parameter - leave param_size so bytes left will be calculated properly*/
1341 param = (struct sctp_paramhdr *) &((struct sctp_asconf_addrv4_param *) param)->addrp;
1342 case SCTP_IPV4_ADDRESS:
1343 ipv4_param = (struct sctp_ipv4addr_param *) param;
1344 /* add addresses to association */
1345 G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
1346 if (G_Addr == NULL) {/* out of resources */
1347 SN_LOG(SN_LOG_EVENT,
1348 logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
1349 sm->sctp_hdr->v_tag, 0, direction));
1350 assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
1351 sysctl_track_global_addresses=0;
1352 return;
1353 }
1354 /* add address */
1355 addr_param_count++;
1356 if ((sm->msg == SN_SCTP_ASCONF) && (ipv4_param->addr == INADDR_ANY)) { /* use packet address */
1357 G_Addr->g_addr = g_addr;
1358 if (!Add_Global_Address_to_List(assoc, G_Addr))
1359 SN_LOG(SN_LOG_EVENT,
1360 logsctperror("AddGlobalIPAddress: Address already in list",
1361 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1362 return; /*shouldn't be any other addresses if the zero address is given*/
1363 } else {
1364 G_Addr->g_addr.s_addr = ipv4_param->addr;
1365 if (!Add_Global_Address_to_List(assoc, G_Addr))
1366 SN_LOG(SN_LOG_EVENT,
1367 logsctperror("AddGlobalIPAddress: Address already in list",
1368 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1369 }
1370 }
1393
1371
1394 bytes_left -= param_size;
1395 if (bytes_left < SN_MIN_PARAM_SIZE)
1396 break;
1372 bytes_left -= param_size;
1373 if (bytes_left < SN_MIN_PARAM_SIZE)
1374 break;
1397
1375
1398 param = SN_SCTP_NEXTPARAM(param);
1399 param_size = SCTP_SIZE32(ntohs(param->param_length));
1400 if (++param_count > sysctl_param_proc_limit) {
1401 SN_LOG(SN_LOG_EVENT,
1402 logsctperror("Parameter parse limit exceeded (AddGlobalIPAddress)",
1403 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1404 break; /* limit exceeded*/
1405 }
1406 }
1407 if (addr_param_count == 0) {
1408 SN_LOG(SN_LOG_DETAIL,
1409 logsctperror("AddGlobalIPAddress: no address parameters to add",
1376 param = SN_SCTP_NEXTPARAM(param);
1377 param_size = SCTP_SIZE32(ntohs(param->param_length));
1378 if (++param_count > sysctl_param_proc_limit) {
1379 SN_LOG(SN_LOG_EVENT,
1380 logsctperror("Parameter parse limit exceeded (AddGlobalIPAddress)",
1381 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1382 break; /* limit exceeded*/
1383 }
1384 }
1385 if (addr_param_count == 0) {
1386 SN_LOG(SN_LOG_DETAIL,
1387 logsctperror("AddGlobalIPAddress: no address parameters to add",
1410 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1388 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1411 }
1389 }
1412}
1413
1414/**
1415 * @brief Add_Global_Address_to_List
1416 *
1417 * Adds a global IP address to an associations address list, if it is not
1418 * already there. The first address added us usually the packet's address, and
1419 * is most likely to be used, so it is added at the beginning. Subsequent
1420 * addresses are added after this one.
1421 *
1422 * @param assoc Pointer to the association this SCTP Message belongs to
1423 * @param G_addr Pointer to the global address to add
1424 *
1425 * @return 1 - success | 0 - fail
1426 */
1427static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr)
1428{
1390}
1391
1392/**
1393 * @brief Add_Global_Address_to_List
1394 *
1395 * Adds a global IP address to an associations address list, if it is not
1396 * already there. The first address added us usually the packet's address, and
1397 * is most likely to be used, so it is added at the beginning. Subsequent
1398 * addresses are added after this one.
1399 *
1400 * @param assoc Pointer to the association this SCTP Message belongs to
1401 * @param G_addr Pointer to the global address to add
1402 *
1403 * @return 1 - success | 0 - fail
1404 */
1405static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr)
1406{
1429 struct sctp_GlobalAddress *iter_G_Addr = NULL, *first_G_Addr = NULL;
1430 first_G_Addr = LIST_FIRST(&(assoc->Gaddr));
1431 if (first_G_Addr == NULL) {
1432 LIST_INSERT_HEAD(&(assoc->Gaddr), G_addr, list_Gaddr); /* add new address to beginning of list*/
1433 } else {
1434 LIST_FOREACH(iter_G_Addr, &(assoc->Gaddr), list_Gaddr) {
1435 if (G_addr->g_addr.s_addr == iter_G_Addr->g_addr.s_addr)
1436 return(0); /* already exists, so don't add */
1437 }
1438 LIST_INSERT_AFTER(first_G_Addr, G_addr, list_Gaddr); /* add address to end of list*/
1439 }
1440 assoc->num_Gaddr++;
1441 return(1); /* success */
1407 struct sctp_GlobalAddress *iter_G_Addr = NULL, *first_G_Addr = NULL;
1408 first_G_Addr = LIST_FIRST(&(assoc->Gaddr));
1409 if (first_G_Addr == NULL) {
1410 LIST_INSERT_HEAD(&(assoc->Gaddr), G_addr, list_Gaddr); /* add new address to beginning of list*/
1411 } else {
1412 LIST_FOREACH(iter_G_Addr, &(assoc->Gaddr), list_Gaddr) {
1413 if (G_addr->g_addr.s_addr == iter_G_Addr->g_addr.s_addr)
1414 return(0); /* already exists, so don't add */
1415 }
1416 LIST_INSERT_AFTER(first_G_Addr, G_addr, list_Gaddr); /* add address to end of list*/
1417 }
1418 assoc->num_Gaddr++;
1419 return(1); /* success */
1442}
1443
1444/** @ingroup packet_parser
1445 * @brief RmGlobalIPAddresses from DelIP packets
1446 *
1447 * RmGlobalIPAddresses scans an ASCONF chunk for DelIP parameters to remove the
1448 * given Global IP addresses from the association. It will not delete the
1449 * the address if it is a list of one address.
1450 *
1451 *
1452 * @param sm Pointer to sctp message information
1453 * @param assoc Pointer to the association this SCTP Message belongs to
1454 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1455 *
1456 */
1457static void
1458RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
1459{
1420}
1421
1422/** @ingroup packet_parser
1423 * @brief RmGlobalIPAddresses from DelIP packets
1424 *
1425 * RmGlobalIPAddresses scans an ASCONF chunk for DelIP parameters to remove the
1426 * given Global IP addresses from the association. It will not delete the
1427 * the address if it is a list of one address.
1428 *
1429 *
1430 * @param sm Pointer to sctp message information
1431 * @param assoc Pointer to the association this SCTP Message belongs to
1432 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1433 *
1434 */
1435static void
1436RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
1437{
1460 struct sctp_asconf_addrv4_param *asconf_ipv4_param;
1461 struct sctp_paramhdr *param;
1462 struct sctp_GlobalAddress *G_Addr, *G_Addr_tmp;
1463 struct in_addr g_addr;
1464 int bytes_left;
1465 int param_size;
1466 int param_count;
1438 struct sctp_asconf_addrv4_param *asconf_ipv4_param;
1439 struct sctp_paramhdr *param;
1440 struct sctp_GlobalAddress *G_Addr, *G_Addr_tmp;
1441 struct in_addr g_addr;
1442 int bytes_left;
1443 int param_size;
1444 int param_count;
1467
1445
1468 if(direction == SN_TO_GLOBAL)
1469 g_addr = sm->ip_hdr->ip_dst;
1470 else
1471 g_addr = sm->ip_hdr->ip_src;
1446 if(direction == SN_TO_GLOBAL)
1447 g_addr = sm->ip_hdr->ip_dst;
1448 else
1449 g_addr = sm->ip_hdr->ip_src;
1472
1450
1473 bytes_left = sm->chunk_length;
1474 param_count = 1;
1475 param = sm->sctpchnk.Asconf;
1476 if (bytes_left >= SN_MIN_PARAM_SIZE) {
1477 param_size = SCTP_SIZE32(ntohs(param->param_length));
1478 } else {
1479 SN_LOG(SN_LOG_EVENT,
1480 logsctperror("RmGlobalIPAddress: truncated packet - cannot remove IP addresses",
1451 bytes_left = sm->chunk_length;
1452 param_count = 1;
1453 param = sm->sctpchnk.Asconf;
1454 if (bytes_left >= SN_MIN_PARAM_SIZE) {
1455 param_size = SCTP_SIZE32(ntohs(param->param_length));
1456 } else {
1457 SN_LOG(SN_LOG_EVENT,
1458 logsctperror("RmGlobalIPAddress: truncated packet - cannot remove IP addresses",
1481 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1459 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1482 return;
1483 }
1484
1485 /* step through Asconf parameters */
1486 while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
1487 if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) {
1488 asconf_ipv4_param = (struct sctp_asconf_addrv4_param *) param;
1489 if (asconf_ipv4_param->addrp.addr == INADDR_ANY) { /* remove all bar pkt address */
1490 LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
1491 if(G_Addr->g_addr.s_addr != sm->ip_hdr->ip_src.s_addr) {
1492 if (assoc->num_Gaddr > 1) { /* only delete if more than one */
1493 LIST_REMOVE(G_Addr, list_Gaddr);
1494 sn_free(G_Addr);
1495 assoc->num_Gaddr--;
1496 } else {
1497 SN_LOG(SN_LOG_EVENT,
1498 logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
1499 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1500 }
1501 }
1460 return;
1502 }
1461 }
1503 return; /*shouldn't be any other addresses if the zero address is given*/
1504 } else {
1505 LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
1506 if(G_Addr->g_addr.s_addr == asconf_ipv4_param->addrp.addr) {
1507 if (assoc->num_Gaddr > 1) { /* only delete if more than one */
1508 LIST_REMOVE(G_Addr, list_Gaddr);
1509 sn_free(G_Addr);
1510 assoc->num_Gaddr--;
1511 break; /* Since add only adds new addresses, there should be no double entries */
1512 } else {
1513 SN_LOG(SN_LOG_EVENT,
1514 logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
1515 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1516 }
1517 }
1518 }
1519 }
1520 }
1521 bytes_left -= param_size;
1522 if (bytes_left == 0) return;
1523 else if (bytes_left < SN_MIN_PARAM_SIZE) {
1524 SN_LOG(SN_LOG_EVENT,
1525 logsctperror("RmGlobalIPAddress: truncated packet - may not have removed all IP addresses",
1526 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1527 return;
1528 }
1462
1463 /* step through Asconf parameters */
1464 while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
1465 if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) {
1466 asconf_ipv4_param = (struct sctp_asconf_addrv4_param *) param;
1467 if (asconf_ipv4_param->addrp.addr == INADDR_ANY) { /* remove all bar pkt address */
1468 LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
1469 if(G_Addr->g_addr.s_addr != sm->ip_hdr->ip_src.s_addr) {
1470 if (assoc->num_Gaddr > 1) { /* only delete if more than one */
1471 LIST_REMOVE(G_Addr, list_Gaddr);
1472 sn_free(G_Addr);
1473 assoc->num_Gaddr--;
1474 } else {
1475 SN_LOG(SN_LOG_EVENT,
1476 logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
1477 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1478 }
1479 }
1480 }
1481 return; /*shouldn't be any other addresses if the zero address is given*/
1482 } else {
1483 LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
1484 if(G_Addr->g_addr.s_addr == asconf_ipv4_param->addrp.addr) {
1485 if (assoc->num_Gaddr > 1) { /* only delete if more than one */
1486 LIST_REMOVE(G_Addr, list_Gaddr);
1487 sn_free(G_Addr);
1488 assoc->num_Gaddr--;
1489 break; /* Since add only adds new addresses, there should be no double entries */
1490 } else {
1491 SN_LOG(SN_LOG_EVENT,
1492 logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
1493 sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
1494 }
1495 }
1496 }
1497 }
1498 }
1499 bytes_left -= param_size;
1500 if (bytes_left == 0) return;
1501 else if (bytes_left < SN_MIN_PARAM_SIZE) {
1502 SN_LOG(SN_LOG_EVENT,
1503 logsctperror("RmGlobalIPAddress: truncated packet - may not have removed all IP addresses",
1504 sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
1505 return;
1506 }
1529
1507
1530 param = SN_SCTP_NEXTPARAM(param);
1531 param_size = SCTP_SIZE32(ntohs(param->param_length));
1532 if (++param_count > sysctl_param_proc_limit) {
1533 SN_LOG(SN_LOG_EVENT,
1534 logsctperror("Parameter parse limit exceeded (RmGlobalIPAddress)",
1535 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1536 return; /* limit exceeded*/
1537 }
1538 }
1508 param = SN_SCTP_NEXTPARAM(param);
1509 param_size = SCTP_SIZE32(ntohs(param->param_length));
1510 if (++param_count > sysctl_param_proc_limit) {
1511 SN_LOG(SN_LOG_EVENT,
1512 logsctperror("Parameter parse limit exceeded (RmGlobalIPAddress)",
1513 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1514 return; /* limit exceeded*/
1515 }
1516 }
1539}
1540
1541/** @ingroup packet_parser
1542 * @brief Check that ASCONF was successful
1543 *
1544 * Each ASCONF configuration parameter carries a correlation ID which should be
1545 * matched with an ASCONFack. This is difficult for a NAT, since every
1546 * association could potentially have a number of outstanding ASCONF

--- 11 unchanged lines hidden (view full) ---

1558 * @param sm Pointer to sctp message information
1559 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1560 *
1561 * @return 1 - success | 0 - fail
1562 */
1563static int
1564IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction)
1565{
1517}
1518
1519/** @ingroup packet_parser
1520 * @brief Check that ASCONF was successful
1521 *
1522 * Each ASCONF configuration parameter carries a correlation ID which should be
1523 * matched with an ASCONFack. This is difficult for a NAT, since every
1524 * association could potentially have a number of outstanding ASCONF

--- 11 unchanged lines hidden (view full) ---

1536 * @param sm Pointer to sctp message information
1537 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1538 *
1539 * @return 1 - success | 0 - fail
1540 */
1541static int
1542IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction)
1543{
1566 struct sctp_paramhdr *param;
1567 int bytes_left;
1568 int param_size;
1569 int param_count;
1544 struct sctp_paramhdr *param;
1545 int bytes_left;
1546 int param_size;
1547 int param_count;
1570
1548
1571 param_count = 1;
1572 param = sm->sctpchnk.Asconf;
1573 param_size = SCTP_SIZE32(ntohs(param->param_length));
1574 if (param_size == 8)
1575 return(1); /*success - default acknowledgement of everything */
1549 param_count = 1;
1550 param = sm->sctpchnk.Asconf;
1551 param_size = SCTP_SIZE32(ntohs(param->param_length));
1552 if (param_size == 8)
1553 return(1); /*success - default acknowledgement of everything */
1576
1554
1577 bytes_left = sm->chunk_length;
1578 if (bytes_left < param_size)
1579 return(0); /* not found */
1580 /* step through Asconf parameters */
1581 while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
1582 if (ntohs(param->param_type) == SCTP_SUCCESS_REPORT)
1583 return(1); /* success - but can't match correlation IDs - should only be one */
1584 /* check others just in case */
1585 bytes_left -= param_size;
1586 if (bytes_left >= SN_MIN_PARAM_SIZE) {
1587 param = SN_SCTP_NEXTPARAM(param);
1588 } else {
1589 return(0);
1590 }
1591 param_size = SCTP_SIZE32(ntohs(param->param_length));
1592 if (bytes_left < param_size) return(0);
1555 bytes_left = sm->chunk_length;
1556 if (bytes_left < param_size)
1557 return(0); /* not found */
1558 /* step through Asconf parameters */
1559 while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
1560 if (ntohs(param->param_type) == SCTP_SUCCESS_REPORT)
1561 return(1); /* success - but can't match correlation IDs - should only be one */
1562 /* check others just in case */
1563 bytes_left -= param_size;
1564 if (bytes_left >= SN_MIN_PARAM_SIZE) {
1565 param = SN_SCTP_NEXTPARAM(param);
1566 } else {
1567 return(0);
1568 }
1569 param_size = SCTP_SIZE32(ntohs(param->param_length));
1570 if (bytes_left < param_size) return(0);
1593
1571
1594 if (++param_count > sysctl_param_proc_limit) {
1595 SN_LOG(SN_LOG_EVENT,
1596 logsctperror("Parameter parse limit exceeded (IsASCONFack)",
1597 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1598 return(0); /* not found limit exceeded*/
1599 }
1600 }
1601 return(0); /* not success */
1572 if (++param_count > sysctl_param_proc_limit) {
1573 SN_LOG(SN_LOG_EVENT,
1574 logsctperror("Parameter parse limit exceeded (IsASCONFack)",
1575 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1576 return(0); /* not found limit exceeded*/
1577 }
1578 }
1579 return(0); /* not success */
1602}
1603
1604/** @ingroup packet_parser
1605 * @brief Check to see if ASCONF contains an Add IP or Del IP parameter
1606 *
1607 * IsADDorDEL scans an ASCONF packet to see if it contains an AddIP or DelIP
1608 * parameter
1609 *
1610 * @param la Pointer to the relevant libalias instance
1611 * @param sm Pointer to sctp message information
1612 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1613 *
1614 * @return SCTP_ADD_IP_ADDRESS | SCTP_DEL_IP_ADDRESS | 0 - fail
1615 */
1616static int
1617IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction)
1618{
1580}
1581
1582/** @ingroup packet_parser
1583 * @brief Check to see if ASCONF contains an Add IP or Del IP parameter
1584 *
1585 * IsADDorDEL scans an ASCONF packet to see if it contains an AddIP or DelIP
1586 * parameter
1587 *
1588 * @param la Pointer to the relevant libalias instance
1589 * @param sm Pointer to sctp message information
1590 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1591 *
1592 * @return SCTP_ADD_IP_ADDRESS | SCTP_DEL_IP_ADDRESS | 0 - fail
1593 */
1594static int
1595IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction)
1596{
1619 struct sctp_paramhdr *param;
1620 int bytes_left;
1621 int param_size;
1622 int param_count;
1597 struct sctp_paramhdr *param;
1598 int bytes_left;
1599 int param_size;
1600 int param_count;
1623
1601
1624 param_count = 1;
1625 param = sm->sctpchnk.Asconf;
1626 param_size = SCTP_SIZE32(ntohs(param->param_length));
1602 param_count = 1;
1603 param = sm->sctpchnk.Asconf;
1604 param_size = SCTP_SIZE32(ntohs(param->param_length));
1627
1605
1628 bytes_left = sm->chunk_length;
1629 if (bytes_left < param_size)
1630 return(0); /* not found */
1631 /* step through Asconf parameters */
1632 while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
1633 if (ntohs(param->param_type) == SCTP_ADD_IP_ADDRESS)
1634 return(SCTP_ADD_IP_ADDRESS);
1635 else if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS)
1636 return(SCTP_DEL_IP_ADDRESS);
1637 /* check others just in case */
1638 bytes_left -= param_size;
1639 if (bytes_left >= SN_MIN_PARAM_SIZE) {
1640 param = SN_SCTP_NEXTPARAM(param);
1641 } else {
1642 return(0); /*Neither found */
1643 }
1644 param_size = SCTP_SIZE32(ntohs(param->param_length));
1645 if (bytes_left < param_size) return(0);
1606 bytes_left = sm->chunk_length;
1607 if (bytes_left < param_size)
1608 return(0); /* not found */
1609 /* step through Asconf parameters */
1610 while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
1611 if (ntohs(param->param_type) == SCTP_ADD_IP_ADDRESS)
1612 return(SCTP_ADD_IP_ADDRESS);
1613 else if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS)
1614 return(SCTP_DEL_IP_ADDRESS);
1615 /* check others just in case */
1616 bytes_left -= param_size;
1617 if (bytes_left >= SN_MIN_PARAM_SIZE) {
1618 param = SN_SCTP_NEXTPARAM(param);
1619 } else {
1620 return(0); /*Neither found */
1621 }
1622 param_size = SCTP_SIZE32(ntohs(param->param_length));
1623 if (bytes_left < param_size) return(0);
1646
1624
1647 if (++param_count > sysctl_param_proc_limit) {
1648 SN_LOG(SN_LOG_EVENT,
1649 logsctperror("Parameter parse limit exceeded IsADDorDEL)",
1650 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1651 return(0); /* not found limit exceeded*/
1652 }
1653 }
1654 return(0); /*Neither found */
1625 if (++param_count > sysctl_param_proc_limit) {
1626 SN_LOG(SN_LOG_EVENT,
1627 logsctperror("Parameter parse limit exceeded IsADDorDEL)",
1628 sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
1629 return(0); /* not found limit exceeded*/
1630 }
1631 }
1632 return(0); /*Neither found */
1655}
1656
1657/* ----------------------------------------------------------------------
1658 * STATE MACHINE CODE
1659 * ----------------------------------------------------------------------
1660 */
1661/** @addtogroup state_machine
1662 *

--- 15 unchanged lines hidden (view full) ---

1678 * @param sm Pointer to sctp message information
1679 * @param assoc Pointer to the association this SCTP Message belongs to
1680 *
1681 * @return SN_DROP_PKT | SN_NAT_PKT | SN_REPLY_ABORT | SN_REPLY_ERROR | SN_PROCESSING_ERROR
1682 */
1683static int
1684ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
1685{
1633}
1634
1635/* ----------------------------------------------------------------------
1636 * STATE MACHINE CODE
1637 * ----------------------------------------------------------------------
1638 */
1639/** @addtogroup state_machine
1640 *

--- 15 unchanged lines hidden (view full) ---

1656 * @param sm Pointer to sctp message information
1657 * @param assoc Pointer to the association this SCTP Message belongs to
1658 *
1659 * @return SN_DROP_PKT | SN_NAT_PKT | SN_REPLY_ABORT | SN_REPLY_ERROR | SN_PROCESSING_ERROR
1660 */
1661static int
1662ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
1663{
1686 int rtnval;
1664 int rtnval;
1687
1665
1688 switch (assoc->state) {
1689 case SN_ID: /* Idle */
1690 rtnval = ID_process(la, direction, assoc, sm);
1691 if (rtnval != SN_NAT_PKT) {
1692 assoc->state = SN_RM;/* Mark for removal*/
1693 }
1694 return(rtnval);
1695 case SN_INi: /* Initialising - Init */
1696 return(INi_process(la, direction, assoc, sm));
1697 case SN_INa: /* Initialising - AddIP */
1698 return(INa_process(la, direction, assoc, sm));
1699 case SN_UP: /* Association UP */
1700 return(UP_process(la, direction, assoc, sm));
1701 case SN_CL: /* Association Closing */
1702 return(CL_process(la, direction, assoc, sm));
1703 }
1704 return(SN_PROCESSING_ERROR);
1666 switch (assoc->state) {
1667 case SN_ID: /* Idle */
1668 rtnval = ID_process(la, direction, assoc, sm);
1669 if (rtnval != SN_NAT_PKT) {
1670 assoc->state = SN_RM;/* Mark for removal*/
1671 }
1672 return(rtnval);
1673 case SN_INi: /* Initialising - Init */
1674 return(INi_process(la, direction, assoc, sm));
1675 case SN_INa: /* Initialising - AddIP */
1676 return(INa_process(la, direction, assoc, sm));
1677 case SN_UP: /* Association UP */
1678 return(UP_process(la, direction, assoc, sm));
1679 case SN_CL: /* Association Closing */
1680 return(CL_process(la, direction, assoc, sm));
1681 }
1682 return(SN_PROCESSING_ERROR);
1705}
1706
1707/** @ingroup state_machine
1708 * @brief Process SCTP message while in the Idle state
1709 *
1710 * This function looks for an Incoming INIT or AddIP message.
1711 *
1712 * All other SCTP messages are invalid when in SN_ID, and are dropped.
1713 *
1714 * @param la Pointer to the relevant libalias instance
1715 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1716 * @param sm Pointer to sctp message information
1717 * @param assoc Pointer to the association this SCTP Message belongs to
1718 *
1719 * @return SN_NAT_PKT | SN_DROP_PKT | SN_REPLY_ABORT | SN_REPLY_ERROR
1720 */
1721static int
1722ID_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1723{
1683}
1684
1685/** @ingroup state_machine
1686 * @brief Process SCTP message while in the Idle state
1687 *
1688 * This function looks for an Incoming INIT or AddIP message.
1689 *
1690 * All other SCTP messages are invalid when in SN_ID, and are dropped.
1691 *
1692 * @param la Pointer to the relevant libalias instance
1693 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1694 * @param sm Pointer to sctp message information
1695 * @param assoc Pointer to the association this SCTP Message belongs to
1696 *
1697 * @return SN_NAT_PKT | SN_DROP_PKT | SN_REPLY_ABORT | SN_REPLY_ERROR
1698 */
1699static int
1700ID_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1701{
1724 switch(sm->msg) {
1725 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk with ADDIP */
1726 if (!sysctl_accept_global_ootb_addip && (direction == SN_TO_LOCAL))
1727 return(SN_DROP_PKT);
1728 /* if this Asconf packet does not contain the Vtag parameters it is of no use in Idle state */
1729 if (!GetAsconfVtags(la, sm, &(assoc->l_vtag), &(assoc->g_vtag), direction))
1730 return(SN_DROP_PKT);
1731 case SN_SCTP_INIT: /* a packet containing an INIT chunk or an ASCONF AddIP */
1732 if (sysctl_track_global_addresses)
1733 AddGlobalIPAddresses(sm, assoc, direction);
1734 switch(direction){
1735 case SN_TO_GLOBAL:
1736 assoc->l_addr = sm->ip_hdr->ip_src;
1737 assoc->a_addr = FindAliasAddress(la, assoc->l_addr);
1738 assoc->l_port = sm->sctp_hdr->src_port;
1739 assoc->g_port = sm->sctp_hdr->dest_port;
1740 if(sm->msg == SN_SCTP_INIT)
1741 assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
1742 if (AddSctpAssocGlobal(la, assoc)) /* DB clash *///**** need to add dst address
1743 return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
1744 if(sm->msg == SN_SCTP_ASCONF) {
1745 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_dst)) /* DB clash */
1746 return(SN_REPLY_ERROR);
1747 assoc->TableRegister |= SN_WAIT_TOLOCAL; /* wait for tolocal ack */
1748 }
1749 break;
1750 case SN_TO_LOCAL:
1751 assoc->l_addr = FindSctpRedirectAddress(la, sm);
1752 assoc->a_addr = sm->ip_hdr->ip_dst;
1753 assoc->l_port = sm->sctp_hdr->dest_port;
1754 assoc->g_port = sm->sctp_hdr->src_port;
1755 if(sm->msg == SN_SCTP_INIT)
1756 assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
1757 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) /* DB clash */
1758 return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
1759 if(sm->msg == SN_SCTP_ASCONF) {
1760 if (AddSctpAssocGlobal(la, assoc)) /* DB clash */ //**** need to add src address
1761 return(SN_REPLY_ERROR);
1762 assoc->TableRegister |= SN_WAIT_TOGLOBAL; /* wait for toglobal ack */
1763 }
1764 break;
1765 }
1766 assoc->state = (sm->msg == SN_SCTP_INIT) ? SN_INi : SN_INa;
1767 assoc->exp = SN_I_T(la);
1768 sctp_AddTimeOut(la,assoc);
1769 return(SN_NAT_PKT);
1770 default: /* Any other type of SCTP message is not valid in Idle */
1771 return(SN_DROP_PKT);
1772 }
1773 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1702 switch(sm->msg) {
1703 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk with ADDIP */
1704 if (!sysctl_accept_global_ootb_addip && (direction == SN_TO_LOCAL))
1705 return(SN_DROP_PKT);
1706 /* if this Asconf packet does not contain the Vtag parameters it is of no use in Idle state */
1707 if (!GetAsconfVtags(la, sm, &(assoc->l_vtag), &(assoc->g_vtag), direction))
1708 return(SN_DROP_PKT);
1709 case SN_SCTP_INIT: /* a packet containing an INIT chunk or an ASCONF AddIP */
1710 if (sysctl_track_global_addresses)
1711 AddGlobalIPAddresses(sm, assoc, direction);
1712 switch(direction){
1713 case SN_TO_GLOBAL:
1714 assoc->l_addr = sm->ip_hdr->ip_src;
1715 assoc->a_addr = FindAliasAddress(la, assoc->l_addr);
1716 assoc->l_port = sm->sctp_hdr->src_port;
1717 assoc->g_port = sm->sctp_hdr->dest_port;
1718 if(sm->msg == SN_SCTP_INIT)
1719 assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
1720 if (AddSctpAssocGlobal(la, assoc)) /* DB clash *///**** need to add dst address
1721 return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
1722 if(sm->msg == SN_SCTP_ASCONF) {
1723 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_dst)) /* DB clash */
1724 return(SN_REPLY_ERROR);
1725 assoc->TableRegister |= SN_WAIT_TOLOCAL; /* wait for tolocal ack */
1726 }
1727 break;
1728 case SN_TO_LOCAL:
1729 assoc->l_addr = FindSctpRedirectAddress(la, sm);
1730 assoc->a_addr = sm->ip_hdr->ip_dst;
1731 assoc->l_port = sm->sctp_hdr->dest_port;
1732 assoc->g_port = sm->sctp_hdr->src_port;
1733 if(sm->msg == SN_SCTP_INIT)
1734 assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
1735 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) /* DB clash */
1736 return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
1737 if(sm->msg == SN_SCTP_ASCONF) {
1738 if (AddSctpAssocGlobal(la, assoc)) /* DB clash */ //**** need to add src address
1739 return(SN_REPLY_ERROR);
1740 assoc->TableRegister |= SN_WAIT_TOGLOBAL; /* wait for toglobal ack */
1741 }
1742 break;
1743 }
1744 assoc->state = (sm->msg == SN_SCTP_INIT) ? SN_INi : SN_INa;
1745 assoc->exp = SN_I_T(la);
1746 sctp_AddTimeOut(la,assoc);
1747 return(SN_NAT_PKT);
1748 default: /* Any other type of SCTP message is not valid in Idle */
1749 return(SN_DROP_PKT);
1750 }
1751return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1774}
1775
1776/** @ingroup state_machine
1777 * @brief Process SCTP message while waiting for an INIT-ACK message
1778 *
1779 * Only an INIT-ACK, resent INIT, or an ABORT SCTP packet are valid in this
1780 * state, all other packets are dropped.
1781 *
1782 * @param la Pointer to the relevant libalias instance
1783 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1784 * @param sm Pointer to sctp message information
1785 * @param assoc Pointer to the association this SCTP Message belongs to
1786 *
1787 * @return SN_NAT_PKT | SN_DROP_PKT | SN_REPLY_ABORT
1788 */
1789static int
1790INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1791{
1752}
1753
1754/** @ingroup state_machine
1755 * @brief Process SCTP message while waiting for an INIT-ACK message
1756 *
1757 * Only an INIT-ACK, resent INIT, or an ABORT SCTP packet are valid in this
1758 * state, all other packets are dropped.
1759 *
1760 * @param la Pointer to the relevant libalias instance
1761 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1762 * @param sm Pointer to sctp message information
1763 * @param assoc Pointer to the association this SCTP Message belongs to
1764 *
1765 * @return SN_NAT_PKT | SN_DROP_PKT | SN_REPLY_ABORT
1766 */
1767static int
1768INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1769{
1792 switch(sm->msg) {
1793 case SN_SCTP_INIT: /* a packet containing a retransmitted INIT chunk */
1794 sctp_ResetTimeOut(la, assoc, SN_I_T(la));
1795 return(SN_NAT_PKT);
1796 case SN_SCTP_INITACK: /* a packet containing an INIT-ACK chunk */
1797 switch(direction){
1798 case SN_TO_LOCAL:
1799 if (assoc->num_Gaddr) /*If tracking global addresses for this association */
1800 AddGlobalIPAddresses(sm, assoc, direction);
1801 assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
1802 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) { /* DB clash */
1803 assoc->state = SN_RM;/* Mark for removal*/
1804 return(SN_SEND_ABORT);
1805 }
1806 break;
1807 case SN_TO_GLOBAL:
1808 assoc->l_addr = sm->ip_hdr->ip_src; // Only if not set in Init! *
1809 assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
1810 if (AddSctpAssocGlobal(la, assoc)) { /* DB clash */
1811 assoc->state = SN_RM;/* Mark for removal*/
1812 return(SN_SEND_ABORT);
1813 }
1814 break;
1815 }
1816 assoc->state = SN_UP;/* association established for NAT */
1817 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1818 return(SN_NAT_PKT);
1819 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1820 assoc->state = SN_RM;/* Mark for removal*/
1821 return(SN_NAT_PKT);
1822 default:
1823 return(SN_DROP_PKT);
1824 }
1825 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1770 switch(sm->msg) {
1771 case SN_SCTP_INIT: /* a packet containing a retransmitted INIT chunk */
1772 sctp_ResetTimeOut(la, assoc, SN_I_T(la));
1773 return(SN_NAT_PKT);
1774 case SN_SCTP_INITACK: /* a packet containing an INIT-ACK chunk */
1775 switch(direction){
1776 case SN_TO_LOCAL:
1777 if (assoc->num_Gaddr) /*If tracking global addresses for this association */
1778 AddGlobalIPAddresses(sm, assoc, direction);
1779 assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
1780 if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) { /* DB clash */
1781 assoc->state = SN_RM;/* Mark for removal*/
1782 return(SN_SEND_ABORT);
1783 }
1784 break;
1785 case SN_TO_GLOBAL:
1786 assoc->l_addr = sm->ip_hdr->ip_src; // Only if not set in Init! *
1787 assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
1788 if (AddSctpAssocGlobal(la, assoc)) { /* DB clash */
1789 assoc->state = SN_RM;/* Mark for removal*/
1790 return(SN_SEND_ABORT);
1791 }
1792 break;
1793 }
1794 assoc->state = SN_UP;/* association established for NAT */
1795 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1796 return(SN_NAT_PKT);
1797 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1798 assoc->state = SN_RM;/* Mark for removal*/
1799 return(SN_NAT_PKT);
1800 default:
1801 return(SN_DROP_PKT);
1802 }
1803 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1826}
1827
1828/** @ingroup state_machine
1829 * @brief Process SCTP message while waiting for an AddIp-ACK message
1830 *
1831 * Only an AddIP-ACK, resent AddIP, or an ABORT message are valid, all other
1832 * SCTP packets are dropped
1833 *
1834 * @param la Pointer to the relevant libalias instance
1835 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1836 * @param sm Pointer to sctp message information
1837 * @param assoc Pointer to the association this SCTP Message belongs to
1838 *
1839 * @return SN_NAT_PKT | SN_DROP_PKT
1840 */
1841static int
1842INa_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1843{
1804}
1805
1806/** @ingroup state_machine
1807 * @brief Process SCTP message while waiting for an AddIp-ACK message
1808 *
1809 * Only an AddIP-ACK, resent AddIP, or an ABORT message are valid, all other
1810 * SCTP packets are dropped
1811 *
1812 * @param la Pointer to the relevant libalias instance
1813 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1814 * @param sm Pointer to sctp message information
1815 * @param assoc Pointer to the association this SCTP Message belongs to
1816 *
1817 * @return SN_NAT_PKT | SN_DROP_PKT
1818 */
1819static int
1820INa_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1821{
1844 switch(sm->msg) {
1845 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
1846 sctp_ResetTimeOut(la,assoc, SN_I_T(la));
1847 return(SN_NAT_PKT);
1848 case SN_SCTP_ASCONFACK: /* a packet containing an ASCONF chunk with a ADDIP-ACK */
1849 switch(direction){
1850 case SN_TO_LOCAL:
1851 if (!(assoc->TableRegister & SN_WAIT_TOLOCAL)) /* wrong direction */
1852 return(SN_DROP_PKT);
1853 break;
1854 case SN_TO_GLOBAL:
1855 if (!(assoc->TableRegister & SN_WAIT_TOGLOBAL)) /* wrong direction */
1856 return(SN_DROP_PKT);
1857 }
1858 if (IsASCONFack(la,sm,direction)) {
1859 assoc->TableRegister &= SN_BOTH_TBL; /* remove wait flags */
1860 assoc->state = SN_UP; /* association established for NAT */
1861 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1862 return(SN_NAT_PKT);
1863 } else {
1864 assoc->state = SN_RM;/* Mark for removal*/
1865 return(SN_NAT_PKT);
1866 }
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 */
1822 switch(sm->msg) {
1823 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
1824 sctp_ResetTimeOut(la,assoc, SN_I_T(la));
1825 return(SN_NAT_PKT);
1826 case SN_SCTP_ASCONFACK: /* a packet containing an ASCONF chunk with a ADDIP-ACK */
1827 switch(direction){
1828 case SN_TO_LOCAL:
1829 if (!(assoc->TableRegister & SN_WAIT_TOLOCAL)) /* wrong direction */
1830 return(SN_DROP_PKT);
1831 break;
1832 case SN_TO_GLOBAL:
1833 if (!(assoc->TableRegister & SN_WAIT_TOGLOBAL)) /* wrong direction */
1834 return(SN_DROP_PKT);
1835 }
1836 if (IsASCONFack(la,sm,direction)) {
1837 assoc->TableRegister &= SN_BOTH_TBL; /* remove wait flags */
1838 assoc->state = SN_UP; /* association established for NAT */
1839 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1840 return(SN_NAT_PKT);
1841 } else {
1842 assoc->state = SN_RM;/* Mark for removal*/
1843 return(SN_NAT_PKT);
1844 }
1845 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1846 assoc->state = SN_RM;/* Mark for removal*/
1847 return(SN_NAT_PKT);
1848 default:
1849 return(SN_DROP_PKT);
1850 }
1851 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1874}
1875
1876/** @ingroup state_machine
1877 * @brief Process SCTP messages while association is UP redirecting packets
1878 *
1879 * While in the SN_UP state, all packets for the particular association
1880 * are passed. Only a SHUT-ACK or an ABORT will cause a change of state.
1881 *
1882 * @param la Pointer to the relevant libalias instance
1883 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1884 * @param sm Pointer to sctp message information
1885 * @param assoc Pointer to the association this SCTP Message belongs to
1886 *
1887 * @return SN_NAT_PKT | SN_DROP_PKT
1888 */
1889static int
1890UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1891{
1852}
1853
1854/** @ingroup state_machine
1855 * @brief Process SCTP messages while association is UP redirecting packets
1856 *
1857 * While in the SN_UP state, all packets for the particular association
1858 * are passed. Only a SHUT-ACK or an ABORT will cause a change of state.
1859 *
1860 * @param la Pointer to the relevant libalias instance
1861 * @param direction SN_TO_LOCAL | SN_TO_GLOBAL
1862 * @param sm Pointer to sctp message information
1863 * @param assoc Pointer to the association this SCTP Message belongs to
1864 *
1865 * @return SN_NAT_PKT | SN_DROP_PKT
1866 */
1867static int
1868UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1869{
1892 switch(sm->msg) {
1893 case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
1894 assoc->state = SN_CL;
1895 sctp_ResetTimeOut(la,assoc, SN_C_T(la));
1896 return(SN_NAT_PKT);
1897 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1898 assoc->state = SN_RM;/* Mark for removal*/
1899 return(SN_NAT_PKT);
1900 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
1901 if ((direction == SN_TO_LOCAL) && assoc->num_Gaddr) /*If tracking global addresses for this association & from global side */
1902 switch(IsADDorDEL(la,sm,direction)) {
1903 case SCTP_ADD_IP_ADDRESS:
1904 AddGlobalIPAddresses(sm, assoc, direction);
1905 break;
1906 case SCTP_DEL_IP_ADDRESS:
1907 RmGlobalIPAddresses(sm, assoc, direction);
1908 break;
1909 } /* fall through to default */
1910 default:
1911 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1912 return(SN_NAT_PKT); /* forward packet */
1913 }
1914 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1870 switch(sm->msg) {
1871 case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
1872 assoc->state = SN_CL;
1873 sctp_ResetTimeOut(la,assoc, SN_C_T(la));
1874 return(SN_NAT_PKT);
1875 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1876 assoc->state = SN_RM;/* Mark for removal*/
1877 return(SN_NAT_PKT);
1878 case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
1879 if ((direction == SN_TO_LOCAL) && assoc->num_Gaddr) /*If tracking global addresses for this association & from global side */
1880 switch(IsADDorDEL(la,sm,direction)) {
1881 case SCTP_ADD_IP_ADDRESS:
1882 AddGlobalIPAddresses(sm, assoc, direction);
1883 break;
1884 case SCTP_DEL_IP_ADDRESS:
1885 RmGlobalIPAddresses(sm, assoc, direction);
1886 break;
1887 } /* fall through to default */
1888 default:
1889 sctp_ResetTimeOut(la,assoc, SN_U_T(la));
1890 return(SN_NAT_PKT); /* forward packet */
1891 }
1892 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1915}
1916
1917/** @ingroup state_machine
1918 * @brief Process SCTP message while association is in the process of closing
1919 *
1920 * This function waits for a SHUT-COMP to close the association. Depending on
1921 * the the setting of sysctl_holddown_timer it may not remove the association
1922 * immediately, but leave it up until SN_X_T(la). Only SHUT-COMP, SHUT-ACK, and

--- 4 unchanged lines hidden (view full) ---

1927 * @param sm Pointer to sctp message information
1928 * @param assoc Pointer to the association this SCTP Message belongs to
1929 *
1930 * @return SN_NAT_PKT | SN_DROP_PKT
1931 */
1932static int
1933CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1934{
1893}
1894
1895/** @ingroup state_machine
1896 * @brief Process SCTP message while association is in the process of closing
1897 *
1898 * This function waits for a SHUT-COMP to close the association. Depending on
1899 * the the setting of sysctl_holddown_timer it may not remove the association
1900 * immediately, but leave it up until SN_X_T(la). Only SHUT-COMP, SHUT-ACK, and

--- 4 unchanged lines hidden (view full) ---

1905 * @param sm Pointer to sctp message information
1906 * @param assoc Pointer to the association this SCTP Message belongs to
1907 *
1908 * @return SN_NAT_PKT | SN_DROP_PKT
1909 */
1910static int
1911CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
1912{
1935 switch(sm->msg) {
1936 case SN_SCTP_SHUTCOMP: /* a packet containing a SHUTDOWN-COMPLETE chunk */
1937 assoc->state = SN_CL; /* Stay in Close state until timeout */
1938 if (sysctl_holddown_timer > 0)
1939 sctp_ResetTimeOut(la, assoc, SN_X_T(la));/* allow to stay open for Tbit packets*/
1940 else
1941 assoc->state = SN_RM;/* Mark for removal*/
1942 return(SN_NAT_PKT);
1943 case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
1944 assoc->state = SN_CL; /* Stay in Close state until timeout */
1945 sctp_ResetTimeOut(la, assoc, SN_C_T(la));
1946 return(SN_NAT_PKT);
1947 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1948 assoc->state = SN_RM;/* Mark for removal*/
1949 return(SN_NAT_PKT);
1950 default:
1951 return(SN_DROP_PKT);
1952 }
1953 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1913 switch(sm->msg) {
1914 case SN_SCTP_SHUTCOMP: /* a packet containing a SHUTDOWN-COMPLETE chunk */
1915 assoc->state = SN_CL; /* Stay in Close state until timeout */
1916 if (sysctl_holddown_timer > 0)
1917 sctp_ResetTimeOut(la, assoc, SN_X_T(la));/* allow to stay open for Tbit packets*/
1918 else
1919 assoc->state = SN_RM;/* Mark for removal*/
1920 return(SN_NAT_PKT);
1921 case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
1922 assoc->state = SN_CL; /* Stay in Close state until timeout */
1923 sctp_ResetTimeOut(la, assoc, SN_C_T(la));
1924 return(SN_NAT_PKT);
1925 case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
1926 assoc->state = SN_RM;/* Mark for removal*/
1927 return(SN_NAT_PKT);
1928 default:
1929 return(SN_DROP_PKT);
1930 }
1931 return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
1954}
1955
1956/* ----------------------------------------------------------------------
1957 * HASH TABLE CODE
1958 * ----------------------------------------------------------------------
1959 */
1960/** @addtogroup Hash
1961 *

--- 13 unchanged lines hidden (view full) ---

1975 * @param l_port local Port
1976 * @param g_port global Port
1977 *
1978 * @return pointer to association or NULL
1979 */
1980static struct sctp_nat_assoc*
1981FindSctpLocal(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)
1982{
1932}
1933
1934/* ----------------------------------------------------------------------
1935 * HASH TABLE CODE
1936 * ----------------------------------------------------------------------
1937 */
1938/** @addtogroup Hash
1939 *

--- 13 unchanged lines hidden (view full) ---

1953 * @param l_port local Port
1954 * @param g_port global Port
1955 *
1956 * @return pointer to association or NULL
1957 */
1958static struct sctp_nat_assoc*
1959FindSctpLocal(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)
1960{
1983 u_int i;
1984 struct sctp_nat_assoc *assoc = NULL;
1985 struct sctp_GlobalAddress *G_Addr = NULL;
1961 u_int i;
1962 struct sctp_nat_assoc *assoc = NULL;
1963 struct sctp_GlobalAddress *G_Addr = NULL;
1986
1964
1987 if (l_vtag != 0) { /* an init packet, vtag==0 */
1988 i = SN_TABLE_HASH(l_vtag, l_port, la->sctpNatTableSize);
1989 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
1990 if ((assoc->l_vtag == l_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)\
1991 && (assoc->l_addr.s_addr == l_addr.s_addr)) {
1992 if (assoc->num_Gaddr) {
1993 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
1994 if(G_Addr->g_addr.s_addr == g_addr.s_addr)
1995 return(assoc);
1996 }
1997 } else {
1998 return(assoc);
1965 if (l_vtag != 0) { /* an init packet, vtag==0 */
1966 i = SN_TABLE_HASH(l_vtag, l_port, la->sctpNatTableSize);
1967 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
1968 if ((assoc->l_vtag == l_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)\
1969 && (assoc->l_addr.s_addr == l_addr.s_addr)) {
1970 if (assoc->num_Gaddr) {
1971 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
1972 if(G_Addr->g_addr.s_addr == g_addr.s_addr)
1973 return(assoc);
1974 }
1975 } else {
1976 return(assoc);
1977 }
1978 }
1979 }
1999 }
1980 }
2000 }
2001 }
2002 }
2003 return(NULL);
1981 return(NULL);
2004}
2005
2006/** @ingroup Hash
2007 * @brief Check for Global Clash
2008 *
2009 * Searches the global look-up table for the association entry matching the
2010 * provided global <(addresses):ports:vtag> tuple
2011 *
2012 * @param la Pointer to the relevant libalias instance
2013 * @param Cassoc association being checked for a clash
2014 *
2015 * @return pointer to association or NULL
2016 */
2017static struct sctp_nat_assoc*
2018FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc)
2019{
1982}
1983
1984/** @ingroup Hash
1985 * @brief Check for Global Clash
1986 *
1987 * Searches the global look-up table for the association entry matching the
1988 * provided global <(addresses):ports:vtag> tuple
1989 *
1990 * @param la Pointer to the relevant libalias instance
1991 * @param Cassoc association being checked for a clash
1992 *
1993 * @return pointer to association or NULL
1994 */
1995static struct sctp_nat_assoc*
1996FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc)
1997{
2020 u_int i;
2021 struct sctp_nat_assoc *assoc = NULL;
2022 struct sctp_GlobalAddress *G_Addr = NULL;
2023 struct sctp_GlobalAddress *G_AddrC = NULL;
1998 u_int i;
1999 struct sctp_nat_assoc *assoc = NULL;
2000 struct sctp_GlobalAddress *G_Addr = NULL;
2001 struct sctp_GlobalAddress *G_AddrC = NULL;
2024
2002
2025 if (Cassoc->g_vtag != 0) { /* an init packet, vtag==0 */
2026 i = SN_TABLE_HASH(Cassoc->g_vtag, Cassoc->g_port, la->sctpNatTableSize);
2027 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2028 if ((assoc->g_vtag == Cassoc->g_vtag) && (assoc->g_port == Cassoc->g_port) && (assoc->l_port == Cassoc->l_port)) {
2029 if (assoc->num_Gaddr) {
2030 LIST_FOREACH(G_AddrC, &(Cassoc->Gaddr), list_Gaddr) {
2031 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2032 if(G_Addr->g_addr.s_addr == G_AddrC->g_addr.s_addr)
2033 return(assoc);
2034 }
2035 }
2036 } else {
2037 return(assoc);
2003 if (Cassoc->g_vtag != 0) { /* an init packet, vtag==0 */
2004 i = SN_TABLE_HASH(Cassoc->g_vtag, Cassoc->g_port, la->sctpNatTableSize);
2005 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2006 if ((assoc->g_vtag == Cassoc->g_vtag) && (assoc->g_port == Cassoc->g_port) && (assoc->l_port == Cassoc->l_port)) {
2007 if (assoc->num_Gaddr) {
2008 LIST_FOREACH(G_AddrC, &(Cassoc->Gaddr), list_Gaddr) {
2009 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2010 if(G_Addr->g_addr.s_addr == G_AddrC->g_addr.s_addr)
2011 return(assoc);
2012 }
2013 }
2014 } else {
2015 return(assoc);
2016 }
2017 }
2018 }
2038 }
2019 }
2039 }
2040 }
2041 }
2042 return(NULL);
2020 return(NULL);
2043}
2044
2045/** @ingroup Hash
2046 * @brief Find the SCTP association given the global port and vtag
2047 *
2048 * Searches the global look-up table for the association entry matching the
2049 * provided global <address:ports:vtag> tuple
2050 *

--- 8 unchanged lines hidden (view full) ---

2059 * @param g_port global port
2060 * @param l_port local port
2061 *
2062 * @return pointer to association or NULL
2063 */
2064static struct sctp_nat_assoc*
2065FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match)
2066{
2021}
2022
2023/** @ingroup Hash
2024 * @brief Find the SCTP association given the global port and vtag
2025 *
2026 * Searches the global look-up table for the association entry matching the
2027 * provided global <address:ports:vtag> tuple
2028 *

--- 8 unchanged lines hidden (view full) ---

2037 * @param g_port global port
2038 * @param l_port local port
2039 *
2040 * @return pointer to association or NULL
2041 */
2042static struct sctp_nat_assoc*
2043FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match)
2044{
2067 u_int i;
2068 struct sctp_nat_assoc *assoc = NULL;
2069 struct sctp_GlobalAddress *G_Addr = NULL;
2045 u_int i;
2046 struct sctp_nat_assoc *assoc = NULL;
2047 struct sctp_GlobalAddress *G_Addr = NULL;
2070
2048
2071 *partial_match = 0;
2072 if (g_vtag != 0) { /* an init packet, vtag==0 */
2073 i = SN_TABLE_HASH(g_vtag, g_port, la->sctpNatTableSize);
2074 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2075 if ((assoc->g_vtag == g_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
2076 *partial_match = 1;
2077 if (assoc->num_Gaddr) {
2078 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2079 if(G_Addr->g_addr.s_addr == g_addr.s_addr)
2080 return(assoc);
2081 }
2082 } else {
2083 return(assoc);
2049 *partial_match = 0;
2050 if (g_vtag != 0) { /* an init packet, vtag==0 */
2051 i = SN_TABLE_HASH(g_vtag, g_port, la->sctpNatTableSize);
2052 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2053 if ((assoc->g_vtag == g_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
2054 *partial_match = 1;
2055 if (assoc->num_Gaddr) {
2056 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2057 if(G_Addr->g_addr.s_addr == g_addr.s_addr)
2058 return(assoc);
2059 }
2060 } else {
2061 return(assoc);
2062 }
2063 }
2064 }
2084 }
2065 }
2085 }
2086 }
2087 }
2088 return(NULL);
2066 return(NULL);
2089}
2090
2091/** @ingroup Hash
2092 * @brief Find the SCTP association for a T-Flag message (given the global port and local vtag)
2093 *
2094 * Searches the local look-up table for a unique association entry matching the
2095 * provided global port and local vtag information
2096 *
2097 * @param la Pointer to the relevant libalias instance
2098 * @param g_addr global address
2099 * @param l_vtag local Vtag
2100 * @param g_port global Port
2101 * @param l_port local Port
2102 *
2103 * @return pointer to association or NULL
2104 */
2105static struct sctp_nat_assoc*
2106FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uint16_t g_port, uint16_t l_port)
2107{
2067}
2068
2069/** @ingroup Hash
2070 * @brief Find the SCTP association for a T-Flag message (given the global port and local vtag)
2071 *
2072 * Searches the local look-up table for a unique association entry matching the
2073 * provided global port and local vtag information
2074 *
2075 * @param la Pointer to the relevant libalias instance
2076 * @param g_addr global address
2077 * @param l_vtag local Vtag
2078 * @param g_port global Port
2079 * @param l_port local Port
2080 *
2081 * @return pointer to association or NULL
2082 */
2083static struct sctp_nat_assoc*
2084FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uint16_t g_port, uint16_t l_port)
2085{
2108 u_int i;
2109 struct sctp_nat_assoc *assoc = NULL, *lastmatch = NULL;
2110 struct sctp_GlobalAddress *G_Addr = NULL;
2111 int cnt = 0;
2086 u_int i;
2087 struct sctp_nat_assoc *assoc = NULL, *lastmatch = NULL;
2088 struct sctp_GlobalAddress *G_Addr = NULL;
2089 int cnt = 0;
2112
2090
2113 if (l_vtag != 0) { /* an init packet, vtag==0 */
2114 i = SN_TABLE_HASH(l_vtag, g_port, la->sctpNatTableSize);
2115 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2116 if ((assoc->g_vtag == l_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
2117 if (assoc->num_Gaddr) {
2118 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2119 if(G_Addr->g_addr.s_addr == G_Addr->g_addr.s_addr)
2120 return(assoc); /* full match */
2121 }
2122 } else {
2123 if (++cnt > 1) return(NULL);
2124 lastmatch = assoc;
2091 if (l_vtag != 0) { /* an init packet, vtag==0 */
2092 i = SN_TABLE_HASH(l_vtag, g_port, la->sctpNatTableSize);
2093 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2094 if ((assoc->g_vtag == l_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
2095 if (assoc->num_Gaddr) {
2096 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2097 if(G_Addr->g_addr.s_addr == G_Addr->g_addr.s_addr)
2098 return(assoc); /* full match */
2099 }
2100 } else {
2101 if (++cnt > 1) return(NULL);
2102 lastmatch = assoc;
2103 }
2104 }
2105 }
2125 }
2106 }
2126 }
2127 }
2128 }
2129 /* If there is more than one match we do not know which local address to send to */
2130 return( cnt ? lastmatch : NULL );
2107 /* If there is more than one match we do not know which local address to send to */
2108 return( cnt ? lastmatch : NULL );
2131}
2132
2133/** @ingroup Hash
2134 * @brief Find the SCTP association for a T-Flag message (given the local port and global vtag)
2135 *
2136 * Searches the global look-up table for a unique association entry matching the
2137 * provided local port and global vtag information
2138 *
2139 * @param la Pointer to the relevant libalias instance
2140 * @param g_addr global address
2141 * @param g_vtag global vtag
2142 * @param l_port local port
2143 * @param g_port global port
2144 *
2145 * @return pointer to association or NULL
2146 */
2147static struct sctp_nat_assoc*
2148FindSctpGlobalT(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t l_port, uint16_t g_port)
2149{
2109}
2110
2111/** @ingroup Hash
2112 * @brief Find the SCTP association for a T-Flag message (given the local port and global vtag)
2113 *
2114 * Searches the global look-up table for a unique association entry matching the
2115 * provided local port and global vtag information
2116 *
2117 * @param la Pointer to the relevant libalias instance
2118 * @param g_addr global address
2119 * @param g_vtag global vtag
2120 * @param l_port local port
2121 * @param g_port global port
2122 *
2123 * @return pointer to association or NULL
2124 */
2125static struct sctp_nat_assoc*
2126FindSctpGlobalT(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t l_port, uint16_t g_port)
2127{
2150 u_int i;
2151 struct sctp_nat_assoc *assoc = NULL;
2152 struct sctp_GlobalAddress *G_Addr = NULL;
2128 u_int i;
2129 struct sctp_nat_assoc *assoc = NULL;
2130 struct sctp_GlobalAddress *G_Addr = NULL;
2153
2131
2154 if (g_vtag != 0) { /* an init packet, vtag==0 */
2155 i = SN_TABLE_HASH(g_vtag, l_port, la->sctpNatTableSize);
2156 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
2157 if ((assoc->l_vtag == g_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)) {
2158 if (assoc->num_Gaddr) {
2159 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2160 if(G_Addr->g_addr.s_addr == g_addr.s_addr)
2161 return(assoc);
2162 }
2163 } else {
2164 return(assoc);
2132 if (g_vtag != 0) { /* an init packet, vtag==0 */
2133 i = SN_TABLE_HASH(g_vtag, l_port, la->sctpNatTableSize);
2134 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
2135 if ((assoc->l_vtag == g_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)) {
2136 if (assoc->num_Gaddr) {
2137 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2138 if(G_Addr->g_addr.s_addr == g_addr.s_addr)
2139 return(assoc);
2140 }
2141 } else {
2142 return(assoc);
2143 }
2144 }
2145 }
2165 }
2146 }
2166 }
2167 }
2168 }
2169 return(NULL);
2147 return(NULL);
2170}
2171
2172/** @ingroup Hash
2173 * @brief Add the sctp association information to the local look up table
2174 *
2175 * Searches the local look-up table for an existing association with the same
2176 * details. If a match exists and is ONLY in the local look-up table then this
2177 * is a repeated INIT packet, we need to remove this association from the

--- 5 unchanged lines hidden (view full) ---

2183 * @param assoc pointer to sctp association
2184 * @param g_addr global address
2185 *
2186 * @return SN_ADD_OK | SN_ADD_CLASH
2187 */
2188static int
2189AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_addr g_addr)
2190{
2148}
2149
2150/** @ingroup Hash
2151 * @brief Add the sctp association information to the local look up table
2152 *
2153 * Searches the local look-up table for an existing association with the same
2154 * details. If a match exists and is ONLY in the local look-up table then this
2155 * is a repeated INIT packet, we need to remove this association from the

--- 5 unchanged lines hidden (view full) ---

2161 * @param assoc pointer to sctp association
2162 * @param g_addr global address
2163 *
2164 * @return SN_ADD_OK | SN_ADD_CLASH
2165 */
2166static int
2167AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_addr g_addr)
2168{
2191 struct sctp_nat_assoc *found;
2169 struct sctp_nat_assoc *found;
2192
2170
2193 LIBALIAS_LOCK_ASSERT(la);
2194 found = FindSctpLocal(la, assoc->l_addr, g_addr, assoc->l_vtag, assoc->l_port, assoc->g_port);
2195 /*
2196 * Note that if a different global address initiated this Init,
2197 * ie it wasn't resent as presumed:
2198 * - the local receiver if receiving it for the first time will establish
2199 * an association with the new global host
2200 * - if receiving an init from a different global address after sending a
2201 * lost initack it will send an initack to the new global host, the first
2202 * association attempt will then be blocked if retried.
2203 */
2204 if (found != NULL) {
2205 if ((found->TableRegister == SN_LOCAL_TBL) && (found->g_port == assoc->g_port)) { /* resent message */
2206 RmSctpAssoc(la, found);
2207 sctp_RmTimeOut(la, found);
2208 freeGlobalAddressList(found);
2209 sn_free(found);
2210 } else
2211 return(SN_ADD_CLASH);
2212 }
2171 LIBALIAS_LOCK_ASSERT(la);
2172 found = FindSctpLocal(la, assoc->l_addr, g_addr, assoc->l_vtag, assoc->l_port, assoc->g_port);
2173 /*
2174 * Note that if a different global address initiated this Init,
2175 * ie it wasn't resent as presumed:
2176 * - the local receiver if receiving it for the first time will establish
2177 * an association with the new global host
2178 * - if receiving an init from a different global address after sending a
2179 * lost initack it will send an initack to the new global host, the first
2180 * association attempt will then be blocked if retried.
2181 */
2182 if (found != NULL) {
2183 if ((found->TableRegister == SN_LOCAL_TBL) && (found->g_port == assoc->g_port)) { /* resent message */
2184 RmSctpAssoc(la, found);
2185 sctp_RmTimeOut(la, found);
2186 freeGlobalAddressList(found);
2187 sn_free(found);
2188 } else
2189 return(SN_ADD_CLASH);
2190 }
2213
2191
2214 LIST_INSERT_HEAD(&la->sctpTableLocal[SN_TABLE_HASH(assoc->l_vtag, assoc->l_port, la->sctpNatTableSize)],
2215 assoc, list_L);
2216 assoc->TableRegister |= SN_LOCAL_TBL;
2217 la->sctpLinkCount++; //increment link count
2192 LIST_INSERT_HEAD(&la->sctpTableLocal[SN_TABLE_HASH(assoc->l_vtag, assoc->l_port, la->sctpNatTableSize)],
2193 assoc, list_L);
2194 assoc->TableRegister |= SN_LOCAL_TBL;
2195 la->sctpLinkCount++; //increment link count
2218
2196
2219 if (assoc->TableRegister == SN_BOTH_TBL) {
2220 /* libalias log -- controlled by libalias */
2221 if (la->packetAliasMode & PKT_ALIAS_LOG)
2222 SctpShowAliasStats(la);
2197 if (assoc->TableRegister == SN_BOTH_TBL) {
2198 /* libalias log -- controlled by libalias */
2199 if (la->packetAliasMode & PKT_ALIAS_LOG)
2200 SctpShowAliasStats(la);
2223
2201
2224 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
2225 }
2202 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
2203 }
2226
2204
2227 return(SN_ADD_OK);
2205 return(SN_ADD_OK);
2228}
2229
2230/** @ingroup Hash
2231 * @brief Add the sctp association information to the global look up table
2232 *
2233 * Searches the global look-up table for an existing association with the same
2234 * details. If a match exists and is ONLY in the global look-up table then this
2235 * is a repeated INIT packet, we need to remove this association from the

--- 4 unchanged lines hidden (view full) ---

2240 * @param la Pointer to the relevant libalias instance
2241 * @param assoc pointer to sctp association
2242 *
2243 * @return SN_ADD_OK | SN_ADD_CLASH
2244 */
2245static int
2246AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc)
2247{
2206}
2207
2208/** @ingroup Hash
2209 * @brief Add the sctp association information to the global look up table
2210 *
2211 * Searches the global look-up table for an existing association with the same
2212 * details. If a match exists and is ONLY in the global look-up table then this
2213 * is a repeated INIT packet, we need to remove this association from the

--- 4 unchanged lines hidden (view full) ---

2218 * @param la Pointer to the relevant libalias instance
2219 * @param assoc pointer to sctp association
2220 *
2221 * @return SN_ADD_OK | SN_ADD_CLASH
2222 */
2223static int
2224AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc)
2225{
2248 struct sctp_nat_assoc *found;
2226 struct sctp_nat_assoc *found;
2249
2227
2250 LIBALIAS_LOCK_ASSERT(la);
2251 found = FindSctpGlobalClash(la, assoc);
2252 if (found != NULL) {
2253 if ((found->TableRegister == SN_GLOBAL_TBL) && \
2254 (found->l_addr.s_addr == assoc->l_addr.s_addr) && (found->l_port == assoc->l_port)) { /* resent message */
2255 RmSctpAssoc(la, found);
2256 sctp_RmTimeOut(la, found);
2257 freeGlobalAddressList(found);
2258 sn_free(found);
2259 } else
2260 return(SN_ADD_CLASH);
2261 }
2228 LIBALIAS_LOCK_ASSERT(la);
2229 found = FindSctpGlobalClash(la, assoc);
2230 if (found != NULL) {
2231 if ((found->TableRegister == SN_GLOBAL_TBL) && \
2232 (found->l_addr.s_addr == assoc->l_addr.s_addr) && (found->l_port == assoc->l_port)) { /* resent message */
2233 RmSctpAssoc(la, found);
2234 sctp_RmTimeOut(la, found);
2235 freeGlobalAddressList(found);
2236 sn_free(found);
2237 } else
2238 return(SN_ADD_CLASH);
2239 }
2262
2240
2263 LIST_INSERT_HEAD(&la->sctpTableGlobal[SN_TABLE_HASH(assoc->g_vtag, assoc->g_port, la->sctpNatTableSize)],
2264 assoc, list_G);
2265 assoc->TableRegister |= SN_GLOBAL_TBL;
2266 la->sctpLinkCount++; //increment link count
2241 LIST_INSERT_HEAD(&la->sctpTableGlobal[SN_TABLE_HASH(assoc->g_vtag, assoc->g_port, la->sctpNatTableSize)],
2242 assoc, list_G);
2243 assoc->TableRegister |= SN_GLOBAL_TBL;
2244 la->sctpLinkCount++; //increment link count
2267
2245
2268 if (assoc->TableRegister == SN_BOTH_TBL) {
2269 /* libalias log -- controlled by libalias */
2270 if (la->packetAliasMode & PKT_ALIAS_LOG)
2271 SctpShowAliasStats(la);
2246 if (assoc->TableRegister == SN_BOTH_TBL) {
2247 /* libalias log -- controlled by libalias */
2248 if (la->packetAliasMode & PKT_ALIAS_LOG)
2249 SctpShowAliasStats(la);
2272
2250
2273 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
2274 }
2251 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
2252 }
2275
2253
2276 return(SN_ADD_OK);
2254 return(SN_ADD_OK);
2277}
2278
2279/** @ingroup Hash
2280 * @brief Remove the sctp association information from the look up table
2281 *
2282 * For each of the two (local/global) look-up tables, remove the association
2283 * from that table IF it has been registered in that table.
2284 *
2285 * NOTE: The calling code is responsible for freeing memory allocated to the
2286 * association structure itself
2287 *
2288 * NOTE: The association is NOT removed from the timer queue
2289 *
2290 * @param la Pointer to the relevant libalias instance
2291 * @param assoc pointer to sctp association
2292 */
2293static void
2294RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc)
2295{
2255}
2256
2257/** @ingroup Hash
2258 * @brief Remove the sctp association information from the look up table
2259 *
2260 * For each of the two (local/global) look-up tables, remove the association
2261 * from that table IF it has been registered in that table.
2262 *
2263 * NOTE: The calling code is responsible for freeing memory allocated to the
2264 * association structure itself
2265 *
2266 * NOTE: The association is NOT removed from the timer queue
2267 *
2268 * @param la Pointer to the relevant libalias instance
2269 * @param assoc pointer to sctp association
2270 */
2271static void
2272RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc)
2273{
2296 // struct sctp_nat_assoc *found;
2297 if (assoc == NULL) {
2298 /* very bad, log and die*/
2299 SN_LOG(SN_LOG_LOW,
2300 logsctperror("ERROR: alias_sctp:RmSctpAssoc(NULL)\n", 0, 0, SN_TO_NODIR));
2301 return;
2302 }
2303 /* log if association is fully up and now closing */
2304 if (assoc->TableRegister == SN_BOTH_TBL) {
2305 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "$"));
2306 }
2307 LIBALIAS_LOCK_ASSERT(la);
2308 if (assoc->TableRegister & SN_LOCAL_TBL) {
2309 assoc->TableRegister ^= SN_LOCAL_TBL;
2310 la->sctpLinkCount--; //decrement link count
2311 LIST_REMOVE(assoc, list_L);
2312 }
2274 // struct sctp_nat_assoc *found;
2275 if (assoc == NULL) {
2276 /* very bad, log and die*/
2277 SN_LOG(SN_LOG_LOW,
2278 logsctperror("ERROR: alias_sctp:RmSctpAssoc(NULL)\n", 0, 0, SN_TO_NODIR));
2279 return;
2280 }
2281 /* log if association is fully up and now closing */
2282 if (assoc->TableRegister == SN_BOTH_TBL) {
2283 SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "$"));
2284 }
2285 LIBALIAS_LOCK_ASSERT(la);
2286 if (assoc->TableRegister & SN_LOCAL_TBL) {
2287 assoc->TableRegister ^= SN_LOCAL_TBL;
2288 la->sctpLinkCount--; //decrement link count
2289 LIST_REMOVE(assoc, list_L);
2290 }
2313
2291
2314 if (assoc->TableRegister & SN_GLOBAL_TBL) {
2315 assoc->TableRegister ^= SN_GLOBAL_TBL;
2316 la->sctpLinkCount--; //decrement link count
2317 LIST_REMOVE(assoc, list_G);
2318 }
2319 // sn_free(assoc); //Don't remove now, remove if needed later
2320 /* libalias logging -- controlled by libalias log definition */
2321 if (la->packetAliasMode & PKT_ALIAS_LOG)
2322 SctpShowAliasStats(la);
2292 if (assoc->TableRegister & SN_GLOBAL_TBL) {
2293 assoc->TableRegister ^= SN_GLOBAL_TBL;
2294 la->sctpLinkCount--; //decrement link count
2295 LIST_REMOVE(assoc, list_G);
2296 }
2297 // sn_free(assoc); //Don't remove now, remove if needed later
2298 /* libalias logging -- controlled by libalias log definition */
2299 if (la->packetAliasMode & PKT_ALIAS_LOG)
2300 SctpShowAliasStats(la);
2323}
2324
2325/**
2326 * @ingroup Hash
2327 * @brief free the Global Address List memory
2328 *
2329 * freeGlobalAddressList deletes all global IP addresses in an associations
2330 * global IP address list.
2331 *
2332 * @param assoc
2333 */
2334static void freeGlobalAddressList(struct sctp_nat_assoc *assoc)
2335{
2301}
2302
2303/**
2304 * @ingroup Hash
2305 * @brief free the Global Address List memory
2306 *
2307 * freeGlobalAddressList deletes all global IP addresses in an associations
2308 * global IP address list.
2309 *
2310 * @param assoc
2311 */
2312static void freeGlobalAddressList(struct sctp_nat_assoc *assoc)
2313{
2336 struct sctp_GlobalAddress *gaddr1=NULL,*gaddr2=NULL;
2337 /*free global address list*/
2338 gaddr1 = LIST_FIRST(&(assoc->Gaddr));
2339 while (gaddr1 != NULL) {
2340 gaddr2 = LIST_NEXT(gaddr1, list_Gaddr);
2341 sn_free(gaddr1);
2342 gaddr1 = gaddr2;
2343 }
2314 struct sctp_GlobalAddress *gaddr1=NULL,*gaddr2=NULL;
2315 /*free global address list*/
2316 gaddr1 = LIST_FIRST(&(assoc->Gaddr));
2317 while (gaddr1 != NULL) {
2318 gaddr2 = LIST_NEXT(gaddr1, list_Gaddr);
2319 sn_free(gaddr1);
2320 gaddr1 = gaddr2;
2321 }
2344}
2345/* ----------------------------------------------------------------------
2346 * TIMER QUEUE CODE
2347 * ----------------------------------------------------------------------
2348 */
2349/** @addtogroup Timer
2350 *
2351 * The timer queue management functions are designed to operate efficiently with

--- 15 unchanged lines hidden (view full) ---

2367 * association into the list at that queue position
2368 *
2369 * @param la
2370 * @param assoc
2371 */
2372static void
2373sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
2374{
2322}
2323/* ----------------------------------------------------------------------
2324 * TIMER QUEUE CODE
2325 * ----------------------------------------------------------------------
2326 */
2327/** @addtogroup Timer
2328 *
2329 * The timer queue management functions are designed to operate efficiently with

--- 15 unchanged lines hidden (view full) ---

2345 * association into the list at that queue position
2346 *
2347 * @param la
2348 * @param assoc
2349 */
2350static void
2351sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
2352{
2375 int add_loc;
2376 LIBALIAS_LOCK_ASSERT(la);
2377 add_loc = assoc->exp - la->sctpNatTimer.loc_time + la->sctpNatTimer.cur_loc;
2378 if (add_loc >= SN_TIMER_QUEUE_SIZE)
2379 add_loc -= SN_TIMER_QUEUE_SIZE;
2380 LIST_INSERT_HEAD(&la->sctpNatTimer.TimerQ[add_loc], assoc, timer_Q);
2381 assoc->exp_loc = add_loc;
2353 int add_loc;
2354 LIBALIAS_LOCK_ASSERT(la);
2355 add_loc = assoc->exp - la->sctpNatTimer.loc_time + la->sctpNatTimer.cur_loc;
2356 if (add_loc >= SN_TIMER_QUEUE_SIZE)
2357 add_loc -= SN_TIMER_QUEUE_SIZE;
2358 LIST_INSERT_HEAD(&la->sctpNatTimer.TimerQ[add_loc], assoc, timer_Q);
2359 assoc->exp_loc = add_loc;
2382}
2383
2384/** @ingroup Timer
2385 * @brief Remove an association from timer queue
2386 *
2387 * This is an O(1) operation to remove the association pointer from its
2388 * current position in the timer queue
2389 *
2390 * @param la Pointer to the relevant libalias instance
2391 * @param assoc pointer to sctp association
2392 */
2393static void
2394sctp_RmTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
2395{
2360}
2361
2362/** @ingroup Timer
2363 * @brief Remove an association from timer queue
2364 *
2365 * This is an O(1) operation to remove the association pointer from its
2366 * current position in the timer queue
2367 *
2368 * @param la Pointer to the relevant libalias instance
2369 * @param assoc pointer to sctp association
2370 */
2371static void
2372sctp_RmTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
2373{
2396 LIBALIAS_LOCK_ASSERT(la);
2397 LIST_REMOVE(assoc, timer_Q);/* Note this is O(1) */
2374 LIBALIAS_LOCK_ASSERT(la);
2375 LIST_REMOVE(assoc, timer_Q);/* Note this is O(1) */
2398}
2399
2400
2401/** @ingroup Timer
2402 * @brief Reset timer in timer queue
2403 *
2404 * Reset the actual timeout for the specified association. If it is earlier than
2405 * the existing timeout, then remove and re-install the association into the
2406 * queue
2407 *
2408 * @param la Pointer to the relevant libalias instance
2409 * @param assoc pointer to sctp association
2410 * @param newexp New expiration time
2411 */
2412static void
2413sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp)
2414{
2376}
2377
2378
2379/** @ingroup Timer
2380 * @brief Reset timer in timer queue
2381 *
2382 * Reset the actual timeout for the specified association. If it is earlier than
2383 * the existing timeout, then remove and re-install the association into the
2384 * queue
2385 *
2386 * @param la Pointer to the relevant libalias instance
2387 * @param assoc pointer to sctp association
2388 * @param newexp New expiration time
2389 */
2390static void
2391sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp)
2392{
2415 if (newexp < assoc->exp) {
2416 sctp_RmTimeOut(la, assoc);
2417 assoc->exp = newexp;
2418 sctp_AddTimeOut(la, assoc);
2419 } else {
2420 assoc->exp = newexp;
2421 }
2393 if (newexp < assoc->exp) {
2394 sctp_RmTimeOut(la, assoc);
2395 assoc->exp = newexp;
2396 sctp_AddTimeOut(la, assoc);
2397 } else {
2398 assoc->exp = newexp;
2399 }
2422}
2423
2424/** @ingroup Timer
2425 * @brief Check timer Q against current time
2426 *
2427 * Loop through each entry in the timer queue since the last time we processed
2428 * the timer queue until now (the current time). For each association in the
2429 * event list, we remove it from that position in the timer queue and check if

--- 5 unchanged lines hidden (view full) ---

2435 * If the timer hasn't really expired we place the association into its new
2436 * correct position in the timer queue.
2437 *
2438 * @param la Pointer to the relevant libalias instance
2439 */
2440void
2441sctp_CheckTimers(struct libalias *la)
2442{
2400}
2401
2402/** @ingroup Timer
2403 * @brief Check timer Q against current time
2404 *
2405 * Loop through each entry in the timer queue since the last time we processed
2406 * the timer queue until now (the current time). For each association in the
2407 * event list, we remove it from that position in the timer queue and check if

--- 5 unchanged lines hidden (view full) ---

2413 * If the timer hasn't really expired we place the association into its new
2414 * correct position in the timer queue.
2415 *
2416 * @param la Pointer to the relevant libalias instance
2417 */
2418void
2419sctp_CheckTimers(struct libalias *la)
2420{
2443 struct sctp_nat_assoc *assoc;
2421 struct sctp_nat_assoc *assoc;
2444
2422
2445 LIBALIAS_LOCK_ASSERT(la);
2446 while(la->timeStamp >= la->sctpNatTimer.loc_time) {
2447 while (!LIST_EMPTY(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc])) {
2448 assoc = LIST_FIRST(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc]);
2449 //SLIST_REMOVE_HEAD(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc], timer_Q);
2450 LIST_REMOVE(assoc, timer_Q);
2451 if (la->timeStamp >= assoc->exp) { /* state expired */
2452 SN_LOG(((assoc->state == SN_CL)?(SN_LOG_DEBUG):(SN_LOG_INFO)),
2453 logsctperror("Timer Expired", assoc->g_vtag, assoc->state, SN_TO_NODIR));
2454 RmSctpAssoc(la, assoc);
2455 freeGlobalAddressList(assoc);
2456 sn_free(assoc);
2457 } else {/* state not expired, reschedule timer*/
2458 sctp_AddTimeOut(la, assoc);
2459 }
2460 }
2461 /* Goto next location in the timer queue*/
2462 ++la->sctpNatTimer.loc_time;
2463 if (++la->sctpNatTimer.cur_loc >= SN_TIMER_QUEUE_SIZE)
2464 la->sctpNatTimer.cur_loc = 0;
2465 }
2423 LIBALIAS_LOCK_ASSERT(la);
2424 while(la->timeStamp >= la->sctpNatTimer.loc_time) {
2425 while (!LIST_EMPTY(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc])) {
2426 assoc = LIST_FIRST(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc]);
2427 //SLIST_REMOVE_HEAD(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc], timer_Q);
2428 LIST_REMOVE(assoc, timer_Q);
2429 if (la->timeStamp >= assoc->exp) { /* state expired */
2430 SN_LOG(((assoc->state == SN_CL)?(SN_LOG_DEBUG):(SN_LOG_INFO)),
2431 logsctperror("Timer Expired", assoc->g_vtag, assoc->state, SN_TO_NODIR));
2432 RmSctpAssoc(la, assoc);
2433 freeGlobalAddressList(assoc);
2434 sn_free(assoc);
2435 } else {/* state not expired, reschedule timer*/
2436 sctp_AddTimeOut(la, assoc);
2437 }
2438 }
2439 /* Goto next location in the timer queue*/
2440 ++la->sctpNatTimer.loc_time;
2441 if (++la->sctpNatTimer.cur_loc >= SN_TIMER_QUEUE_SIZE)
2442 la->sctpNatTimer.cur_loc = 0;
2443 }
2466}
2467
2468/* ----------------------------------------------------------------------
2469 * LOGGING CODE
2470 * ----------------------------------------------------------------------
2471 */
2472/** @addtogroup Logging
2473 *

--- 7 unchanged lines hidden (view full) ---

2481 * @param errormsg Error message to be logged
2482 * @param vtag Current Vtag
2483 * @param error Error number
2484 * @param direction Direction of packet
2485 */
2486static void
2487logsctperror(char* errormsg, uint32_t vtag, int error, int direction)
2488{
2444}
2445
2446/* ----------------------------------------------------------------------
2447 * LOGGING CODE
2448 * ----------------------------------------------------------------------
2449 */
2450/** @addtogroup Logging
2451 *

--- 7 unchanged lines hidden (view full) ---

2459 * @param errormsg Error message to be logged
2460 * @param vtag Current Vtag
2461 * @param error Error number
2462 * @param direction Direction of packet
2463 */
2464static void
2465logsctperror(char* errormsg, uint32_t vtag, int error, int direction)
2466{
2489 char dir;
2490 switch(direction) {
2491 case SN_TO_LOCAL:
2492 dir = 'L';
2493 break;
2494 case SN_TO_GLOBAL:
2495 dir = 'G';
2496 break;
2497 default:
2498 dir = '*';
2499 break;
2500 }
2501 SctpAliasLog("->%c %s (vt=%u) %d\n", dir, errormsg, ntohl(vtag), error);
2467 char dir;
2468 switch(direction) {
2469 case SN_TO_LOCAL:
2470 dir = 'L';
2471 break;
2472 case SN_TO_GLOBAL:
2473 dir = 'G';
2474 break;
2475 default:
2476 dir = '*';
2477 break;
2478 }
2479 SctpAliasLog("->%c %s (vt=%u) %d\n", dir, errormsg, ntohl(vtag), error);
2502}
2503
2504/** @ingroup Logging
2505 * @brief Log what the parser parsed
2506 *
2507 * @param direction Direction of packet
2508 * @param sm Pointer to sctp message information
2509 */
2510static void
2511logsctpparse(int direction, struct sctp_nat_msg *sm)
2512{
2480}
2481
2482/** @ingroup Logging
2483 * @brief Log what the parser parsed
2484 *
2485 * @param direction Direction of packet
2486 * @param sm Pointer to sctp message information
2487 */
2488static void
2489logsctpparse(int direction, struct sctp_nat_msg *sm)
2490{
2513 char *ploc, *pstate;
2514 switch(direction) {
2515 case SN_TO_LOCAL:
2516 ploc = "TO_LOCAL -";
2517 break;
2518 case SN_TO_GLOBAL:
2519 ploc = "TO_GLOBAL -";
2520 break;
2521 default:
2522 ploc = "";
2523 }
2524 switch(sm->msg) {
2525 case SN_SCTP_INIT:
2526 pstate = "Init";
2527 break;
2528 case SN_SCTP_INITACK:
2529 pstate = "InitAck";
2530 break;
2531 case SN_SCTP_ABORT:
2532 pstate = "Abort";
2533 break;
2534 case SN_SCTP_SHUTACK:
2535 pstate = "ShutAck";
2536 break;
2537 case SN_SCTP_SHUTCOMP:
2538 pstate = "ShutComp";
2539 break;
2540 case SN_SCTP_ASCONF:
2541 pstate = "Asconf";
2542 break;
2543 case SN_SCTP_ASCONFACK:
2544 pstate = "AsconfAck";
2545 break;
2546 case SN_SCTP_OTHER:
2547 pstate = "Other";
2548 break;
2549 default:
2550 pstate = "***ERROR***";
2551 break;
2552 }
2553 SctpAliasLog("Parsed: %s %s\n", ploc, pstate);
2491 char *ploc, *pstate;
2492 switch(direction) {
2493 case SN_TO_LOCAL:
2494 ploc = "TO_LOCAL -";
2495 break;
2496 case SN_TO_GLOBAL:
2497 ploc = "TO_GLOBAL -";
2498 break;
2499 default:
2500 ploc = "";
2501 }
2502 switch(sm->msg) {
2503 case SN_SCTP_INIT:
2504 pstate = "Init";
2505 break;
2506 case SN_SCTP_INITACK:
2507 pstate = "InitAck";
2508 break;
2509 case SN_SCTP_ABORT:
2510 pstate = "Abort";
2511 break;
2512 case SN_SCTP_SHUTACK:
2513 pstate = "ShutAck";
2514 break;
2515 case SN_SCTP_SHUTCOMP:
2516 pstate = "ShutComp";
2517 break;
2518 case SN_SCTP_ASCONF:
2519 pstate = "Asconf";
2520 break;
2521 case SN_SCTP_ASCONFACK:
2522 pstate = "AsconfAck";
2523 break;
2524 case SN_SCTP_OTHER:
2525 pstate = "Other";
2526 break;
2527 default:
2528 pstate = "***ERROR***";
2529 break;
2530 }
2531 SctpAliasLog("Parsed: %s %s\n", ploc, pstate);
2554}
2555
2556/** @ingroup Logging
2557 * @brief Log an SCTP association's details
2558 *
2559 * @param assoc pointer to sctp association
2560 * @param s Character that indicates the state of processing for this packet
2561 */
2562static void logsctpassoc(struct sctp_nat_assoc *assoc, char* s)
2563{
2532}
2533
2534/** @ingroup Logging
2535 * @brief Log an SCTP association's details
2536 *
2537 * @param assoc pointer to sctp association
2538 * @param s Character that indicates the state of processing for this packet
2539 */
2540static void logsctpassoc(struct sctp_nat_assoc *assoc, char* s)
2541{
2564 struct sctp_GlobalAddress *G_Addr = NULL;
2565 char *sp;
2566 switch(assoc->state) {
2567 case SN_ID:
2568 sp = "ID ";
2569 break;
2570 case SN_INi:
2571 sp = "INi ";
2572 break;
2573 case SN_INa:
2574 sp = "INa ";
2575 break;
2576 case SN_UP:
2577 sp = "UP ";
2578 break;
2579 case SN_CL:
2580 sp = "CL ";
2581 break;
2582 case SN_RM:
2583 sp = "RM ";
2584 break;
2585 default:
2586 sp = "***ERROR***";
2587 break;
2588 }
2589 SctpAliasLog("%sAssoc: %s exp=%u la=%s lv=%u lp=%u gv=%u gp=%u tbl=%d\n",
2590 s, sp, assoc->exp, inet_ntoa(assoc->l_addr), ntohl(assoc->l_vtag),
2591 ntohs(assoc->l_port), ntohl(assoc->g_vtag), ntohs(assoc->g_port),
2592 assoc->TableRegister);
2593 /* list global addresses */
2594 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2595 SctpAliasLog("\t\tga=%s\n",inet_ntoa(G_Addr->g_addr));
2596 }
2542 struct sctp_GlobalAddress *G_Addr = NULL;
2543 char *sp;
2544 switch(assoc->state) {
2545 case SN_ID:
2546 sp = "ID ";
2547 break;
2548 case SN_INi:
2549 sp = "INi ";
2550 break;
2551 case SN_INa:
2552 sp = "INa ";
2553 break;
2554 case SN_UP:
2555 sp = "UP ";
2556 break;
2557 case SN_CL:
2558 sp = "CL ";
2559 break;
2560 case SN_RM:
2561 sp = "RM ";
2562 break;
2563 default:
2564 sp = "***ERROR***";
2565 break;
2566 }
2567 SctpAliasLog("%sAssoc: %s exp=%u la=%s lv=%u lp=%u gv=%u gp=%u tbl=%d\n",
2568 s, sp, assoc->exp, inet_ntoa(assoc->l_addr), ntohl(assoc->l_vtag),
2569 ntohs(assoc->l_port), ntohl(assoc->g_vtag), ntohs(assoc->g_port),
2570 assoc->TableRegister);
2571 /* list global addresses */
2572 LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
2573 SctpAliasLog("\t\tga=%s\n",inet_ntoa(G_Addr->g_addr));
2574 }
2597}
2598
2599/** @ingroup Logging
2600 * @brief Output Global table to log
2601 *
2602 * @param la Pointer to the relevant libalias instance
2603 */
2604static void logSctpGlobal(struct libalias *la)
2605{
2575}
2576
2577/** @ingroup Logging
2578 * @brief Output Global table to log
2579 *
2580 * @param la Pointer to the relevant libalias instance
2581 */
2582static void logSctpGlobal(struct libalias *la)
2583{
2606 u_int i;
2607 struct sctp_nat_assoc *assoc = NULL;
2584 u_int i;
2585 struct sctp_nat_assoc *assoc = NULL;
2608
2586
2609 SctpAliasLog("G->\n");
2610 for (i=0; i < la->sctpNatTableSize; i++) {
2611 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2612 logsctpassoc(assoc, " ");
2613 }
2614 }
2587 SctpAliasLog("G->\n");
2588 for (i=0; i < la->sctpNatTableSize; i++) {
2589 LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
2590 logsctpassoc(assoc, " ");
2591 }
2592 }
2615}
2616
2617/** @ingroup Logging
2618 * @brief Output Local table to log
2619 *
2620 * @param la Pointer to the relevant libalias instance
2621 */
2622static void logSctpLocal(struct libalias *la)
2623{
2593}
2594
2595/** @ingroup Logging
2596 * @brief Output Local table to log
2597 *
2598 * @param la Pointer to the relevant libalias instance
2599 */
2600static void logSctpLocal(struct libalias *la)
2601{
2624 u_int i;
2625 struct sctp_nat_assoc *assoc = NULL;
2602 u_int i;
2603 struct sctp_nat_assoc *assoc = NULL;
2626
2604
2627 SctpAliasLog("L->\n");
2628 for (i=0; i < la->sctpNatTableSize; i++) {
2629 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
2630 logsctpassoc(assoc, " ");
2631 }
2632 }
2605 SctpAliasLog("L->\n");
2606 for (i=0; i < la->sctpNatTableSize; i++) {
2607 LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
2608 logsctpassoc(assoc, " ");
2609 }
2610 }
2633}
2634
2635/** @ingroup Logging
2636 * @brief Output timer queue to log
2637 *
2638 * @param la Pointer to the relevant libalias instance
2639 */
2640static void logTimerQ(struct libalias *la)
2641{
2611}
2612
2613/** @ingroup Logging
2614 * @brief Output timer queue to log
2615 *
2616 * @param la Pointer to the relevant libalias instance
2617 */
2618static void logTimerQ(struct libalias *la)
2619{
2642 static char buf[50];
2643 u_int i;
2644 struct sctp_nat_assoc *assoc = NULL;
2620 static char buf[50];
2621 u_int i;
2622 struct sctp_nat_assoc *assoc = NULL;
2645
2623
2646 SctpAliasLog("t->\n");
2647 for (i=0; i < SN_TIMER_QUEUE_SIZE; i++) {
2648 LIST_FOREACH(assoc, &la->sctpNatTimer.TimerQ[i], timer_Q) {
2649 snprintf(buf, 50, " l=%u ",i);
2650 //SctpAliasLog(la->logDesc," l=%d ",i);
2651 logsctpassoc(assoc, buf);
2652 }
2653 }
2624 SctpAliasLog("t->\n");
2625 for (i=0; i < SN_TIMER_QUEUE_SIZE; i++) {
2626 LIST_FOREACH(assoc, &la->sctpNatTimer.TimerQ[i], timer_Q) {
2627 snprintf(buf, 50, " l=%u ",i);
2628 //SctpAliasLog(la->logDesc," l=%d ",i);
2629 logsctpassoc(assoc, buf);
2630 }
2631 }
2654}
2655
2656/** @ingroup Logging
2657 * @brief Sctp NAT logging function
2658 *
2659 * This function is based on a similar function in alias_db.c
2660 *
2661 * @param str/stream logging descriptor
2662 * @param format printf type string
2663 */
2664#ifdef _KERNEL
2665static void
2666SctpAliasLog(const char *format, ...)
2667{
2632}
2633
2634/** @ingroup Logging
2635 * @brief Sctp NAT logging function
2636 *
2637 * This function is based on a similar function in alias_db.c
2638 *
2639 * @param str/stream logging descriptor
2640 * @param format printf type string
2641 */
2642#ifdef _KERNEL
2643static void
2644SctpAliasLog(const char *format, ...)
2645{
2668 char buffer[LIBALIAS_BUF_SIZE];
2669 va_list ap;
2670 va_start(ap, format);
2671 vsnprintf(buffer, LIBALIAS_BUF_SIZE, format, ap);
2672 va_end(ap);
2673 log(LOG_SECURITY | LOG_INFO,
2674 "alias_sctp: %s", buffer);
2646 char buffer[LIBALIAS_BUF_SIZE];
2647 va_list ap;
2648 va_start(ap, format);
2649 vsnprintf(buffer, LIBALIAS_BUF_SIZE, format, ap);
2650 va_end(ap);
2651 log(LOG_SECURITY | LOG_INFO,
2652 "alias_sctp: %s", buffer);
2675}
2676#else
2677static void
2678SctpAliasLog(FILE *stream, const char *format, ...)
2679{
2653}
2654#else
2655static void
2656SctpAliasLog(FILE *stream, const char *format, ...)
2657{
2680 va_list ap;
2658 va_list ap;
2681
2659
2682 va_start(ap, format);
2683 vfprintf(stream, format, ap);
2684 va_end(ap);
2685 fflush(stream);
2660 va_start(ap, format);
2661 vfprintf(stream, format, ap);
2662 va_end(ap);
2663 fflush(stream);
2686}
2687#endif
2664}
2665#endif