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