1 /* 2 * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.jmx.snmp.IPAcl; 27 28 import static com.sun.jmx.defaults.JmxProperties.SNMP_LOGGER; 29 30 import java.util.logging.Level; 31 import java.util.Vector; 32 import java.util.Enumeration; 33 import java.io.Serializable; 34 import java.net.UnknownHostException; 35 import java.net.InetAddress; 36 37 import java.security.Principal; 38 import java.security.acl.Group; 39 40 41 /** 42 * This class is used to represent a subnet mask (a group of hosts matching the same 43 * IP mask). 44 * 45 * @see java.security.acl.Group 46 */ 47 48 class NetMaskImpl extends PrincipalImpl implements Group, Serializable { 49 private static final long serialVersionUID = -7332541893877932896L; 50 51 protected byte[] subnet = null; 52 protected int prefix = -1; 53 /** 54 * Constructs an empty group. 55 * @exception UnknownHostException Not implemented 56 */ 57 public NetMaskImpl () throws UnknownHostException { 58 } 59 60 private byte[] extractSubNet(byte[] b) { 61 int addrLength = b.length; 62 byte[] subnet = null; 63 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 64 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), 65 "extractSubNet", "BINARY ARRAY :"); 66 StringBuilder sb = new StringBuilder(); 67 for(int i =0; i < addrLength; i++) { 68 sb.append((b[i] & 0xFF) + ":"); 69 } 70 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), 71 "extractSubNet", sb.toString()); 72 } 73 74 // 8 is a byte size. Common to any InetAddress (V4 or V6). 75 int fullyCoveredByte = prefix / 8; 76 if(fullyCoveredByte == addrLength) { 77 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 78 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 79 "The mask is the complete address, strange..." + addrLength); 80 } 81 subnet = b; 82 return subnet; 83 } 84 if(fullyCoveredByte > addrLength) { 85 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 86 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 87 "The number of covered byte is longer than the address. BUG"); 88 } 89 throw new IllegalArgumentException("The number of covered byte is longer than the address."); 90 } 91 int partialyCoveredIndex = fullyCoveredByte; 92 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 93 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 94 "Partially covered index : " + partialyCoveredIndex); 95 } 96 byte toDeal = b[partialyCoveredIndex]; 97 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 98 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 99 "Partially covered byte : " + toDeal); 100 } 101 102 // 8 is a byte size. Common to any InetAddress (V4 or V6). 103 int nbbits = prefix % 8; 104 int subnetSize = 0; 105 106 if(nbbits == 0) 107 subnetSize = partialyCoveredIndex; 108 else 109 subnetSize = partialyCoveredIndex + 1; 110 111 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 112 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 113 "Remains : " + nbbits); 114 } 115 116 byte mask = 0; 117 for(int i = 0; i < nbbits; i++) { 118 mask |= (1 << (7 - i)); 119 } 120 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 121 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 122 "Mask value : " + (mask & 0xFF)); 123 } 124 125 byte maskedValue = (byte) ((int)toDeal & (int)mask); 126 127 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 128 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 129 "Masked byte : " + (maskedValue &0xFF)); 130 } 131 subnet = new byte[subnetSize]; 132 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 133 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 134 "Resulting subnet : "); 135 } 136 for(int i = 0; i < partialyCoveredIndex; i++) { 137 subnet[i] = b[i]; 138 139 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 140 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 141 (subnet[i] & 0xFF) +":"); 142 } 143 } 144 145 if(nbbits != 0) { 146 subnet[partialyCoveredIndex] = maskedValue; 147 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 148 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "extractSubNet", 149 "Last subnet byte : " + (subnet[partialyCoveredIndex] &0xFF)); 150 } 151 } 152 return subnet; 153 } 154 155 /** 156 * Constructs a group using the specified subnet mask. 157 * THIS ALGORITHM IS V4 and V6 compatible. 158 * 159 * @exception UnknownHostException if the subnet mask cann't be built. 160 */ 161 public NetMaskImpl (String a, int prefix) throws UnknownHostException { 162 super(a); 163 this.prefix = prefix; 164 subnet = extractSubNet(getAddress().getAddress()); 165 } 166 167 /** 168 * Adds the specified member to the group. 169 * 170 * @param p the principal to add to this group. 171 * @return true if the member was successfully added, false if the 172 * principal was already a member. 173 */ 174 public boolean addMember(Principal p) { 175 // we don't need to add members because the ip address is a subnet mask 176 return true; 177 } 178 179 public int hashCode() { 180 return super.hashCode(); 181 } 182 183 /** 184 * Compares this group to the specified object. Returns true if the object 185 * passed in matches the group represented. 186 * 187 * @param p the object to compare with. 188 * @return true if the object passed in matches the subnet mask, 189 * false otherwise. 190 */ 191 public boolean equals (Object p) { 192 if (p instanceof PrincipalImpl || p instanceof NetMaskImpl){ 193 PrincipalImpl received = (PrincipalImpl) p; 194 InetAddress addr = received.getAddress(); 195 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 196 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "equals", 197 "Received Address : " + addr); 198 } 199 byte[] recAddr = addr.getAddress(); 200 for(int i = 0; i < subnet.length; i++) { 201 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 202 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "equals", 203 "(recAddr[i]) : " + (recAddr[i] & 0xFF)); 204 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "equals", 205 "(recAddr[i] & subnet[i]) : " + 206 ((recAddr[i] & (int)subnet[i]) &0xFF) + 207 " subnet[i] : " + (subnet[i] &0xFF)); 208 } 209 if((recAddr[i] & subnet[i]) != subnet[i]) { 210 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 211 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "equals", 212 "FALSE"); 213 } 214 return false; 215 } 216 } 217 if (SNMP_LOGGER.isLoggable(Level.FINEST)) { 218 SNMP_LOGGER.logp(Level.FINEST, NetMaskImpl.class.getName(), "equals", 219 "TRUE"); 220 } 221 return true; 222 } else 223 return false; 224 } 225 /** 226 * Returns true if the passed principal is a member of the group. 227 * 228 * @param p the principal whose membership is to be checked. 229 * @return true if the principal is a member of this group, false otherwise. 230 */ 231 public boolean isMember(Principal p) { 232 if ((p.hashCode() & super.hashCode()) == p.hashCode()) return true; 233 else return false; 234 } 235 236 /** 237 * Returns an enumeration which contains the subnet mask. 238 * 239 * @return an enumeration which contains the subnet mask. 240 */ 241 public Enumeration<? extends Principal> members(){ 242 Vector<Principal> v = new Vector<Principal>(1); 243 v.addElement(this); 244 return v.elements(); 245 } 246 247 /** 248 * Removes the specified member from the group. (Not implemented) 249 * 250 * @param p the principal to remove from this group. 251 * @return allways return true. 252 */ 253 public boolean removeMember(Principal p) { 254 return true; 255 } 256 257 /** 258 * Prints a string representation of this group. 259 * 260 * @return a string representation of this group. 261 */ 262 public String toString() { 263 return ("NetMaskImpl :"+ super.getAddress().toString() + "/" + prefix); 264 } 265 266 }