1 /* $NetBSD: pf.c,v 1.3 2016/12/10 05:43:11 christos 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: pf.c,v 1.3 2016/12/10 05:43:11 christos Exp $"); 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 29 int 30 pf_natlookup(const struct sockaddr_storage *ss, 31 struct sockaddr_storage *nat_addr, in_port_t *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, &csatosin(&ss[0])->sin_addr, 42 sizeof(struct in_addr)); 43 (void)memcpy(&nl.saddr.v4, &csatosin(&ss[1])->sin_addr, 44 sizeof(struct in_addr)); 45 nl.dport = csatosin(&ss[0])->sin_port; 46 nl.sport = csatosin(&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, &csatosin6(&ss[0])->sin6_addr, 53 sizeof(struct in6_addr)); 54 (void)memcpy(&nl.saddr.v6, &csatosin6(&ss[1])->sin6_addr, 55 sizeof(struct in6_addr)); 56 nl.dport = csatosin6(&ss[0])->sin6_port; 57 nl.sport = csatosin6(&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