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