I was asked if I could share this code with the world from a few people.

The l4ip code itself is not quite ready, it only checks TCP so far, I have UDP and SYSTEM type checks to go. But you can pull it out of my cvs under "l4ip" if you want to look at it.

But if you are only interested in how to add/remove ipnat rules, my functions (based heavily on Darren Reeds sources) has been attached.

I can't guarantee I did everything correctly, but it does appear to work.

The inip, and outip seem to be a "union" between ipv4 and ipv6, so it will need tweaking if you want ipv6 support.

Lund


// // Support ioctl()s functions shamelessly taken from ipfil/l4check by // Darren Reed. // static void nat_add(cluster_t *cluster, member_t *member) { struct ipnat l4_nat; unsigned long addr; // ipv4 only :( struct ipfobj obj;

        if (main_harmless)
                return;


// We wrap all ioctl() in ipfobj for future compatibility memset(&obj, 0, sizeof(obj)); obj.ipfo_rev = 4010300; // FIXME - IPFILTER_VERSION define from somewhere obj.ipfo_size = sizeof(l4_nat); obj.ipfo_ptr = &l4_nat; obj.ipfo_type = IPFOBJ_IPNAT;


memset(&l4_nat, 0, sizeof(l4_nat));

        l4_nat.in_flags = IPN_TCP|IPN_ROUNDR;
        l4_nat.in_redir = NAT_REDIRECT;

        // Set ifname, eg "fxp0" "ppp0"..
        strncpy(l4_nat.in_ifname, cluster->ifname,
                        MIN(sizeof(l4_nat.in_ifname),
                                strlen(cluster->ifname)+1));
        l4_nat.in_ifname[sizeof(l4_nat.in_ifname)-1] = 0; //probably not needed

        // Copy over to the other ifname as well, as per ipnat_y.y
        memcpy(l4_nat.in_ifnames[1], l4_nat.in_ifnames[0],
                   sizeof(l4_nat.in_ifnames[1]));

        addr = lion_addr(cluster->listen_ip);
        addr = htonl(addr);
        memcpy(&l4_nat.in_outip, &addr,
                   sizeof(l4_nat.in_outip));
        l4_nat.in_pmin = htons(cluster->listen_port);
        l4_nat.in_pmax = l4_nat.in_pmin;
        l4_nat.in_outmsk = 0xffffffff;
        
        l4_nat.in_pnext = 0;

        addr = lion_addr(member->ip);
        addr = htonl(addr);
        memcpy(&l4_nat.in_inip, &addr,
                        sizeof(l4_nat.in_inip));
        l4_nat.in_pnext = htons(member->port);
        
        l4_nat.in_inmsk = 0xffffffff;

        // This code came straight out of ipnat_y.y by Darren Reed
        if ((l4_nat.in_p == 0) &&
                ((l4_nat.in_flags & IPN_TCPUDP) == 0) &&
                (l4_nat.in_pmin != 0 ||
                 l4_nat.in_pmax != 0 ||
                 l4_nat.in_pnext != 0))
                l4_nat.in_p = IPPROTO_TCP;

        if (!l4_nat.in_pnext)
                l4_nat.in_pnext = l4_nat.in_pmin;

        debugf("Add NAT rule '%s' for %s/%#x,%u -> ", l4_nat.in_ifname,
                   inet_ntoa(l4_nat.in_out[0]),
                   l4_nat.in_outmsk, ntohs(l4_nat.in_pmin));
        debugf("%s,%u\n", inet_ntoa(l4_nat.in_in[0]), ntohs(l4_nat.in_pnext));


if (ioctl(nat_fd, SIOCADNAT, &obj) == -1) {

                if (errno != EEXIST) {
                        perror("ioctl(SIOCADNAT)");
                        log_f("[nat] WARNING could not add member: %s\n",
                                  strerror(errno));
                }
        }
}






-- Jorgen Lundman | <[EMAIL PROTECTED]> Unix Administrator | +81 (0)3 -5456-2687 ext 1017 (work) Shibuya-ku, Tokyo | +81 (0)90-5578-8500 (cell) Japan | +81 (0)3 -3375-1767 (home)

Reply via email to