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 java.nio.ByteBuffer;
     21 
     22 
     23 /**
     24  * struct nlmsghdr
     25  *
     26  * see <linux_src>/include/uapi/linux/netlink.h
     27  *
     28  * @hide
     29  */
     30 public class StructNlMsgHdr {
     31     // Already aligned.
     32     public static final int STRUCT_SIZE = 16;
     33 
     34     public static final short NLM_F_REQUEST = 0x0001;
     35     public static final short NLM_F_MULTI   = 0x0002;
     36     public static final short NLM_F_ACK     = 0x0004;
     37     public static final short NLM_F_ECHO    = 0x0008;
     38     // Flags for a GET request.
     39     public static final short NLM_F_ROOT    = 0x0100;
     40     public static final short NLM_F_MATCH   = 0x0200;
     41     public static final short NLM_F_DUMP    = NLM_F_ROOT|NLM_F_MATCH;
     42     // Flags for a NEW request.
     43     public static final short NLM_F_REPLACE   = 0x100;
     44     public static final short NLM_F_EXCL      = 0x200;
     45     public static final short NLM_F_CREATE    = 0x400;
     46     public static final short NLM_F_APPEND    = 0x800;
     47 
     48 
     49     public static String stringForNlMsgFlags(short flags) {
     50         final StringBuilder sb = new StringBuilder();
     51         if ((flags & NLM_F_REQUEST) != 0) {
     52             sb.append("NLM_F_REQUEST");
     53         }
     54         if ((flags & NLM_F_MULTI) != 0) {
     55             if (sb.length() > 0) { sb.append("|"); }
     56             sb.append("NLM_F_MULTI");
     57         }
     58         if ((flags & NLM_F_ACK) != 0) {
     59             if (sb.length() > 0) { sb.append("|"); }
     60             sb.append("NLM_F_ACK");
     61         }
     62         if ((flags & NLM_F_ECHO) != 0) {
     63             if (sb.length() > 0) { sb.append("|"); }
     64             sb.append("NLM_F_ECHO");
     65         }
     66         if ((flags & NLM_F_ROOT) != 0) {
     67             if (sb.length() > 0) { sb.append("|"); }
     68             sb.append("NLM_F_ROOT");
     69         }
     70         if ((flags & NLM_F_MATCH) != 0) {
     71             if (sb.length() > 0) { sb.append("|"); }
     72             sb.append("NLM_F_MATCH");
     73         }
     74         return sb.toString();
     75     }
     76 
     77     public static boolean hasAvailableSpace(ByteBuffer byteBuffer) {
     78         return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE;
     79     }
     80 
     81     public static StructNlMsgHdr parse(ByteBuffer byteBuffer) {
     82         if (!hasAvailableSpace(byteBuffer)) { return null; }
     83 
     84         // The ByteOrder must have already been set by the caller.  In most
     85         // cases ByteOrder.nativeOrder() is correct, with the exception
     86         // of usage within unittests.
     87         final StructNlMsgHdr struct = new StructNlMsgHdr();
     88         struct.nlmsg_len = byteBuffer.getInt();
     89         struct.nlmsg_type = byteBuffer.getShort();
     90         struct.nlmsg_flags = byteBuffer.getShort();
     91         struct.nlmsg_seq = byteBuffer.getInt();
     92         struct.nlmsg_pid = byteBuffer.getInt();
     93 
     94         if (struct.nlmsg_len < STRUCT_SIZE) {
     95             // Malformed.
     96             return null;
     97         }
     98         return struct;
     99     }
    100 
    101     public int nlmsg_len;
    102     public short nlmsg_type;
    103     public short nlmsg_flags;
    104     public int nlmsg_seq;
    105     public int nlmsg_pid;
    106 
    107     public StructNlMsgHdr() {
    108         nlmsg_len = 0;
    109         nlmsg_type = 0;
    110         nlmsg_flags = 0;
    111         nlmsg_seq = 0;
    112         nlmsg_pid = 0;
    113     }
    114 
    115     public void pack(ByteBuffer byteBuffer) {
    116         // The ByteOrder must have already been set by the caller.  In most
    117         // cases ByteOrder.nativeOrder() is correct, with the possible
    118         // exception of usage within unittests.
    119         byteBuffer.putInt(nlmsg_len);
    120         byteBuffer.putShort(nlmsg_type);
    121         byteBuffer.putShort(nlmsg_flags);
    122         byteBuffer.putInt(nlmsg_seq);
    123         byteBuffer.putInt(nlmsg_pid);
    124     }
    125 
    126     @Override
    127     public String toString() {
    128         final String typeStr = "" + nlmsg_type
    129                 + "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")";
    130         final String flagsStr = "" + nlmsg_flags
    131                 + "(" + stringForNlMsgFlags(nlmsg_flags) + ")";
    132         return "StructNlMsgHdr{ "
    133                 + "nlmsg_len{" + nlmsg_len + "}, "
    134                 + "nlmsg_type{" + typeStr + "}, "
    135                 + "nlmsg_flags{" + flagsStr + ")}, "
    136                 + "nlmsg_seq{" + nlmsg_seq + "}, "
    137                 + "nlmsg_pid{" + nlmsg_pid + "} "
    138                 + "}";
    139     }
    140 }
    141