1/* $NetBSD: netmask.c,v 1.2 2009/06/30 02:44:52 agc Exp $ */ 2 3/* 4 * Copyright � 2006 Alistair Crooks. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote 15 * products derived from this software without specific prior written 16 * permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 24 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30#include "config.h" 31 32#include <sys/types.h> 33#include <sys/param.h> 34 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <unistd.h> 39 40#ifdef HAVE_NETINET_IN_H 41#include <netinet/in.h> 42#endif 43 44#ifdef HAVE_ARPA_INET_H 45#include <arpa/inet.h> 46#endif 47 48#include "iscsiutil.h" 49 50enum { 51 NETMASK_BUFFER_SIZE = 256 52}; 53 54/* this struct is used to define a magic netmask value */ 55typedef struct magic_t { 56 const char *magic; /* string to match */ 57 const char *xform; /* string to transform it into */ 58} magic_t; 59 60 61static magic_t magics[] = { 62 { "any", "0/0" }, 63 { "all", "0/0" }, 64 { "none", "0/32" }, 65 { NULL, NULL }, 66}; 67 68#ifndef ISCSI_HTONL 69#define ISCSI_HTONL(x) htonl(x) 70#endif 71 72/* return 1 if address is in netmask's range */ 73int 74allow_netmask(const char *netmaskarg, const char *addr) 75{ 76 struct in_addr a; 77 struct in_addr m; 78 const char *netmask; 79 magic_t *mp; 80 char maskaddr[NETMASK_BUFFER_SIZE]; 81 char *cp; 82 int slash; 83 int i; 84 85 /* firstly check for any magic values in the netmask */ 86 netmask = netmaskarg; 87 for (mp = magics ; mp->magic ; mp++) { 88 if (strcmp(netmask, mp->magic) == 0) { 89 netmask = mp->xform; 90 break; 91 } 92 } 93 94 /* find out if slash notation has been used */ 95 (void) memset(&a, 0x0, sizeof(a)); 96 if ((cp = strchr(netmask, '/')) == NULL) { 97 (void) strlcpy(maskaddr, netmask, sizeof(maskaddr)); 98 slash = 32; 99 } else { 100 (void) strlcpy(maskaddr, netmask, MIN(sizeof(maskaddr), (size_t)(cp - netmask) + 1)); 101 slash = atoi(cp + 1); 102 } 103 104 /* if we have a wildcard "slash" netmask, then we allow it */ 105 if (slash == 0) { 106 return 1; 107 } 108 109 /* canonicalise IPv4 address to dotted quad */ 110 for (i = 0, cp = maskaddr ; *cp ; cp++) { 111 if (*cp == '.') { 112 i += 1; 113 } 114 } 115 for ( ; i < 3 ; i++) { 116 (void) snprintf(cp, sizeof(maskaddr) - (int)(cp - maskaddr), ".0"); 117 cp += 2; 118 } 119 120 /* translate netmask to in_addr */ 121 if (!inet_aton(maskaddr, &m)) { 122 (void) fprintf(stderr, "allow_netmask: can't interpret mask `%s' as an IPv4 address\n", maskaddr); 123 return 0; 124 } 125 126 /* translate address to in_addr */ 127 if (!inet_aton(addr, &a)) { 128 (void) fprintf(stderr, "allow_netmask: can't interpret address `%s' as an IPv4 address\n", addr); 129 return 0; 130 } 131 132#ifdef ALLOW_NETMASK_DEBUG 133 printf("addr %s %08x, mask %s %08x, slash %d\n", addr, (ISCSI_HTONL(a.s_addr) >> (32 - slash)), maskaddr, (ISCSI_HTONL(m.s_addr) >> (32 - slash)), slash); 134#endif 135 136 /* and return 1 if address is in netmask */ 137 return (ISCSI_HTONL(a.s_addr) >> (32 - slash)) == (ISCSI_HTONL(m.s_addr) >> (32 - slash)); 138} 139 140#ifdef ALLOW_NETMASK_DEBUG 141int 142main(int argc, char **argv) 143{ 144 int i; 145 146 for (i = 1 ; i < argc ; i+= 2) { 147 if (allow_netmask(argv[i], argv[i + 1])) { 148 printf("mask %s matches addr %s\n\n", argv[i], argv[i + 1]); 149 } else { 150 printf("No match for mask %s from addr %s\n\n", argv[i], argv[i + 1]); 151 } 152 } 153 exit(EXIT_SUCCESS); 154} 155#endif 156 157#if 0 158[11:33:02] agc@sys3 ...local/src/netmask 248 > ./n 10.4/16 10.4.0.29 10.4/16 10.5.0.29 10.4/0 10.4.0.19 10.4 10.4.0.19 10.4.3/8 10.4.3.7 10.4.3/24 10.4.3.7 159mask 10.4/16 matches addr 10.4.0.29 160 161No match for mask 10.4/16 from addr 10.5.0.29 162 163mask 10.4/0 matches addr 10.4.0.19 164 165No match for mask 10.4 from addr 10.4.0.19 166 167mask 10.4.3/8 matches addr 10.4.3.7 168 169mask 10.4.3/24 matches addr 10.4.3.7 170 171[14:44:52] agc@sys3 ...local/src/netmask 249 > 172#endif 173