2 3/* 4 * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <syslog.h> 20 21#include <sys/ioctl.h> 22#include <sys/types.h> 23#include <sys/socket.h> 24 25#include <net/if.h> 26#include <net/pfvar.h> 27#include <netinet/in.h> 28#include <netinet/tcp.h> 29#include <arpa/inet.h> 30 31#include <err.h> 32#include <errno.h> 33#include <fcntl.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37#include <unistd.h> 38 39#include "filter.h" 40 41/* From netinet/in.h, but only _KERNEL_ gets them. */ 42#define satosin(sa) ((struct sockaddr_in *)(sa)) 43#define satosin6(sa) ((struct sockaddr_in6 *)(sa)) 44 45enum { TRANS_FILTER = 0, TRANS_NAT, TRANS_RDR, TRANS_SIZE }; 46 47int prepare_rule(u_int32_t, int, struct sockaddr *, struct sockaddr *, 48 u_int16_t, u_int8_t); 49int server_lookup4(struct sockaddr_in *, struct sockaddr_in *, 50 struct sockaddr_in *, u_int8_t); 51int server_lookup6(struct sockaddr_in6 *, struct sockaddr_in6 *, 52 struct sockaddr_in6 *, u_int8_t); 53 54static struct pfioc_pooladdr pfp; 55static struct pfioc_rule pfr; 56static struct pfioc_trans pft; 57static struct pfioc_trans_e pfte[TRANS_SIZE]; 58static int dev, rule_log; 59static char *qname; 60 61int 62add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src, 63 struct sockaddr *dst, u_int16_t d_port, u_int8_t proto) 64{ 65 if (!src || !dst || !d_port || !proto) { 66 errno = EINVAL; 67 return (-1); 68 } 69 70 if (prepare_rule(id, PF_RULESET_FILTER, src, dst, d_port, proto) == -1) 71 return (-1); 72 73 pfr.rule.direction = dir; 74 if (ioctl(dev, DIOCADDRULE, &pfr) == -1) 75 return (-1); 76 77 return (0); 78} 79 80int 81add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst, 82 u_int16_t d_port, struct sockaddr *nat, u_int16_t nat_range_low, 83 u_int16_t nat_range_high, u_int8_t proto) 84{ 85 if (!src || !dst || !d_port || !nat || !nat_range_low || !proto || 86 (src->sa_family != nat->sa_family)) { 87 errno = EINVAL; 88 return (-1); 89 } 90 91 if (prepare_rule(id, PF_RULESET_NAT, src, dst, d_port, proto) == -1) 92 return (-1); 93 94 if (nat->sa_family == AF_INET) { 95 memcpy(&pfp.addr.addr.v.a.addr.v4, 96 &satosin(nat)->sin_addr.s_addr, 4); 97 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4); 98 } else { 99 memcpy(&pfp.addr.addr.v.a.addr.v6, 100 &satosin6(nat)->sin6_addr.s6_addr, 16); 101 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16); 102 } 103 if (ioctl(dev, DIOCADDADDR, &pfp) == -1) 104 return (-1); 105 106 pfr.rule.rpool.proxy_port[0] = nat_range_low; 107 pfr.rule.rpool.proxy_port[1] = nat_range_high; 108 if (ioctl(dev, DIOCADDRULE, &pfr) == -1) 109 return (-1); 110 111 return (0); 112} 113 114int 115add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst, 116 u_int16_t d_port, struct sockaddr *rdr, u_int16_t rdr_port, u_int8_t proto) 117{ 118 if (!src || !dst || !d_port || !rdr || !rdr_port || !proto || 119 (src->sa_family != rdr->sa_family)) { 120 errno = EINVAL; 121 return (-1); 122 } 123 124 if (prepare_rule(id, PF_RULESET_RDR, src, dst, d_port, proto) == -1) 125 return (-1); 126 127 if (rdr->sa_family == AF_INET) { 128 memcpy(&pfp.addr.addr.v.a.addr.v4, 129 &satosin(rdr)->sin_addr.s_addr, 4); 130 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4); 131 } else { 132 memcpy(&pfp.addr.addr.v.a.addr.v6, 133 &satosin6(rdr)->sin6_addr.s6_addr, 16); 134 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16); 135 } 136 if (ioctl(dev, DIOCADDADDR, &pfp) == -1) 137 return (-1); 138 139 pfr.rule.rpool.proxy_port[0] = rdr_port; 140 if (ioctl(dev, DIOCADDRULE, &pfr) == -1) 141 return (-1); 142 143 return (0); 144} 145 146int 147do_commit(void) 148{ 149 if (ioctl(dev, DIOCXCOMMIT, &pft) == -1) 150 return (-1); 151 152 return (0); 153} 154 155int 156do_rollback(void) 157{ 158 if (ioctl(dev, DIOCXROLLBACK, &pft) == -1) 159 return (-1); 160 161 return (0); 162} 163 164void 165init_filter(char *opt_qname, int opt_verbose) 166{ 167 struct pf_status status; 168 169 qname = opt_qname; 170 171 if (opt_verbose == 1) 172 rule_log = PF_LOG; 173 else if (opt_verbose == 2) 174 rule_log = PF_LOG_ALL; 175 176 dev = open("/dev/pf", O_RDWR); 177 if (dev == -1) { 178 syslog(LOG_ERR, "can't open /dev/pf"); 179 exit(1); 180 } 181 if (ioctl(dev, DIOCGETSTATUS, &status) == -1) { 182 syslog(LOG_ERR, "DIOCGETSTATUS"); 183 exit(1); 184 } 185 if (!status.running) { 186 syslog(LOG_ERR, "pf is disabled"); 187 exit(1); 188 } 189} 190 191int 192prepare_commit(u_int32_t id) 193{ 194 char an[PF_ANCHOR_NAME_SIZE]; 195 int i; 196 197 memset(&pft, 0, sizeof pft); 198 pft.size = TRANS_SIZE; 199 pft.esize = sizeof pfte[0]; 200 pft.array = pfte; 201 202 snprintf(an, PF_ANCHOR_NAME_SIZE, "%s/%d.%d", FTP_PROXY_ANCHOR, 203 getpid(), id); 204 for (i = 0; i < TRANS_SIZE; i++) { 205 memset(&pfte[i], 0, sizeof pfte[0]); 206 strlcpy(pfte[i].anchor, an, PF_ANCHOR_NAME_SIZE); 207 switch (i) { 208 case TRANS_FILTER: 209 pfte[i].rs_num = PF_RULESET_FILTER; 210 break; 211 case TRANS_NAT: 212 pfte[i].rs_num = PF_RULESET_NAT; 213 break; 214 case TRANS_RDR: 215 pfte[i].rs_num = PF_RULESET_RDR; 216 break; 217 default: 218 errno = EINVAL; 219 return (-1); 220 } 221 } 222 223 if (ioctl(dev, DIOCXBEGIN, &pft) == -1) 224 return (-1); 225 226 return (0); 227} 228 229int 230prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src, 231 struct sockaddr *dst, u_int16_t d_port, u_int8_t proto) 232{ 233 char an[PF_ANCHOR_NAME_SIZE]; 234 235 if ((src->sa_family != AF_INET && src->sa_family != AF_INET6) || 236 (src->sa_family != dst->sa_family)) { 237 errno = EPROTONOSUPPORT; 238 return (-1); 239 } 240 241 memset(&pfp, 0, sizeof pfp); 242 memset(&pfr, 0, sizeof pfr); 243 snprintf(an, PF_ANCHOR_NAME_SIZE, "%s/%d.%d", FTP_PROXY_ANCHOR, 244 getpid(), id); 245 strlcpy(pfp.anchor, an, PF_ANCHOR_NAME_SIZE); 246 strlcpy(pfr.anchor, an, PF_ANCHOR_NAME_SIZE); 247 248 switch (rs_num) { 249 case PF_RULESET_FILTER: 250 pfr.ticket = pfte[TRANS_FILTER].ticket; 251 break; 252 case PF_RULESET_NAT: 253 pfr.ticket = pfte[TRANS_NAT].ticket; 254 break; 255 case PF_RULESET_RDR: 256 pfr.ticket = pfte[TRANS_RDR].ticket; 257 break; 258 default: 259 errno = EINVAL; 260 return (-1); 261 } 262 if (ioctl(dev, DIOCBEGINADDRS, &pfp) == -1) 263 return (-1); 264 pfr.pool_ticket = pfp.ticket; 265 266 /* Generic for all rule types. */ 267 pfr.rule.af = src->sa_family; 268 pfr.rule.proto = proto; 269 pfr.rule.src.addr.type = PF_ADDR_ADDRMASK; 270 pfr.rule.dst.addr.type = PF_ADDR_ADDRMASK; 271 if (src->sa_family == AF_INET) { 272 memcpy(&pfr.rule.src.addr.v.a.addr.v4, 273 &satosin(src)->sin_addr.s_addr, 4); 274 memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 4); 275 memcpy(&pfr.rule.dst.addr.v.a.addr.v4, 276 &satosin(dst)->sin_addr.s_addr, 4); 277 memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 4); 278 } else { 279 memcpy(&pfr.rule.src.addr.v.a.addr.v6, 280 &satosin6(src)->sin6_addr.s6_addr, 16); 281 memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 16); 282 memcpy(&pfr.rule.dst.addr.v.a.addr.v6, 283 &satosin6(dst)->sin6_addr.s6_addr, 16); 284 memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 16); 285 } 286 pfr.rule.dst.port_op = PF_OP_EQ; 287 pfr.rule.dst.port[0] = htons(d_port); 288 289 switch (rs_num) { 290 case PF_RULESET_FILTER: 291 /* 292 * pass quick [log] inet[6] proto tcp \ 293 * from $src to $dst port = $d_port flags S/SAFR keep state 294 * (max 1) [queue qname] 295 */ 296 pfr.rule.action = PF_PASS; 297 pfr.rule.quick = 1; 298 pfr.rule.log = rule_log; 299 pfr.rule.keep_state = 1;
| 3 4/* 5 * Copyright (c) 2004, 2005 Camiel Dobbelaar, <cd@sentia.nl> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <syslog.h> 21 22#include <sys/ioctl.h> 23#include <sys/types.h> 24#include <sys/socket.h> 25 26#include <net/if.h> 27#include <net/pfvar.h> 28#include <netinet/in.h> 29#include <netinet/tcp.h> 30#include <arpa/inet.h> 31 32#include <err.h> 33#include <errno.h> 34#include <fcntl.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <unistd.h> 39 40#include "filter.h" 41 42/* From netinet/in.h, but only _KERNEL_ gets them. */ 43#define satosin(sa) ((struct sockaddr_in *)(sa)) 44#define satosin6(sa) ((struct sockaddr_in6 *)(sa)) 45 46enum { TRANS_FILTER = 0, TRANS_NAT, TRANS_RDR, TRANS_SIZE }; 47 48int prepare_rule(u_int32_t, int, struct sockaddr *, struct sockaddr *, 49 u_int16_t, u_int8_t); 50int server_lookup4(struct sockaddr_in *, struct sockaddr_in *, 51 struct sockaddr_in *, u_int8_t); 52int server_lookup6(struct sockaddr_in6 *, struct sockaddr_in6 *, 53 struct sockaddr_in6 *, u_int8_t); 54 55static struct pfioc_pooladdr pfp; 56static struct pfioc_rule pfr; 57static struct pfioc_trans pft; 58static struct pfioc_trans_e pfte[TRANS_SIZE]; 59static int dev, rule_log; 60static char *qname; 61 62int 63add_filter(u_int32_t id, u_int8_t dir, struct sockaddr *src, 64 struct sockaddr *dst, u_int16_t d_port, u_int8_t proto) 65{ 66 if (!src || !dst || !d_port || !proto) { 67 errno = EINVAL; 68 return (-1); 69 } 70 71 if (prepare_rule(id, PF_RULESET_FILTER, src, dst, d_port, proto) == -1) 72 return (-1); 73 74 pfr.rule.direction = dir; 75 if (ioctl(dev, DIOCADDRULE, &pfr) == -1) 76 return (-1); 77 78 return (0); 79} 80 81int 82add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst, 83 u_int16_t d_port, struct sockaddr *nat, u_int16_t nat_range_low, 84 u_int16_t nat_range_high, u_int8_t proto) 85{ 86 if (!src || !dst || !d_port || !nat || !nat_range_low || !proto || 87 (src->sa_family != nat->sa_family)) { 88 errno = EINVAL; 89 return (-1); 90 } 91 92 if (prepare_rule(id, PF_RULESET_NAT, src, dst, d_port, proto) == -1) 93 return (-1); 94 95 if (nat->sa_family == AF_INET) { 96 memcpy(&pfp.addr.addr.v.a.addr.v4, 97 &satosin(nat)->sin_addr.s_addr, 4); 98 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4); 99 } else { 100 memcpy(&pfp.addr.addr.v.a.addr.v6, 101 &satosin6(nat)->sin6_addr.s6_addr, 16); 102 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16); 103 } 104 if (ioctl(dev, DIOCADDADDR, &pfp) == -1) 105 return (-1); 106 107 pfr.rule.rpool.proxy_port[0] = nat_range_low; 108 pfr.rule.rpool.proxy_port[1] = nat_range_high; 109 if (ioctl(dev, DIOCADDRULE, &pfr) == -1) 110 return (-1); 111 112 return (0); 113} 114 115int 116add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst, 117 u_int16_t d_port, struct sockaddr *rdr, u_int16_t rdr_port, u_int8_t proto) 118{ 119 if (!src || !dst || !d_port || !rdr || !rdr_port || !proto || 120 (src->sa_family != rdr->sa_family)) { 121 errno = EINVAL; 122 return (-1); 123 } 124 125 if (prepare_rule(id, PF_RULESET_RDR, src, dst, d_port, proto) == -1) 126 return (-1); 127 128 if (rdr->sa_family == AF_INET) { 129 memcpy(&pfp.addr.addr.v.a.addr.v4, 130 &satosin(rdr)->sin_addr.s_addr, 4); 131 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4); 132 } else { 133 memcpy(&pfp.addr.addr.v.a.addr.v6, 134 &satosin6(rdr)->sin6_addr.s6_addr, 16); 135 memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16); 136 } 137 if (ioctl(dev, DIOCADDADDR, &pfp) == -1) 138 return (-1); 139 140 pfr.rule.rpool.proxy_port[0] = rdr_port; 141 if (ioctl(dev, DIOCADDRULE, &pfr) == -1) 142 return (-1); 143 144 return (0); 145} 146 147int 148do_commit(void) 149{ 150 if (ioctl(dev, DIOCXCOMMIT, &pft) == -1) 151 return (-1); 152 153 return (0); 154} 155 156int 157do_rollback(void) 158{ 159 if (ioctl(dev, DIOCXROLLBACK, &pft) == -1) 160 return (-1); 161 162 return (0); 163} 164 165void 166init_filter(char *opt_qname, int opt_verbose) 167{ 168 struct pf_status status; 169 170 qname = opt_qname; 171 172 if (opt_verbose == 1) 173 rule_log = PF_LOG; 174 else if (opt_verbose == 2) 175 rule_log = PF_LOG_ALL; 176 177 dev = open("/dev/pf", O_RDWR); 178 if (dev == -1) { 179 syslog(LOG_ERR, "can't open /dev/pf"); 180 exit(1); 181 } 182 if (ioctl(dev, DIOCGETSTATUS, &status) == -1) { 183 syslog(LOG_ERR, "DIOCGETSTATUS"); 184 exit(1); 185 } 186 if (!status.running) { 187 syslog(LOG_ERR, "pf is disabled"); 188 exit(1); 189 } 190} 191 192int 193prepare_commit(u_int32_t id) 194{ 195 char an[PF_ANCHOR_NAME_SIZE]; 196 int i; 197 198 memset(&pft, 0, sizeof pft); 199 pft.size = TRANS_SIZE; 200 pft.esize = sizeof pfte[0]; 201 pft.array = pfte; 202 203 snprintf(an, PF_ANCHOR_NAME_SIZE, "%s/%d.%d", FTP_PROXY_ANCHOR, 204 getpid(), id); 205 for (i = 0; i < TRANS_SIZE; i++) { 206 memset(&pfte[i], 0, sizeof pfte[0]); 207 strlcpy(pfte[i].anchor, an, PF_ANCHOR_NAME_SIZE); 208 switch (i) { 209 case TRANS_FILTER: 210 pfte[i].rs_num = PF_RULESET_FILTER; 211 break; 212 case TRANS_NAT: 213 pfte[i].rs_num = PF_RULESET_NAT; 214 break; 215 case TRANS_RDR: 216 pfte[i].rs_num = PF_RULESET_RDR; 217 break; 218 default: 219 errno = EINVAL; 220 return (-1); 221 } 222 } 223 224 if (ioctl(dev, DIOCXBEGIN, &pft) == -1) 225 return (-1); 226 227 return (0); 228} 229 230int 231prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src, 232 struct sockaddr *dst, u_int16_t d_port, u_int8_t proto) 233{ 234 char an[PF_ANCHOR_NAME_SIZE]; 235 236 if ((src->sa_family != AF_INET && src->sa_family != AF_INET6) || 237 (src->sa_family != dst->sa_family)) { 238 errno = EPROTONOSUPPORT; 239 return (-1); 240 } 241 242 memset(&pfp, 0, sizeof pfp); 243 memset(&pfr, 0, sizeof pfr); 244 snprintf(an, PF_ANCHOR_NAME_SIZE, "%s/%d.%d", FTP_PROXY_ANCHOR, 245 getpid(), id); 246 strlcpy(pfp.anchor, an, PF_ANCHOR_NAME_SIZE); 247 strlcpy(pfr.anchor, an, PF_ANCHOR_NAME_SIZE); 248 249 switch (rs_num) { 250 case PF_RULESET_FILTER: 251 pfr.ticket = pfte[TRANS_FILTER].ticket; 252 break; 253 case PF_RULESET_NAT: 254 pfr.ticket = pfte[TRANS_NAT].ticket; 255 break; 256 case PF_RULESET_RDR: 257 pfr.ticket = pfte[TRANS_RDR].ticket; 258 break; 259 default: 260 errno = EINVAL; 261 return (-1); 262 } 263 if (ioctl(dev, DIOCBEGINADDRS, &pfp) == -1) 264 return (-1); 265 pfr.pool_ticket = pfp.ticket; 266 267 /* Generic for all rule types. */ 268 pfr.rule.af = src->sa_family; 269 pfr.rule.proto = proto; 270 pfr.rule.src.addr.type = PF_ADDR_ADDRMASK; 271 pfr.rule.dst.addr.type = PF_ADDR_ADDRMASK; 272 if (src->sa_family == AF_INET) { 273 memcpy(&pfr.rule.src.addr.v.a.addr.v4, 274 &satosin(src)->sin_addr.s_addr, 4); 275 memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 4); 276 memcpy(&pfr.rule.dst.addr.v.a.addr.v4, 277 &satosin(dst)->sin_addr.s_addr, 4); 278 memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 4); 279 } else { 280 memcpy(&pfr.rule.src.addr.v.a.addr.v6, 281 &satosin6(src)->sin6_addr.s6_addr, 16); 282 memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 16); 283 memcpy(&pfr.rule.dst.addr.v.a.addr.v6, 284 &satosin6(dst)->sin6_addr.s6_addr, 16); 285 memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 16); 286 } 287 pfr.rule.dst.port_op = PF_OP_EQ; 288 pfr.rule.dst.port[0] = htons(d_port); 289 290 switch (rs_num) { 291 case PF_RULESET_FILTER: 292 /* 293 * pass quick [log] inet[6] proto tcp \ 294 * from $src to $dst port = $d_port flags S/SAFR keep state 295 * (max 1) [queue qname] 296 */ 297 pfr.rule.action = PF_PASS; 298 pfr.rule.quick = 1; 299 pfr.rule.log = rule_log; 300 pfr.rule.keep_state = 1;
|
303 pfr.rule.max_states = 1; 304 if (qname != NULL) 305 strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname); 306 break; 307 case PF_RULESET_NAT: 308 /* 309 * nat inet[6] proto tcp from $src to $dst port $d_port -> $nat 310 */ 311 pfr.rule.action = PF_NAT; 312 break; 313 case PF_RULESET_RDR: 314 /* 315 * rdr inet[6] proto tcp from $src to $dst port $d_port -> $rdr 316 */ 317 pfr.rule.action = PF_RDR; 318 break; 319 default: 320 errno = EINVAL; 321 return (-1); 322 } 323 324 return (0); 325} 326 327int 328server_lookup(struct sockaddr *client, struct sockaddr *proxy, 329 struct sockaddr *server, u_int8_t proto) 330{ 331 if (client->sa_family == AF_INET) 332 return (server_lookup4(satosin(client), satosin(proxy), 333 satosin(server), proto)); 334 335 if (client->sa_family == AF_INET6) 336 return (server_lookup6(satosin6(client), satosin6(proxy), 337 satosin6(server), proto)); 338 339 errno = EPROTONOSUPPORT; 340 return (-1); 341} 342 343int 344server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy, 345 struct sockaddr_in *server, u_int8_t proto) 346{ 347 struct pfioc_natlook pnl; 348 349 memset(&pnl, 0, sizeof pnl); 350 pnl.direction = PF_OUT; 351 pnl.af = AF_INET; 352 pnl.proto = proto; 353 memcpy(&pnl.saddr.v4, &client->sin_addr.s_addr, sizeof pnl.saddr.v4); 354 memcpy(&pnl.daddr.v4, &proxy->sin_addr.s_addr, sizeof pnl.daddr.v4); 355 pnl.sport = client->sin_port; 356 pnl.dport = proxy->sin_port; 357 358 if (ioctl(dev, DIOCNATLOOK, &pnl) == -1) 359 return (-1); 360 361 memset(server, 0, sizeof(struct sockaddr_in)); 362 server->sin_len = sizeof(struct sockaddr_in); 363 server->sin_family = AF_INET; 364 memcpy(&server->sin_addr.s_addr, &pnl.rdaddr.v4, 365 sizeof server->sin_addr.s_addr); 366 server->sin_port = pnl.rdport; 367 368 return (0); 369} 370 371int 372server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy, 373 struct sockaddr_in6 *server, u_int8_t proto) 374{ 375 struct pfioc_natlook pnl; 376 377 memset(&pnl, 0, sizeof pnl); 378 pnl.direction = PF_OUT; 379 pnl.af = AF_INET6; 380 pnl.proto = proto; 381 memcpy(&pnl.saddr.v6, &client->sin6_addr.s6_addr, sizeof pnl.saddr.v6); 382 memcpy(&pnl.daddr.v6, &proxy->sin6_addr.s6_addr, sizeof pnl.daddr.v6); 383 pnl.sport = client->sin6_port; 384 pnl.dport = proxy->sin6_port; 385 386 if (ioctl(dev, DIOCNATLOOK, &pnl) == -1) 387 return (-1); 388 389 memset(server, 0, sizeof(struct sockaddr_in6)); 390 server->sin6_len = sizeof(struct sockaddr_in6); 391 server->sin6_family = AF_INET6; 392 memcpy(&server->sin6_addr.s6_addr, &pnl.rdaddr.v6, 393 sizeof server->sin6_addr); 394 server->sin6_port = pnl.rdport; 395 396 return (0); 397}
| 310 pfr.rule.max_states = 1; 311 if (qname != NULL) 312 strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname); 313 break; 314 case PF_RULESET_NAT: 315 /* 316 * nat inet[6] proto tcp from $src to $dst port $d_port -> $nat 317 */ 318 pfr.rule.action = PF_NAT; 319 break; 320 case PF_RULESET_RDR: 321 /* 322 * rdr inet[6] proto tcp from $src to $dst port $d_port -> $rdr 323 */ 324 pfr.rule.action = PF_RDR; 325 break; 326 default: 327 errno = EINVAL; 328 return (-1); 329 } 330 331 return (0); 332} 333 334int 335server_lookup(struct sockaddr *client, struct sockaddr *proxy, 336 struct sockaddr *server, u_int8_t proto) 337{ 338 if (client->sa_family == AF_INET) 339 return (server_lookup4(satosin(client), satosin(proxy), 340 satosin(server), proto)); 341 342 if (client->sa_family == AF_INET6) 343 return (server_lookup6(satosin6(client), satosin6(proxy), 344 satosin6(server), proto)); 345 346 errno = EPROTONOSUPPORT; 347 return (-1); 348} 349 350int 351server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy, 352 struct sockaddr_in *server, u_int8_t proto) 353{ 354 struct pfioc_natlook pnl; 355 356 memset(&pnl, 0, sizeof pnl); 357 pnl.direction = PF_OUT; 358 pnl.af = AF_INET; 359 pnl.proto = proto; 360 memcpy(&pnl.saddr.v4, &client->sin_addr.s_addr, sizeof pnl.saddr.v4); 361 memcpy(&pnl.daddr.v4, &proxy->sin_addr.s_addr, sizeof pnl.daddr.v4); 362 pnl.sport = client->sin_port; 363 pnl.dport = proxy->sin_port; 364 365 if (ioctl(dev, DIOCNATLOOK, &pnl) == -1) 366 return (-1); 367 368 memset(server, 0, sizeof(struct sockaddr_in)); 369 server->sin_len = sizeof(struct sockaddr_in); 370 server->sin_family = AF_INET; 371 memcpy(&server->sin_addr.s_addr, &pnl.rdaddr.v4, 372 sizeof server->sin_addr.s_addr); 373 server->sin_port = pnl.rdport; 374 375 return (0); 376} 377 378int 379server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy, 380 struct sockaddr_in6 *server, u_int8_t proto) 381{ 382 struct pfioc_natlook pnl; 383 384 memset(&pnl, 0, sizeof pnl); 385 pnl.direction = PF_OUT; 386 pnl.af = AF_INET6; 387 pnl.proto = proto; 388 memcpy(&pnl.saddr.v6, &client->sin6_addr.s6_addr, sizeof pnl.saddr.v6); 389 memcpy(&pnl.daddr.v6, &proxy->sin6_addr.s6_addr, sizeof pnl.daddr.v6); 390 pnl.sport = client->sin6_port; 391 pnl.dport = proxy->sin6_port; 392 393 if (ioctl(dev, DIOCNATLOOK, &pnl) == -1) 394 return (-1); 395 396 memset(server, 0, sizeof(struct sockaddr_in6)); 397 server->sin6_len = sizeof(struct sockaddr_in6); 398 server->sin6_family = AF_INET6; 399 memcpy(&server->sin6_addr.s6_addr, &pnl.rdaddr.v6, 400 sizeof server->sin6_addr); 401 server->sin6_port = pnl.rdport; 402 403 return (0); 404}
|