1/* $NetBSD: pf.c,v 1.1 2005/04/03 22:15:32 peter Exp $ */ 2 3/* 4 * pf.c - NAT lookup code for pf. 5 * 6 * This software is in the public domain. 7 * Written by Peter Postma <peter@NetBSD.org> 8 */ 9 10#include <sys/cdefs.h> 11__RCSID("$NetBSD$"); 12 13#include <sys/types.h> 14#include <sys/socket.h> 15#include <sys/ioctl.h> 16#include <sys/fcntl.h> 17 18#include <net/if.h> 19#include <netinet/in.h> 20#include <net/pfvar.h> 21 22#include <stdlib.h> 23#include <string.h> 24#include <syslog.h> 25#include <unistd.h> 26 27#include "identd.h" 28 29int 30pf_natlookup(struct sockaddr_storage *ss, struct sockaddr *nat_addr, 31 int *nat_lport) 32{ 33 struct pfioc_natlook nl; 34 int dev; 35 36 (void)memset(&nl, 0, sizeof(nl)); 37 38 /* Build the pf natlook structure. */ 39 switch (ss[0].ss_family) { 40 case AF_INET: 41 (void)memcpy(&nl.daddr.v4, &satosin(&ss[0])->sin_addr, 42 sizeof(struct in_addr)); 43 (void)memcpy(&nl.saddr.v4, &satosin(&ss[1])->sin_addr, 44 sizeof(struct in_addr)); 45 nl.dport = satosin(&ss[0])->sin_port; 46 nl.sport = satosin(&ss[1])->sin_port; 47 nl.af = AF_INET; 48 nl.proto = IPPROTO_TCP; 49 nl.direction = PF_IN; 50 break; 51 case AF_INET6: 52 (void)memcpy(&nl.daddr.v6, &satosin6(&ss[0])->sin6_addr, 53 sizeof(struct in6_addr)); 54 (void)memcpy(&nl.saddr.v6, &satosin6(&ss[1])->sin6_addr, 55 sizeof(struct in6_addr)); 56 nl.dport = satosin6(&ss[0])->sin6_port; 57 nl.sport = satosin6(&ss[1])->sin6_port; 58 nl.af = AF_INET6; 59 nl.proto = IPPROTO_TCP; 60 nl.direction = PF_IN; 61 break; 62 default: 63 maybe_syslog(LOG_ERR, "Unsupported protocol for NAT lookup " 64 "(no. %d)", ss[0].ss_family); 65 return 0; 66 } 67 68 /* Open the /dev/pf device and do the lookup. */ 69 if ((dev = open("/dev/pf", O_RDWR)) == -1) { 70 maybe_syslog(LOG_ERR, "Cannot open /dev/pf: %m"); 71 return 0; 72 } 73 if (ioctl(dev, DIOCNATLOOK, &nl) == -1) { 74 maybe_syslog(LOG_ERR, "NAT lookup failure: %m"); 75 (void)close(dev); 76 return 0; 77 } 78 (void)close(dev); 79 80 /* 81 * Put the originating address into nat_addr and fill 82 * the port with the ident port, 113. 83 */ 84 switch (ss[0].ss_family) { 85 case AF_INET: 86 (void)memcpy(&satosin(nat_addr)->sin_addr, &nl.rsaddr.v4, 87 sizeof(struct in_addr)); 88 satosin(nat_addr)->sin_port = htons(113); 89 satosin(nat_addr)->sin_len = sizeof(struct sockaddr_in); 90 satosin(nat_addr)->sin_family = AF_INET; 91 break; 92 case AF_INET6: 93 (void)memcpy(&satosin6(nat_addr)->sin6_addr, &nl.rsaddr.v6, 94 sizeof(struct in6_addr)); 95 satosin6(nat_addr)->sin6_port = htons(113); 96 satosin6(nat_addr)->sin6_len = sizeof(struct sockaddr_in6); 97 satosin6(nat_addr)->sin6_family = AF_INET6; 98 break; 99 } 100 /* Put the originating port into nat_lport. */ 101 *nat_lport = nl.rsport; 102 103 return 1; 104} 105