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