1 2/* 3* Copyright (C) 2012 by Darren Reed. 4* 5* Redistribution and use in source and binary forms are permitted 6* provided that this notice is preserved and due credit is given 7* to the original author and the contributors. 8*/ 9 10#include <sys/param.h> 11#include <sys/types.h> 12#include <sys/time.h> 13#include <sys/socket.h> 14#if defined(__FreeBSD__) 15# if defined(_KERNEL) 16# include <sys/libkern.h> 17# else 18# include <sys/unistd.h> 19# endif 20#else 21# include <sys/systm.h> 22#endif 23#include <sys/errno.h> 24#include <sys/param.h> 25#if !defined(__SVR4) 26# include <sys/mbuf.h> 27#endif 28#if defined(__FreeBSD__) 29# include <sys/sockio.h> 30#if defined(_KERNEL) 31#include <net/vnet.h> 32#else 33#define CURVNET_SET(arg) 34#define CURVNET_RESTORE() 35#define VNET_DEFINE(_t, _v) _t _v 36#define VNET_DECLARE(_t, _v) extern _t _v 37#define VNET(arg) arg 38#endif 39#else 40# include <sys/ioctl.h> 41#endif /* FreeBSD */ 42#include <net/if.h> 43#include <netinet/in.h> 44#include <netinet/in_systm.h> 45#include <netinet/ip.h> 46#include <netinet/tcp.h> 47#include "netinet/ip_compat.h" 48#include "netinet/ip_fil.h" 49 50#include "netinet/ip_rules.h" 51 52#ifndef _KERNEL 53# include <string.h> 54#endif /* _KERNEL */ 55 56#ifdef IPFILTER_COMPILED 57 58VNET_DECLARE(ipf_main_softc_t, ipfmain); 59#define V_ipfmain VNET(ipfmain) 60 61 62static u_long in_rule__0[] = { 630, 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 64}; 65 66static u_long out_rule__0[] = { 670, 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 68}; 69 70frentry_t *ipf_rules_in_[1] = { 71 (frentry_t *)&in_rule__0 72}; 73 74/* XXX This file (ip_rules.c) is not part of the ipfilter tarball, it is 75 XXX generated by the ipfilter build process. Unfortunately the build 76 XXX process did not generate the following lines so they are added 77 XXX by hand here. This is a bit of a hack but it works for now. Future 78 XXX imports/merges of ipfilter may generate this so the following will 79 XXX need to be removed following some future merge. 80 XXX */ 81frentry_t *ipf_rules_out_[1] = { 82 (frentry_t *)&out_rule__0 83}; 84 85frentry_t *ipfrule_match_in_(fin, passp) 86fr_info_t *fin; 87u_32_t *passp; 88{ 89 frentry_t *fr = NULL; 90 91 fr = (frentry_t *)&in_rule__0; 92 return (fr); 93} 94 95frentry_t *ipfrule_match_out_(fin, passp) 96fr_info_t *fin; 97u_32_t *passp; 98{ 99 frentry_t *fr = NULL; 100 101 fr = (frentry_t *)&out_rule__0; 102 return (fr); 103} 104static frentry_t ipfrule_out_; 105 106int ipfrule_add_out_(void) 107{ 108 int i, j, err = 0, max; 109 frentry_t *fp; 110 111 max = sizeof(ipf_rules_out_)/sizeof(frentry_t *); 112 for (i = 0; i < max; i++) { 113 fp = ipf_rules_out_[i]; 114 fp->fr_next = NULL; 115 for (j = i + 1; j < max; j++) 116 if (strncmp(fp->fr_names + fp->fr_group, 117 ipf_rules_out_[j]->fr_names + 118 ipf_rules_out_[j]->fr_group, 119 FR_GROUPLEN) == 0) { 120 if (ipf_rules_out_[j] != NULL) 121 ipf_rules_out_[j]->fr_pnext = 122 &fp->fr_next; 123 fp->fr_pnext = &ipf_rules_out_[j]; 124 fp->fr_next = ipf_rules_out_[j]; 125 break; 126 } 127 } 128 129 fp = &ipfrule_out_; 130 bzero((char *)fp, sizeof(*fp)); 131 fp->fr_type = FR_T_CALLFUNC_BUILTIN; 132 fp->fr_flags = FR_OUTQUE|FR_NOMATCH; 133 fp->fr_data = (void *)ipf_rules_out_[0]; 134 fp->fr_dsize = sizeof(ipf_rules_out_[0]); 135 fp->fr_family = AF_INET; 136 fp->fr_func = (ipfunc_t)ipfrule_match_out_; 137 err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, 138 V_ipfmain.ipf_active, 0); 139 return (err); 140} 141 142 143int ipfrule_remove_out_(void) 144{ 145 int err = 0, i; 146 frentry_t *fp; 147 148 /* 149 * Try to remove the outbound rule. 150 */ 151 if (ipfrule_out_.fr_ref > 0) { 152 err = EBUSY; 153 } else { 154 i = sizeof(ipf_rules_out_)/sizeof(frentry_t *) - 1; 155 for (; i >= 0; i--) { 156 fp = ipf_rules_out_[i]; 157 if (fp->fr_ref > 1) { 158 err = EBUSY; 159 break; 160 } 161 } 162 } 163 if (err == 0) 164 err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR, 165 (caddr_t)&ipfrule_out_, 166 V_ipfmain.ipf_active, 0); 167 if (err) 168 return (err); 169 170 171 return (err); 172} 173static frentry_t ipfrule_in_; 174 175int ipfrule_add_in_(void) 176{ 177 int i, j, err = 0, max; 178 frentry_t *fp; 179 180 max = sizeof(ipf_rules_in_)/sizeof(frentry_t *); 181 for (i = 0; i < max; i++) { 182 fp = ipf_rules_in_[i]; 183 fp->fr_next = NULL; 184 for (j = i + 1; j < max; j++) 185 if (strncmp(fp->fr_names + fp->fr_group, 186 ipf_rules_in_[j]->fr_names + 187 ipf_rules_in_[j]->fr_group, 188 FR_GROUPLEN) == 0) { 189 if (ipf_rules_in_[j] != NULL) 190 ipf_rules_in_[j]->fr_pnext = 191 &fp->fr_next; 192 fp->fr_pnext = &ipf_rules_in_[j]; 193 fp->fr_next = ipf_rules_in_[j]; 194 break; 195 } 196 } 197 198 fp = &ipfrule_in_; 199 bzero((char *)fp, sizeof(*fp)); 200 fp->fr_type = FR_T_CALLFUNC_BUILTIN; 201 fp->fr_flags = FR_INQUE|FR_NOMATCH; 202 fp->fr_data = (void *)ipf_rules_in_[0]; 203 fp->fr_dsize = sizeof(ipf_rules_in_[0]); 204 fp->fr_family = AF_INET; 205 fp->fr_func = (ipfunc_t)ipfrule_match_in_; 206 err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, 207 V_ipfmain.ipf_active, 0); 208 return (err); 209} 210 211 212int ipfrule_remove_in_(void) 213{ 214 int err = 0, i; 215 frentry_t *fp; 216 217 /* 218 * Try to remove the inbound rule. 219 */ 220 if (ipfrule_in_.fr_ref > 0) { 221 err = EBUSY; 222 } else { 223 i = sizeof(ipf_rules_in_)/sizeof(frentry_t *) - 1; 224 for (; i >= 0; i--) { 225 fp = ipf_rules_in_[i]; 226 if (fp->fr_ref > 1) { 227 err = EBUSY; 228 break; 229 } 230 } 231 } 232 if (err == 0) 233 err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR, 234 (caddr_t)&ipfrule_in_, 235 V_ipfmain.ipf_active, 0); 236 if (err) 237 return (err); 238 239 240 return (err); 241} 242 243int ipfrule_add(void) 244{ 245 int err; 246 247 err = ipfrule_add_out_(); 248 if (err != 0) 249 return (err); 250 err = ipfrule_add_in_(); 251 if (err != 0) 252 return (err); 253 return (0); 254} 255 256 257int ipfrule_remove(void) 258{ 259 int err; 260 261 err = ipfrule_remove_out_(); 262 if (err != 0) 263 return (err); 264 err = ipfrule_remove_in_(); 265 if (err != 0) 266 return (err); 267 return (0); 268} 269#endif /* IPFILTER_COMPILED */ 270