Actually, the previous post's usage of netmask would probably do the trick:
[EMAIL PROTECTED]:~$ netmask -c 1.2.3.1:1.2.3.4 1.2.3.1/32 1.2.3.2/31 1.2.3.4/32 so, e.g.: for hostmask in `netmask -c 1.2.3.1:1.2.3.4`; do iptables -A INPUT -s $hostmask -d `ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | cut -d: -f2` -p tcp --dport 22 -j ACCEPT; done would work nicely. Actually, this may make a nice module for netfilter in the kernel for ipv4. That is, being able to specify a contiguous IP block to iptables and have it do the internal calculations that netmask -c is doing. Something like: iptables -m ip_block -A INPUT -s 1.2.3.1:1.2.3.4 -d ... Would be really cool. Anyway, thanks for the suggestions all! Josh --- Karl Hammar <[EMAIL PROTECTED]> wrote: > > It would be useful to have something that would > take > > an IP address range and return the minimum > coverage > > CIDR for that block (for use in feeding to > iptables). > > > > For example, if I want to allow access for hosts > > 1.2.3.1 - 1.2.3.4, I currently can allow them > > individually or just allow the entire /24. But is > > there any easier way to allow ip ranges in > iptables, > > short of doing each individual IP or generalizing > to a > > class boundary? Can ipsc do this easily? > > > > Thanks, > > Josh > ... > > I don't really have that, but attached program > gives you the longest > common prefix for a few ip's. > > $ ./ipnumber -p 192.168.93.3 192.168.93.2 > 192.168.93.1 > 192.168.93.0/30 (255.255.255.252) > $ ./ipnumber -p 192.168.90.3 192.168.2.28 > > 192.168.0.0/17 (255.255.128.0) > > Regards, > /Karl > > ----------------------------------------------------------------------- > Karl Hammar Aspö Data > [EMAIL PROTECTED] > Lilla Aspö 2340 > Networks > S-742 94 Östhammar +46 173 140 57 > Computers > Sweden +46 70 511 97 84 > Consulting > ----------------------------------------------------------------------- > > > /** Copyright: Karl Hammar, Aspö Data > ** Copyright terms: GPL > **/ > > #include <arpa/inet.h> > #include <ctype.h> > #include <errno.h> > #include <netinet/in.h> > #include <stdio.h> > #include <stdlib.h> > #include <string.h> > #include <unistd.h> > > /* int function return value: 0 == SUCCESS, else > error */ > > /* > * Ip numbers (or addresses, same thing differnet > names) > * are just 32 bit unsigned integers > * the numbers we are used to (e.g. "192.168.1.3") > * are only a way to present thoose ip numbers for > humans. > * That format is called dotted quad, since it > consists of > * four ("quad") numbers with dots between. > * > * Theese two routinges convert between the human > and computer > * way of seeing the ip numbers > */ > int dot2num( char *dotted_quad, uint32_t *num); > > /* len is length of dotted_quad buffer. > * len >= INET_ADDRSTRLEN, see man inet_ntop > */ > int num2dot( uint32_t num, char *dotted_quad, > size_t len); > > /* convert so can print/read binary numbers, sorry > printf/scanf don't do this */ > int str2num( char *str, uint32_t *num, char **ptr); > /* the buffers length (len) must be at least 33 > characters long (32 digits + one '\0') */ > int num2str( uint32_t num, char *buffer, size_t > buflen); > > /* > to help routers, ip numbers are split in two parts: > the first is a network prefix and > the latter is computer (or host, well actually > interface) number on that network > > It works like ip_address = network_number + > computer_number_on_that_network > You can compare it to a memory buffer, address (aka. > ip number) = buffer_pointer (aka. network) + offset > (aka. host number on that network) > > This helps routers since they don't have to store > routes to all hosts > they only have to keep records of networks. > Also "network" is not necceserely the same thing as > a LAN. > Network is just all computers with some common top > bits in their ip numbers > (note: "common top bits" i.e. ALL bits before the > split, and > remember ip numbers is a simple unsigned integer) > that you can reach if you go along a given route. > > Subnetting is really that simple! > But the dotted quad format makes it hard see and > understand. > Why -- because the dot makes the split between > network and host part hard to see. > > By counting number of bits in the prefix we get the > prefix length, > which is the same number as used in the cidr > notation. > > Public example: > hostname ip number as binary > www.ibm.com 129.42.17.99 > 10000001001010100001000101100011 > www.ge.com 216.74.139.56 > 11011000010010101000101100111000 > common prefix 1 > prefix length 1 > > Local example: > calcit 192.168.93.1 > 11000000101010000101110100000001 > hematit 192.168.93.2 > 11000000101010000101110100000010 > granat 192.168.93.37 > 11000000101010000101110100100101 > common prefix > 11000000101010000101110100 > prefix length 26 > > The bit positions where the prefix is, are called > network bits, > and the others (representing the host part) are > called the host bits. > > The ip number with address 0 on a network is called > the "network address" > and it is that number which goes into the routing > table along with the prefix length. > Another related number is the broadcast address. > It is useful on a ethernet LAN. > The broadcast address is by convention the last > address of a network. > > The network address is only meaningful for routing, > i.e. in the IP-layer, > and the broadcast address have the same meaning as > the ip number. > A given host accept packets to that address as > destined to itself and have > no meaning besides that and that all hosts on a > given physical (or end) network > should have the same broadcast address so you easily > can address them all. > So, the broadcast address do not have a meaning for > all networks. > > To tell the world about a network, we use the > network address > (or any address on the same network, since they have > the same prefix) > and the prefix length. > It is usually presented like "192.168.93.0/26" or > "network: 192.168.93.0, subnet mask: > 255.255.255.192" > The first variant is called the CIDR notation and > the second is presented with a netmask (or subnet > mask). > In the CIDR notation we uses the prefix length > directly, > The netmask is an 32 bit unsigned integer with all > bits in the prefix set to high (1) > and all other set to low (0). > It is then converted to dotted quad notation just as > eny other ip number. > > Example: > network 192.168.93.0 > 11000000101010000101110100000000 > granat 192.168.93.37 > 11000000101010000101110100100101 > broadcast 192.168.93.63 > 11000000101010000101110100111111 > > prefix 11000000101010000101110100 > netmask 255.255.255.192 > 11111111111111111111111111000000 > */ > > uint32_t get_network_bits(uint32_t num, uint32_t > mask); > uint32_t get_host_bits( uint32_t num, uint32_t > mask); > uint32_t get_network_number(uint32_t num, uint32_t > mask); > uint32_t get_broadcast_address(uint32_t num, > uint32_t mask); > > int update_common_prefix(uint32_t *prefix, int > *cidr, uint32_t num); > int cidr2mask(int cidr, uint32_t *mask); > int mask2cidr(uint32_t mask, int *cidr); > > /************************************************************************/ > struct { > char *cmd; > } global; > > int Usage(void); > int do_b(int argc, char *argv[]); > int do_B(int argc, char *argv[]); > int do_m(int argc, char *argv[]); > int do_M(int argc, char *argv[]); > int do_p(int argc, char *argv[]); > int do_i(int argc, char *argv[]); > int do_r(int argc, char *argv[]); > > int Usage(void) { > printf("Usage:\n"); > printf(" %s -b ip.nr\n", global.cmd); > printf(" %s -B binary_number\n", global.cmd); > printf(" %s -m netmask\n", global.cmd); > printf(" %s -M cidr\n", global.cmd); > printf(" %s -p ip.nr ...\n", global.cmd); > printf(" %s -i ip.nr subnetmask\n", global.cmd); > printf(" %s -i ip.nr/cidr\n", global.cmd); > printf(" %s -r ip.nr subnetmask\n", global.cmd); > printf(" %s -r ip.nr/cidr\n", global.cmd); > printf("Synopsis:\n"); > === message truncated ===