1145516Sdarrenr/* $FreeBSD$ */ 2145516Sdarrenr 3145516Sdarrenr/* 4255332Scy* Copyright (C) 2012 by Darren Reed. 5145516Sdarrenr* 6145516Sdarrenr* Redistribution and use in source and binary forms are permitted 7145516Sdarrenr* provided that this notice is preserved and due credit is given 8145516Sdarrenr* to the original author and the contributors. 9145516Sdarrenr*/ 10145516Sdarrenr 11255332Scy#include <sys/param.h> 12145516Sdarrenr#include <sys/types.h> 13145516Sdarrenr#include <sys/time.h> 14145516Sdarrenr#include <sys/socket.h> 15255332Scy#if defined(__FreeBSD_version) && (__FreeBSD_version >= 40000) 16255332Scy# if defined(_KERNEL) 17255332Scy# include <sys/libkern.h> 18255332Scy# else 19255332Scy# include <sys/unistd.h> 20255332Scy# endif 21145516Sdarrenr#endif 22255332Scy#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 399000000) 23255332Scy#else 24255332Scy# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi) 25255332Scy# include <sys/systm.h> 26255332Scy# endif 27255332Scy#endif 28145516Sdarrenr#include <sys/errno.h> 29145516Sdarrenr#include <sys/param.h> 30145516Sdarrenr#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux) 31145516Sdarrenr# include <sys/mbuf.h> 32145516Sdarrenr#endif 33145516Sdarrenr#if defined(__FreeBSD__) && (__FreeBSD_version > 220000) 34145516Sdarrenr# include <sys/sockio.h> 35145516Sdarrenr#else 36145516Sdarrenr# include <sys/ioctl.h> 37145516Sdarrenr#endif /* FreeBSD */ 38145516Sdarrenr#include <net/if.h> 39145516Sdarrenr#include <netinet/in.h> 40145516Sdarrenr#include <netinet/in_systm.h> 41145516Sdarrenr#include <netinet/ip.h> 42145516Sdarrenr#include <netinet/tcp.h> 43145516Sdarrenr#include "netinet/ip_compat.h" 44145516Sdarrenr#include "netinet/ip_fil.h" 45145516Sdarrenr 46145516Sdarrenr#include "netinet/ip_rules.h" 47145516Sdarrenr 48145516Sdarrenr#ifndef _KERNEL 49145516Sdarrenr# include <string.h> 50145516Sdarrenr#endif /* _KERNEL */ 51145516Sdarrenr 52145516Sdarrenr#ifdef IPFILTER_COMPILED 53145516Sdarrenr 54255332Scyextern ipf_main_softc_t ipfmain; 55255332Scy 56255332Scy 57145516Sdarrenrstatic u_long in_rule__0[] = { 58255332Scy0, 0, 0, 0, 0, 0, 0, 0x8070d88, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0x1b0, 0x1, 0, 0, 0, 0x2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40000000, 0x8002, 0, 0, 0, 0xffff, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0 59145516Sdarrenr}; 60145516Sdarrenr 61145516Sdarrenrstatic u_long out_rule__0[] = { 62255332Scy0, 0, 0, 0, 0, 0, 0, 0x8070d88, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0x1b0, 0x1, 0, 0, 0, 0x3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40000000, 0x4002, 0, 0, 0, 0xffff, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0 63145516Sdarrenr}; 64145516Sdarrenr 65145516Sdarrenrfrentry_t *ipf_rules_in_[1] = { 66145516Sdarrenr (frentry_t *)&in_rule__0 67145516Sdarrenr}; 68145516Sdarrenr 69255332Scy/* XXX This file (ip_rules.c) is not part of the ipfilter tarball, it is 70255332Scy XXX generated by the ipfilter build process. Unfortunately the build 71255332Scy XXX process did not generate the following lines so they are added 72255332Scy XXX by hand here. This is a bit of a hack but it works for now. Future 73255332Scy XXX imports/merges of ipfilter may generate this so the following will 74255332Scy XXX need to be removed following some future merge. 75255332Scy XXX */ 76255332Scyfrentry_t *ipf_rules_out_[1] = { 77255332Scy (frentry_t *)&out_rule__0 78255332Scy}; 79255332Scy 80145516Sdarrenrfrentry_t *ipfrule_match_in_(fin, passp) 81145516Sdarrenrfr_info_t *fin; 82145516Sdarrenru_32_t *passp; 83145516Sdarrenr{ 84145516Sdarrenr frentry_t *fr = NULL; 85145516Sdarrenr 86145516Sdarrenr fr = (frentry_t *)&in_rule__0; 87145516Sdarrenr return fr; 88145516Sdarrenr} 89145516Sdarrenr 90145516Sdarrenrfrentry_t *ipfrule_match_out_(fin, passp) 91145516Sdarrenrfr_info_t *fin; 92145516Sdarrenru_32_t *passp; 93145516Sdarrenr{ 94145516Sdarrenr frentry_t *fr = NULL; 95145516Sdarrenr 96145516Sdarrenr fr = (frentry_t *)&out_rule__0; 97145516Sdarrenr return fr; 98145516Sdarrenr} 99145516Sdarrenrstatic frentry_t ipfrule_out_; 100145516Sdarrenr 101145516Sdarrenrint ipfrule_add_out_() 102145516Sdarrenr{ 103145516Sdarrenr int i, j, err = 0, max; 104145516Sdarrenr frentry_t *fp; 105145516Sdarrenr 106145516Sdarrenr max = sizeof(ipf_rules_out_)/sizeof(frentry_t *); 107145516Sdarrenr for (i = 0; i < max; i++) { 108145516Sdarrenr fp = ipf_rules_out_[i]; 109145516Sdarrenr fp->fr_next = NULL; 110145516Sdarrenr for (j = i + 1; j < max; j++) 111255332Scy if (strncmp(fp->fr_names + fp->fr_group, 112255332Scy ipf_rules_out_[j]->fr_names + 113145516Sdarrenr ipf_rules_out_[j]->fr_group, 114145516Sdarrenr FR_GROUPLEN) == 0) { 115255332Scy if (ipf_rules_out_[j] != NULL) 116255332Scy ipf_rules_out_[j]->fr_pnext = 117255332Scy &fp->fr_next; 118255332Scy fp->fr_pnext = &ipf_rules_out_[j]; 119145516Sdarrenr fp->fr_next = ipf_rules_out_[j]; 120145516Sdarrenr break; 121145516Sdarrenr } 122145516Sdarrenr } 123145516Sdarrenr 124145516Sdarrenr fp = &ipfrule_out_; 125145516Sdarrenr bzero((char *)fp, sizeof(*fp)); 126255332Scy fp->fr_type = FR_T_CALLFUNC_BUILTIN; 127145516Sdarrenr fp->fr_flags = FR_OUTQUE|FR_NOMATCH; 128145516Sdarrenr fp->fr_data = (void *)ipf_rules_out_[0]; 129145516Sdarrenr fp->fr_dsize = sizeof(ipf_rules_out_[0]); 130255332Scy fp->fr_family = AF_INET; 131145516Sdarrenr fp->fr_func = (ipfunc_t)ipfrule_match_out_; 132255332Scy err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, 133255332Scy ipfmain.ipf_active, 0); 134145516Sdarrenr return err; 135145516Sdarrenr} 136145516Sdarrenr 137145516Sdarrenr 138145516Sdarrenrint ipfrule_remove_out_() 139145516Sdarrenr{ 140145516Sdarrenr int err = 0, i; 141145516Sdarrenr frentry_t *fp; 142145516Sdarrenr 143145516Sdarrenr /* 144145516Sdarrenr * Try to remove the outbound rule. 145145516Sdarrenr */ 146145516Sdarrenr if (ipfrule_out_.fr_ref > 0) { 147145516Sdarrenr err = EBUSY; 148145516Sdarrenr } else { 149145516Sdarrenr i = sizeof(ipf_rules_out_)/sizeof(frentry_t *) - 1; 150145516Sdarrenr for (; i >= 0; i--) { 151145516Sdarrenr fp = ipf_rules_out_[i]; 152145516Sdarrenr if (fp->fr_ref > 1) { 153145516Sdarrenr err = EBUSY; 154145516Sdarrenr break; 155145516Sdarrenr } 156145516Sdarrenr } 157145516Sdarrenr } 158145516Sdarrenr if (err == 0) 159255332Scy err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR, 160255332Scy (caddr_t)&ipfrule_out_, 161255332Scy ipfmain.ipf_active, 0); 162145516Sdarrenr if (err) 163145516Sdarrenr return err; 164145516Sdarrenr 165145516Sdarrenr 166145516Sdarrenr return err; 167145516Sdarrenr} 168145516Sdarrenrstatic frentry_t ipfrule_in_; 169145516Sdarrenr 170145516Sdarrenrint ipfrule_add_in_() 171145516Sdarrenr{ 172145516Sdarrenr int i, j, err = 0, max; 173145516Sdarrenr frentry_t *fp; 174145516Sdarrenr 175145516Sdarrenr max = sizeof(ipf_rules_in_)/sizeof(frentry_t *); 176145516Sdarrenr for (i = 0; i < max; i++) { 177145516Sdarrenr fp = ipf_rules_in_[i]; 178145516Sdarrenr fp->fr_next = NULL; 179145516Sdarrenr for (j = i + 1; j < max; j++) 180255332Scy if (strncmp(fp->fr_names + fp->fr_group, 181255332Scy ipf_rules_in_[j]->fr_names + 182145516Sdarrenr ipf_rules_in_[j]->fr_group, 183145516Sdarrenr FR_GROUPLEN) == 0) { 184255332Scy if (ipf_rules_in_[j] != NULL) 185255332Scy ipf_rules_in_[j]->fr_pnext = 186255332Scy &fp->fr_next; 187255332Scy fp->fr_pnext = &ipf_rules_in_[j]; 188145516Sdarrenr fp->fr_next = ipf_rules_in_[j]; 189145516Sdarrenr break; 190145516Sdarrenr } 191145516Sdarrenr } 192145516Sdarrenr 193145516Sdarrenr fp = &ipfrule_in_; 194145516Sdarrenr bzero((char *)fp, sizeof(*fp)); 195255332Scy fp->fr_type = FR_T_CALLFUNC_BUILTIN; 196145516Sdarrenr fp->fr_flags = FR_INQUE|FR_NOMATCH; 197145516Sdarrenr fp->fr_data = (void *)ipf_rules_in_[0]; 198145516Sdarrenr fp->fr_dsize = sizeof(ipf_rules_in_[0]); 199255332Scy fp->fr_family = AF_INET; 200145516Sdarrenr fp->fr_func = (ipfunc_t)ipfrule_match_in_; 201255332Scy err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, 202255332Scy ipfmain.ipf_active, 0); 203145516Sdarrenr return err; 204145516Sdarrenr} 205145516Sdarrenr 206145516Sdarrenr 207145516Sdarrenrint ipfrule_remove_in_() 208145516Sdarrenr{ 209145516Sdarrenr int err = 0, i; 210145516Sdarrenr frentry_t *fp; 211145516Sdarrenr 212145516Sdarrenr /* 213145516Sdarrenr * Try to remove the inbound rule. 214145516Sdarrenr */ 215145516Sdarrenr if (ipfrule_in_.fr_ref > 0) { 216145516Sdarrenr err = EBUSY; 217145516Sdarrenr } else { 218145516Sdarrenr i = sizeof(ipf_rules_in_)/sizeof(frentry_t *) - 1; 219145516Sdarrenr for (; i >= 0; i--) { 220145516Sdarrenr fp = ipf_rules_in_[i]; 221145516Sdarrenr if (fp->fr_ref > 1) { 222145516Sdarrenr err = EBUSY; 223145516Sdarrenr break; 224145516Sdarrenr } 225145516Sdarrenr } 226145516Sdarrenr } 227145516Sdarrenr if (err == 0) 228255332Scy err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR, 229255332Scy (caddr_t)&ipfrule_in_, 230255332Scy ipfmain.ipf_active, 0); 231145516Sdarrenr if (err) 232145516Sdarrenr return err; 233145516Sdarrenr 234145516Sdarrenr 235145516Sdarrenr return err; 236145516Sdarrenr} 237145516Sdarrenr 238145516Sdarrenrint ipfrule_add() 239145516Sdarrenr{ 240145516Sdarrenr int err; 241145516Sdarrenr 242145516Sdarrenr err = ipfrule_add_out_(); 243145516Sdarrenr if (err != 0) 244145516Sdarrenr return err; 245145516Sdarrenr err = ipfrule_add_in_(); 246145516Sdarrenr if (err != 0) 247145516Sdarrenr return err; 248145516Sdarrenr return 0; 249145516Sdarrenr} 250145516Sdarrenr 251145516Sdarrenr 252145516Sdarrenrint ipfrule_remove() 253145516Sdarrenr{ 254145516Sdarrenr int err; 255145516Sdarrenr 256145516Sdarrenr err = ipfrule_remove_out_(); 257145516Sdarrenr if (err != 0) 258145516Sdarrenr return err; 259145516Sdarrenr err = ipfrule_remove_in_(); 260145516Sdarrenr if (err != 0) 261145516Sdarrenr return err; 262145516Sdarrenr return 0; 263145516Sdarrenr} 264145516Sdarrenr#endif /* IPFILTER_COMPILED */ 265