1 | /* $NetBSD: ipf.c,v 1.4 2018/12/13 13:11:28 sborrill Exp $ */ |
2 | |
3 | /* |
4 | * ipf.c - NAT lookup code for IP Filter. |
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: ipf.c,v 1.4 2018/12/13 13:11:28 sborrill 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 <netinet/in_systm.h> |
21 | #include <netinet/ipl.h> |
22 | #include <netinet/ip_compat.h> |
23 | #include <netinet/ip_fil.h> |
24 | #include <netinet/ip_nat.h> |
25 | |
26 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #include <syslog.h> |
29 | #include <unistd.h> |
30 | |
31 | #include "identd.h" |
32 | |
33 | int |
34 | ipf_natlookup(const struct sockaddr_storage *ss, |
35 | struct sockaddr_storage *nat_addr, in_port_t *nat_lport) |
36 | { |
37 | natlookup_t nl; |
38 | ipfobj_t obj; |
39 | int dev; |
40 | |
41 | (void)memset(&obj, 0, sizeof(obj)); |
42 | (void)memset(&nl, 0, sizeof(nl)); |
43 | |
44 | /* Build the ipf object description structure. */ |
45 | obj.ipfo_rev = IPFILTER_VERSION; |
46 | obj.ipfo_size = sizeof(nl); |
47 | obj.ipfo_ptr = &nl; |
48 | obj.ipfo_type = IPFOBJ_NATLOOKUP; |
49 | |
50 | /* Build the ipf natlook structure. */ |
51 | switch (ss[0].ss_family) { |
52 | case AF_INET: |
53 | (void)memcpy(&nl.nl_realip, &csatosin(&ss[0])->sin_addr, |
54 | sizeof(struct in_addr)); |
55 | (void)memcpy(&nl.nl_outip, &csatosin(&ss[1])->sin_addr, |
56 | sizeof(struct in_addr)); |
57 | nl.nl_realport = ntohs(csatosin(&ss[0])->sin_port); |
58 | nl.nl_outport = ntohs(csatosin(&ss[1])->sin_port); |
59 | nl.nl_flags = IPN_TCP | IPN_IN; |
60 | nl.nl_v = 4; /* IPv4 */ |
61 | break; |
62 | case AF_INET6: |
63 | /* XXX IP Filter doesn't support IPv6 NAT yet. */ |
64 | default: |
65 | maybe_syslog(LOG_ERR, "Unsupported protocol for NAT lookup " |
66 | "(no. %d)" , ss[0].ss_family); |
67 | return 0; |
68 | } |
69 | |
70 | /* Open the NAT device and do the lookup. */ |
71 | if ((dev = open(IPNAT_NAME, O_RDONLY)) == -1) { |
72 | maybe_syslog(LOG_ERR, "Cannot open %s: %m" , IPNAT_NAME); |
73 | return 0; |
74 | } |
75 | if (ioctl(dev, SIOCGNATL, &obj) == -1) { |
76 | maybe_syslog(LOG_ERR, "NAT lookup failure: %m" ); |
77 | (void)close(dev); |
78 | return 0; |
79 | } |
80 | (void)close(dev); |
81 | |
82 | /* |
83 | * Put the originating address into nat_addr and fill |
84 | * the port with the ident port, 113. |
85 | */ |
86 | switch (ss[0].ss_family) { |
87 | case AF_INET: |
88 | (void)memcpy(&satosin(nat_addr)->sin_addr, &nl.nl_inip, |
89 | sizeof(struct in_addr)); |
90 | satosin(nat_addr)->sin_port = htons(113); |
91 | satosin(nat_addr)->sin_len = sizeof(struct sockaddr_in); |
92 | satosin(nat_addr)->sin_family = AF_INET; |
93 | break; |
94 | case AF_INET6: |
95 | break; |
96 | } |
97 | /* Put the originating port into nat_lport. */ |
98 | *nat_lport = nl.nl_inport; |
99 | |
100 | return 1; |
101 | } |
102 | |