1145516Sdarrenr/* $FreeBSD$ */ 2145516Sdarrenr 3145516Sdarrenr/* 4145516Sdarrenr * Copyright (C) 1995-1998 by Darren Reed. 5145516Sdarrenr * 6145516Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7145516Sdarrenr */ 8145516Sdarrenr#if defined(KERNEL) || defined(_KERNEL) 9145516Sdarrenr# undef KERNEL 10145516Sdarrenr# undef _KERNEL 11145516Sdarrenr# define KERNEL 1 12145516Sdarrenr# define _KERNEL 1 13145516Sdarrenr#endif 14145516Sdarrenr#include <sys/errno.h> 15145516Sdarrenr#include <sys/types.h> 16145516Sdarrenr#include <sys/param.h> 17145516Sdarrenr#include <sys/file.h> 18145516Sdarrenr#if !defined(_KERNEL) && !defined(__KERNEL__) 19145516Sdarrenr# include <stdio.h> 20145516Sdarrenr# include <stdlib.h> 21145516Sdarrenr# include <string.h> 22145516Sdarrenr# define _KERNEL 23145516Sdarrenr# define KERNEL 24145516Sdarrenr# ifdef __OpenBSD__ 25145516Sdarrenrstruct file; 26145516Sdarrenr# endif 27145516Sdarrenr# include <sys/uio.h> 28145516Sdarrenr# undef _KERNEL 29145516Sdarrenr# undef KERNEL 30145516Sdarrenr#else 31145516Sdarrenr# include <sys/systm.h> 32145516Sdarrenr# if !defined(__SVR4) && !defined(__svr4__) 33145516Sdarrenr# include <sys/mbuf.h> 34145516Sdarrenr# endif 35145516Sdarrenr#endif 36145516Sdarrenr#if defined(__NetBSD__) && (__NetBSD_Version__ >= 104000000) 37145516Sdarrenr# include <sys/proc.h> 38145516Sdarrenr#endif 39145516Sdarrenr#if defined(_KERNEL) && (__FreeBSD_version >= 220000) 40145516Sdarrenr# include <sys/filio.h> 41145516Sdarrenr# include <sys/fcntl.h> 42145516Sdarrenr# if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM) 43145516Sdarrenr# include "opt_ipfilter.h" 44145516Sdarrenr# endif 45145516Sdarrenr#else 46145516Sdarrenr# include <sys/ioctl.h> 47145516Sdarrenr#endif 48145516Sdarrenr#include <sys/time.h> 49145516Sdarrenr#if !defined(linux) 50145516Sdarrenr# include <sys/protosw.h> 51145516Sdarrenr#endif 52145516Sdarrenr#include <sys/socket.h> 53145516Sdarrenr#if defined(__SVR4) || defined(__svr4__) 54145516Sdarrenr# include <sys/filio.h> 55145516Sdarrenr# include <sys/byteorder.h> 56145516Sdarrenr# ifdef _KERNEL 57145516Sdarrenr# include <sys/dditypes.h> 58145516Sdarrenr# endif 59145516Sdarrenr# include <sys/stream.h> 60145516Sdarrenr# include <sys/kmem.h> 61145516Sdarrenr#endif 62145516Sdarrenr 63145516Sdarrenr#include <net/if.h> 64145516Sdarrenr#ifdef sun 65145516Sdarrenr# include <net/af.h> 66145516Sdarrenr#endif 67145516Sdarrenr#include <net/route.h> 68145516Sdarrenr#include <netinet/in.h> 69145516Sdarrenr#include <netinet/in_systm.h> 70145516Sdarrenr#include <netinet/ip.h> 71145516Sdarrenr#include <netinet/tcp.h> 72145516Sdarrenr#if !defined(linux) 73145516Sdarrenr# include <netinet/ip_var.h> 74145516Sdarrenr#endif 75145516Sdarrenr#if !defined(__hpux) && !defined(linux) 76145516Sdarrenr# include <netinet/tcp_fsm.h> 77145516Sdarrenr#endif 78145516Sdarrenr#include <netinet/udp.h> 79145516Sdarrenr#include <netinet/ip_icmp.h> 80145516Sdarrenr#include "netinet/ip_compat.h" 81145516Sdarrenr#include <netinet/tcpip.h> 82145516Sdarrenr#include "netinet/ip_fil.h" 83145516Sdarrenr#include "netinet/ip_nat.h" 84145516Sdarrenr#include "netinet/ip_frag.h" 85145516Sdarrenr#include "netinet/ip_state.h" 86145516Sdarrenr#include "netinet/ip_proxy.h" 87145516Sdarrenr#include "netinet/ip_sync.h" 88145516Sdarrenr#ifdef USE_INET6 89145516Sdarrenr#include <netinet/icmp6.h> 90145516Sdarrenr#endif 91145516Sdarrenr#if (__FreeBSD_version >= 300000) 92145516Sdarrenr# include <sys/malloc.h> 93145516Sdarrenr# if defined(_KERNEL) && !defined(IPFILTER_LKM) 94145516Sdarrenr# include <sys/libkern.h> 95145516Sdarrenr# include <sys/systm.h> 96145516Sdarrenr# endif 97145516Sdarrenr#endif 98145516Sdarrenr/* END OF INCLUDES */ 99145516Sdarrenr 100145516Sdarrenr#if !defined(lint) 101172776Sdarrenrstatic const char rcsid[] = "@(#)$Id: ip_sync.c,v 2.40.2.9 2007/06/02 21:22:28 darrenr Exp $"; 102145516Sdarrenr#endif 103145516Sdarrenr 104145516Sdarrenr#define SYNC_STATETABSZ 256 105145516Sdarrenr#define SYNC_NATTABSZ 256 106145516Sdarrenr 107145516Sdarrenr#ifdef IPFILTER_SYNC 108145516Sdarrenripfmutex_t ipf_syncadd, ipsl_mutex; 109145516Sdarrenripfrwlock_t ipf_syncstate, ipf_syncnat; 110145516Sdarrenr#if SOLARIS && defined(_KERNEL) 111145516Sdarrenrkcondvar_t ipslwait; 112145516Sdarrenr#endif 113145516Sdarrenrsynclist_t *syncstatetab[SYNC_STATETABSZ]; 114145516Sdarrenrsynclist_t *syncnattab[SYNC_NATTABSZ]; 115145516Sdarrenrsynclogent_t synclog[SYNCLOG_SZ]; 116145516Sdarrenrsyncupdent_t syncupd[SYNCLOG_SZ]; 117145516Sdarrenru_int ipf_syncnum = 1; 118145516Sdarrenru_int ipf_syncwrap = 0; 119145516Sdarrenru_int sl_idx = 0, /* next available sync log entry */ 120145516Sdarrenr su_idx = 0, /* next available sync update entry */ 121145516Sdarrenr sl_tail = 0, /* next sync log entry to read */ 122145516Sdarrenr su_tail = 0; /* next sync update entry to read */ 123145516Sdarrenrint ipf_sync_debug = 0; 124145516Sdarrenr 125145516Sdarrenr 126145516Sdarrenr# if !defined(sparc) && !defined(__hppa) 127145516Sdarrenrvoid ipfsync_tcporder __P((int, struct tcpdata *)); 128145516Sdarrenrvoid ipfsync_natorder __P((int, struct nat *)); 129145516Sdarrenrvoid ipfsync_storder __P((int, struct ipstate *)); 130145516Sdarrenr# endif 131145516Sdarrenr 132145516Sdarrenr 133145516Sdarrenr/* ------------------------------------------------------------------------ */ 134145516Sdarrenr/* Function: ipfsync_init */ 135145516Sdarrenr/* Returns: int - 0 == success, -1 == failure */ 136145516Sdarrenr/* Parameters: Nil */ 137145516Sdarrenr/* */ 138145516Sdarrenr/* Initialise all of the locks required for the sync code and initialise */ 139145516Sdarrenr/* any data structures, as required. */ 140145516Sdarrenr/* ------------------------------------------------------------------------ */ 141145516Sdarrenrint ipfsync_init() 142145516Sdarrenr{ 143145516Sdarrenr RWLOCK_INIT(&ipf_syncstate, "add things to state sync table"); 144145516Sdarrenr RWLOCK_INIT(&ipf_syncnat, "add things to nat sync table"); 145145516Sdarrenr MUTEX_INIT(&ipf_syncadd, "add things to sync table"); 146145516Sdarrenr MUTEX_INIT(&ipsl_mutex, "add things to sync table"); 147145516Sdarrenr# if SOLARIS && defined(_KERNEL) 148145516Sdarrenr cv_init(&ipslwait, "ipsl condvar", CV_DRIVER, NULL); 149145516Sdarrenr# endif 150145516Sdarrenr 151145516Sdarrenr bzero((char *)syncnattab, sizeof(syncnattab)); 152145516Sdarrenr bzero((char *)syncstatetab, sizeof(syncstatetab)); 153145516Sdarrenr 154145516Sdarrenr return 0; 155145516Sdarrenr} 156145516Sdarrenr 157145516Sdarrenr 158145516Sdarrenr# if !defined(sparc) && !defined(__hppa) 159145516Sdarrenr/* ------------------------------------------------------------------------ */ 160145516Sdarrenr/* Function: ipfsync_tcporder */ 161145516Sdarrenr/* Returns: Nil */ 162145516Sdarrenr/* Parameters: way(I) - direction of byte order conversion. */ 163145516Sdarrenr/* td(IO) - pointer to data to be converted. */ 164145516Sdarrenr/* */ 165145516Sdarrenr/* Do byte swapping on values in the TCP state information structure that */ 166145516Sdarrenr/* need to be used at both ends by the host in their native byte order. */ 167145516Sdarrenr/* ------------------------------------------------------------------------ */ 168145516Sdarrenrvoid ipfsync_tcporder(way, td) 169145516Sdarrenrint way; 170145516Sdarrenrtcpdata_t *td; 171145516Sdarrenr{ 172145516Sdarrenr if (way) { 173145516Sdarrenr td->td_maxwin = htons(td->td_maxwin); 174145516Sdarrenr td->td_end = htonl(td->td_end); 175145516Sdarrenr td->td_maxend = htonl(td->td_maxend); 176145516Sdarrenr } else { 177145516Sdarrenr td->td_maxwin = ntohs(td->td_maxwin); 178145516Sdarrenr td->td_end = ntohl(td->td_end); 179145516Sdarrenr td->td_maxend = ntohl(td->td_maxend); 180145516Sdarrenr } 181145516Sdarrenr} 182145516Sdarrenr 183145516Sdarrenr 184145516Sdarrenr/* ------------------------------------------------------------------------ */ 185145516Sdarrenr/* Function: ipfsync_natorder */ 186145516Sdarrenr/* Returns: Nil */ 187145516Sdarrenr/* Parameters: way(I) - direction of byte order conversion. */ 188145516Sdarrenr/* nat(IO) - pointer to data to be converted. */ 189145516Sdarrenr/* */ 190145516Sdarrenr/* Do byte swapping on values in the NAT data structure that need to be */ 191145516Sdarrenr/* used at both ends by the host in their native byte order. */ 192145516Sdarrenr/* ------------------------------------------------------------------------ */ 193145516Sdarrenrvoid ipfsync_natorder(way, n) 194145516Sdarrenrint way; 195145516Sdarrenrnat_t *n; 196145516Sdarrenr{ 197145516Sdarrenr if (way) { 198145516Sdarrenr n->nat_age = htonl(n->nat_age); 199145516Sdarrenr n->nat_flags = htonl(n->nat_flags); 200145516Sdarrenr n->nat_ipsumd = htonl(n->nat_ipsumd); 201145516Sdarrenr n->nat_use = htonl(n->nat_use); 202145516Sdarrenr n->nat_dir = htonl(n->nat_dir); 203145516Sdarrenr } else { 204145516Sdarrenr n->nat_age = ntohl(n->nat_age); 205145516Sdarrenr n->nat_flags = ntohl(n->nat_flags); 206145516Sdarrenr n->nat_ipsumd = ntohl(n->nat_ipsumd); 207145516Sdarrenr n->nat_use = ntohl(n->nat_use); 208145516Sdarrenr n->nat_dir = ntohl(n->nat_dir); 209145516Sdarrenr } 210145516Sdarrenr} 211145516Sdarrenr 212145516Sdarrenr 213145516Sdarrenr/* ------------------------------------------------------------------------ */ 214145516Sdarrenr/* Function: ipfsync_storder */ 215145516Sdarrenr/* Returns: Nil */ 216145516Sdarrenr/* Parameters: way(I) - direction of byte order conversion. */ 217145516Sdarrenr/* ips(IO) - pointer to data to be converted. */ 218145516Sdarrenr/* */ 219145516Sdarrenr/* Do byte swapping on values in the IP state data structure that need to */ 220145516Sdarrenr/* be used at both ends by the host in their native byte order. */ 221145516Sdarrenr/* ------------------------------------------------------------------------ */ 222145516Sdarrenrvoid ipfsync_storder(way, ips) 223145516Sdarrenrint way; 224145516Sdarrenripstate_t *ips; 225145516Sdarrenr{ 226145516Sdarrenr ipfsync_tcporder(way, &ips->is_tcp.ts_data[0]); 227145516Sdarrenr ipfsync_tcporder(way, &ips->is_tcp.ts_data[1]); 228145516Sdarrenr 229145516Sdarrenr if (way) { 230145516Sdarrenr ips->is_hv = htonl(ips->is_hv); 231145516Sdarrenr ips->is_die = htonl(ips->is_die); 232145516Sdarrenr ips->is_pass = htonl(ips->is_pass); 233145516Sdarrenr ips->is_flags = htonl(ips->is_flags); 234153876Sguido ips->is_opt[0] = htonl(ips->is_opt[0]); 235153876Sguido ips->is_opt[1] = htonl(ips->is_opt[1]); 236153876Sguido ips->is_optmsk[0] = htonl(ips->is_optmsk[0]); 237153876Sguido ips->is_optmsk[1] = htonl(ips->is_optmsk[1]); 238145516Sdarrenr ips->is_sec = htons(ips->is_sec); 239145516Sdarrenr ips->is_secmsk = htons(ips->is_secmsk); 240145516Sdarrenr ips->is_auth = htons(ips->is_auth); 241145516Sdarrenr ips->is_authmsk = htons(ips->is_authmsk); 242145516Sdarrenr ips->is_s0[0] = htonl(ips->is_s0[0]); 243145516Sdarrenr ips->is_s0[1] = htonl(ips->is_s0[1]); 244145516Sdarrenr ips->is_smsk[0] = htons(ips->is_smsk[0]); 245145516Sdarrenr ips->is_smsk[1] = htons(ips->is_smsk[1]); 246145516Sdarrenr } else { 247145516Sdarrenr ips->is_hv = ntohl(ips->is_hv); 248145516Sdarrenr ips->is_die = ntohl(ips->is_die); 249145516Sdarrenr ips->is_pass = ntohl(ips->is_pass); 250145516Sdarrenr ips->is_flags = ntohl(ips->is_flags); 251153876Sguido ips->is_opt[0] = ntohl(ips->is_opt[0]); 252153876Sguido ips->is_opt[1] = ntohl(ips->is_opt[1]); 253153876Sguido ips->is_optmsk[0] = ntohl(ips->is_optmsk[0]); 254153876Sguido ips->is_optmsk[1] = ntohl(ips->is_optmsk[1]); 255145516Sdarrenr ips->is_sec = ntohs(ips->is_sec); 256145516Sdarrenr ips->is_secmsk = ntohs(ips->is_secmsk); 257145516Sdarrenr ips->is_auth = ntohs(ips->is_auth); 258145516Sdarrenr ips->is_authmsk = ntohs(ips->is_authmsk); 259145516Sdarrenr ips->is_s0[0] = ntohl(ips->is_s0[0]); 260145516Sdarrenr ips->is_s0[1] = ntohl(ips->is_s0[1]); 261145516Sdarrenr ips->is_smsk[0] = ntohl(ips->is_smsk[0]); 262145516Sdarrenr ips->is_smsk[1] = ntohl(ips->is_smsk[1]); 263145516Sdarrenr } 264145516Sdarrenr} 265145516Sdarrenr# else /* !defined(sparc) && !defined(__hppa) */ 266145516Sdarrenr# define ipfsync_tcporder(x,y) 267145516Sdarrenr# define ipfsync_natorder(x,y) 268145516Sdarrenr# define ipfsync_storder(x,y) 269145516Sdarrenr# endif /* !defined(sparc) && !defined(__hppa) */ 270145516Sdarrenr 271145516Sdarrenr/* enable this for debugging */ 272145516Sdarrenr 273145516Sdarrenr# ifdef _KERNEL 274145516Sdarrenr/* ------------------------------------------------------------------------ */ 275145516Sdarrenr/* Function: ipfsync_write */ 276145516Sdarrenr/* Returns: int - 0 == success, else error value. */ 277145516Sdarrenr/* Parameters: uio(I) - pointer to information about data to write */ 278145516Sdarrenr/* */ 279145516Sdarrenr/* Moves data from user space into the kernel and uses it for updating data */ 280145516Sdarrenr/* structures in the state/NAT tables. */ 281145516Sdarrenr/* ------------------------------------------------------------------------ */ 282145516Sdarrenrint ipfsync_write(uio) 283145516Sdarrenrstruct uio *uio; 284145516Sdarrenr{ 285145516Sdarrenr synchdr_t sh; 286145516Sdarrenr 287145516Sdarrenr /* 288145516Sdarrenr * THIS MUST BE SUFFICIENT LARGE TO STORE 289145516Sdarrenr * ANY POSSIBLE DATA TYPE 290145516Sdarrenr */ 291145516Sdarrenr char data[2048]; 292145516Sdarrenr 293145516Sdarrenr int err = 0; 294145516Sdarrenr 295145516Sdarrenr# if (BSD >= 199306) || defined(__FreeBSD__) || defined(__osf__) 296145516Sdarrenr uio->uio_rw = UIO_WRITE; 297145516Sdarrenr# endif 298145516Sdarrenr 299145516Sdarrenr /* Try to get bytes */ 300145516Sdarrenr while (uio->uio_resid > 0) { 301145516Sdarrenr 302145516Sdarrenr if (uio->uio_resid >= sizeof(sh)) { 303145516Sdarrenr 304172776Sdarrenr err = UIOMOVE(&sh, sizeof(sh), UIO_WRITE, uio); 305145516Sdarrenr 306145516Sdarrenr if (err) { 307145516Sdarrenr if (ipf_sync_debug > 2) 308145516Sdarrenr printf("uiomove(header) failed: %d\n", 309145516Sdarrenr err); 310145516Sdarrenr return err; 311145516Sdarrenr } 312145516Sdarrenr 313145516Sdarrenr /* convert to host order */ 314145516Sdarrenr sh.sm_magic = ntohl(sh.sm_magic); 315145516Sdarrenr sh.sm_len = ntohl(sh.sm_len); 316145516Sdarrenr sh.sm_num = ntohl(sh.sm_num); 317145516Sdarrenr 318145516Sdarrenr if (ipf_sync_debug > 8) 319145516Sdarrenr printf("[%d] Read v:%d p:%d cmd:%d table:%d rev:%d len:%d magic:%x\n", 320145516Sdarrenr sh.sm_num, sh.sm_v, sh.sm_p, sh.sm_cmd, 321145516Sdarrenr sh.sm_table, sh.sm_rev, sh.sm_len, 322145516Sdarrenr sh.sm_magic); 323145516Sdarrenr 324145516Sdarrenr if (sh.sm_magic != SYNHDRMAGIC) { 325145516Sdarrenr if (ipf_sync_debug > 2) 326145516Sdarrenr printf("uiomove(header) invalud %s\n", 327145516Sdarrenr "magic"); 328145516Sdarrenr return EINVAL; 329145516Sdarrenr } 330145516Sdarrenr 331145516Sdarrenr if (sh.sm_v != 4 && sh.sm_v != 6) { 332145516Sdarrenr if (ipf_sync_debug > 2) 333145516Sdarrenr printf("uiomove(header) invalid %s\n", 334145516Sdarrenr "protocol"); 335145516Sdarrenr return EINVAL; 336145516Sdarrenr } 337145516Sdarrenr 338145516Sdarrenr if (sh.sm_cmd > SMC_MAXCMD) { 339145516Sdarrenr if (ipf_sync_debug > 2) 340145516Sdarrenr printf("uiomove(header) invalid %s\n", 341145516Sdarrenr "command"); 342145516Sdarrenr return EINVAL; 343145516Sdarrenr } 344145516Sdarrenr 345145516Sdarrenr 346145516Sdarrenr if (sh.sm_table > SMC_MAXTBL) { 347145516Sdarrenr if (ipf_sync_debug > 2) 348145516Sdarrenr printf("uiomove(header) invalid %s\n", 349145516Sdarrenr "table"); 350145516Sdarrenr return EINVAL; 351145516Sdarrenr } 352145516Sdarrenr 353145516Sdarrenr } else { 354145516Sdarrenr /* unsufficient data, wait until next call */ 355145516Sdarrenr if (ipf_sync_debug > 2) 356145516Sdarrenr printf("uiomove(header) insufficient data"); 357145516Sdarrenr return EAGAIN; 358145516Sdarrenr } 359145516Sdarrenr 360145516Sdarrenr 361145516Sdarrenr /* 362145516Sdarrenr * We have a header, so try to read the amount of data 363145516Sdarrenr * needed for the request 364145516Sdarrenr */ 365145516Sdarrenr 366145516Sdarrenr /* not supported */ 367145516Sdarrenr if (sh.sm_len == 0) { 368145516Sdarrenr if (ipf_sync_debug > 2) 369145516Sdarrenr printf("uiomove(data zero length %s\n", 370145516Sdarrenr "not supported"); 371145516Sdarrenr return EINVAL; 372145516Sdarrenr } 373145516Sdarrenr 374145516Sdarrenr if (uio->uio_resid >= sh.sm_len) { 375145516Sdarrenr 376172776Sdarrenr err = UIOMOVE(data, sh.sm_len, UIO_WRITE, uio); 377145516Sdarrenr 378145516Sdarrenr if (err) { 379145516Sdarrenr if (ipf_sync_debug > 2) 380145516Sdarrenr printf("uiomove(data) failed: %d\n", 381145516Sdarrenr err); 382145516Sdarrenr return err; 383145516Sdarrenr } 384145516Sdarrenr 385145516Sdarrenr if (ipf_sync_debug > 7) 386145516Sdarrenr printf("uiomove(data) %d bytes read\n", 387145516Sdarrenr sh.sm_len); 388145516Sdarrenr 389145516Sdarrenr if (sh.sm_table == SMC_STATE) 390145516Sdarrenr err = ipfsync_state(&sh, data); 391145516Sdarrenr else if (sh.sm_table == SMC_NAT) 392145516Sdarrenr err = ipfsync_nat(&sh, data); 393145516Sdarrenr if (ipf_sync_debug > 7) 394145516Sdarrenr printf("[%d] Finished with error %d\n", 395145516Sdarrenr sh.sm_num, err); 396145516Sdarrenr 397145516Sdarrenr } else { 398145516Sdarrenr /* insufficient data, wait until next call */ 399145516Sdarrenr if (ipf_sync_debug > 2) 400145516Sdarrenr printf("uiomove(data) %s %d bytes, got %d\n", 401145516Sdarrenr "insufficient data, need", 402145516Sdarrenr sh.sm_len, uio->uio_resid); 403145516Sdarrenr return EAGAIN; 404145516Sdarrenr } 405145516Sdarrenr } 406145516Sdarrenr 407145516Sdarrenr /* no more data */ 408145516Sdarrenr return 0; 409145516Sdarrenr} 410145516Sdarrenr 411145516Sdarrenr 412145516Sdarrenr/* ------------------------------------------------------------------------ */ 413145516Sdarrenr/* Function: ipfsync_read */ 414145516Sdarrenr/* Returns: int - 0 == success, else error value. */ 415145516Sdarrenr/* Parameters: uio(O) - pointer to information about where to store data */ 416145516Sdarrenr/* */ 417145516Sdarrenr/* This function is called when a user program wants to read some data */ 418145516Sdarrenr/* for pending state/NAT updates. If no data is available, the caller is */ 419145516Sdarrenr/* put to sleep, pending a wakeup from the "lower half" of this code. */ 420145516Sdarrenr/* ------------------------------------------------------------------------ */ 421145516Sdarrenrint ipfsync_read(uio) 422145516Sdarrenrstruct uio *uio; 423145516Sdarrenr{ 424145516Sdarrenr syncupdent_t *su; 425145516Sdarrenr synclogent_t *sl; 426145516Sdarrenr int err = 0; 427145516Sdarrenr 428145516Sdarrenr if ((uio->uio_resid & 3) || (uio->uio_resid < 8)) 429145516Sdarrenr return EINVAL; 430145516Sdarrenr 431145516Sdarrenr# if (BSD >= 199306) || defined(__FreeBSD__) || defined(__osf__) 432145516Sdarrenr uio->uio_rw = UIO_READ; 433145516Sdarrenr# endif 434145516Sdarrenr 435145516Sdarrenr MUTEX_ENTER(&ipsl_mutex); 436145516Sdarrenr while ((sl_tail == sl_idx) && (su_tail == su_idx)) { 437145516Sdarrenr# if SOLARIS && defined(_KERNEL) 438145516Sdarrenr if (!cv_wait_sig(&ipslwait, &ipsl_mutex)) { 439145516Sdarrenr MUTEX_EXIT(&ipsl_mutex); 440145516Sdarrenr return EINTR; 441145516Sdarrenr } 442145516Sdarrenr# else 443145516Sdarrenr# ifdef __hpux 444145516Sdarrenr { 445145516Sdarrenr lock_t *l; 446145516Sdarrenr 447145516Sdarrenr l = get_sleep_lock(&sl_tail); 448145516Sdarrenr err = sleep(&sl_tail, PZERO+1); 449147367Sdarrenr if (err) { 450147367Sdarrenr MUTEX_EXIT(&ipsl_mutex); 451147367Sdarrenr return EINTR; 452147367Sdarrenr } 453145516Sdarrenr spinunlock(l); 454145516Sdarrenr } 455145516Sdarrenr# else /* __hpux */ 456145516Sdarrenr# ifdef __osf__ 457145516Sdarrenr err = mpsleep(&sl_tail, PSUSP|PCATCH, "ipl sleep", 0, 458145516Sdarrenr &ipsl_mutex, MS_LOCK_SIMPLE); 459147367Sdarrenr if (err) 460147367Sdarrenr return EINTR; 461145516Sdarrenr# else 462145516Sdarrenr MUTEX_EXIT(&ipsl_mutex); 463145516Sdarrenr err = SLEEP(&sl_tail, "ipl sleep"); 464147367Sdarrenr if (err) 465147367Sdarrenr return EINTR; 466147367Sdarrenr MUTEX_ENTER(&ipsl_mutex); 467145516Sdarrenr# endif /* __osf__ */ 468145516Sdarrenr# endif /* __hpux */ 469145516Sdarrenr# endif /* SOLARIS */ 470145516Sdarrenr } 471145516Sdarrenr MUTEX_EXIT(&ipsl_mutex); 472145516Sdarrenr 473145516Sdarrenr READ_ENTER(&ipf_syncstate); 474145516Sdarrenr while ((sl_tail < sl_idx) && (uio->uio_resid > sizeof(*sl))) { 475145516Sdarrenr sl = synclog + sl_tail++; 476172776Sdarrenr err = UIOMOVE(sl, sizeof(*sl), UIO_READ, uio); 477145516Sdarrenr if (err != 0) 478145516Sdarrenr break; 479145516Sdarrenr } 480145516Sdarrenr 481145516Sdarrenr while ((su_tail < su_idx) && (uio->uio_resid > sizeof(*su))) { 482145516Sdarrenr su = syncupd + su_tail; 483145516Sdarrenr su_tail++; 484172776Sdarrenr err = UIOMOVE(su, sizeof(*su), UIO_READ, uio); 485145516Sdarrenr if (err != 0) 486145516Sdarrenr break; 487145516Sdarrenr if (su->sup_hdr.sm_sl != NULL) 488145516Sdarrenr su->sup_hdr.sm_sl->sl_idx = -1; 489145516Sdarrenr } 490145516Sdarrenr 491145516Sdarrenr MUTEX_ENTER(&ipf_syncadd); 492145516Sdarrenr if (su_tail == su_idx) 493145516Sdarrenr su_tail = su_idx = 0; 494145516Sdarrenr if (sl_tail == sl_idx) 495145516Sdarrenr sl_tail = sl_idx = 0; 496145516Sdarrenr MUTEX_EXIT(&ipf_syncadd); 497145516Sdarrenr RWLOCK_EXIT(&ipf_syncstate); 498145516Sdarrenr return err; 499145516Sdarrenr} 500145516Sdarrenr 501145516Sdarrenr 502145516Sdarrenr/* ------------------------------------------------------------------------ */ 503145516Sdarrenr/* Function: ipfsync_state */ 504145516Sdarrenr/* Returns: int - 0 == success, else error value. */ 505145516Sdarrenr/* Parameters: sp(I) - pointer to sync packet data header */ 506145516Sdarrenr/* uio(I) - pointer to user data for further information */ 507145516Sdarrenr/* */ 508145516Sdarrenr/* Updates the state table according to information passed in the sync */ 509145516Sdarrenr/* header. As required, more data is fetched from the uio structure but */ 510145516Sdarrenr/* varies depending on the contents of the sync header. This function can */ 511145516Sdarrenr/* create a new state entry or update one. Deletion is left to the state */ 512145516Sdarrenr/* structures being timed out correctly. */ 513145516Sdarrenr/* ------------------------------------------------------------------------ */ 514145516Sdarrenrint ipfsync_state(sp, data) 515145516Sdarrenrsynchdr_t *sp; 516145516Sdarrenrvoid *data; 517145516Sdarrenr{ 518145516Sdarrenr synctcp_update_t su; 519145516Sdarrenr ipstate_t *is, sn; 520145516Sdarrenr synclist_t *sl; 521145516Sdarrenr frentry_t *fr; 522145516Sdarrenr u_int hv; 523145516Sdarrenr int err = 0; 524145516Sdarrenr 525145516Sdarrenr hv = sp->sm_num & (SYNC_STATETABSZ - 1); 526145516Sdarrenr 527145516Sdarrenr switch (sp->sm_cmd) 528145516Sdarrenr { 529145516Sdarrenr case SMC_CREATE : 530145516Sdarrenr 531145516Sdarrenr bcopy(data, &sn, sizeof(sn)); 532145516Sdarrenr KMALLOC(is, ipstate_t *); 533145516Sdarrenr if (is == NULL) { 534145516Sdarrenr err = ENOMEM; 535145516Sdarrenr break; 536145516Sdarrenr } 537145516Sdarrenr 538145516Sdarrenr KMALLOC(sl, synclist_t *); 539145516Sdarrenr if (sl == NULL) { 540145516Sdarrenr err = ENOMEM; 541145516Sdarrenr KFREE(is); 542145516Sdarrenr break; 543145516Sdarrenr } 544145516Sdarrenr 545145516Sdarrenr bzero((char *)is, offsetof(ipstate_t, is_die)); 546145516Sdarrenr bcopy((char *)&sn.is_die, (char *)&is->is_die, 547145516Sdarrenr sizeof(*is) - offsetof(ipstate_t, is_die)); 548145516Sdarrenr ipfsync_storder(0, is); 549145516Sdarrenr 550145516Sdarrenr /* 551145516Sdarrenr * We need to find the same rule on the slave as was used on 552145516Sdarrenr * the master to create this state entry. 553145516Sdarrenr */ 554145516Sdarrenr READ_ENTER(&ipf_mutex); 555145516Sdarrenr fr = fr_getrulen(IPL_LOGIPF, sn.is_group, sn.is_rulen); 556145516Sdarrenr if (fr != NULL) { 557145516Sdarrenr MUTEX_ENTER(&fr->fr_lock); 558145516Sdarrenr fr->fr_ref++; 559145516Sdarrenr fr->fr_statecnt++; 560145516Sdarrenr MUTEX_EXIT(&fr->fr_lock); 561145516Sdarrenr } 562145516Sdarrenr RWLOCK_EXIT(&ipf_mutex); 563145516Sdarrenr 564145516Sdarrenr if (ipf_sync_debug > 4) 565145516Sdarrenr printf("[%d] Filter rules = %p\n", sp->sm_num, fr); 566145516Sdarrenr 567145516Sdarrenr is->is_rule = fr; 568145516Sdarrenr is->is_sync = sl; 569145516Sdarrenr 570145516Sdarrenr sl->sl_idx = -1; 571145516Sdarrenr sl->sl_ips = is; 572145516Sdarrenr bcopy(sp, &sl->sl_hdr, sizeof(struct synchdr)); 573145516Sdarrenr 574145516Sdarrenr WRITE_ENTER(&ipf_syncstate); 575145516Sdarrenr WRITE_ENTER(&ipf_state); 576145516Sdarrenr 577145516Sdarrenr sl->sl_pnext = syncstatetab + hv; 578145516Sdarrenr sl->sl_next = syncstatetab[hv]; 579145516Sdarrenr if (syncstatetab[hv] != NULL) 580145516Sdarrenr syncstatetab[hv]->sl_pnext = &sl->sl_next; 581145516Sdarrenr syncstatetab[hv] = sl; 582145516Sdarrenr MUTEX_DOWNGRADE(&ipf_syncstate); 583145516Sdarrenr fr_stinsert(is, sp->sm_rev); 584145516Sdarrenr /* 585145516Sdarrenr * Do not initialise the interface pointers for the state 586145516Sdarrenr * entry as the full complement of interface names may not 587145516Sdarrenr * be present. 588145516Sdarrenr * 589145516Sdarrenr * Put this state entry on its timeout queue. 590145516Sdarrenr */ 591145516Sdarrenr /*fr_setstatequeue(is, sp->sm_rev);*/ 592145516Sdarrenr break; 593145516Sdarrenr 594145516Sdarrenr case SMC_UPDATE : 595145516Sdarrenr bcopy(data, &su, sizeof(su)); 596145516Sdarrenr 597145516Sdarrenr if (ipf_sync_debug > 4) 598145516Sdarrenr printf("[%d] Update age %lu state %d/%d \n", 599145516Sdarrenr sp->sm_num, su.stu_age, su.stu_state[0], 600145516Sdarrenr su.stu_state[1]); 601145516Sdarrenr 602145516Sdarrenr READ_ENTER(&ipf_syncstate); 603145516Sdarrenr for (sl = syncstatetab[hv]; (sl != NULL); sl = sl->sl_next) 604145516Sdarrenr if (sl->sl_hdr.sm_num == sp->sm_num) 605145516Sdarrenr break; 606145516Sdarrenr if (sl == NULL) { 607145516Sdarrenr if (ipf_sync_debug > 1) 608145516Sdarrenr printf("[%d] State not found - can't update\n", 609145516Sdarrenr sp->sm_num); 610145516Sdarrenr RWLOCK_EXIT(&ipf_syncstate); 611145516Sdarrenr err = ENOENT; 612145516Sdarrenr break; 613145516Sdarrenr } 614145516Sdarrenr 615145516Sdarrenr READ_ENTER(&ipf_state); 616145516Sdarrenr 617145516Sdarrenr if (ipf_sync_debug > 6) 618145516Sdarrenr printf("[%d] Data from state v:%d p:%d cmd:%d table:%d rev:%d\n", 619145516Sdarrenr sp->sm_num, sl->sl_hdr.sm_v, sl->sl_hdr.sm_p, 620145516Sdarrenr sl->sl_hdr.sm_cmd, sl->sl_hdr.sm_table, 621145516Sdarrenr sl->sl_hdr.sm_rev); 622145516Sdarrenr 623145516Sdarrenr is = sl->sl_ips; 624145516Sdarrenr 625145516Sdarrenr MUTEX_ENTER(&is->is_lock); 626145516Sdarrenr switch (sp->sm_p) 627145516Sdarrenr { 628145516Sdarrenr case IPPROTO_TCP : 629145516Sdarrenr /* XXX FV --- shouldn't we do ntohl/htonl???? XXX */ 630145516Sdarrenr is->is_send = su.stu_data[0].td_end; 631145516Sdarrenr is->is_maxsend = su.stu_data[0].td_maxend; 632145516Sdarrenr is->is_maxswin = su.stu_data[0].td_maxwin; 633145516Sdarrenr is->is_state[0] = su.stu_state[0]; 634145516Sdarrenr is->is_dend = su.stu_data[1].td_end; 635145516Sdarrenr is->is_maxdend = su.stu_data[1].td_maxend; 636145516Sdarrenr is->is_maxdwin = su.stu_data[1].td_maxwin; 637145516Sdarrenr is->is_state[1] = su.stu_state[1]; 638145516Sdarrenr break; 639145516Sdarrenr default : 640145516Sdarrenr break; 641145516Sdarrenr } 642145516Sdarrenr 643145516Sdarrenr if (ipf_sync_debug > 6) 644145516Sdarrenr printf("[%d] Setting timers for state\n", sp->sm_num); 645145516Sdarrenr 646145516Sdarrenr fr_setstatequeue(is, sp->sm_rev); 647145516Sdarrenr 648145516Sdarrenr MUTEX_EXIT(&is->is_lock); 649145516Sdarrenr break; 650145516Sdarrenr 651145516Sdarrenr default : 652145516Sdarrenr err = EINVAL; 653145516Sdarrenr break; 654145516Sdarrenr } 655145516Sdarrenr 656145516Sdarrenr if (err == 0) { 657145516Sdarrenr RWLOCK_EXIT(&ipf_state); 658145516Sdarrenr RWLOCK_EXIT(&ipf_syncstate); 659145516Sdarrenr } 660145516Sdarrenr 661145516Sdarrenr if (ipf_sync_debug > 6) 662145516Sdarrenr printf("[%d] Update completed with error %d\n", 663145516Sdarrenr sp->sm_num, err); 664145516Sdarrenr 665145516Sdarrenr return err; 666145516Sdarrenr} 667145516Sdarrenr# endif /* _KERNEL */ 668145516Sdarrenr 669145516Sdarrenr 670145516Sdarrenr/* ------------------------------------------------------------------------ */ 671145516Sdarrenr/* Function: ipfsync_del */ 672145516Sdarrenr/* Returns: Nil */ 673145516Sdarrenr/* Parameters: sl(I) - pointer to synclist object to delete */ 674145516Sdarrenr/* */ 675145516Sdarrenr/* Deletes an object from the synclist table and free's its memory. */ 676145516Sdarrenr/* ------------------------------------------------------------------------ */ 677145516Sdarrenrvoid ipfsync_del(sl) 678145516Sdarrenrsynclist_t *sl; 679145516Sdarrenr{ 680145516Sdarrenr WRITE_ENTER(&ipf_syncstate); 681145516Sdarrenr *sl->sl_pnext = sl->sl_next; 682145516Sdarrenr if (sl->sl_next != NULL) 683145516Sdarrenr sl->sl_next->sl_pnext = sl->sl_pnext; 684145516Sdarrenr if (sl->sl_idx != -1) 685145516Sdarrenr syncupd[sl->sl_idx].sup_hdr.sm_sl = NULL; 686145516Sdarrenr RWLOCK_EXIT(&ipf_syncstate); 687145516Sdarrenr KFREE(sl); 688145516Sdarrenr} 689145516Sdarrenr 690145516Sdarrenr 691145516Sdarrenr/* ------------------------------------------------------------------------ */ 692145516Sdarrenr/* Function: ipfsync_nat */ 693145516Sdarrenr/* Returns: int - 0 == success, else error value. */ 694145516Sdarrenr/* Parameters: sp(I) - pointer to sync packet data header */ 695145516Sdarrenr/* uio(I) - pointer to user data for further information */ 696145516Sdarrenr/* */ 697145516Sdarrenr/* Updates the NAT table according to information passed in the sync */ 698145516Sdarrenr/* header. As required, more data is fetched from the uio structure but */ 699145516Sdarrenr/* varies depending on the contents of the sync header. This function can */ 700145516Sdarrenr/* create a new NAT entry or update one. Deletion is left to the NAT */ 701145516Sdarrenr/* structures being timed out correctly. */ 702145516Sdarrenr/* ------------------------------------------------------------------------ */ 703145516Sdarrenrint ipfsync_nat(sp, data) 704145516Sdarrenrsynchdr_t *sp; 705145516Sdarrenrvoid *data; 706145516Sdarrenr{ 707145516Sdarrenr syncupdent_t su; 708145516Sdarrenr nat_t *n, *nat; 709145516Sdarrenr synclist_t *sl; 710145516Sdarrenr u_int hv = 0; 711145516Sdarrenr int err; 712145516Sdarrenr 713145516Sdarrenr READ_ENTER(&ipf_syncstate); 714145516Sdarrenr 715145516Sdarrenr switch (sp->sm_cmd) 716145516Sdarrenr { 717145516Sdarrenr case SMC_CREATE : 718145516Sdarrenr KMALLOC(n, nat_t *); 719145516Sdarrenr if (n == NULL) { 720145516Sdarrenr err = ENOMEM; 721145516Sdarrenr break; 722145516Sdarrenr } 723145516Sdarrenr 724145516Sdarrenr KMALLOC(sl, synclist_t *); 725145516Sdarrenr if (sl == NULL) { 726145516Sdarrenr err = ENOMEM; 727145516Sdarrenr KFREE(n); 728145516Sdarrenr break; 729145516Sdarrenr } 730145516Sdarrenr 731161356Sguido nat = (nat_t *)data; 732145516Sdarrenr bzero((char *)n, offsetof(nat_t, nat_age)); 733145516Sdarrenr bcopy((char *)&nat->nat_age, (char *)&n->nat_age, 734145516Sdarrenr sizeof(*n) - offsetof(nat_t, nat_age)); 735145516Sdarrenr ipfsync_natorder(0, n); 736145516Sdarrenr n->nat_sync = sl; 737145516Sdarrenr 738145516Sdarrenr sl->sl_idx = -1; 739145516Sdarrenr sl->sl_ipn = n; 740145516Sdarrenr sl->sl_num = ntohl(sp->sm_num); 741161356Sguido 742161356Sguido WRITE_ENTER(&ipf_nat); 743145516Sdarrenr sl->sl_pnext = syncstatetab + hv; 744145516Sdarrenr sl->sl_next = syncstatetab[hv]; 745145516Sdarrenr if (syncstatetab[hv] != NULL) 746145516Sdarrenr syncstatetab[hv]->sl_pnext = &sl->sl_next; 747145516Sdarrenr syncstatetab[hv] = sl; 748145516Sdarrenr nat_insert(n, sl->sl_rev); 749145516Sdarrenr RWLOCK_EXIT(&ipf_nat); 750145516Sdarrenr break; 751145516Sdarrenr 752145516Sdarrenr case SMC_UPDATE : 753145516Sdarrenr bcopy(data, &su, sizeof(su)); 754145516Sdarrenr 755145516Sdarrenr READ_ENTER(&ipf_syncstate); 756145516Sdarrenr for (sl = syncstatetab[hv]; (sl != NULL); sl = sl->sl_next) 757145516Sdarrenr if (sl->sl_hdr.sm_num == sp->sm_num) 758145516Sdarrenr break; 759145516Sdarrenr if (sl == NULL) { 760145516Sdarrenr err = ENOENT; 761145516Sdarrenr break; 762145516Sdarrenr } 763145516Sdarrenr 764145516Sdarrenr READ_ENTER(&ipf_nat); 765145516Sdarrenr 766145516Sdarrenr nat = sl->sl_ipn; 767145516Sdarrenr 768145516Sdarrenr MUTEX_ENTER(&nat->nat_lock); 769145516Sdarrenr fr_setnatqueue(nat, sl->sl_rev); 770145516Sdarrenr MUTEX_EXIT(&nat->nat_lock); 771145516Sdarrenr 772145516Sdarrenr RWLOCK_EXIT(&ipf_nat); 773145516Sdarrenr 774145516Sdarrenr break; 775145516Sdarrenr 776145516Sdarrenr default : 777145516Sdarrenr err = EINVAL; 778145516Sdarrenr break; 779145516Sdarrenr } 780145516Sdarrenr 781145516Sdarrenr RWLOCK_EXIT(&ipf_syncstate); 782145516Sdarrenr return 0; 783145516Sdarrenr} 784145516Sdarrenr 785145516Sdarrenr 786145516Sdarrenr/* ------------------------------------------------------------------------ */ 787145516Sdarrenr/* Function: ipfsync_new */ 788145516Sdarrenr/* Returns: synclist_t* - NULL == failure, else pointer to new synclist */ 789145516Sdarrenr/* data structure. */ 790145516Sdarrenr/* Parameters: tab(I) - type of synclist_t to create */ 791145516Sdarrenr/* fin(I) - pointer to packet information */ 792145516Sdarrenr/* ptr(I) - pointer to owning object */ 793145516Sdarrenr/* */ 794145516Sdarrenr/* Creates a new sync table entry and notifies any sleepers that it's there */ 795145516Sdarrenr/* waiting to be processed. */ 796145516Sdarrenr/* ------------------------------------------------------------------------ */ 797145516Sdarrenrsynclist_t *ipfsync_new(tab, fin, ptr) 798145516Sdarrenrint tab; 799145516Sdarrenrfr_info_t *fin; 800145516Sdarrenrvoid *ptr; 801145516Sdarrenr{ 802145516Sdarrenr synclist_t *sl, *ss; 803145516Sdarrenr synclogent_t *sle; 804145516Sdarrenr u_int hv, sz; 805145516Sdarrenr 806145516Sdarrenr if (sl_idx == SYNCLOG_SZ) 807145516Sdarrenr return NULL; 808145516Sdarrenr KMALLOC(sl, synclist_t *); 809145516Sdarrenr if (sl == NULL) 810145516Sdarrenr return NULL; 811145516Sdarrenr 812145516Sdarrenr MUTEX_ENTER(&ipf_syncadd); 813145516Sdarrenr /* 814145516Sdarrenr * Get a unique number for this synclist_t. The number is only meant 815145516Sdarrenr * to be unique for the lifetime of the structure and may be reused 816145516Sdarrenr * later. 817145516Sdarrenr */ 818145516Sdarrenr ipf_syncnum++; 819145516Sdarrenr if (ipf_syncnum == 0) { 820145516Sdarrenr ipf_syncnum = 1; 821145516Sdarrenr ipf_syncwrap = 1; 822145516Sdarrenr } 823145516Sdarrenr 824145516Sdarrenr hv = ipf_syncnum & (SYNC_STATETABSZ - 1); 825145516Sdarrenr while (ipf_syncwrap != 0) { 826145516Sdarrenr for (ss = syncstatetab[hv]; ss; ss = ss->sl_next) 827145516Sdarrenr if (ss->sl_hdr.sm_num == ipf_syncnum) 828145516Sdarrenr break; 829145516Sdarrenr if (ss == NULL) 830145516Sdarrenr break; 831145516Sdarrenr ipf_syncnum++; 832145516Sdarrenr hv = ipf_syncnum & (SYNC_STATETABSZ - 1); 833145516Sdarrenr } 834145516Sdarrenr /* 835145516Sdarrenr * Use the synch number of the object as the hash key. Should end up 836145516Sdarrenr * with relatively even distribution over time. 837145516Sdarrenr * XXX - an attacker could lunch an DoS attack, of sorts, if they are 838145516Sdarrenr * the only one causing new table entries by only keeping open every 839145516Sdarrenr * nth connection they make, where n is a value in the interval 840145516Sdarrenr * [0, SYNC_STATETABSZ-1]. 841145516Sdarrenr */ 842145516Sdarrenr sl->sl_pnext = syncstatetab + hv; 843145516Sdarrenr sl->sl_next = syncstatetab[hv]; 844145516Sdarrenr syncstatetab[hv] = sl; 845145516Sdarrenr sl->sl_num = ipf_syncnum; 846145516Sdarrenr MUTEX_EXIT(&ipf_syncadd); 847145516Sdarrenr 848145516Sdarrenr sl->sl_magic = htonl(SYNHDRMAGIC); 849145516Sdarrenr sl->sl_v = fin->fin_v; 850145516Sdarrenr sl->sl_p = fin->fin_p; 851145516Sdarrenr sl->sl_cmd = SMC_CREATE; 852145516Sdarrenr sl->sl_idx = -1; 853145516Sdarrenr sl->sl_table = tab; 854145516Sdarrenr sl->sl_rev = fin->fin_rev; 855145516Sdarrenr if (tab == SMC_STATE) { 856145516Sdarrenr sl->sl_ips = ptr; 857145516Sdarrenr sz = sizeof(*sl->sl_ips); 858145516Sdarrenr } else if (tab == SMC_NAT) { 859145516Sdarrenr sl->sl_ipn = ptr; 860145516Sdarrenr sz = sizeof(*sl->sl_ipn); 861145516Sdarrenr } else { 862145516Sdarrenr ptr = NULL; 863145516Sdarrenr sz = 0; 864145516Sdarrenr } 865145516Sdarrenr sl->sl_len = sz; 866145516Sdarrenr 867145516Sdarrenr /* 868145516Sdarrenr * Create the log entry to be read by a user daemon. When it has been 869145516Sdarrenr * finished and put on the queue, send a signal to wakeup any waiters. 870145516Sdarrenr */ 871145516Sdarrenr MUTEX_ENTER(&ipf_syncadd); 872145516Sdarrenr sle = synclog + sl_idx++; 873145516Sdarrenr bcopy((char *)&sl->sl_hdr, (char *)&sle->sle_hdr, 874145516Sdarrenr sizeof(sle->sle_hdr)); 875145516Sdarrenr sle->sle_hdr.sm_num = htonl(sle->sle_hdr.sm_num); 876145516Sdarrenr sle->sle_hdr.sm_len = htonl(sle->sle_hdr.sm_len); 877145516Sdarrenr if (ptr != NULL) { 878145516Sdarrenr bcopy((char *)ptr, (char *)&sle->sle_un, sz); 879145516Sdarrenr if (tab == SMC_STATE) { 880145516Sdarrenr ipfsync_storder(1, &sle->sle_un.sleu_ips); 881145516Sdarrenr } else if (tab == SMC_NAT) { 882145516Sdarrenr ipfsync_natorder(1, &sle->sle_un.sleu_ipn); 883145516Sdarrenr } 884145516Sdarrenr } 885145516Sdarrenr MUTEX_EXIT(&ipf_syncadd); 886145516Sdarrenr 887145516Sdarrenr MUTEX_ENTER(&ipsl_mutex); 888145516Sdarrenr# if SOLARIS 889145516Sdarrenr# ifdef _KERNEL 890145516Sdarrenr cv_signal(&ipslwait); 891145516Sdarrenr# endif 892145516Sdarrenr MUTEX_EXIT(&ipsl_mutex); 893145516Sdarrenr# else 894145516Sdarrenr MUTEX_EXIT(&ipsl_mutex); 895145516Sdarrenr# ifdef _KERNEL 896145516Sdarrenr wakeup(&sl_tail); 897145516Sdarrenr# endif 898145516Sdarrenr# endif 899145516Sdarrenr return sl; 900145516Sdarrenr} 901145516Sdarrenr 902145516Sdarrenr 903145516Sdarrenr/* ------------------------------------------------------------------------ */ 904145516Sdarrenr/* Function: ipfsync_update */ 905145516Sdarrenr/* Returns: Nil */ 906145516Sdarrenr/* Parameters: tab(I) - type of synclist_t to create */ 907145516Sdarrenr/* fin(I) - pointer to packet information */ 908145516Sdarrenr/* sl(I) - pointer to synchronisation object */ 909145516Sdarrenr/* */ 910145516Sdarrenr/* For outbound packets, only, create an sync update record for the user */ 911145516Sdarrenr/* process to read. */ 912145516Sdarrenr/* ------------------------------------------------------------------------ */ 913145516Sdarrenrvoid ipfsync_update(tab, fin, sl) 914145516Sdarrenrint tab; 915145516Sdarrenrfr_info_t *fin; 916145516Sdarrenrsynclist_t *sl; 917145516Sdarrenr{ 918145516Sdarrenr synctcp_update_t *st; 919145516Sdarrenr syncupdent_t *slu; 920145516Sdarrenr ipstate_t *ips; 921145516Sdarrenr nat_t *nat; 922145516Sdarrenr 923145516Sdarrenr if (fin->fin_out == 0 || sl == NULL) 924145516Sdarrenr return; 925145516Sdarrenr 926145516Sdarrenr WRITE_ENTER(&ipf_syncstate); 927145516Sdarrenr MUTEX_ENTER(&ipf_syncadd); 928145516Sdarrenr if (sl->sl_idx == -1) { 929145516Sdarrenr slu = syncupd + su_idx; 930145516Sdarrenr sl->sl_idx = su_idx++; 931145516Sdarrenr bcopy((char *)&sl->sl_hdr, (char *)&slu->sup_hdr, 932145516Sdarrenr sizeof(slu->sup_hdr)); 933145516Sdarrenr slu->sup_hdr.sm_magic = htonl(SYNHDRMAGIC); 934145516Sdarrenr slu->sup_hdr.sm_sl = sl; 935145516Sdarrenr slu->sup_hdr.sm_cmd = SMC_UPDATE; 936145516Sdarrenr slu->sup_hdr.sm_table = tab; 937145516Sdarrenr slu->sup_hdr.sm_num = htonl(sl->sl_num); 938145516Sdarrenr slu->sup_hdr.sm_len = htonl(sizeof(struct synctcp_update)); 939145516Sdarrenr slu->sup_hdr.sm_rev = fin->fin_rev; 940145516Sdarrenr# if 0 941145516Sdarrenr if (fin->fin_p == IPPROTO_TCP) { 942145516Sdarrenr st->stu_len[0] = 0; 943145516Sdarrenr st->stu_len[1] = 0; 944145516Sdarrenr } 945145516Sdarrenr# endif 946145516Sdarrenr } else 947145516Sdarrenr slu = syncupd + sl->sl_idx; 948145516Sdarrenr MUTEX_EXIT(&ipf_syncadd); 949145516Sdarrenr MUTEX_DOWNGRADE(&ipf_syncstate); 950145516Sdarrenr 951145516Sdarrenr /* 952145516Sdarrenr * Only TCP has complex timeouts, others just use default timeouts. 953145516Sdarrenr * For TCP, we only need to track the connection state and window. 954145516Sdarrenr */ 955145516Sdarrenr if (fin->fin_p == IPPROTO_TCP) { 956145516Sdarrenr st = &slu->sup_tcp; 957145516Sdarrenr if (tab == SMC_STATE) { 958145516Sdarrenr ips = sl->sl_ips; 959145516Sdarrenr st->stu_age = htonl(ips->is_die); 960145516Sdarrenr st->stu_data[0].td_end = ips->is_send; 961145516Sdarrenr st->stu_data[0].td_maxend = ips->is_maxsend; 962145516Sdarrenr st->stu_data[0].td_maxwin = ips->is_maxswin; 963145516Sdarrenr st->stu_state[0] = ips->is_state[0]; 964145516Sdarrenr st->stu_data[1].td_end = ips->is_dend; 965145516Sdarrenr st->stu_data[1].td_maxend = ips->is_maxdend; 966145516Sdarrenr st->stu_data[1].td_maxwin = ips->is_maxdwin; 967145516Sdarrenr st->stu_state[1] = ips->is_state[1]; 968145516Sdarrenr } else if (tab == SMC_NAT) { 969145516Sdarrenr nat = sl->sl_ipn; 970145516Sdarrenr st->stu_age = htonl(nat->nat_age); 971145516Sdarrenr } 972145516Sdarrenr } 973145516Sdarrenr RWLOCK_EXIT(&ipf_syncstate); 974145516Sdarrenr 975145516Sdarrenr MUTEX_ENTER(&ipsl_mutex); 976145516Sdarrenr# if SOLARIS 977145516Sdarrenr# ifdef _KERNEL 978145516Sdarrenr cv_signal(&ipslwait); 979145516Sdarrenr# endif 980145516Sdarrenr MUTEX_EXIT(&ipsl_mutex); 981145516Sdarrenr# else 982145516Sdarrenr MUTEX_EXIT(&ipsl_mutex); 983145516Sdarrenr# ifdef _KERNEL 984145516Sdarrenr wakeup(&sl_tail); 985145516Sdarrenr# endif 986145516Sdarrenr# endif 987145516Sdarrenr} 988145516Sdarrenr 989145516Sdarrenr 990145516Sdarrenr/* ------------------------------------------------------------------------ */ 991145516Sdarrenr/* Function: fr_sync_ioctl */ 992145516Sdarrenr/* Returns: int - 0 == success, != 0 == failure */ 993145516Sdarrenr/* Parameters: data(I) - pointer to ioctl data */ 994145516Sdarrenr/* cmd(I) - ioctl command integer */ 995145516Sdarrenr/* mode(I) - file mode bits used with open */ 996145516Sdarrenr/* */ 997145516Sdarrenr/* This function currently does not handle any ioctls and so just returns */ 998145516Sdarrenr/* EINVAL on all occasions. */ 999145516Sdarrenr/* ------------------------------------------------------------------------ */ 1000170268Sdarrenrint fr_sync_ioctl(data, cmd, mode, uid, ctx) 1001145516Sdarrenrcaddr_t data; 1002145516Sdarrenrioctlcmd_t cmd; 1003170268Sdarrenrint mode, uid; 1004170268Sdarrenrvoid *ctx; 1005145516Sdarrenr{ 1006145516Sdarrenr return EINVAL; 1007145516Sdarrenr} 1008161356Sguido 1009161356Sguido 1010161356Sguidoint ipfsync_canread() 1011161356Sguido{ 1012161356Sguido return !((sl_tail == sl_idx) && (su_tail == su_idx)); 1013161356Sguido} 1014161356Sguido 1015161356Sguido 1016161356Sguidoint ipfsync_canwrite() 1017161356Sguido{ 1018161356Sguido return 1; 1019161356Sguido} 1020145516Sdarrenr#endif /* IPFILTER_SYNC */ 1021