Home | History | Annotate | Download | only in netlink
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.net.netlink;
     18 
     19 import android.net.netlink.NetlinkConstants;
     20 import android.system.OsConstants;
     21 import java.nio.ByteBuffer;
     22 
     23 
     24 /**
     25  * struct ndmsg
     26  *
     27  * see: <linux_src>/include/uapi/linux/neighbour.h
     28  *
     29  * @hide
     30  */
     31 public class StructNdMsg {
     32     // Already aligned.
     33     public static final int STRUCT_SIZE = 12;
     34 
     35     // Neighbor Cache Entry States
     36     public static final short NUD_NONE        = 0x00;
     37     public static final short NUD_INCOMPLETE  = 0x01;
     38     public static final short NUD_REACHABLE   = 0x02;
     39     public static final short NUD_STALE       = 0x04;
     40     public static final short NUD_DELAY       = 0x08;
     41     public static final short NUD_PROBE       = 0x10;
     42     public static final short NUD_FAILED      = 0x20;
     43     public static final short NUD_NOARP       = 0x40;
     44     public static final short NUD_PERMANENT   = 0x80;
     45 
     46     public static String stringForNudState(short nudState) {
     47         switch (nudState) {
     48             case NUD_NONE: return "NUD_NONE";
     49             case NUD_INCOMPLETE: return "NUD_INCOMPLETE";
     50             case NUD_REACHABLE: return "NUD_REACHABLE";
     51             case NUD_STALE: return "NUD_STALE";
     52             case NUD_DELAY: return "NUD_DELAY";
     53             case NUD_PROBE: return "NUD_PROBE";
     54             case NUD_FAILED: return "NUD_FAILED";
     55             case NUD_NOARP: return "NUD_NOARP";
     56             case NUD_PERMANENT: return "NUD_PERMANENT";
     57             default:
     58                 return "unknown NUD state: " + String.valueOf(nudState);
     59         }
     60     }
     61 
     62     public static boolean isNudStateConnected(short nudState) {
     63         return ((nudState & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)) != 0);
     64     }
     65 
     66     public static boolean isNudStateValid(short nudState) {
     67         return (isNudStateConnected(nudState) ||
     68                 ((nudState & (NUD_PROBE|NUD_STALE|NUD_DELAY)) != 0));
     69     }
     70 
     71     // Neighbor Cache Entry Flags
     72     public static byte NTF_USE       = (byte) 0x01;
     73     public static byte NTF_SELF      = (byte) 0x02;
     74     public static byte NTF_MASTER    = (byte) 0x04;
     75     public static byte NTF_PROXY     = (byte) 0x08;
     76     public static byte NTF_ROUTER    = (byte) 0x80;
     77 
     78     public static String stringForNudFlags(byte flags) {
     79         final StringBuilder sb = new StringBuilder();
     80         if ((flags & NTF_USE) != 0) {
     81             sb.append("NTF_USE");
     82         }
     83         if ((flags & NTF_SELF) != 0) {
     84             if (sb.length() > 0) { sb.append("|"); }
     85             sb.append("NTF_SELF");
     86         }
     87         if ((flags & NTF_MASTER) != 0) {
     88             if (sb.length() > 0) { sb.append("|"); }
     89             sb.append("NTF_MASTER");
     90         }
     91         if ((flags & NTF_PROXY) != 0) {
     92             if (sb.length() > 0) { sb.append("|");
     93         }
     94             sb.append("NTF_PROXY"); }
     95         if ((flags & NTF_ROUTER) != 0) {
     96             if (sb.length() > 0) { sb.append("|"); }
     97             sb.append("NTF_ROUTER");
     98         }
     99         return sb.toString();
    100     }
    101 
    102     private static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
    103         return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
    104     }
    105 
    106     public static StructNdMsg parse(ByteBuffer byteBuffer) {
    107         if (!hasAvailableSpace(byteBuffer)) { return null; }
    108 
    109         // The ByteOrder must have already been set by the caller.  In most
    110         // cases ByteOrder.nativeOrder() is correct, with the possible
    111         // exception of usage within unittests.
    112         final StructNdMsg struct = new StructNdMsg();
    113         struct.ndm_family = byteBuffer.get();
    114         final byte pad1 = byteBuffer.get();
    115         final short pad2 = byteBuffer.getShort();
    116         struct.ndm_ifindex = byteBuffer.getInt();
    117         struct.ndm_state = byteBuffer.getShort();
    118         struct.ndm_flags = byteBuffer.get();
    119         struct.ndm_type = byteBuffer.get();
    120         return struct;
    121     }
    122 
    123     public byte ndm_family;
    124     public int ndm_ifindex;
    125     public short ndm_state;
    126     public byte ndm_flags;
    127     public byte ndm_type;
    128 
    129     public StructNdMsg() {
    130         ndm_family = (byte) OsConstants.AF_UNSPEC;
    131     }
    132 
    133     public void pack(ByteBuffer byteBuffer) {
    134         // The ByteOrder must have already been set by the caller.  In most
    135         // cases ByteOrder.nativeOrder() is correct, with the exception
    136         // of usage within unittests.
    137         byteBuffer.put(ndm_family);
    138         byteBuffer.put((byte) 0);         // pad1
    139         byteBuffer.putShort((short) 0);   // pad2
    140         byteBuffer.putInt(ndm_ifindex);
    141         byteBuffer.putShort(ndm_state);
    142         byteBuffer.put(ndm_flags);
    143         byteBuffer.put(ndm_type);
    144     }
    145 
    146     public boolean nudConnected() {
    147         return isNudStateConnected(ndm_state);
    148     }
    149 
    150     public boolean nudValid() {
    151         return isNudStateValid(ndm_state);
    152     }
    153 
    154     @Override
    155     public String toString() {
    156         final String stateStr = "" + ndm_state + " (" + stringForNudState(ndm_state) + ")";
    157         final String flagsStr = "" + ndm_flags + " (" + stringForNudFlags(ndm_flags) + ")";
    158         return "StructNdMsg{ "
    159                 + "family{" + NetlinkConstants.stringForAddressFamily((int) ndm_family) + "}, "
    160                 + "ifindex{" + ndm_ifindex + "}, "
    161                 + "state{" + stateStr + "}, "
    162                 + "flags{" + flagsStr + "}, "
    163                 + "type{" + ndm_type + "} "
    164                 + "}";
    165     }
    166 }
    167