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